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 com.android.internal.telephony.CommandException;
     20 import com.android.internal.telephony.CommandsInterface;
     21 import com.android.internal.telephony.DataConnectionTracker;
     22 import com.android.internal.telephony.EventLogTags;
     23 import com.android.internal.telephony.IccCardConstants;
     24 import com.android.internal.telephony.MccTable;
     25 import com.android.internal.telephony.PhoneConstants;
     26 import com.android.internal.telephony.RILConstants;
     27 import com.android.internal.telephony.Phone;
     28 import com.android.internal.telephony.ServiceStateTracker;
     29 import com.android.internal.telephony.TelephonyIntents;
     30 import com.android.internal.telephony.TelephonyProperties;
     31 import com.android.internal.telephony.UiccCard;
     32 import com.android.internal.telephony.UiccCardApplication;
     33 import com.android.internal.telephony.CommandsInterface.RadioState;
     34 import com.android.internal.telephony.uicc.UiccController;
     35 
     36 import android.app.AlarmManager;
     37 import android.content.ContentResolver;
     38 import android.content.Context;
     39 import android.content.Intent;
     40 import android.database.ContentObserver;
     41 import android.os.AsyncResult;
     42 import android.os.Handler;
     43 import android.os.Message;
     44 import android.os.PowerManager;
     45 import android.os.Registrant;
     46 import android.os.RegistrantList;
     47 import android.os.SystemClock;
     48 import android.os.SystemProperties;
     49 import android.os.UserHandle;
     50 import android.provider.Settings;
     51 import android.provider.Settings.Secure;
     52 import android.provider.Settings.SettingNotFoundException;
     53 import android.telephony.CellInfo;
     54 import android.telephony.CellInfoCdma;
     55 import android.telephony.ServiceState;
     56 import android.telephony.SignalStrength;
     57 import android.telephony.cdma.CdmaCellLocation;
     58 import android.text.TextUtils;
     59 import android.util.EventLog;
     60 import android.util.Log;
     61 import android.util.TimeUtils;
     62 
     63 import java.io.FileDescriptor;
     64 import java.io.PrintWriter;
     65 import java.util.Arrays;
     66 import java.util.Calendar;
     67 import java.util.Date;
     68 import java.util.List;
     69 import java.util.TimeZone;
     70 
     71 /**
     72  * {@hide}
     73  */
     74 public class CdmaServiceStateTracker extends ServiceStateTracker {
     75     static final String LOG_TAG = "CDMA";
     76 
     77     CDMAPhone phone;
     78     CdmaCellLocation cellLoc;
     79     CdmaCellLocation newCellLoc;
     80 
     81     // Min values used to by getOtasp()
     82     private static final String UNACTIVATED_MIN2_VALUE = "000000";
     83     private static final String UNACTIVATED_MIN_VALUE = "1111110111";
     84 
     85     // Current Otasp value
     86     int mCurrentOtaspMode = OTASP_UNINITIALIZED;
     87 
     88      /** if time between NITZ updates is less than mNitzUpdateSpacing the update may be ignored. */
     89     private static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10;
     90     private int mNitzUpdateSpacing = SystemProperties.getInt("ro.nitz_update_spacing",
     91             NITZ_UPDATE_SPACING_DEFAULT);
     92 
     93     /** If mNitzUpdateSpacing hasn't been exceeded but update is > mNitzUpdate do the update */
     94     private static final int NITZ_UPDATE_DIFF_DEFAULT = 2000;
     95     private int mNitzUpdateDiff = SystemProperties.getInt("ro.nitz_update_diff",
     96             NITZ_UPDATE_DIFF_DEFAULT);
     97 
     98     private boolean mCdmaRoaming = false;
     99     private int mRoamingIndicator;
    100     private boolean mIsInPrl;
    101     private int mDefaultRoamingIndicator;
    102 
    103     /**
    104      * Initially assume no data connection.
    105      */
    106     protected int mDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
    107     protected int mNewDataConnectionState = ServiceState.STATE_OUT_OF_SERVICE;
    108     protected int mRegistrationState = -1;
    109     protected RegistrantList cdmaForSubscriptionInfoReadyRegistrants = new RegistrantList();
    110 
    111     /**
    112      * Sometimes we get the NITZ time before we know what country we
    113      * are in. Keep the time zone information from the NITZ string so
    114      * we can fix the time zone once know the country.
    115      */
    116     protected boolean mNeedFixZone = false;
    117     private int mZoneOffset;
    118     private boolean mZoneDst;
    119     private long mZoneTime;
    120     protected boolean mGotCountryCode = false;
    121     String mSavedTimeZone;
    122     long mSavedTime;
    123     long mSavedAtTime;
    124 
    125     /** Wake lock used while setting time of day. */
    126     private PowerManager.WakeLock mWakeLock;
    127     private static final String WAKELOCK_TAG = "ServiceStateTracker";
    128 
    129     /** Contains the name of the registered network in CDMA (either ONS or ERI text). */
    130     protected String mCurPlmn = null;
    131 
    132     protected String mMdn;
    133     protected int mHomeSystemId[] = null;
    134     protected int mHomeNetworkId[] = null;
    135     protected String mMin;
    136     protected String mPrlVersion;
    137     protected boolean mIsMinInfoReady = false;
    138 
    139     private boolean isEriTextLoaded = false;
    140     protected boolean isSubscriptionFromRuim = false;
    141     private CdmaSubscriptionSourceManager mCdmaSSM;
    142 
    143     /* Used only for debugging purposes. */
    144     private String mRegistrationDeniedReason;
    145 
    146     private ContentResolver cr;
    147     private String currentCarrier = null;
    148 
    149     private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) {
    150         @Override
    151         public void onChange(boolean selfChange) {
    152             if (DBG) log("Auto time state changed");
    153             revertToNitzTime();
    154         }
    155     };
    156 
    157     private ContentObserver mAutoTimeZoneObserver = new ContentObserver(new Handler()) {
    158         @Override
    159         public void onChange(boolean selfChange) {
    160             if (DBG) log("Auto time zone state changed");
    161             revertToNitzTimeZone();
    162         }
    163     };
    164 
    165     public CdmaServiceStateTracker(CDMAPhone phone) {
    166         this(phone, new CellInfoCdma());
    167     }
    168 
    169     protected CdmaServiceStateTracker(CDMAPhone phone, CellInfo cellInfo) {
    170         super(phone, phone.mCM, cellInfo);
    171 
    172         this.phone = phone;
    173         cr = phone.getContext().getContentResolver();
    174         cellLoc = new CdmaCellLocation();
    175         newCellLoc = new CdmaCellLocation();
    176 
    177         mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(phone.getContext(), cm, this,
    178                 EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
    179         isSubscriptionFromRuim = (mCdmaSSM.getCdmaSubscriptionSource() ==
    180                           CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
    181 
    182         PowerManager powerManager =
    183                 (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE);
    184         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
    185 
    186         cm.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
    187 
    188         cm.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED_CDMA, null);
    189         cm.setOnNITZTime(this, EVENT_NITZ_TIME, null);
    190 
    191         cm.registerForCdmaPrlChanged(this, EVENT_CDMA_PRL_VERSION_CHANGED, null);
    192         phone.registerForEriFileLoaded(this, EVENT_ERI_FILE_LOADED, null);
    193         cm.registerForCdmaOtaProvision(this,EVENT_OTA_PROVISION_STATUS_CHANGE, null);
    194 
    195         // System setting property AIRPLANE_MODE_ON is set in Settings.
    196         int airplaneMode = Settings.System.getInt(cr, Settings.System.AIRPLANE_MODE_ON, 0);
    197         mDesiredPowerState = ! (airplaneMode > 0);
    198 
    199         cr.registerContentObserver(
    200                 Settings.System.getUriFor(Settings.System.AUTO_TIME), true,
    201                 mAutoTimeObserver);
    202         cr.registerContentObserver(
    203             Settings.System.getUriFor(Settings.System.AUTO_TIME_ZONE), true,
    204             mAutoTimeZoneObserver);
    205         setSignalStrengthDefaultValues();
    206     }
    207 
    208     @Override
    209     public void dispose() {
    210         checkCorrectThread();
    211         // Unregister for all events.
    212         cm.unregisterForRadioStateChanged(this);
    213         cm.unregisterForVoiceNetworkStateChanged(this);
    214         cm.unregisterForCdmaOtaProvision(this);
    215         phone.unregisterForEriFileLoaded(this);
    216         if (mUiccApplcation != null) {mUiccApplcation.unregisterForReady(this);}
    217         if (mIccRecords != null) {mIccRecords.unregisterForRecordsLoaded(this);}
    218         cm.unSetOnNITZTime(this);
    219         cr.unregisterContentObserver(mAutoTimeObserver);
    220         cr.unregisterContentObserver(mAutoTimeZoneObserver);
    221         mCdmaSSM.dispose(this);
    222         cm.unregisterForCdmaPrlChanged(this);
    223         super.dispose();
    224     }
    225 
    226     @Override
    227     protected void finalize() {
    228         if (DBG) log("CdmaServiceStateTracker finalized");
    229     }
    230 
    231     /**
    232      * Registration point for subscription info ready
    233      * @param h handler to notify
    234      * @param what what code of message when delivered
    235      * @param obj placed in Message.obj
    236      */
    237     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
    238         Registrant r = new Registrant(h, what, obj);
    239         cdmaForSubscriptionInfoReadyRegistrants.add(r);
    240 
    241         if (isMinInfoReady()) {
    242             r.notifyRegistrant();
    243         }
    244     }
    245 
    246     public void unregisterForSubscriptionInfoReady(Handler h) {
    247         cdmaForSubscriptionInfoReadyRegistrants.remove(h);
    248     }
    249 
    250     /**
    251      * Save current source of cdma subscription
    252      * @param source - 1 for NV, 0 for RUIM
    253      */
    254     private void saveCdmaSubscriptionSource(int source) {
    255         log("Storing cdma subscription source: " + source);
    256         Settings.Global.putInt(phone.getContext().getContentResolver(),
    257                 Settings.Global.CDMA_SUBSCRIPTION_MODE,
    258                 source );
    259     }
    260 
    261     private void getSubscriptionInfoAndStartPollingThreads() {
    262         cm.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
    263 
    264         // Get Registration Information
    265         pollState();
    266     }
    267 
    268     @Override
    269     public void handleMessage (Message msg) {
    270         AsyncResult ar;
    271         int[] ints;
    272         String[] strings;
    273 
    274         if (!phone.mIsTheCurrentActivePhone) {
    275             loge("Received message " + msg + "[" + msg.what + "]" +
    276                     " while being destroyed. Ignoring.");
    277             return;
    278         }
    279 
    280         switch (msg.what) {
    281         case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
    282             handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
    283             break;
    284 
    285         case EVENT_RUIM_READY:
    286             // TODO: Consider calling setCurrentPreferredNetworkType as we do in GsmSST.
    287             // cm.setCurrentPreferredNetworkType();
    288 
    289             if (phone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
    290                 // Subscription will be read from SIM I/O
    291                 if (DBG) log("Receive EVENT_RUIM_READY");
    292                 pollState();
    293             } else {
    294                 if (DBG) log("Receive EVENT_RUIM_READY and Send Request getCDMASubscription.");
    295                 getSubscriptionInfoAndStartPollingThreads();
    296             }
    297             phone.prepareEri();
    298             break;
    299 
    300         case EVENT_NV_READY:
    301             // For Non-RUIM phones, the subscription information is stored in
    302             // Non Volatile. Here when Non-Volatile is ready, we can poll the CDMA
    303             // subscription info.
    304             getSubscriptionInfoAndStartPollingThreads();
    305             break;
    306 
    307         case EVENT_RADIO_STATE_CHANGED:
    308             if(cm.getRadioState() == RadioState.RADIO_ON) {
    309                 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
    310 
    311                 // Signal strength polling stops when radio is off.
    312                 queueNextSignalStrengthPoll();
    313             }
    314             // This will do nothing in the 'radio not available' case.
    315             setPowerStateToDesired();
    316             pollState();
    317             break;
    318 
    319         case EVENT_NETWORK_STATE_CHANGED_CDMA:
    320             pollState();
    321             break;
    322 
    323         case EVENT_GET_SIGNAL_STRENGTH:
    324             // This callback is called when signal strength is polled
    325             // all by itself.
    326 
    327             if (!(cm.getRadioState().isOn())) {
    328                 // Polling will continue when radio turns back on.
    329                 return;
    330             }
    331             ar = (AsyncResult) msg.obj;
    332             onSignalStrengthResult(ar, false);
    333             queueNextSignalStrengthPoll();
    334 
    335             break;
    336 
    337         case EVENT_GET_LOC_DONE_CDMA:
    338             ar = (AsyncResult) msg.obj;
    339 
    340             if (ar.exception == null) {
    341                 String states[] = (String[])ar.result;
    342                 int baseStationId = -1;
    343                 int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
    344                 int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
    345                 int systemId = -1;
    346                 int networkId = -1;
    347 
    348                 if (states.length > 9) {
    349                     try {
    350                         if (states[4] != null) {
    351                             baseStationId = Integer.parseInt(states[4]);
    352                         }
    353                         if (states[5] != null) {
    354                             baseStationLatitude = Integer.parseInt(states[5]);
    355                         }
    356                         if (states[6] != null) {
    357                             baseStationLongitude = Integer.parseInt(states[6]);
    358                         }
    359                         // Some carriers only return lat-lngs of 0,0
    360                         if (baseStationLatitude == 0 && baseStationLongitude == 0) {
    361                             baseStationLatitude  = CdmaCellLocation.INVALID_LAT_LONG;
    362                             baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
    363                         }
    364                         if (states[8] != null) {
    365                             systemId = Integer.parseInt(states[8]);
    366                         }
    367                         if (states[9] != null) {
    368                             networkId = Integer.parseInt(states[9]);
    369                         }
    370                     } catch (NumberFormatException ex) {
    371                         loge("error parsing cell location data: " + ex);
    372                     }
    373                 }
    374 
    375                 cellLoc.setCellLocationData(baseStationId, baseStationLatitude,
    376                         baseStationLongitude, systemId, networkId);
    377                 phone.notifyLocationChanged();
    378             }
    379 
    380             // Release any temporary cell lock, which could have been
    381             // acquired to allow a single-shot location update.
    382             disableSingleLocationUpdate();
    383             break;
    384 
    385         case EVENT_POLL_STATE_REGISTRATION_CDMA:
    386         case EVENT_POLL_STATE_OPERATOR_CDMA:
    387             ar = (AsyncResult) msg.obj;
    388             handlePollStateResult(msg.what, ar);
    389             break;
    390 
    391         case EVENT_POLL_STATE_CDMA_SUBSCRIPTION: // Handle RIL_CDMA_SUBSCRIPTION
    392             ar = (AsyncResult) msg.obj;
    393 
    394             if (ar.exception == null) {
    395                 String cdmaSubscription[] = (String[])ar.result;
    396                 if (cdmaSubscription != null && cdmaSubscription.length >= 5) {
    397                     mMdn = cdmaSubscription[0];
    398                     parseSidNid(cdmaSubscription[1], cdmaSubscription[2]);
    399 
    400                     mMin = cdmaSubscription[3];
    401                     mPrlVersion = cdmaSubscription[4];
    402                     if (DBG) log("GET_CDMA_SUBSCRIPTION: MDN=" + mMdn);
    403 
    404                     mIsMinInfoReady = true;
    405 
    406                     updateOtaspState();
    407                     if (!isSubscriptionFromRuim && mIccRecords != null) {
    408                         if (DBG) {
    409                             log("GET_CDMA_SUBSCRIPTION set imsi in mIccRecords");
    410                         }
    411                         mIccRecords.setImsi(getImsi());
    412                     } else {
    413                         if (DBG) {
    414                             log("GET_CDMA_SUBSCRIPTION either mIccRecords is null  or NV type device" +
    415                                     " - not setting Imsi in mIccRecords");
    416                         }
    417                     }
    418                 } else {
    419                     if (DBG) {
    420                         log("GET_CDMA_SUBSCRIPTION: error parsing cdmaSubscription params num="
    421                             + cdmaSubscription.length);
    422                     }
    423                 }
    424             }
    425             break;
    426 
    427         case EVENT_POLL_SIGNAL_STRENGTH:
    428             // Just poll signal strength...not part of pollState()
    429 
    430             cm.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
    431             break;
    432 
    433         case EVENT_NITZ_TIME:
    434             ar = (AsyncResult) msg.obj;
    435 
    436             String nitzString = (String)((Object[])ar.result)[0];
    437             long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue();
    438 
    439             setTimeFromNITZString(nitzString, nitzReceiveTime);
    440             break;
    441 
    442         case EVENT_SIGNAL_STRENGTH_UPDATE:
    443             // This is a notification from CommandsInterface.setOnSignalStrengthUpdate.
    444 
    445             ar = (AsyncResult) msg.obj;
    446 
    447             // The radio is telling us about signal strength changes,
    448             // so we don't have to ask it.
    449             dontPollSignalStrength = true;
    450 
    451             onSignalStrengthResult(ar, false);
    452             break;
    453 
    454         case EVENT_RUIM_RECORDS_LOADED:
    455             updateSpnDisplay();
    456             break;
    457 
    458         case EVENT_LOCATION_UPDATES_ENABLED:
    459             ar = (AsyncResult) msg.obj;
    460 
    461             if (ar.exception == null) {
    462                 cm.getVoiceRegistrationState(obtainMessage(EVENT_GET_LOC_DONE_CDMA, null));
    463             }
    464             break;
    465 
    466         case EVENT_ERI_FILE_LOADED:
    467             // Repoll the state once the ERI file has been loaded.
    468             if (DBG) log("[CdmaServiceStateTracker] ERI file has been loaded, repolling.");
    469             pollState();
    470             break;
    471 
    472         case EVENT_OTA_PROVISION_STATUS_CHANGE:
    473             ar = (AsyncResult)msg.obj;
    474             if (ar.exception == null) {
    475                 ints = (int[]) ar.result;
    476                 int otaStatus = ints[0];
    477                 if (otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED
    478                     || otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED) {
    479                     if (DBG) log("EVENT_OTA_PROVISION_STATUS_CHANGE: Complete, Reload MDN");
    480                     cm.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
    481                 }
    482             }
    483             break;
    484 
    485         case EVENT_CDMA_PRL_VERSION_CHANGED:
    486             ar = (AsyncResult)msg.obj;
    487             if (ar.exception == null) {
    488                 ints = (int[]) ar.result;
    489                 mPrlVersion = Integer.toString(ints[0]);
    490             }
    491             break;
    492 
    493         default:
    494             super.handleMessage(msg);
    495         break;
    496         }
    497     }
    498 
    499     //***** Private Instance Methods
    500 
    501     private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
    502         log("Subscription Source : " + newSubscriptionSource);
    503         isSubscriptionFromRuim =
    504             (newSubscriptionSource == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
    505         saveCdmaSubscriptionSource(newSubscriptionSource);
    506         if (!isSubscriptionFromRuim) {
    507             // NV is ready when subscription source is NV
    508             sendMessage(obtainMessage(EVENT_NV_READY));
    509         }
    510     }
    511 
    512     @Override
    513     protected void setPowerStateToDesired() {
    514         // If we want it on and it's off, turn it on
    515         if (mDesiredPowerState
    516             && cm.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) {
    517             cm.setRadioPower(true, null);
    518         } else if (!mDesiredPowerState && cm.getRadioState().isOn()) {
    519             DataConnectionTracker dcTracker = phone.mDataConnectionTracker;
    520 
    521             // If it's on and available and we want it off gracefully
    522             powerOffRadioSafely(dcTracker);
    523         } // Otherwise, we're in the desired state
    524     }
    525 
    526     @Override
    527     protected void updateSpnDisplay() {
    528         // mOperatorAlphaLong contains the ERI text
    529         String plmn = ss.getOperatorAlphaLong();
    530         if (!TextUtils.equals(plmn, mCurPlmn)) {
    531             // Allow A blank plmn, "" to set showPlmn to true. Previously, we
    532             // would set showPlmn to true only if plmn was not empty, i.e. was not
    533             // null and not blank. But this would cause us to incorrectly display
    534             // "No Service". Now showPlmn is set to true for any non null string.
    535             boolean showPlmn = plmn != null;
    536             if (DBG) {
    537                 log(String.format("updateSpnDisplay: changed sending intent" +
    538                             " showPlmn='%b' plmn='%s'", showPlmn, plmn));
    539             }
    540             Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
    541             intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
    542             intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, false);
    543             intent.putExtra(TelephonyIntents.EXTRA_SPN, "");
    544             intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
    545             intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
    546             phone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
    547         }
    548 
    549         mCurPlmn = plmn;
    550     }
    551 
    552     @Override
    553     protected Phone getPhone() {
    554         return phone;
    555     }
    556 
    557     /**
    558     * Determine data network type based on radio technology.
    559     */
    560     protected void setCdmaTechnology(int radioTech){
    561         mNewDataConnectionState = radioTechnologyToDataServiceState(radioTech);
    562         newSS.setRadioTechnology(radioTech);
    563         mNewRilRadioTechnology = radioTech;
    564     }
    565 
    566     /**
    567     * Hanlde the PollStateResult message
    568     */
    569     protected void handlePollStateResultMessage(int what, AsyncResult ar){
    570         int ints[];
    571         String states[];
    572         switch (what) {
    573         case EVENT_POLL_STATE_REGISTRATION_CDMA: // Handle RIL_REQUEST_REGISTRATION_STATE.
    574             states = (String[])ar.result;
    575 
    576             int registrationState = 4;     //[0] registrationState
    577             int radioTechnology = -1;      //[3] radioTechnology
    578             int baseStationId = -1;        //[4] baseStationId
    579             //[5] baseStationLatitude
    580             int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG;
    581             //[6] baseStationLongitude
    582             int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
    583             int cssIndicator = 0;          //[7] init with 0, because it is treated as a boolean
    584             int systemId = 0;              //[8] systemId
    585             int networkId = 0;             //[9] networkId
    586             int roamingIndicator = -1;     //[10] Roaming indicator
    587             int systemIsInPrl = 0;         //[11] Indicates if current system is in PRL
    588             int defaultRoamingIndicator = 0;  //[12] Is default roaming indicator from PRL
    589             int reasonForDenial = 0;       //[13] Denial reason if registrationState = 3
    590 
    591             if (states.length >= 14) {
    592                 try {
    593                     if (states[0] != null) {
    594                         registrationState = Integer.parseInt(states[0]);
    595                     }
    596                     if (states[3] != null) {
    597                         radioTechnology = Integer.parseInt(states[3]);
    598                     }
    599                     if (states[4] != null) {
    600                         baseStationId = Integer.parseInt(states[4]);
    601                     }
    602                     if (states[5] != null) {
    603                         baseStationLatitude = Integer.parseInt(states[5]);
    604                     }
    605                     if (states[6] != null) {
    606                         baseStationLongitude = Integer.parseInt(states[6]);
    607                     }
    608                     // Some carriers only return lat-lngs of 0,0
    609                     if (baseStationLatitude == 0 && baseStationLongitude == 0) {
    610                         baseStationLatitude  = CdmaCellLocation.INVALID_LAT_LONG;
    611                         baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG;
    612                     }
    613                     if (states[7] != null) {
    614                         cssIndicator = Integer.parseInt(states[7]);
    615                     }
    616                     if (states[8] != null) {
    617                         systemId = Integer.parseInt(states[8]);
    618                     }
    619                     if (states[9] != null) {
    620                         networkId = Integer.parseInt(states[9]);
    621                     }
    622                     if (states[10] != null) {
    623                         roamingIndicator = Integer.parseInt(states[10]);
    624                     }
    625                     if (states[11] != null) {
    626                         systemIsInPrl = Integer.parseInt(states[11]);
    627                     }
    628                     if (states[12] != null) {
    629                         defaultRoamingIndicator = Integer.parseInt(states[12]);
    630                     }
    631                     if (states[13] != null) {
    632                         reasonForDenial = Integer.parseInt(states[13]);
    633                     }
    634                 } catch (NumberFormatException ex) {
    635                     loge("EVENT_POLL_STATE_REGISTRATION_CDMA: error parsing: " + ex);
    636                 }
    637             } else {
    638                 throw new RuntimeException("Warning! Wrong number of parameters returned from "
    639                                      + "RIL_REQUEST_REGISTRATION_STATE: expected 14 or more "
    640                                      + "strings and got " + states.length + " strings");
    641             }
    642 
    643             mRegistrationState = registrationState;
    644             // When registration state is roaming and TSB58
    645             // roaming indicator is not in the carrier-specified
    646             // list of ERIs for home system, mCdmaRoaming is true.
    647             mCdmaRoaming =
    648                     regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]);
    649             newSS.setState (regCodeToServiceState(registrationState));
    650 
    651             setCdmaTechnology(radioTechnology);
    652 
    653             newSS.setCssIndicator(cssIndicator);
    654             newSS.setSystemAndNetworkId(systemId, networkId);
    655             mRoamingIndicator = roamingIndicator;
    656             mIsInPrl = (systemIsInPrl == 0) ? false : true;
    657             mDefaultRoamingIndicator = defaultRoamingIndicator;
    658 
    659 
    660             // Values are -1 if not available.
    661             newCellLoc.setCellLocationData(baseStationId, baseStationLatitude,
    662                     baseStationLongitude, systemId, networkId);
    663 
    664             if (reasonForDenial == 0) {
    665                 mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN;
    666             } else if (reasonForDenial == 1) {
    667                 mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH;
    668             } else {
    669                 mRegistrationDeniedReason = "";
    670             }
    671 
    672             if (mRegistrationState == 3) {
    673                 if (DBG) log("Registration denied, " + mRegistrationDeniedReason);
    674             }
    675             break;
    676 
    677         case EVENT_POLL_STATE_OPERATOR_CDMA: // Handle RIL_REQUEST_OPERATOR
    678             String opNames[] = (String[])ar.result;
    679 
    680             if (opNames != null && opNames.length >= 3) {
    681                 // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC
    682                 if ((opNames[2] == null) || (opNames[2].length() < 5)
    683                         || ("00000".equals(opNames[2]))) {
    684                     opNames[2] = SystemProperties.get(
    685                             CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000");
    686                     if (DBG) {
    687                         log("RIL_REQUEST_OPERATOR.response[2], the numeric, " +
    688                                 " is bad. Using SystemProperties '" +
    689                                         CDMAPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC +
    690                                 "'= " + opNames[2]);
    691                     }
    692                 }
    693 
    694                 if (!isSubscriptionFromRuim) {
    695                     // In CDMA in case on NV, the ss.mOperatorAlphaLong is set later with the
    696                     // ERI text, so here it is ignored what is coming from the modem.
    697                     newSS.setOperatorName(null, opNames[1], opNames[2]);
    698                 } else {
    699                     newSS.setOperatorName(opNames[0], opNames[1], opNames[2]);
    700                 }
    701             } else {
    702                 if (DBG) log("EVENT_POLL_STATE_OPERATOR_CDMA: error parsing opNames");
    703             }
    704             break;
    705         default:
    706             loge("handlePollStateResultMessage: RIL response handle in wrong phone!"
    707                     + " Expected CDMA RIL request and get GSM RIL request.");
    708         break;
    709         }
    710     }
    711 
    712     /**
    713      * Handle the result of one of the pollState() - related requests
    714      */
    715     @Override
    716     protected void handlePollStateResult(int what, AsyncResult ar) {
    717         // Ignore stale requests from last poll.
    718         if (ar.userObj != pollingContext) return;
    719 
    720         if (ar.exception != null) {
    721             CommandException.Error err=null;
    722 
    723             if (ar.exception instanceof CommandException) {
    724                 err = ((CommandException)(ar.exception)).getCommandError();
    725             }
    726 
    727             if (err == CommandException.Error.RADIO_NOT_AVAILABLE) {
    728                 // Radio has crashed or turned off.
    729                 cancelPollState();
    730                 return;
    731             }
    732 
    733             if (!cm.getRadioState().isOn()) {
    734                 // Radio has crashed or turned off.
    735                 cancelPollState();
    736                 return;
    737             }
    738 
    739             if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) {
    740                 loge("handlePollStateResult: RIL returned an error where it must succeed"
    741                         + ar.exception);
    742             }
    743         } else try {
    744             handlePollStateResultMessage(what, ar);
    745         } catch (RuntimeException ex) {
    746             loge("handlePollStateResult: Exception while polling service state. "
    747                     + "Probably malformed RIL response." + ex);
    748         }
    749 
    750         pollingContext[0]--;
    751 
    752         if (pollingContext[0] == 0) {
    753             boolean namMatch = false;
    754             if (!isSidsAllZeros() && isHomeSid(newSS.getSystemId())) {
    755                 namMatch = true;
    756             }
    757 
    758             // Setting SS Roaming (general)
    759             if (isSubscriptionFromRuim) {
    760                 newSS.setRoaming(isRoamingBetweenOperators(mCdmaRoaming, newSS));
    761             } else {
    762                 newSS.setRoaming(mCdmaRoaming);
    763             }
    764 
    765             // Setting SS CdmaRoamingIndicator and CdmaDefaultRoamingIndicator
    766             newSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator);
    767             newSS.setCdmaRoamingIndicator(mRoamingIndicator);
    768             boolean isPrlLoaded = true;
    769             if (TextUtils.isEmpty(mPrlVersion)) {
    770                 isPrlLoaded = false;
    771             }
    772             if (!isPrlLoaded) {
    773                 newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
    774             } else if (!isSidsAllZeros()) {
    775                 if (!namMatch && !mIsInPrl) {
    776                     // Use default
    777                     newSS.setCdmaRoamingIndicator(mDefaultRoamingIndicator);
    778                 } else if (namMatch && !mIsInPrl) {
    779                     newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH);
    780                 } else if (!namMatch && mIsInPrl) {
    781                     // Use the one from PRL/ERI
    782                     newSS.setCdmaRoamingIndicator(mRoamingIndicator);
    783                 } else {
    784                     // It means namMatch && mIsInPrl
    785                     if ((mRoamingIndicator <= 2)) {
    786                         newSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF);
    787                     } else {
    788                         // Use the one from PRL/ERI
    789                         newSS.setCdmaRoamingIndicator(mRoamingIndicator);
    790                     }
    791                 }
    792             }
    793 
    794             int roamingIndicator = newSS.getCdmaRoamingIndicator();
    795             newSS.setCdmaEriIconIndex(phone.mEriManager.getCdmaEriIconIndex(roamingIndicator,
    796                     mDefaultRoamingIndicator));
    797             newSS.setCdmaEriIconMode(phone.mEriManager.getCdmaEriIconMode(roamingIndicator,
    798                     mDefaultRoamingIndicator));
    799 
    800             // NOTE: Some operator may require overriding mCdmaRoaming
    801             // (set by the modem), depending on the mRoamingIndicator.
    802 
    803             if (DBG) {
    804                 log("Set CDMA Roaming Indicator to: " + newSS.getCdmaRoamingIndicator()
    805                     + ". mCdmaRoaming = " + mCdmaRoaming + ", isPrlLoaded = " + isPrlLoaded
    806                     + ". namMatch = " + namMatch + " , mIsInPrl = " + mIsInPrl
    807                     + ", mRoamingIndicator = " + mRoamingIndicator
    808                     + ", mDefaultRoamingIndicator= " + mDefaultRoamingIndicator);
    809             }
    810             pollStateDone();
    811         }
    812 
    813     }
    814 
    815     protected void setSignalStrengthDefaultValues() {
    816         mSignalStrength = new SignalStrength( false);
    817     }
    818 
    819     /**
    820      * A complete "service state" from our perspective is
    821      * composed of a handful of separate requests to the radio.
    822      *
    823      * We make all of these requests at once, but then abandon them
    824      * and start over again if the radio notifies us that some
    825      * event has changed
    826      */
    827     protected void
    828     pollState() {
    829         pollingContext = new int[1];
    830         pollingContext[0] = 0;
    831 
    832         switch (cm.getRadioState()) {
    833         case RADIO_UNAVAILABLE:
    834             newSS.setStateOutOfService();
    835             newCellLoc.setStateInvalid();
    836             setSignalStrengthDefaultValues();
    837             mGotCountryCode = false;
    838 
    839             pollStateDone();
    840             break;
    841 
    842         case RADIO_OFF:
    843             newSS.setStateOff();
    844             newCellLoc.setStateInvalid();
    845             setSignalStrengthDefaultValues();
    846             mGotCountryCode = false;
    847 
    848             pollStateDone();
    849             break;
    850 
    851         default:
    852             // Issue all poll-related commands at once, then count
    853             // down the responses which are allowed to arrive
    854             // out-of-order.
    855 
    856             pollingContext[0]++;
    857             // RIL_REQUEST_OPERATOR is necessary for CDMA
    858             cm.getOperator(
    859                     obtainMessage(EVENT_POLL_STATE_OPERATOR_CDMA, pollingContext));
    860 
    861             pollingContext[0]++;
    862             // RIL_REQUEST_VOICE_REGISTRATION_STATE is necessary for CDMA
    863             cm.getVoiceRegistrationState(
    864                     obtainMessage(EVENT_POLL_STATE_REGISTRATION_CDMA, pollingContext));
    865 
    866             break;
    867         }
    868     }
    869 
    870     protected void fixTimeZone(String isoCountryCode) {
    871         TimeZone zone = null;
    872         // If the offset is (0, false) and the time zone property
    873         // is set, use the time zone property rather than GMT.
    874         String zoneName = SystemProperties.get(TIMEZONE_PROPERTY);
    875         if (DBG) {
    876             log("fixTimeZone zoneName='" + zoneName +
    877                 "' mZoneOffset=" + mZoneOffset + " mZoneDst=" + mZoneDst +
    878                 " iso-cc='" + isoCountryCode +
    879                 "' iso-cc-idx=" + Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode));
    880         }
    881         if ((mZoneOffset == 0) && (mZoneDst == false) && (zoneName != null)
    882                 && (zoneName.length() > 0)
    883                 && (Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode) < 0)) {
    884             // For NITZ string without time zone,
    885             // need adjust time to reflect default time zone setting
    886             zone = TimeZone.getDefault();
    887             if (mNeedFixZone) {
    888                 long ctm = System.currentTimeMillis();
    889                 long tzOffset = zone.getOffset(ctm);
    890                 if (DBG) {
    891                     log("fixTimeZone: tzOffset=" + tzOffset +
    892                             " ltod=" + TimeUtils.logTimeOfDay(ctm));
    893                 }
    894                 if (getAutoTime()) {
    895                     long adj = ctm - tzOffset;
    896                     if (DBG) log("fixTimeZone: adj ltod=" + TimeUtils.logTimeOfDay(adj));
    897                     setAndBroadcastNetworkSetTime(adj);
    898                 } else {
    899                     // Adjust the saved NITZ time to account for tzOffset.
    900                     mSavedTime = mSavedTime - tzOffset;
    901                     if (DBG) log("fixTimeZone: adj mSavedTime=" + mSavedTime);
    902                 }
    903             }
    904             if (DBG) log("fixTimeZone: using default TimeZone");
    905         } else if (isoCountryCode.equals("")) {
    906             // Country code not found. This is likely a test network.
    907             // Get a TimeZone based only on the NITZ parameters (best guess).
    908             zone = getNitzTimeZone(mZoneOffset, mZoneDst, mZoneTime);
    909             if (DBG) log("fixTimeZone: using NITZ TimeZone");
    910         } else {
    911             zone = TimeUtils.getTimeZone(mZoneOffset, mZoneDst, mZoneTime, isoCountryCode);
    912             if (DBG) log("fixTimeZone: using getTimeZone(off, dst, time, iso)");
    913         }
    914 
    915         mNeedFixZone = false;
    916 
    917         if (zone != null) {
    918             log("fixTimeZone: zone != null zone.getID=" + zone.getID());
    919             if (getAutoTimeZone()) {
    920                 setAndBroadcastNetworkSetTimeZone(zone.getID());
    921             } else {
    922                 log("fixTimeZone: skip changing zone as getAutoTimeZone was false");
    923             }
    924             saveNitzTimeZone(zone.getID());
    925         } else {
    926             log("fixTimeZone: zone == null, do nothing for zone");
    927         }
    928     }
    929 
    930     protected void pollStateDone() {
    931         if (DBG) log("pollStateDone: oldSS=[" + ss + "] newSS=[" + newSS + "]");
    932 
    933         boolean hasRegistered =
    934             ss.getState() != ServiceState.STATE_IN_SERVICE
    935             && newSS.getState() == ServiceState.STATE_IN_SERVICE;
    936 
    937         boolean hasDeregistered =
    938             ss.getState() == ServiceState.STATE_IN_SERVICE
    939             && newSS.getState() != ServiceState.STATE_IN_SERVICE;
    940 
    941         boolean hasCdmaDataConnectionAttached =
    942             mDataConnectionState != ServiceState.STATE_IN_SERVICE
    943             && mNewDataConnectionState == ServiceState.STATE_IN_SERVICE;
    944 
    945         boolean hasCdmaDataConnectionDetached =
    946             mDataConnectionState == ServiceState.STATE_IN_SERVICE
    947             && mNewDataConnectionState != ServiceState.STATE_IN_SERVICE;
    948 
    949         boolean hasCdmaDataConnectionChanged =
    950                        mDataConnectionState != mNewDataConnectionState;
    951 
    952         boolean hasRadioTechnologyChanged = mRilRadioTechnology != mNewRilRadioTechnology;
    953 
    954         boolean hasChanged = !newSS.equals(ss);
    955 
    956         boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
    957 
    958         boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
    959 
    960         boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
    961 
    962         // Add an event log when connection state changes
    963         if (ss.getState() != newSS.getState() ||
    964                 mDataConnectionState != mNewDataConnectionState) {
    965             EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE,
    966                     ss.getState(), mDataConnectionState,
    967                     newSS.getState(), mNewDataConnectionState);
    968         }
    969 
    970         ServiceState tss;
    971         tss = ss;
    972         ss = newSS;
    973         newSS = tss;
    974         // clean slate for next time
    975         newSS.setStateOutOfService();
    976 
    977         CdmaCellLocation tcl = cellLoc;
    978         cellLoc = newCellLoc;
    979         newCellLoc = tcl;
    980 
    981         mDataConnectionState = mNewDataConnectionState;
    982         mRilRadioTechnology = mNewRilRadioTechnology;
    983         // this new state has been applied - forget it until we get a new new state
    984         mNewRilRadioTechnology = 0;
    985 
    986         newSS.setStateOutOfService(); // clean slate for next time
    987 
    988         if (hasRadioTechnologyChanged) {
    989             phone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
    990                     ServiceState.rilRadioTechnologyToString(mRilRadioTechnology));
    991         }
    992 
    993         if (hasRegistered) {
    994             mNetworkAttachedRegistrants.notifyRegistrants();
    995         }
    996 
    997         if (hasChanged) {
    998             if ((cm.getRadioState().isOn()) && (!isSubscriptionFromRuim)) {
    999                 String eriText;
   1000                 // Now the CDMAPhone sees the new ServiceState so it can get the new ERI text
   1001                 if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
   1002                     eriText = phone.getCdmaEriText();
   1003                 } else {
   1004                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used for
   1005                     // mRegistrationState 0,2,3 and 4
   1006                     eriText = phone.getContext().getText(
   1007                             com.android.internal.R.string.roamingTextSearching).toString();
   1008                 }
   1009                 ss.setOperatorAlphaLong(eriText);
   1010             }
   1011 
   1012             String operatorNumeric;
   1013 
   1014             phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
   1015                     ss.getOperatorAlphaLong());
   1016 
   1017             String prevOperatorNumeric =
   1018                     SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
   1019             operatorNumeric = ss.getOperatorNumeric();
   1020             phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
   1021 
   1022             if (operatorNumeric == null) {
   1023                 if (DBG) log("operatorNumeric is null");
   1024                 phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
   1025                 mGotCountryCode = false;
   1026             } else {
   1027                 String isoCountryCode = "";
   1028                 String mcc = operatorNumeric.substring(0, 3);
   1029                 try{
   1030                     isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(
   1031                             operatorNumeric.substring(0,3)));
   1032                 } catch ( NumberFormatException ex){
   1033                     loge("pollStateDone: countryCodeForMcc error" + ex);
   1034                 } catch ( StringIndexOutOfBoundsException ex) {
   1035                     loge("pollStateDone: countryCodeForMcc error" + ex);
   1036                 }
   1037 
   1038                 phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY,
   1039                         isoCountryCode);
   1040                 mGotCountryCode = true;
   1041 
   1042                 if (shouldFixTimeZoneNow(phone, operatorNumeric, prevOperatorNumeric,
   1043                         mNeedFixZone)) {
   1044                     fixTimeZone(isoCountryCode);
   1045                 }
   1046             }
   1047 
   1048             phone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
   1049                     ss.getRoaming() ? "true" : "false");
   1050 
   1051             updateSpnDisplay();
   1052             phone.notifyServiceStateChanged(ss);
   1053         }
   1054 
   1055         if (hasCdmaDataConnectionAttached) {
   1056             mAttachedRegistrants.notifyRegistrants();
   1057         }
   1058 
   1059         if (hasCdmaDataConnectionDetached) {
   1060             mDetachedRegistrants.notifyRegistrants();
   1061         }
   1062 
   1063         if (hasCdmaDataConnectionChanged || hasRadioTechnologyChanged) {
   1064             phone.notifyDataConnection(null);
   1065         }
   1066 
   1067         if (hasRoamingOn) {
   1068             mRoamingOnRegistrants.notifyRegistrants();
   1069         }
   1070 
   1071         if (hasRoamingOff) {
   1072             mRoamingOffRegistrants.notifyRegistrants();
   1073         }
   1074 
   1075         if (hasLocationChanged) {
   1076             phone.notifyLocationChanged();
   1077         }
   1078         // TODO: Add CdmaCellIdenity updating, see CdmaLteServiceStateTracker.
   1079     }
   1080 
   1081     /**
   1082      * Returns a TimeZone object based only on parameters from the NITZ string.
   1083      */
   1084     private TimeZone getNitzTimeZone(int offset, boolean dst, long when) {
   1085         TimeZone guess = findTimeZone(offset, dst, when);
   1086         if (guess == null) {
   1087             // Couldn't find a proper timezone.  Perhaps the DST data is wrong.
   1088             guess = findTimeZone(offset, !dst, when);
   1089         }
   1090         if (DBG) log("getNitzTimeZone returning " + (guess == null ? guess : guess.getID()));
   1091         return guess;
   1092     }
   1093 
   1094     private TimeZone findTimeZone(int offset, boolean dst, long when) {
   1095         int rawOffset = offset;
   1096         if (dst) {
   1097             rawOffset -= 3600000;
   1098         }
   1099         String[] zones = TimeZone.getAvailableIDs(rawOffset);
   1100         TimeZone guess = null;
   1101         Date d = new Date(when);
   1102         for (String zone : zones) {
   1103             TimeZone tz = TimeZone.getTimeZone(zone);
   1104             if (tz.getOffset(when) == offset &&
   1105                     tz.inDaylightTime(d) == dst) {
   1106                 guess = tz;
   1107                 break;
   1108             }
   1109         }
   1110 
   1111         return guess;
   1112     }
   1113 
   1114     /**
   1115      * TODO: This code is exactly the same as in GsmServiceStateTracker
   1116      * and has a TODO to not poll signal strength if screen is off.
   1117      * This code should probably be hoisted to the base class so
   1118      * the fix, when added, works for both.
   1119      */
   1120     private void
   1121     queueNextSignalStrengthPoll() {
   1122         if (dontPollSignalStrength) {
   1123             // The radio is telling us about signal strength changes
   1124             // we don't have to ask it
   1125             return;
   1126         }
   1127 
   1128         Message msg;
   1129 
   1130         msg = obtainMessage();
   1131         msg.what = EVENT_POLL_SIGNAL_STRENGTH;
   1132 
   1133         // TODO Don't poll signal strength if screen is off
   1134         sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
   1135     }
   1136 
   1137     protected int radioTechnologyToDataServiceState(int code) {
   1138         int retVal = ServiceState.STATE_OUT_OF_SERVICE;
   1139         switch(code) {
   1140         case 0:
   1141         case 1:
   1142         case 2:
   1143         case 3:
   1144         case 4:
   1145         case 5:
   1146             break;
   1147         case 6: // RADIO_TECHNOLOGY_1xRTT
   1148         case 7: // RADIO_TECHNOLOGY_EVDO_0
   1149         case 8: // RADIO_TECHNOLOGY_EVDO_A
   1150         case 12: // RADIO_TECHNOLOGY_EVDO_B
   1151         case 13: // RADIO_TECHNOLOGY_EHRPD
   1152             retVal = ServiceState.STATE_IN_SERVICE;
   1153             break;
   1154         default:
   1155             loge("radioTechnologyToDataServiceState: Wrong radioTechnology code.");
   1156         break;
   1157         }
   1158         return(retVal);
   1159     }
   1160 
   1161     /** code is registration state 0-5 from TS 27.007 7.2 */
   1162     protected int
   1163     regCodeToServiceState(int code) {
   1164         switch (code) {
   1165         case 0: // Not searching and not registered
   1166             return ServiceState.STATE_OUT_OF_SERVICE;
   1167         case 1:
   1168             return ServiceState.STATE_IN_SERVICE;
   1169         case 2: // 2 is "searching", fall through
   1170         case 3: // 3 is "registration denied", fall through
   1171         case 4: // 4 is "unknown", not valid in current baseband
   1172             return ServiceState.STATE_OUT_OF_SERVICE;
   1173         case 5:// 5 is "Registered, roaming"
   1174             return ServiceState.STATE_IN_SERVICE;
   1175 
   1176         default:
   1177             loge("regCodeToServiceState: unexpected service state " + code);
   1178         return ServiceState.STATE_OUT_OF_SERVICE;
   1179         }
   1180     }
   1181 
   1182     public int getCurrentDataConnectionState() {
   1183         return mDataConnectionState;
   1184     }
   1185 
   1186     /**
   1187      * code is registration state 0-5 from TS 27.007 7.2
   1188      * returns true if registered roam, false otherwise
   1189      */
   1190     private boolean
   1191     regCodeIsRoaming (int code) {
   1192         // 5 is  "in service -- roam"
   1193         return 5 == code;
   1194     }
   1195 
   1196     /**
   1197      * Determine whether a roaming indicator is in the carrier-specified list of ERIs for
   1198      * home system
   1199      *
   1200      * @param roamInd roaming indicator in String
   1201      * @return true if the roamInd is in the carrier-specified list of ERIs for home network
   1202      */
   1203     private boolean isRoamIndForHomeSystem(String roamInd) {
   1204         // retrieve the carrier-specified list of ERIs for home system
   1205         String homeRoamIndicators = SystemProperties.get("ro.cdma.homesystem");
   1206 
   1207         if (!TextUtils.isEmpty(homeRoamIndicators)) {
   1208             // searches through the comma-separated list for a match,
   1209             // return true if one is found.
   1210             for (String homeRoamInd : homeRoamIndicators.split(",")) {
   1211                 if (homeRoamInd.equals(roamInd)) {
   1212                     return true;
   1213                 }
   1214             }
   1215             // no matches found against the list!
   1216             return false;
   1217         }
   1218 
   1219         // no system property found for the roaming indicators for home system
   1220         return false;
   1221     }
   1222 
   1223     /**
   1224      * Set roaming state when cdmaRoaming is true and ons is different from spn
   1225      * @param cdmaRoaming TS 27.007 7.2 CREG registered roaming
   1226      * @param s ServiceState hold current ons
   1227      * @return true for roaming state set
   1228      */
   1229     private
   1230     boolean isRoamingBetweenOperators(boolean cdmaRoaming, ServiceState s) {
   1231         String spn = SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA, "empty");
   1232 
   1233         // NOTE: in case of RUIM we should completely ignore the ERI data file and
   1234         // mOperatorAlphaLong is set from RIL_REQUEST_OPERATOR response 0 (alpha ONS)
   1235         String onsl = s.getOperatorAlphaLong();
   1236         String onss = s.getOperatorAlphaShort();
   1237 
   1238         boolean equalsOnsl = onsl != null && spn.equals(onsl);
   1239         boolean equalsOnss = onss != null && spn.equals(onss);
   1240 
   1241         return cdmaRoaming && !(equalsOnsl || equalsOnss);
   1242     }
   1243 
   1244 
   1245     /**
   1246      * nitzReceiveTime is time_t that the NITZ time was posted
   1247      */
   1248 
   1249     private
   1250     void setTimeFromNITZString (String nitz, long nitzReceiveTime)
   1251     {
   1252         // "yy/mm/dd,hh:mm:ss(+/-)tz"
   1253         // tz is in number of quarter-hours
   1254 
   1255         long start = SystemClock.elapsedRealtime();
   1256         if (DBG) {
   1257             log("NITZ: " + nitz + "," + nitzReceiveTime +
   1258                         " start=" + start + " delay=" + (start - nitzReceiveTime));
   1259         }
   1260 
   1261         try {
   1262             /* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone
   1263              * offset as well (which we won't worry about until later) */
   1264             Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
   1265 
   1266             c.clear();
   1267             c.set(Calendar.DST_OFFSET, 0);
   1268 
   1269             String[] nitzSubs = nitz.split("[/:,+-]");
   1270 
   1271             int year = 2000 + Integer.parseInt(nitzSubs[0]);
   1272             c.set(Calendar.YEAR, year);
   1273 
   1274             // month is 0 based!
   1275             int month = Integer.parseInt(nitzSubs[1]) - 1;
   1276             c.set(Calendar.MONTH, month);
   1277 
   1278             int date = Integer.parseInt(nitzSubs[2]);
   1279             c.set(Calendar.DATE, date);
   1280 
   1281             int hour = Integer.parseInt(nitzSubs[3]);
   1282             c.set(Calendar.HOUR, hour);
   1283 
   1284             int minute = Integer.parseInt(nitzSubs[4]);
   1285             c.set(Calendar.MINUTE, minute);
   1286 
   1287             int second = Integer.parseInt(nitzSubs[5]);
   1288             c.set(Calendar.SECOND, second);
   1289 
   1290             boolean sign = (nitz.indexOf('-') == -1);
   1291 
   1292             int tzOffset = Integer.parseInt(nitzSubs[6]);
   1293 
   1294             int dst = (nitzSubs.length >= 8 ) ? Integer.parseInt(nitzSubs[7])
   1295                                               : 0;
   1296 
   1297             // The zone offset received from NITZ is for current local time,
   1298             // so DST correction is already applied.  Don't add it again.
   1299             //
   1300             // tzOffset += dst * 4;
   1301             //
   1302             // We could unapply it if we wanted the raw offset.
   1303 
   1304             tzOffset = (sign ? 1 : -1) * tzOffset * 15 * 60 * 1000;
   1305 
   1306             TimeZone    zone = null;
   1307 
   1308             // As a special extension, the Android emulator appends the name of
   1309             // the host computer's timezone to the nitz string. this is zoneinfo
   1310             // timezone name of the form Area!Location or Area!Location!SubLocation
   1311             // so we need to convert the ! into /
   1312             if (nitzSubs.length >= 9) {
   1313                 String  tzname = nitzSubs[8].replace('!','/');
   1314                 zone = TimeZone.getTimeZone( tzname );
   1315             }
   1316 
   1317             String iso = SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY);
   1318 
   1319             if (zone == null) {
   1320                 if (mGotCountryCode) {
   1321                     if (iso != null && iso.length() > 0) {
   1322                         zone = TimeUtils.getTimeZone(tzOffset, dst != 0,
   1323                                 c.getTimeInMillis(),
   1324                                 iso);
   1325                     } else {
   1326                         // We don't have a valid iso country code.  This is
   1327                         // most likely because we're on a test network that's
   1328                         // using a bogus MCC (eg, "001"), so get a TimeZone
   1329                         // based only on the NITZ parameters.
   1330                         zone = getNitzTimeZone(tzOffset, (dst != 0), c.getTimeInMillis());
   1331                     }
   1332                 }
   1333             }
   1334 
   1335             if ((zone == null) || (mZoneOffset != tzOffset) || (mZoneDst != (dst != 0))){
   1336                 // We got the time before the country or the zone has changed
   1337                 // so we don't know how to identify the DST rules yet.  Save
   1338                 // the information and hope to fix it up later.
   1339 
   1340                 mNeedFixZone = true;
   1341                 mZoneOffset  = tzOffset;
   1342                 mZoneDst     = dst != 0;
   1343                 mZoneTime    = c.getTimeInMillis();
   1344             }
   1345             if (DBG) {
   1346                 log("NITZ: tzOffset=" + tzOffset + " dst=" + dst + " zone=" +
   1347                         (zone!=null ? zone.getID() : "NULL") +
   1348                         " iso=" + iso + " mGotCountryCode=" + mGotCountryCode +
   1349                         " mNeedFixZone=" + mNeedFixZone);
   1350             }
   1351 
   1352             if (zone != null) {
   1353                 if (getAutoTimeZone()) {
   1354                     setAndBroadcastNetworkSetTimeZone(zone.getID());
   1355                 }
   1356                 saveNitzTimeZone(zone.getID());
   1357             }
   1358 
   1359             String ignore = SystemProperties.get("gsm.ignore-nitz");
   1360             if (ignore != null && ignore.equals("yes")) {
   1361                 if (DBG) log("NITZ: Not setting clock because gsm.ignore-nitz is set");
   1362                 return;
   1363             }
   1364 
   1365             try {
   1366                 mWakeLock.acquire();
   1367 
   1368                 /**
   1369                  * Correct the NITZ time by how long its taken to get here.
   1370                  */
   1371                 long millisSinceNitzReceived
   1372                         = SystemClock.elapsedRealtime() - nitzReceiveTime;
   1373 
   1374                 if (millisSinceNitzReceived < 0) {
   1375                     // Sanity check: something is wrong
   1376                     if (DBG) {
   1377                         log("NITZ: not setting time, clock has rolled "
   1378                                         + "backwards since NITZ time was received, "
   1379                                         + nitz);
   1380                     }
   1381                     return;
   1382                 }
   1383 
   1384                 if (millisSinceNitzReceived > Integer.MAX_VALUE) {
   1385                     // If the time is this far off, something is wrong > 24 days!
   1386                     if (DBG) {
   1387                         log("NITZ: not setting time, processing has taken "
   1388                                     + (millisSinceNitzReceived / (1000 * 60 * 60 * 24))
   1389                                     + " days");
   1390                     }
   1391                     return;
   1392                 }
   1393 
   1394                 // Note: with range checks above, cast to int is safe
   1395                 c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived);
   1396 
   1397                 if (getAutoTime()) {
   1398                     /**
   1399                      * Update system time automatically
   1400                      */
   1401                     long gained = c.getTimeInMillis() - System.currentTimeMillis();
   1402                     long timeSinceLastUpdate = SystemClock.elapsedRealtime() - mSavedAtTime;
   1403                     int nitzUpdateSpacing = Settings.Global.getInt(cr,
   1404                             Settings.Global.NITZ_UPDATE_SPACING, mNitzUpdateSpacing);
   1405                     int nitzUpdateDiff = Settings.Global.getInt(cr,
   1406                             Settings.Global.NITZ_UPDATE_DIFF, mNitzUpdateDiff);
   1407 
   1408                     if ((mSavedAtTime == 0) || (timeSinceLastUpdate > nitzUpdateSpacing)
   1409                             || (Math.abs(gained) > nitzUpdateDiff)) {
   1410                         if (DBG) {
   1411                             log("NITZ: Auto updating time of day to " + c.getTime()
   1412                                 + " NITZ receive delay=" + millisSinceNitzReceived
   1413                                 + "ms gained=" + gained + "ms from " + nitz);
   1414                         }
   1415 
   1416                         setAndBroadcastNetworkSetTime(c.getTimeInMillis());
   1417                     } else {
   1418                         if (DBG) {
   1419                             log("NITZ: ignore, a previous update was "
   1420                                 + timeSinceLastUpdate + "ms ago and gained=" + gained + "ms");
   1421                         }
   1422                         return;
   1423                     }
   1424                 }
   1425 
   1426                 /**
   1427                  * Update properties and save the time we did the update
   1428                  */
   1429                 if (DBG) log("NITZ: update nitz time property");
   1430                 SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis()));
   1431                 mSavedTime = c.getTimeInMillis();
   1432                 mSavedAtTime = SystemClock.elapsedRealtime();
   1433             } finally {
   1434                 long end = SystemClock.elapsedRealtime();
   1435                 if (DBG) log("NITZ: end=" + end + " dur=" + (end - start));
   1436                 mWakeLock.release();
   1437             }
   1438         } catch (RuntimeException ex) {
   1439             loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex);
   1440         }
   1441     }
   1442 
   1443     private boolean getAutoTime() {
   1444         try {
   1445             return Settings.System.getInt(cr, Settings.System.AUTO_TIME) > 0;
   1446         } catch (SettingNotFoundException snfe) {
   1447             return true;
   1448         }
   1449     }
   1450 
   1451     private boolean getAutoTimeZone() {
   1452         try {
   1453             return Settings.System.getInt(cr, Settings.System.AUTO_TIME_ZONE) > 0;
   1454         } catch (SettingNotFoundException snfe) {
   1455             return true;
   1456         }
   1457     }
   1458 
   1459     private void saveNitzTimeZone(String zoneId) {
   1460         mSavedTimeZone = zoneId;
   1461     }
   1462 
   1463     /**
   1464      * Set the timezone and send out a sticky broadcast so the system can
   1465      * determine if the timezone was set by the carrier.
   1466      *
   1467      * @param zoneId timezone set by carrier
   1468      */
   1469     private void setAndBroadcastNetworkSetTimeZone(String zoneId) {
   1470         if (DBG) log("setAndBroadcastNetworkSetTimeZone: setTimeZone=" + zoneId);
   1471         AlarmManager alarm =
   1472             (AlarmManager) phone.getContext().getSystemService(Context.ALARM_SERVICE);
   1473         alarm.setTimeZone(zoneId);
   1474         Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
   1475         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
   1476         intent.putExtra("time-zone", zoneId);
   1477         phone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1478     }
   1479 
   1480     /**
   1481      * Set the time and Send out a sticky broadcast so the system can determine
   1482      * if the time was set by the carrier.
   1483      *
   1484      * @param time time set by network
   1485      */
   1486     private void setAndBroadcastNetworkSetTime(long time) {
   1487         if (DBG) log("setAndBroadcastNetworkSetTime: time=" + time + "ms");
   1488         SystemClock.setCurrentTimeMillis(time);
   1489         Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME);
   1490         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
   1491         intent.putExtra("time", time);
   1492         phone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
   1493     }
   1494 
   1495     private void revertToNitzTime() {
   1496         if (Settings.System.getInt(cr, Settings.System.AUTO_TIME, 0) == 0) {
   1497             return;
   1498         }
   1499         if (DBG) {
   1500             log("revertToNitzTime: mSavedTime=" + mSavedTime + " mSavedAtTime=" + mSavedAtTime);
   1501         }
   1502         if (mSavedTime != 0 && mSavedAtTime != 0) {
   1503             setAndBroadcastNetworkSetTime(mSavedTime
   1504                     + (SystemClock.elapsedRealtime() - mSavedAtTime));
   1505         }
   1506     }
   1507 
   1508     private void revertToNitzTimeZone() {
   1509         if (Settings.System.getInt(phone.getContext().getContentResolver(),
   1510                 Settings.System.AUTO_TIME_ZONE, 0) == 0) {
   1511             return;
   1512         }
   1513         if (DBG) log("revertToNitzTimeZone: tz='" + mSavedTimeZone);
   1514         if (mSavedTimeZone != null) {
   1515             setAndBroadcastNetworkSetTimeZone(mSavedTimeZone);
   1516         }
   1517     }
   1518 
   1519     protected boolean isSidsAllZeros() {
   1520         if (mHomeSystemId != null) {
   1521             for (int i=0; i < mHomeSystemId.length; i++) {
   1522                 if (mHomeSystemId[i] != 0) {
   1523                     return false;
   1524                 }
   1525             }
   1526         }
   1527         return true;
   1528     }
   1529 
   1530     /**
   1531      * Check whether a specified system ID that matches one of the home system IDs.
   1532      */
   1533     private boolean isHomeSid(int sid) {
   1534         if (mHomeSystemId != null) {
   1535             for (int i=0; i < mHomeSystemId.length; i++) {
   1536                 if (sid == mHomeSystemId[i]) {
   1537                     return true;
   1538                 }
   1539             }
   1540         }
   1541         return false;
   1542     }
   1543 
   1544     /**
   1545      * @return true if phone is camping on a technology
   1546      * that could support voice and data simultaneously.
   1547      */
   1548     public boolean isConcurrentVoiceAndDataAllowed() {
   1549         // Note: it needs to be confirmed which CDMA network types
   1550         // can support voice and data calls concurrently.
   1551         // For the time-being, the return value will be false.
   1552         return false;
   1553     }
   1554 
   1555     public String getMdnNumber() {
   1556         return mMdn;
   1557     }
   1558 
   1559     public String getCdmaMin() {
   1560          return mMin;
   1561     }
   1562 
   1563     /** Returns null if NV is not yet ready */
   1564     public String getPrlVersion() {
   1565         return mPrlVersion;
   1566     }
   1567 
   1568     /**
   1569      * Returns IMSI as MCC + MNC + MIN
   1570      */
   1571     String getImsi() {
   1572         // TODO: When RUIM is enabled, IMSI will come from RUIM not build-time props.
   1573         String operatorNumeric = SystemProperties.get(
   1574                 TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "");
   1575 
   1576         if (!TextUtils.isEmpty(operatorNumeric) && getCdmaMin() != null) {
   1577             return (operatorNumeric + getCdmaMin());
   1578         } else {
   1579             return null;
   1580         }
   1581     }
   1582 
   1583     /**
   1584      * Check if subscription data has been assigned to mMin
   1585      *
   1586      * return true if MIN info is ready; false otherwise.
   1587      */
   1588     public boolean isMinInfoReady() {
   1589         return mIsMinInfoReady;
   1590     }
   1591 
   1592     /**
   1593      * Returns OTASP_UNKNOWN, OTASP_NEEDED or OTASP_NOT_NEEDED
   1594      */
   1595     int getOtasp() {
   1596         int provisioningState;
   1597         if (mMin == null || (mMin.length() < 6)) {
   1598             if (DBG) log("getOtasp: bad mMin='" + mMin + "'");
   1599             provisioningState = OTASP_UNKNOWN;
   1600         } else {
   1601             if ((mMin.equals(UNACTIVATED_MIN_VALUE)
   1602                     || mMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE))
   1603                     || SystemProperties.getBoolean("test_cdma_setup", false)) {
   1604                 provisioningState = OTASP_NEEDED;
   1605             } else {
   1606                 provisioningState = OTASP_NOT_NEEDED;
   1607             }
   1608         }
   1609         if (DBG) log("getOtasp: state=" + provisioningState);
   1610         return provisioningState;
   1611     }
   1612 
   1613     @Override
   1614     protected void hangupAndPowerOff() {
   1615         // hang up all active voice calls
   1616         phone.mCT.ringingCall.hangupIfAlive();
   1617         phone.mCT.backgroundCall.hangupIfAlive();
   1618         phone.mCT.foregroundCall.hangupIfAlive();
   1619         cm.setRadioPower(false, null);
   1620     }
   1621 
   1622     protected void parseSidNid (String sidStr, String nidStr) {
   1623         if (sidStr != null) {
   1624             String[] sid = sidStr.split(",");
   1625             mHomeSystemId = new int[sid.length];
   1626             for (int i = 0; i < sid.length; i++) {
   1627                 try {
   1628                     mHomeSystemId[i] = Integer.parseInt(sid[i]);
   1629                 } catch (NumberFormatException ex) {
   1630                     loge("error parsing system id: " + ex);
   1631                 }
   1632             }
   1633         }
   1634         if (DBG) log("CDMA_SUBSCRIPTION: SID=" + sidStr);
   1635 
   1636         if (nidStr != null) {
   1637             String[] nid = nidStr.split(",");
   1638             mHomeNetworkId = new int[nid.length];
   1639             for (int i = 0; i < nid.length; i++) {
   1640                 try {
   1641                     mHomeNetworkId[i] = Integer.parseInt(nid[i]);
   1642                 } catch (NumberFormatException ex) {
   1643                     loge("CDMA_SUBSCRIPTION: error parsing network id: " + ex);
   1644                 }
   1645             }
   1646         }
   1647         if (DBG) log("CDMA_SUBSCRIPTION: NID=" + nidStr);
   1648     }
   1649 
   1650     protected void updateOtaspState() {
   1651         int otaspMode = getOtasp();
   1652         int oldOtaspMode = mCurrentOtaspMode;
   1653         mCurrentOtaspMode = otaspMode;
   1654 
   1655         // Notify apps subscription info is ready
   1656         if (cdmaForSubscriptionInfoReadyRegistrants != null) {
   1657             if (DBG) log("CDMA_SUBSCRIPTION: call notifyRegistrants()");
   1658             cdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants();
   1659         }
   1660         if (oldOtaspMode != mCurrentOtaspMode) {
   1661             if (DBG) {
   1662                 log("CDMA_SUBSCRIPTION: call notifyOtaspChanged old otaspMode=" +
   1663                     oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode);
   1664             }
   1665             phone.notifyOtaspChanged(mCurrentOtaspMode);
   1666         }
   1667     }
   1668 
   1669     @Override
   1670     protected void onUpdateIccAvailability() {
   1671         if (mUiccController == null ) {
   1672             return;
   1673         }
   1674 
   1675         UiccCardApplication newUiccApplication =
   1676                 mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP2);
   1677 
   1678         if (mUiccApplcation != newUiccApplication) {
   1679             if (mUiccApplcation != null) {
   1680                 log("Removing stale icc objects.");
   1681                 mUiccApplcation.unregisterForReady(this);
   1682                 if (mIccRecords != null) {
   1683                     mIccRecords.unregisterForRecordsLoaded(this);
   1684                 }
   1685                 mIccRecords = null;
   1686                 mUiccApplcation = null;
   1687             }
   1688             if (newUiccApplication != null) {
   1689                 log("New card found");
   1690                 mUiccApplcation = newUiccApplication;
   1691                 mIccRecords = mUiccApplcation.getIccRecords();
   1692                 if (isSubscriptionFromRuim) {
   1693                     mUiccApplcation.registerForReady(this, EVENT_RUIM_READY, null);
   1694                     if (mIccRecords != null) {
   1695                         mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
   1696                     }
   1697                 }
   1698             }
   1699         }
   1700     }
   1701 
   1702     /**
   1703      * @return all available cell information or null if none.
   1704      */
   1705     @Override
   1706     public List<CellInfo> getAllCellInfo() {
   1707         return null;
   1708     }
   1709 
   1710     @Override
   1711     protected void log(String s) {
   1712         Log.d(LOG_TAG, "[CdmaSST] " + s);
   1713     }
   1714 
   1715     @Override
   1716     protected void loge(String s) {
   1717         Log.e(LOG_TAG, "[CdmaSST] " + s);
   1718     }
   1719 
   1720     @Override
   1721     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1722         pw.println("CdmaServiceStateTracker extends:");
   1723         super.dump(fd, pw, args);
   1724         pw.println(" phone=" + phone);
   1725         pw.println(" cellLoc=" + cellLoc);
   1726         pw.println(" newCellLoc=" + newCellLoc);
   1727         pw.println(" mCurrentOtaspMode=" + mCurrentOtaspMode);
   1728         pw.println(" mCdmaRoaming=" + mCdmaRoaming);
   1729         pw.println(" mRoamingIndicator=" + mRoamingIndicator);
   1730         pw.println(" mIsInPrl=" + mIsInPrl);
   1731         pw.println(" mDefaultRoamingIndicator=" + mDefaultRoamingIndicator);
   1732         pw.println(" mDataConnectionState=" + mDataConnectionState);
   1733         pw.println(" mNewDataConnectionState=" + mNewDataConnectionState);
   1734         pw.println(" mRegistrationState=" + mRegistrationState);
   1735         pw.println(" mNeedFixZone=" + mNeedFixZone);
   1736         pw.println(" mZoneOffset=" + mZoneOffset);
   1737         pw.println(" mZoneDst=" + mZoneDst);
   1738         pw.println(" mZoneTime=" + mZoneTime);
   1739         pw.println(" mGotCountryCode=" + mGotCountryCode);
   1740         pw.println(" mSavedTimeZone=" + mSavedTimeZone);
   1741         pw.println(" mSavedTime=" + mSavedTime);
   1742         pw.println(" mSavedAtTime=" + mSavedAtTime);
   1743         pw.println(" mWakeLock=" + mWakeLock);
   1744         pw.println(" mCurPlmn=" + mCurPlmn);
   1745         pw.println(" mMdn=" + mMdn);
   1746         pw.println(" mHomeSystemId=" + mHomeSystemId);
   1747         pw.println(" mHomeNetworkId=" + mHomeNetworkId);
   1748         pw.println(" mMin=" + mMin);
   1749         pw.println(" mPrlVersion=" + mPrlVersion);
   1750         pw.println(" mIsMinInfoReady=" + mIsMinInfoReady);
   1751         pw.println(" isEriTextLoaded=" + isEriTextLoaded);
   1752         pw.println(" isSubscriptionFromRuim=" + isSubscriptionFromRuim);
   1753         pw.println(" mCdmaSSM=" + mCdmaSSM);
   1754         pw.println(" mRegistrationDeniedReason=" + mRegistrationDeniedReason);
   1755         pw.println(" currentCarrier=" + currentCarrier);
   1756     }
   1757 }
   1758