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