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