Home | History | Annotate | Download | only in cdma
      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 android.content.Intent;
     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.uicc.RuimRecords;
     24 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
     25 import com.android.internal.telephony.TelephonyIntents;
     26 import com.android.internal.telephony.Phone;
     27 import com.android.internal.telephony.PhoneFactory;
     28 
     29 import android.telephony.CellInfo;
     30 import android.telephony.CellInfoLte;
     31 import android.telephony.CellSignalStrengthLte;
     32 import android.telephony.CellIdentityLte;
     33 import android.telephony.SignalStrength;
     34 import android.telephony.ServiceState;
     35 import android.telephony.cdma.CdmaCellLocation;
     36 import android.telephony.TelephonyManager;
     37 import android.text.TextUtils;
     38 import android.os.AsyncResult;
     39 import android.os.Message;
     40 import android.os.UserHandle;
     41 import android.os.SystemClock;
     42 import android.os.SystemProperties;
     43 
     44 import android.telephony.Rlog;
     45 import android.util.EventLog;
     46 
     47 import com.android.internal.telephony.dataconnection.DcTrackerBase;
     48 import com.android.internal.telephony.ProxyController;
     49 import android.telephony.SubscriptionManager;
     50 import com.android.internal.telephony.uicc.UiccCardApplication;
     51 import com.android.internal.telephony.uicc.UiccController;
     52 
     53 import java.io.FileDescriptor;
     54 import java.io.PrintWriter;
     55 import java.util.ArrayList;
     56 import java.util.List;
     57 
     58 public class CdmaLteServiceStateTracker extends CdmaServiceStateTracker {
     59     private CDMALTEPhone mCdmaLtePhone;
     60     private final CellInfoLte mCellInfoLte;
     61     private static final int EVENT_ALL_DATA_DISCONNECTED = 1001;
     62 
     63     private CellIdentityLte mNewCellIdentityLte = new CellIdentityLte();
     64     private CellIdentityLte mLasteCellIdentityLte = new CellIdentityLte();
     65 
     66     public CdmaLteServiceStateTracker(CDMALTEPhone phone) {
     67         super(phone, new CellInfoLte());
     68         mCdmaLtePhone = phone;
     69         mCellInfoLte = (CellInfoLte) mCellInfo;
     70 
     71         ((CellInfoLte)mCellInfo).setCellSignalStrength(new CellSignalStrengthLte());
     72         ((CellInfoLte)mCellInfo).setCellIdentity(new CellIdentityLte());
     73 
     74         if (DBG) log("CdmaLteServiceStateTracker Constructors");
     75     }
     76 
     77     @Override
     78     public void handleMessage(Message msg) {
     79         AsyncResult ar;
     80         int[] ints;
     81         String[] strings;
     82 
     83         if (!mPhone.mIsTheCurrentActivePhone) {
     84             loge("Received message " + msg + "[" + msg.what + "]" +
     85                     " while being destroyed. Ignoring.");
     86             return;
     87         }
     88 
     89         if (DBG) log("handleMessage: " + msg.what);
     90         switch (msg.what) {
     91         case EVENT_POLL_STATE_GPRS:
     92             if (DBG) log("handleMessage EVENT_POLL_STATE_GPRS");
     93             ar = (AsyncResult)msg.obj;
     94             handlePollStateResult(msg.what, ar);
     95             break;
     96         case EVENT_RUIM_RECORDS_LOADED:
     97             updatePhoneObject();
     98             RuimRecords ruim = (RuimRecords)mIccRecords;
     99             if (ruim != null) {
    100                 if (ruim.isProvisioned()) {
    101                     mMdn = ruim.getMdn();
    102                     mMin = ruim.getMin();
    103                     parseSidNid(ruim.getSid(), ruim.getNid());
    104                     mPrlVersion = ruim.getPrlVersion();
    105                     mIsMinInfoReady = true;
    106                 }
    107                 updateOtaspState();
    108             }
    109             // reload eri in case of IMSI changed
    110             // eri.xml can be defined by mcc mnc
    111             mPhone.prepareEri();
    112             // SID/NID/PRL is loaded. Poll service state
    113             // again to update to the roaming state with
    114             // the latest variables.
    115             pollState();
    116             break;
    117         case EVENT_ALL_DATA_DISCONNECTED:
    118             long dds = SubscriptionManager.getDefaultDataSubId();
    119             ProxyController.getInstance().unregisterForAllDataDisconnected(dds, this);
    120             synchronized(this) {
    121                 if (mPendingRadioPowerOffAfterDataOff) {
    122                     if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now.");
    123                     hangupAndPowerOff();
    124                     mPendingRadioPowerOffAfterDataOff = false;
    125                 } else {
    126                     log("EVENT_ALL_DATA_DISCONNECTED is stale");
    127                 }
    128             }
    129             break;
    130         default:
    131             super.handleMessage(msg);
    132         }
    133     }
    134 
    135     /**
    136      * Handle the result of one of the pollState()-related requests
    137      */
    138     @Override
    139     protected void handlePollStateResultMessage(int what, AsyncResult ar) {
    140         if (what == EVENT_POLL_STATE_GPRS) {
    141             String states[] = (String[])ar.result;
    142             if (DBG) {
    143                 log("handlePollStateResultMessage: EVENT_POLL_STATE_GPRS states.length=" +
    144                         states.length + " states=" + states);
    145             }
    146 
    147             int type = 0;
    148             int regState = -1;
    149             if (states.length > 0) {
    150                 try {
    151                     regState = Integer.parseInt(states[0]);
    152 
    153                     // states[3] (if present) is the current radio technology
    154                     if (states.length >= 4 && states[3] != null) {
    155                         type = Integer.parseInt(states[3]);
    156                     }
    157                 } catch (NumberFormatException ex) {
    158                     loge("handlePollStateResultMessage: error parsing GprsRegistrationState: "
    159                                     + ex);
    160                 }
    161                 if (states.length >= 10) {
    162                     int mcc;
    163                     int mnc;
    164                     int tac;
    165                     int pci;
    166                     int eci;
    167                     int csgid;
    168                     String operatorNumeric = null;
    169 
    170                     try {
    171                         operatorNumeric = mNewSS.getOperatorNumeric();
    172                         mcc = Integer.parseInt(operatorNumeric.substring(0,3));
    173                     } catch (Exception e) {
    174                         try {
    175                             operatorNumeric = mSS.getOperatorNumeric();
    176                             mcc = Integer.parseInt(operatorNumeric.substring(0,3));
    177                         } catch (Exception ex) {
    178                             loge("handlePollStateResultMessage: bad mcc operatorNumeric=" +
    179                                     operatorNumeric + " ex=" + ex);
    180                             operatorNumeric = "";
    181                             mcc = Integer.MAX_VALUE;
    182                         }
    183                     }
    184                     try {
    185                         mnc = Integer.parseInt(operatorNumeric.substring(3));
    186                     } catch (Exception e) {
    187                         loge("handlePollStateResultMessage: bad mnc operatorNumeric=" +
    188                                 operatorNumeric + " e=" + e);
    189                         mnc = Integer.MAX_VALUE;
    190                     }
    191 
    192                     // Use Integer#decode to be generous in what we receive and allow
    193                     // decimal, hex or octal values.
    194                     try {
    195                         tac = Integer.decode(states[6]);
    196                     } catch (Exception e) {
    197                         loge("handlePollStateResultMessage: bad tac states[6]=" +
    198                                 states[6] + " e=" + e);
    199                         tac = Integer.MAX_VALUE;
    200                     }
    201                     try {
    202                         pci = Integer.decode(states[7]);
    203                     } catch (Exception e) {
    204                         loge("handlePollStateResultMessage: bad pci states[7]=" +
    205                                 states[7] + " e=" + e);
    206                         pci = Integer.MAX_VALUE;
    207                     }
    208                     try {
    209                         eci = Integer.decode(states[8]);
    210                     } catch (Exception e) {
    211                         loge("handlePollStateResultMessage: bad eci states[8]=" +
    212                                 states[8] + " e=" + e);
    213                         eci = Integer.MAX_VALUE;
    214                     }
    215                     try {
    216                         csgid = Integer.decode(states[9]);
    217                     } catch (Exception e) {
    218                         // FIX: Always bad so don't pollute the logs
    219                         // loge("handlePollStateResultMessage: bad csgid states[9]=" +
    220                         //        states[9] + " e=" + e);
    221                         csgid = Integer.MAX_VALUE;
    222                     }
    223                     mNewCellIdentityLte = new CellIdentityLte(mcc, mnc, eci, pci, tac);
    224                     if (DBG) {
    225                         log("handlePollStateResultMessage: mNewLteCellIdentity=" +
    226                                 mNewCellIdentityLte);
    227                     }
    228                 }
    229             }
    230 
    231             mNewSS.setRilDataRadioTechnology(type);
    232             int dataRegState = regCodeToServiceState(regState);
    233             mNewSS.setDataRegState(dataRegState);
    234             if (DBG) {
    235                 log("handlPollStateResultMessage: CdmaLteSST setDataRegState=" + dataRegState
    236                         + " regState=" + regState
    237                         + " dataRadioTechnology=" + type);
    238             }
    239         } else {
    240             super.handlePollStateResultMessage(what, ar);
    241         }
    242     }
    243 
    244     @Override
    245     public void pollState() {
    246         mPollingContext = new int[1];
    247         mPollingContext[0] = 0;
    248 
    249         switch (mCi.getRadioState()) {
    250             case RADIO_UNAVAILABLE:
    251                 mNewSS.setStateOutOfService();
    252                 mNewCellLoc.setStateInvalid();
    253                 setSignalStrengthDefaultValues();
    254                 mGotCountryCode = false;
    255 
    256                 pollStateDone();
    257                 break;
    258 
    259             case RADIO_OFF:
    260                 mNewSS.setStateOff();
    261                 mNewCellLoc.setStateInvalid();
    262                 setSignalStrengthDefaultValues();
    263                 mGotCountryCode = false;
    264 
    265                 pollStateDone();
    266                 break;
    267 
    268             default:
    269                 // Issue all poll-related commands at once, then count
    270                 // down the responses which are allowed to arrive
    271                 // out-of-order.
    272 
    273                 mPollingContext[0]++;
    274                 // RIL_REQUEST_OPERATOR is necessary for CDMA
    275                 mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, mPollingContext));
    276 
    277                 mPollingContext[0]++;
    278                 // RIL_REQUEST_VOICE_REGISTRATION_STATE is necessary for CDMA
    279                 mCi.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA,
    280                         mPollingContext));
    281 
    282                 mPollingContext[0]++;
    283                 // RIL_REQUEST_DATA_REGISTRATION_STATE
    284                 mCi.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS,
    285                                             mPollingContext));
    286                 break;
    287         }
    288     }
    289 
    290     @Override
    291     protected void pollStateDone() {
    292         log("pollStateDone: lte 1 ss=[" + mSS + "] newSS=[" + mNewSS + "]");
    293 
    294         useDataRegStateForDataOnlyDevices();
    295 
    296         boolean hasRegistered = mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE
    297                 && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE;
    298 
    299         boolean hasDeregistered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
    300                 && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE;
    301 
    302         boolean hasCdmaDataConnectionAttached =
    303             mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE
    304                 && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
    305 
    306         boolean hasCdmaDataConnectionDetached =
    307                 mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
    308                 && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE;
    309 
    310         boolean hasCdmaDataConnectionChanged =
    311             mSS.getDataRegState() != mNewSS.getDataRegState();
    312 
    313         boolean hasVoiceRadioTechnologyChanged = mSS.getRilVoiceRadioTechnology()
    314                 != mNewSS.getRilVoiceRadioTechnology();
    315 
    316         boolean hasDataRadioTechnologyChanged = mSS.getRilDataRadioTechnology()
    317                 != mNewSS.getRilDataRadioTechnology();
    318 
    319         boolean hasChanged = !mNewSS.equals(mSS);
    320 
    321         boolean hasRoamingOn = !mSS.getRoaming() && mNewSS.getRoaming();
    322 
    323         boolean hasRoamingOff = mSS.getRoaming() && !mNewSS.getRoaming();
    324 
    325         boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc);
    326 
    327         boolean has4gHandoff =
    328                 mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE &&
    329                 (((mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) &&
    330                   (mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) ||
    331                  ((mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD) &&
    332                   (mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE)));
    333 
    334         boolean hasMultiApnSupport =
    335                 (((mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) ||
    336                   (mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) &&
    337                  ((mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_LTE) &&
    338                   (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)));
    339 
    340         boolean hasLostMultiApnSupport =
    341             ((mNewSS.getRilDataRadioTechnology() >= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A) &&
    342              (mNewSS.getRilDataRadioTechnology() <= 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                 + " hasVoiceRadioTechnologyChanged= " + hasVoiceRadioTechnologyChanged
    352                 + " hasDataRadioTechnologyChanged=" + hasDataRadioTechnologyChanged
    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 (mSS.getVoiceRegState() != mNewSS.getVoiceRegState()
    363                 || mSS.getDataRegState() != mNewSS.getDataRegState()) {
    364             EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, mSS.getVoiceRegState(),
    365                     mSS.getDataRegState(), mNewSS.getVoiceRegState(), mNewSS.getDataRegState());
    366         }
    367 
    368         ServiceState tss;
    369         tss = mSS;
    370         mSS = mNewSS;
    371         mNewSS = tss;
    372         // clean slate for next time
    373         mNewSS.setStateOutOfService();
    374 
    375         CdmaCellLocation tcl = mCellLoc;
    376         mCellLoc = mNewCellLoc;
    377         mNewCellLoc = tcl;
    378 
    379         mNewSS.setStateOutOfService(); // clean slate for next time
    380 
    381         if (hasVoiceRadioTechnologyChanged) {
    382             updatePhoneObject();
    383         }
    384 
    385         if (hasDataRadioTechnologyChanged) {
    386             mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
    387                     ServiceState.rilRadioTechnologyToString(mSS.getRilDataRadioTechnology()));
    388         }
    389 
    390         if (hasRegistered) {
    391             mNetworkAttachedRegistrants.notifyRegistrants();
    392         }
    393 
    394         if (hasChanged) {
    395             boolean hasBrandOverride = mUiccController.getUiccCard() == null ? false :
    396                     (mUiccController.getUiccCard().getOperatorBrandOverride() != null);
    397             if (!hasBrandOverride && (mCi.getRadioState().isOn()) && (mPhone.isEriFileLoaded())) {
    398                 String eriText;
    399                 // Now the CDMAPhone sees the new ServiceState so it can get the
    400                 // new ERI text
    401                 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) {
    402                     eriText = mPhone.getCdmaEriText();
    403                 } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF) {
    404                     eriText = (mIccRecords != null) ? mIccRecords.getServiceProviderName() : null;
    405                     if (TextUtils.isEmpty(eriText)) {
    406                         // Sets operator alpha property by retrieving from
    407                         // build-time system property
    408                         eriText = SystemProperties.get("ro.cdma.home.operator.alpha");
    409                     }
    410                 } else {
    411                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used
    412                     // for mRegistrationState 0,2,3 and 4
    413                     eriText = mPhone.getContext()
    414                             .getText(com.android.internal.R.string.roamingTextSearching).toString();
    415                 }
    416                 mSS.setOperatorAlphaLong(eriText);
    417             }
    418 
    419             if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY &&
    420                     mIccRecords != null) {
    421                 // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches
    422                 // one configured in SIM, use operator name  from CSIM record.
    423                 boolean showSpn =
    424                     ((RuimRecords)mIccRecords).getCsimSpnDisplayCondition();
    425                 int iconIndex = mSS.getCdmaEriIconIndex();
    426 
    427                 if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) &&
    428                     isInHomeSidNid(mSS.getSystemId(), mSS.getNetworkId()) &&
    429                     mIccRecords != null) {
    430                     mSS.setOperatorAlphaLong(mIccRecords.getServiceProviderName());
    431                 }
    432             }
    433 
    434             String operatorNumeric;
    435 
    436             mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
    437                     mSS.getOperatorAlphaLong());
    438 
    439             String prevOperatorNumeric =
    440                     SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
    441             operatorNumeric = mSS.getOperatorNumeric();
    442             // try to fix the invalid Operator Numeric
    443             if (isInvalidOperatorNumeric(operatorNumeric)) {
    444                 int sid = mSS.getSystemId();
    445                 operatorNumeric = fixUnknownMcc(operatorNumeric, sid);
    446             }
    447             mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
    448             updateCarrierMccMncConfiguration(operatorNumeric,
    449                     prevOperatorNumeric, mPhone.getContext());
    450 
    451             if (isInvalidOperatorNumeric(operatorNumeric)) {
    452                 if (DBG) log("operatorNumeric is null");
    453                 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
    454                 mGotCountryCode = false;
    455             } else {
    456                 String isoCountryCode = "";
    457                 String mcc = operatorNumeric.substring(0, 3);
    458                 try {
    459                     isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(operatorNumeric
    460                             .substring(0, 3)));
    461                 } catch (NumberFormatException ex) {
    462                     loge("countryCodeForMcc error" + ex);
    463                 } catch (StringIndexOutOfBoundsException ex) {
    464                     loge("countryCodeForMcc error" + ex);
    465                 }
    466 
    467                 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
    468                         isoCountryCode);
    469                 mGotCountryCode = true;
    470 
    471                 setOperatorIdd(operatorNumeric);
    472 
    473                 if (shouldFixTimeZoneNow(mPhone, operatorNumeric, prevOperatorNumeric,
    474                         mNeedFixZone)) {
    475                     fixTimeZone(isoCountryCode);
    476                 }
    477             }
    478 
    479             mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
    480                     mSS.getRoaming() ? "true" : "false");
    481 
    482             updateSpnDisplay();
    483             mPhone.notifyServiceStateChanged(mSS);
    484         }
    485 
    486         if (hasCdmaDataConnectionAttached || has4gHandoff) {
    487             mAttachedRegistrants.notifyRegistrants();
    488         }
    489 
    490         if (hasCdmaDataConnectionDetached) {
    491             mDetachedRegistrants.notifyRegistrants();
    492         }
    493 
    494         if ((hasCdmaDataConnectionChanged || hasDataRadioTechnologyChanged)) {
    495             notifyDataRegStateRilRadioTechnologyChanged();
    496             mPhone.notifyDataConnection(null);
    497         }
    498 
    499         if (hasRoamingOn) {
    500             mRoamingOnRegistrants.notifyRegistrants();
    501         }
    502 
    503         if (hasRoamingOff) {
    504             mRoamingOffRegistrants.notifyRegistrants();
    505         }
    506 
    507         if (hasLocationChanged) {
    508             mPhone.notifyLocationChanged();
    509         }
    510 
    511         ArrayList<CellInfo> arrayCi = new ArrayList<CellInfo>();
    512         synchronized(mCellInfo) {
    513             CellInfoLte cil = (CellInfoLte)mCellInfo;
    514 
    515             boolean cidChanged = ! mNewCellIdentityLte.equals(mLasteCellIdentityLte);
    516             if (hasRegistered || hasDeregistered || cidChanged) {
    517                 // TODO: Handle the absence of LteCellIdentity
    518                 long timeStamp = SystemClock.elapsedRealtime() * 1000;
    519                 boolean registered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE;
    520                 mLasteCellIdentityLte = mNewCellIdentityLte;
    521 
    522                 cil.setRegistered(registered);
    523                 cil.setCellIdentity(mLasteCellIdentityLte);
    524                 if (DBG) {
    525                     log("pollStateDone: hasRegistered=" + hasRegistered +
    526                             " hasDeregistered=" + hasDeregistered +
    527                             " cidChanged=" + cidChanged +
    528                             " mCellInfo=" + mCellInfo);
    529                 }
    530                 arrayCi.add(mCellInfo);
    531             }
    532             mPhoneBase.notifyCellInfo(arrayCi);
    533         }
    534     }
    535 
    536     @Override
    537     protected boolean onSignalStrengthResult(AsyncResult ar, boolean isGsm) {
    538         if (mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) {
    539             isGsm = true;
    540         }
    541         boolean ssChanged = super.onSignalStrengthResult(ar, isGsm);
    542 
    543         synchronized (mCellInfo) {
    544             if (mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_LTE) {
    545                 mCellInfoLte.setTimeStamp(SystemClock.elapsedRealtime() * 1000);
    546                 mCellInfoLte.setTimeStampType(CellInfo.TIMESTAMP_TYPE_JAVA_RIL);
    547                 mCellInfoLte.getCellSignalStrength()
    548                                 .initialize(mSignalStrength,SignalStrength.INVALID);
    549             }
    550             if (mCellInfoLte.getCellIdentity() != null) {
    551                 ArrayList<CellInfo> arrayCi = new ArrayList<CellInfo>();
    552                 arrayCi.add(mCellInfoLte);
    553                 mPhoneBase.notifyCellInfo(arrayCi);
    554             }
    555         }
    556         return ssChanged;
    557     }
    558 
    559     @Override
    560     public boolean isConcurrentVoiceAndDataAllowed() {
    561         // Using the Conncurrent Service Supported flag for CdmaLte devices.
    562         return mSS.getCssIndicator() == 1;
    563     }
    564 
    565     /**
    566      * Check whether the specified SID and NID pair appears in the HOME SID/NID list
    567      * read from NV or SIM.
    568      *
    569      * @return true if provided sid/nid pair belongs to operator's home network.
    570      */
    571     private boolean isInHomeSidNid(int sid, int nid) {
    572         // if SID/NID is not available, assume this is home network.
    573         if (isSidsAllZeros()) return true;
    574 
    575         // length of SID/NID shold be same
    576         if (mHomeSystemId.length != mHomeNetworkId.length) return true;
    577 
    578         if (sid == 0) return true;
    579 
    580         for (int i = 0; i < mHomeSystemId.length; i++) {
    581             // Use SID only if NID is a reserved value.
    582             // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2)
    583             if ((mHomeSystemId[i] == sid) &&
    584                 ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) ||
    585                  (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) {
    586                 return true;
    587             }
    588         }
    589         // SID/NID are not in the list. So device is not in home network
    590         return false;
    591     }
    592 
    593     /**
    594      * TODO: Remove when we get new ril/modem for Galaxy Nexus.
    595      *
    596      * @return all available cell information, the returned List maybe empty but never null.
    597      */
    598     @Override
    599     public List<CellInfo> getAllCellInfo() {
    600         if (mCi.getRilVersion() >= 8) {
    601             return super.getAllCellInfo();
    602         } else {
    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 
    613     @Override
    614     protected UiccCardApplication getUiccCardApplication() {
    615             return  mUiccController.getUiccCardApplication(((CDMALTEPhone)mPhone).
    616                     getPhoneId(), UiccController.APP_FAM_3GPP2);
    617     }
    618 
    619     protected void updateCdmaSubscription() {
    620         mCi.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
    621     }
    622 
    623     /**
    624      * Clean up existing voice and data connection then turn off radio power.
    625      *
    626      * Hang up the existing voice calls to decrease call drop rate.
    627      */
    628     @Override
    629     public void powerOffRadioSafely(DcTrackerBase dcTracker) {
    630         synchronized (this) {
    631             if (!mPendingRadioPowerOffAfterDataOff) {
    632                 long dds = SubscriptionManager.getDefaultDataSubId();
    633                 // To minimize race conditions we call cleanUpAllConnections on
    634                 // both if else paths instead of before this isDisconnected test.
    635                 if (dcTracker.isDisconnected()
    636                         && (dds == mPhone.getSubId()
    637                             || (dds != mPhone.getSubId()
    638                                 && ProxyController.getInstance().isDataDisconnected(dds)))) {
    639                     // To minimize race conditions we do this after isDisconnected
    640                     dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
    641                     if (DBG) log("Data disconnected, turn off radio right away.");
    642                     hangupAndPowerOff();
    643                 } else {
    644                     dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
    645                     if (dds != mPhone.getSubId()
    646                             && !ProxyController.getInstance().isDataDisconnected(dds)) {
    647                         if (DBG) log("Data is active on DDS.  Wait for all data disconnect");
    648                         // Data is not disconnected on DDS. Wait for the data disconnect complete
    649                         // before sending the RADIO_POWER off.
    650                         ProxyController.getInstance().registerForAllDataDisconnected(dds, this,
    651                                 EVENT_ALL_DATA_DISCONNECTED, null);
    652                         mPendingRadioPowerOffAfterDataOff = true;
    653                     }
    654                     Message msg = Message.obtain(this);
    655                     msg.what = EVENT_SET_RADIO_POWER_OFF;
    656                     msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
    657                     if (sendMessageDelayed(msg, 30000)) {
    658                         if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
    659                         mPendingRadioPowerOffAfterDataOff = true;
    660                     } else {
    661                         log("Cannot send delayed Msg, turn off radio right away.");
    662                         hangupAndPowerOff();
    663                         mPendingRadioPowerOffAfterDataOff = false;
    664                     }
    665                 }
    666             }
    667         }
    668     }
    669 
    670     @Override
    671     protected void updatePhoneObject() {
    672         int voiceRat = mSS.getRilVoiceRadioTechnology();
    673         if (mPhone.getContext().getResources().
    674                 getBoolean(com.android.internal.R.bool.config_switch_phone_on_voice_reg_state_change)) {
    675             // For CDMA-LTE phone don't update phone to GSM
    676             // if replacement RAT is unknown
    677             // If there is a  real need to switch to LTE, then it will be done via
    678             // RIL_UNSOL_VOICE_RADIO_TECH_CHANGED from RIL.
    679 
    680             int volteReplacementRat = mPhoneBase.getContext().getResources().getInteger(
    681                     com.android.internal.R.integer.config_volte_replacement_rat);
    682             Rlog.d(LOG_TAG, "updatePhoneObject: volteReplacementRat=" + volteReplacementRat);
    683 
    684             if (voiceRat == ServiceState.RIL_RADIO_TECHNOLOGY_LTE &&
    685                     volteReplacementRat == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
    686                 voiceRat = ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT;
    687             }
    688             mPhoneBase.updatePhoneObject(voiceRat);
    689         }
    690     }
    691 
    692     @Override
    693     protected void log(String s) {
    694         Rlog.d(LOG_TAG, "[CdmaLteSST] " + s);
    695     }
    696 
    697     @Override
    698     protected void loge(String s) {
    699         Rlog.e(LOG_TAG, "[CdmaLteSST] " + s);
    700     }
    701 
    702     @Override
    703     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    704         pw.println("CdmaLteServiceStateTracker extends:");
    705         super.dump(fd, pw, args);
    706         pw.println(" mCdmaLtePhone=" + mCdmaLtePhone);
    707     }
    708 }
    709