e82f07d35150b0a90f697011d2191ea7d1d73b46
[android/platform/frameworks/opt/telephony.git] / src / java / com / android / internal / telephony / cdma / CdmaLteServiceStateTracker.java
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.android.internal.telephony.cdma;
18
19 import com.android.internal.telephony.PhoneBase;
20 import com.android.internal.telephony.TelephonyProperties;
21 import com.android.internal.telephony.MccTable;
22 import com.android.internal.telephony.EventLogTags;
23 import com.android.internal.telephony.RILConstants;
24 import com.android.internal.telephony.IccCard;
25
26 import android.telephony.CellInfo;
27 import android.telephony.CellInfoLte;
28 import android.telephony.CellSignalStrengthLte;
29 import android.telephony.CellIdentityLte;
30 import android.telephony.SignalStrength;
31 import android.telephony.ServiceState;
32 import android.telephony.cdma.CdmaCellLocation;
33 import android.text.TextUtils;
34 import android.os.AsyncResult;
35 import android.os.Message;
36 import android.os.SystemClock;
37 import android.os.SystemProperties;
38
39 import android.text.TextUtils;
40 import android.util.Log;
41 import android.util.EventLog;
42
43 import com.android.internal.telephony.gsm.GsmDataConnectionTracker;
44 import com.android.internal.telephony.IccCardConstants;
45
46 import java.io.FileDescriptor;
47 import java.io.PrintWriter;
48 import java.util.ArrayList;
49 import java.util.List;
50
51 public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
52     private CDMALTEPhone mCdmaLtePhone;
53     private final CellInfoLte mCellInfoLte;
54
55     private ServiceState  mLteSS;  // The last LTE state from Voice Registration
56
57     private CellIdentityLte mNewCellIdentityLte = new CellIdentityLte();
58     private CellIdentityLte mLasteCellIdentityLte = new CellIdentityLte();
59
60     public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
61         super(phone, new CellInfoLte());
62         mCdmaLtePhone = phone;
63         mCellInfoLte = (CellInfoLte) mCellInfo;
64
65         mLteSS = new ServiceState();
66         ((CellInfoLte)mCellInfo).setCellSignalStrength(new CellSignalStrengthLte());
67         ((CellInfoLte)mCellInfo).setCellIdentity(new CellIdentityLte());
68
69         if (DBG) log("CdmaLteServiceStateTracker Constructors");
70     }
71
72     @Override
73     public void handleMessage(Message msg) {
74         AsyncResult ar;
75         int[] ints;
76         String[] strings;
77         switch (msg.what) {
78         case EVENT_POLL_STATE_GPRS:
79             if (DBG) log("handleMessage EVENT_POLL_STATE_GPRS");
80             ar = (AsyncResult)msg.obj;
81             handlePollStateResult(msg.what, ar);
82             break;
83         case EVENT_RUIM_RECORDS_LOADED:
84             CdmaLteUiccRecords sim = (CdmaLteUiccRecords)mIccRecords;
85             if ((sim != null) && sim.isProvisioned()) {
86                 mMdn = sim.getMdn();
87                 mMin = sim.getMin();
88                 parseSidNid(sim.getSid(), sim.getNid());
89                 mPrlVersion = sim.getPrlVersion();;
90                 mIsMinInfoReady = true;
91                 updateOtaspState();
92             }
93             // SID/NID/PRL is loaded. Poll service state
94             // again to update to the roaming state with
95             // the latest variables.
96             pollState();
97             break;
98         default:
99             super.handleMessage(msg);
100         }
101     }
102
103     /**
104      * Set the cdmaSS for EVENT_POLL_STATE_REGISTRATION_CDMA
105      */
106     @Override
107     protected void setCdmaTechnology(int radioTechnology) {
108         // Called on voice registration state response.
109         // Just record new CDMA radio technology
110         newSS.setRadioTechnology(radioTechnology);
111     }
112
113     /**
114      * Handle the result of one of the pollState()-related requests
115      */
116     @Override
117     protected void handlePollStateResultMessage(int what, AsyncResult ar) {
118         if (what == EVENT_POLL_STATE_GPRS) {
119             String states[] = (String[])ar.result;
120             if (DBG) {
121                 log("handlePollStateResultMessage: EVENT_POLL_STATE_GPRS states.length=" +
122                         states.length + " states=" + states);
123             }
124
125             int type = 0;
126             int regState = -1;
127             if (states.length > 0) {
128                 try {
129                     regState = Integer.parseInt(states[0]);
130
131                     // states[3] (if present) is the current radio technology
132                     if (states.length >= 4 && states[3] != null) {
133                         type = Integer.parseInt(states[3]);
134                     }
135                 } catch (NumberFormatException ex) {
136                     loge("handlePollStateResultMessage: error parsing GprsRegistrationState: "
137                                     + ex);
138                 }
139                 if (states.length >= 10) {
140                     int mcc;
141                     int mnc;
142                     int tac;
143                     int pci;
144                     int eci;
145                     int csgid;
146                     String operatorNumeric = null;
147
148                     try {
149                         operatorNumeric = mLteSS.getOperatorNumeric();
150                         mcc = Integer.parseInt(operatorNumeric.substring(0,3));
151                     } catch (Exception e) {
152                         try {
153                             operatorNumeric = ss.getOperatorNumeric();
154                             mcc = Integer.parseInt(operatorNumeric.substring(0,3));
155                         } catch (Exception ex) {
156                             loge("handlePollStateResultMessage: bad mcc operatorNumeric=" +
157                                     operatorNumeric + " ex=" + ex);
158                             operatorNumeric = "";
159                             mcc = Integer.MAX_VALUE;
160                         }
161                     }
162                     try {
163                         mnc = Integer.parseInt(operatorNumeric.substring(3));
164                     } catch (Exception e) {
165                         loge("handlePollStateResultMessage: bad mnc operatorNumeric=" +
166                                 operatorNumeric + " e=" + e);
167                         mnc = Integer.MAX_VALUE;
168                     }
169                     try {
170                         tac = Integer.parseInt(states[6], 16);
171                     } catch (Exception e) {
172                         loge("handlePollStateResultMessage: bad tac states[6]=" +
173                                 states[6] + " e=" + e);
174                         tac = Integer.MAX_VALUE;
175                     }
176                     try {
177                         pci = Integer.parseInt(states[7], 16);
178                     } catch (Exception e) {
179                         loge("handlePollStateResultMessage: bad pci states[7]=" +
180                                 states[7] + " e=" + e);
181                         pci = Integer.MAX_VALUE;
182                     }
183                     try {
184                         eci = Integer.parseInt(states[8], 16);
185                     } catch (Exception e) {
186                         loge("handlePollStateResultMessage: bad eci states[8]=" +
187                                 states[8] + " e=" + e);
188                         eci = Integer.MAX_VALUE;
189                     }
190                     try {
191                         csgid = Integer.parseInt(states[9], 16);
192                     } catch (Exception e) {
193                         // FIX: Always bad so don't pollute the logs
194                         // loge("handlePollStateResultMessage: bad csgid states[9]=" +
195                         //        states[9] + " e=" + e);
196                         csgid = Integer.MAX_VALUE;
197                     }
198                     mNewCellIdentityLte = new CellIdentityLte(mcc, mnc, eci, pci, tac);
199                     if (DBG) {
200                         log("handlePollStateResultMessage: mNewLteCellIdentity=" +
201                                 mNewCellIdentityLte);
202                     }
203                 }
204             }
205
206             mLteSS.setRadioTechnology(type);
207             mLteSS.setState(regCodeToServiceState(regState));
208         } else {
209             super.handlePollStateResultMessage(what, ar);
210         }
211     }
212
213     @Override
214     protected void pollState() {
215         pollingContext = new int[1];
216         pollingContext[0] = 0;
217
218         switch (cm.getRadioState()) {
219             case RADIO_UNAVAILABLE:
220                 newSS.setStateOutOfService();
221                 newCellLoc.setStateInvalid();
222                 setSignalStrengthDefaultValues();
223                 mGotCountryCode = false;
224
225                 pollStateDone();
226                 break;
227
228             case RADIO_OFF:
229                 newSS.setStateOff();
230                 newCellLoc.setStateInvalid();
231                 setSignalStrengthDefaultValues();
232                 mGotCountryCode = false;
233
234                 pollStateDone();
235                 break;
236
237             default:
238                 // Issue all poll-related commands at once, then count
239                 // down the responses which are allowed to arrive
240                 // out-of-order.
241
242                 pollingContext[0]++;
243                 // RIL_REQUEST_OPERATOR is necessary for CDMA
244                 cm.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
245
246                 pollingContext[0]++;
247                 // RIL_REQUEST_VOICE_REGISTRATION_STATE is necessary for CDMA
248                 cm.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA,
249                         pollingContext));
250
251                 pollingContext[0]++;
252                 // RIL_REQUEST_DATA_REGISTRATION_STATE
253                 cm.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS,
254                                             pollingContext));
255                 break;
256         }
257     }
258
259     @Override
260     protected void pollStateDone() {
261         // determine data RadioTechnology from both LET and CDMA SS
262         if (mLteSS.getState() == ServiceState.STATE_IN_SERVICE) {
263             //in LTE service
264             mNewRilRadioTechnology = mLteSS.getRilRadioTechnology();
265             mNewDataConnectionState = mLteSS.getState();
266             newSS.setRadioTechnology(mNewRilRadioTechnology);
267             log("pollStateDone LTE/eHRPD STATE_IN_SERVICE mNewRilRadioTechnology = " +
268                     mNewRilRadioTechnology);
269         } else {
270             // LTE out of service, get CDMA Service State
271             mNewRilRadioTechnology = newSS.getRilRadioTechnology();
272             mNewDataConnectionState = radioTechnologyToDataServiceState(mNewRilRadioTechnology);
273             log("pollStateDone CDMA STATE_IN_SERVICE mNewRilRadioTechnology = " +
274                     mNewRilRadioTechnology + " mNewDataConnectionState = " +
275                     mNewDataConnectionState);
276         }
277
278         // TODO: Add proper support for LTE Only, we should be looking at
279         //       the preferred network mode, to know when newSS state should
280         //       be coming from mLteSs state. This was needed to pass a VZW
281         //       LTE Only test.
282         //
283         // If CDMA service is OOS, double check if the device is running with LTE only
284         // mode. If that is the case, derive the service state from LTE side.
285         // To set in LTE only mode, sqlite3 /data/data/com.android.providers.settings/
286         // databases/settings.db "update secure set value='11' where name='preferred_network_mode'"
287         if (newSS.getState() == ServiceState.STATE_OUT_OF_SERVICE) {
288             int networkMode = android.provider.Settings.Secure.getInt(phone.getContext()
289                                   .getContentResolver(),
290                                   android.provider.Settings.Secure.PREFERRED_NETWORK_MODE,
291                                   RILConstants.PREFERRED_NETWORK_MODE);
292             if (networkMode == RILConstants.NETWORK_MODE_LTE_ONLY) {
293                 if (DBG) log("pollState: LTE Only mode");
294                 newSS.setState(mLteSS.getState());
295             }
296         }
297
298         if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
299
300         boolean hasRegistered = ss.getState() != ServiceState.STATE_IN_SERVICE
301                 && newSS.getState() == ServiceState.STATE_IN_SERVICE;
302
303         boolean hasDeregistered = ss.getState() == ServiceState.STATE_IN_SERVICE
304                 && newSS.getState() != ServiceState.STATE_IN_SERVICE;
305
306         boolean hasCdmaDataConnectionAttached =
307             mDataConnectionState != ServiceState.STATE_IN_SERVICE
308                 && mNewDataConnectionState == ServiceState.STATE_IN_SERVICE;
309
310         boolean hasCdmaDataConnectionDetached =
311             mDataConnectionState == ServiceState.STATE_IN_SERVICE
312                 && mNewDataConnectionState != ServiceState.STATE_IN_SERVICE;
313
314         boolean hasCdmaDataConnectionChanged =
315             mDataConnectionState != mNewDataConnectionState;
316
317         boolean hasRadioTechnologyChanged = mRilRadioTechnology != mNewRilRadioTechnology;
318
319         boolean hasChanged = !newSS.equals(ss);
320
321         boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
322
323         boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
324
325         boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
326
327         boolean has4gHandoff =
328                 mNewDataConnectionState == ServiceState.STATE_IN_SERVICE &&
329                 (((mRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) &&
330                   (mNewRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) ||
331                  ((mRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD) &&
332                   (mNewRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_LTE)));
333
334         boolean hasMultiApnSupport =
335                 (((mNewRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) ||
336                   (mNewRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) &&
337                  ((mRilRadioTechnology != ServiceState.RIL_RADIO_TECHNOLOGY_LTE) &&
338                   (mRilRadioTechnology != ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)));
339
340         boolean hasLostMultiApnSupport =
341             ((mNewRilRadioTechnology >= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A) &&
342              (mNewRilRadioTechnology <= ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A));
343
344         if (DBG) {
345             log("pollStateDone:"
346                 + " hasRegistered=" + hasRegistered
347                 + " hasDeegistered=" + hasDeregistered
348                 + " hasCdmaDataConnectionAttached=" + hasCdmaDataConnectionAttached
349                 + " hasCdmaDataConnectionDetached=" + hasCdmaDataConnectionDetached
350                 + " hasCdmaDataConnectionChanged=" + hasCdmaDataConnectionChanged
351                 + " hasRadioTechnologyChanged = " + hasRadioTechnologyChanged
352                 + " hasChanged=" + hasChanged
353                 + " hasRoamingOn=" + hasRoamingOn
354                 + " hasRoamingOff=" + hasRoamingOff
355                 + " hasLocationChanged=" + hasLocationChanged
356                 + " has4gHandoff = " + has4gHandoff
357                 + " hasMultiApnSupport=" + hasMultiApnSupport
358                 + " hasLostMultiApnSupport=" + hasLostMultiApnSupport);
359         }
360         // Add an event log when connection state changes
361         if (ss.getState() != newSS.getState()
362                 || mDataConnectionState != mNewDataConnectionState) {
363             EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, ss.getState(),
364                     mDataConnectionState, newSS.getState(), mNewDataConnectionState);
365         }
366
367         ServiceState tss;
368         tss = ss;
369         ss = newSS;
370         newSS = tss;
371         // clean slate for next time
372         newSS.setStateOutOfService();
373         mLteSS.setStateOutOfService();
374
375         if ((hasMultiApnSupport)
376                 && (phone.mDataConnectionTracker instanceof CdmaDataConnectionTracker)) {
377             if (DBG) log("GsmDataConnectionTracker Created");
378             phone.mDataConnectionTracker.dispose();
379             phone.mDataConnectionTracker = new GsmDataConnectionTracker(mCdmaLtePhone);
380         }
381
382         if ((hasLostMultiApnSupport)
383                 && (phone.mDataConnectionTracker instanceof GsmDataConnectionTracker)) {
384             if (DBG)log("GsmDataConnectionTracker disposed");
385             phone.mDataConnectionTracker.dispose();
386             phone.mDataConnectionTracker = new CdmaDataConnectionTracker(phone);
387         }
388
389         CdmaCellLocation tcl = cellLoc;
390         cellLoc = newCellLoc;
391         newCellLoc = tcl;
392
393         mDataConnectionState = mNewDataConnectionState;
394         mRilRadioTechnology = mNewRilRadioTechnology;
395         mNewRilRadioTechnology = 0;
396
397         newSS.setStateOutOfService(); // clean slate for next time
398
399         if (hasRadioTechnologyChanged) {
400             phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
401                     ServiceState.rilRadioTechnologyToString(mRilRadioTechnology));
402         }
403
404         if (hasRegistered) {
405             mNetworkAttachedRegistrants.notifyRegistrants();
406         }
407
408         if (hasChanged) {
409             if (phone.isEriFileLoaded()) {
410                 String eriText;
411                 // Now the CDMAPhone sees the new ServiceState so it can get the
412                 // new ERI text
413                 if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
414                     eriText = phone.getCdmaEriText();
415                 } else if (ss.getState() == ServiceState.STATE_POWER_OFF) {
416                     eriText = (mIccRecords != null) ? mIccRecords.getServiceProviderName() : null;
417                     if (TextUtils.isEmpty(eriText)) {
418                         // Sets operator alpha property by retrieving from
419                         // build-time system property
420                         eriText = SystemProperties.get("ro.cdma.home.operator.alpha");
421                     }
422                 } else {
423                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used
424                     // for mRegistrationState 0,2,3 and 4
425                     eriText = phone.getContext()
426                             .getText(com.android.internal.R.string.roamingTextSearching).toString();
427                 }
428                 ss.setOperatorAlphaLong(eriText);
429             }
430
431             if (mIccCard != null && mIccCard.getState() == IccCardConstants.State.READY &&
432                     mIccRecords != null) {
433                 // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches
434                 // one configfured in SIM, use operator name  from CSIM record.
435                 boolean showSpn =
436                     ((CdmaLteUiccRecords)mIccRecords).getCsimSpnDisplayCondition();
437                 int iconIndex = ss.getCdmaEriIconIndex();
438
439                 if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) &&
440                     isInHomeSidNid(ss.getSystemId(), ss.getNetworkId()) &&
441                     mIccRecords != null) {
442                     ss.setOperatorAlphaLong(mIccRecords.getServiceProviderName());
443                 }
444             }
445
446             String operatorNumeric;
447
448             phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
449                     ss.getOperatorAlphaLong());
450
451             String prevOperatorNumeric =
452                     SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
453             operatorNumeric = ss.getOperatorNumeric();
454             phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
455
456             if (operatorNumeric == null) {
457                 if (DBG) log("operatorNumeric is null");
458                 phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
459                 mGotCountryCode = false;
460             } else {
461                 String isoCountryCode = "";
462                 String mcc = operatorNumeric.substring(0, 3);
463                 try {
464                     isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(operatorNumeric
465                             .substring(0, 3)));
466                 } catch (NumberFormatException ex) {
467                     loge("countryCodeForMcc error" + ex);
468                 } catch (StringIndexOutOfBoundsException ex) {
469                     loge("countryCodeForMcc error" + ex);
470                 }
471
472                 phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
473                         isoCountryCode);
474                 mGotCountryCode = true;
475
476                 if (shouldFixTimeZoneNow(phone, operatorNumeric, prevOperatorNumeric,
477                         mNeedFixZone)) {
478                     fixTimeZone(isoCountryCode);
479                 }
480             }
481
482             phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
483                     ss.getRoaming() ? "true" : "false");
484
485             updateSpnDisplay();
486             phone.notifyServiceStateChanged(ss);
487         }
488
489         if (hasCdmaDataConnectionAttached || has4gHandoff) {
490             mAttachedRegistrants.notifyRegistrants();
491         }
492
493         if (hasCdmaDataConnectionDetached) {
494             mDetachedRegistrants.notifyRegistrants();
495         }
496
497         if ((hasCdmaDataConnectionChanged || hasRadioTechnologyChanged)) {
498             phone.notifyDataConnection(null);
499         }
500
501         if (hasRoamingOn) {
502             mRoamingOnRegistrants.notifyRegistrants();
503         }
504
505         if (hasRoamingOff) {
506             mRoamingOffRegistrants.notifyRegistrants();
507         }
508
509         if (hasLocationChanged) {
510             phone.notifyLocationChanged();
511         }
512
513         ArrayList<CellInfo> arrayCi = new ArrayList<CellInfo>();
514         synchronized(mCellInfo) {
515             CellInfoLte cil = (CellInfoLte)mCellInfo;
516
517             boolean cidChanged = ! mNewCellIdentityLte.equals(mLasteCellIdentityLte);
518             if (hasRegistered || hasDeregistered || cidChanged) {
519                 // TODO: Handle the absence of LteCellIdentity
520                 long timeStamp = SystemClock.elapsedRealtime() * 1000;
521                 boolean registered = ss.getState() == ServiceState.STATE_IN_SERVICE;
522                 mLasteCellIdentityLte = mNewCellIdentityLte;
523
524                 cil.setRegisterd(registered);
525                 cil.setCellIdentity(mLasteCellIdentityLte);
526                 if (DBG) {
527                     log("pollStateDone: hasRegistered=" + hasRegistered +
528                             " hasDeregistered=" + hasDeregistered +
529                             " cidChanged=" + cidChanged +
530                             " mCellInfo=" + mCellInfo);
531                 }
532                 arrayCi.add(mCellInfo);
533             }
534             mPhoneBase.notifyCellInfo(arrayCi);
535         }
536     }
537
538     @Override
539     protected boolean onSignalStrengthResult(AsyncResult ar, boolean isGsm) {
540         if (mRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) {
541             isGsm = true;
542         }
543         boolean ssChanged = super.onSignalStrengthResult(ar, isGsm);
544
545         synchronized (mCellInfo) {
546             if (mRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) {
547                 mCellInfoLte.setTimeStamp(SystemClock.elapsedRealtime() * 1000);
548                 mCellInfoLte.setTimeStampType(CellInfo.TIMESTAMP_TYPE_JAVA_RIL);
549                 mCellInfoLte.getCellSignalStrength()
550                                 .initialize(mSignalStrength,SignalStrength.INVALID);
551             }
552             if (mCellInfoLte.getCellIdentity() != null) {
553                 ArrayList<CellInfo> arrayCi = new ArrayList<CellInfo>();
554                 arrayCi.add(mCellInfoLte);
555                 mPhoneBase.notifyCellInfo(arrayCi);
556             }
557         }
558         return ssChanged;
559     }
560
561     @Override
562     public boolean isConcurrentVoiceAndDataAllowed() {
563         // Note: it needs to be confirmed which CDMA network types
564         // can support voice and data calls concurrently.
565         // For the time-being, the return value will be false.
566         return (mRilRadioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_LTE);
567     }
568
569     /**
570      * Check whether the specified SID and NID pair appears in the HOME SID/NID list
571      * read from NV or SIM.
572      *
573      * @return true if provided sid/nid pair belongs to operator's home network.
574      */
575     private boolean isInHomeSidNid(int sid, int nid) {
576         // if SID/NID is not available, assume this is home network.
577         if (isSidsAllZeros()) return true;
578
579         // length of SID/NID shold be same
580         if (mHomeSystemId.length != mHomeNetworkId.length) return true;
581
582         if (sid == 0) return true;
583
584         for (int i = 0; i < mHomeSystemId.length; i++) {
585             // Use SID only if NID is a reserved value.
586             // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2)
587             if ((mHomeSystemId[i] == sid) &&
588                 ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) ||
589                  (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) {
590                 return true;
591             }
592         }
593         // SID/NID are not in the list. So device is not in home network
594         return false;
595     }
596
597     /**
598      * @return all available cell information, the returned List maybe empty but never null.
599      */
600     @Override
601     public List<CellInfo> getAllCellInfo() {
602         ArrayList<CellInfo> arrayList = new ArrayList<CellInfo>();
603         CellInfo ci;
604         synchronized(mCellInfo) {
605             arrayList.add(mCellInfoLte);
606         }
607         if (DBG) log ("getAllCellInfo: arrayList=" + arrayList);
608         return arrayList;
609     }
610
611     @Override
612     protected void log(String s) {
613         Log.d(LOG_TAG, "[CdmaLteSST] " + s);
614     }
615
616     @Override
617     protected void loge(String s) {
618         Log.e(LOG_TAG, "[CdmaLteSST] " + s);
619     }
620
621     @Override
622     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
623         pw.println("CdmaLteServiceStateTracker extends:");
624         super.dump(fd, pw, args);
625         pw.println(" mCdmaLtePhone=" + mCdmaLtePhone);
626         pw.println(" mLteSS=" + mLteSS);
627     }
628 }