Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2006 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;
     18 
     19 import android.content.Context;
     20 import android.os.AsyncResult;
     21 import android.os.Handler;
     22 import android.os.Looper;
     23 import android.os.Message;
     24 import android.os.Registrant;
     25 import android.os.RegistrantList;
     26 import android.os.SystemClock;
     27 import android.telephony.CellInfo;
     28 import android.telephony.ServiceState;
     29 import android.telephony.SignalStrength;
     30 import android.util.TimeUtils;
     31 
     32 import java.io.FileDescriptor;
     33 import java.io.PrintWriter;
     34 import java.util.List;
     35 
     36 import com.android.internal.telephony.IccCardApplicationStatus.AppState;
     37 import com.android.internal.telephony.uicc.UiccController;
     38 
     39 /**
     40  * {@hide}
     41  */
     42 public abstract class ServiceStateTracker extends Handler {
     43 
     44     protected CommandsInterface cm;
     45     protected UiccController mUiccController = null;
     46     protected UiccCardApplication mUiccApplcation = null;
     47     protected IccRecords mIccRecords = null;
     48 
     49     protected PhoneBase mPhoneBase;
     50 
     51     public ServiceState ss = new ServiceState();
     52     protected ServiceState newSS = new ServiceState();
     53 
     54     protected CellInfo mLastCellInfo = null;
     55 
     56     // This is final as subclasses alias to a more specific type
     57     // so we don't want the reference to change.
     58     protected final CellInfo mCellInfo;
     59 
     60     protected SignalStrength mSignalStrength = new SignalStrength();
     61 
     62     // TODO - this should not be public, right now used externally GsmConnetion.
     63     public RestrictedState mRestrictedState = new RestrictedState();
     64 
     65     /* The otaspMode passed to PhoneStateListener#onOtaspChanged */
     66     static public final int OTASP_UNINITIALIZED = 0;
     67     static public final int OTASP_UNKNOWN = 1;
     68     static public final int OTASP_NEEDED = 2;
     69     static public final int OTASP_NOT_NEEDED = 3;
     70 
     71     /**
     72      * A unique identifier to track requests associated with a poll
     73      * and ignore stale responses.  The value is a count-down of
     74      * expected responses in this pollingContext.
     75      */
     76     protected int[] pollingContext;
     77     protected boolean mDesiredPowerState;
     78 
     79     /**
     80      *  Values correspond to ServiceState.RIL_RADIO_TECHNOLOGY_ definitions.
     81      */
     82     protected int mRilRadioTechnology = 0;
     83     protected int mNewRilRadioTechnology = 0;
     84 
     85     /**
     86      * By default, strength polling is enabled.  However, if we're
     87      * getting unsolicited signal strength updates from the radio, set
     88      * value to true and don't bother polling any more.
     89      */
     90     protected boolean dontPollSignalStrength = false;
     91 
     92     protected RegistrantList mRoamingOnRegistrants = new RegistrantList();
     93     protected RegistrantList mRoamingOffRegistrants = new RegistrantList();
     94     protected RegistrantList mAttachedRegistrants = new RegistrantList();
     95     protected RegistrantList mDetachedRegistrants = new RegistrantList();
     96     protected RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
     97     protected RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
     98     protected RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
     99 
    100     /* Radio power off pending flag and tag counter */
    101     private boolean mPendingRadioPowerOffAfterDataOff = false;
    102     private int mPendingRadioPowerOffAfterDataOffTag = 0;
    103 
    104     protected  static final boolean DBG = true;
    105 
    106     /** Signal strength poll rate. */
    107     protected static final int POLL_PERIOD_MILLIS = 20 * 1000;
    108 
    109     /** Waiting period before recheck gprs and voice registration. */
    110     public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
    111 
    112     /** GSM events */
    113     protected static final int EVENT_RADIO_STATE_CHANGED               = 1;
    114     protected static final int EVENT_NETWORK_STATE_CHANGED             = 2;
    115     protected static final int EVENT_GET_SIGNAL_STRENGTH               = 3;
    116     protected static final int EVENT_POLL_STATE_REGISTRATION           = 4;
    117     protected static final int EVENT_POLL_STATE_GPRS                   = 5;
    118     protected static final int EVENT_POLL_STATE_OPERATOR               = 6;
    119     protected static final int EVENT_POLL_SIGNAL_STRENGTH              = 10;
    120     protected static final int EVENT_NITZ_TIME                         = 11;
    121     protected static final int EVENT_SIGNAL_STRENGTH_UPDATE            = 12;
    122     protected static final int EVENT_RADIO_AVAILABLE                   = 13;
    123     protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14;
    124     protected static final int EVENT_GET_LOC_DONE                      = 15;
    125     protected static final int EVENT_SIM_RECORDS_LOADED                = 16;
    126     protected static final int EVENT_SIM_READY                         = 17;
    127     protected static final int EVENT_LOCATION_UPDATES_ENABLED          = 18;
    128     protected static final int EVENT_GET_PREFERRED_NETWORK_TYPE        = 19;
    129     protected static final int EVENT_SET_PREFERRED_NETWORK_TYPE        = 20;
    130     protected static final int EVENT_RESET_PREFERRED_NETWORK_TYPE      = 21;
    131     protected static final int EVENT_CHECK_REPORT_GPRS                 = 22;
    132     protected static final int EVENT_RESTRICTED_STATE_CHANGED          = 23;
    133 
    134     /** CDMA events */
    135     protected static final int EVENT_POLL_STATE_REGISTRATION_CDMA      = 24;
    136     protected static final int EVENT_POLL_STATE_OPERATOR_CDMA          = 25;
    137     protected static final int EVENT_RUIM_READY                        = 26;
    138     protected static final int EVENT_RUIM_RECORDS_LOADED               = 27;
    139     protected static final int EVENT_POLL_SIGNAL_STRENGTH_CDMA         = 28;
    140     protected static final int EVENT_GET_SIGNAL_STRENGTH_CDMA          = 29;
    141     protected static final int EVENT_NETWORK_STATE_CHANGED_CDMA        = 30;
    142     protected static final int EVENT_GET_LOC_DONE_CDMA                 = 31;
    143     //protected static final int EVENT_UNUSED                            = 32;
    144     protected static final int EVENT_NV_LOADED                         = 33;
    145     protected static final int EVENT_POLL_STATE_CDMA_SUBSCRIPTION      = 34;
    146     protected static final int EVENT_NV_READY                          = 35;
    147     protected static final int EVENT_ERI_FILE_LOADED                   = 36;
    148     protected static final int EVENT_OTA_PROVISION_STATUS_CHANGE       = 37;
    149     protected static final int EVENT_SET_RADIO_POWER_OFF               = 38;
    150     protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED  = 39;
    151     protected static final int EVENT_CDMA_PRL_VERSION_CHANGED          = 40;
    152     protected static final int EVENT_RADIO_ON                          = 41;
    153     protected static final int EVENT_ICC_CHANGED                       = 42;
    154 
    155     protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
    156 
    157     /**
    158      * List of ISO codes for countries that can have an offset of
    159      * GMT+0 when not in daylight savings time.  This ignores some
    160      * small places such as the Canary Islands (Spain) and
    161      * Danmarkshavn (Denmark).  The list must be sorted by code.
    162     */
    163     protected static final String[] GMT_COUNTRY_CODES = {
    164         "bf", // Burkina Faso
    165         "ci", // Cote d'Ivoire
    166         "eh", // Western Sahara
    167         "fo", // Faroe Islands, Denmark
    168         "gb", // United Kingdom of Great Britain and Northern Ireland
    169         "gh", // Ghana
    170         "gm", // Gambia
    171         "gn", // Guinea
    172         "gw", // Guinea Bissau
    173         "ie", // Ireland
    174         "lr", // Liberia
    175         "is", // Iceland
    176         "ma", // Morocco
    177         "ml", // Mali
    178         "mr", // Mauritania
    179         "pt", // Portugal
    180         "sl", // Sierra Leone
    181         "sn", // Senegal
    182         "st", // Sao Tome and Principe
    183         "tg", // Togo
    184     };
    185 
    186     /** Reason for registration denial. */
    187     protected static final String REGISTRATION_DENIED_GEN  = "General";
    188     protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure";
    189 
    190     protected ServiceStateTracker(PhoneBase phoneBase, CommandsInterface ci, CellInfo cellInfo) {
    191         mPhoneBase = phoneBase;
    192         mCellInfo = cellInfo;
    193         cm = ci;
    194         mUiccController = UiccController.getInstance();
    195         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
    196         cm.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
    197     }
    198 
    199     public void dispose() {
    200         cm.unSetOnSignalStrengthUpdate(this);
    201     }
    202 
    203     public boolean getDesiredPowerState() {
    204         return mDesiredPowerState;
    205     }
    206 
    207     private SignalStrength mLastSignalStrength = null;
    208     protected boolean notifySignalStrength() {
    209         boolean notified = false;
    210         synchronized(mCellInfo) {
    211             if (!mSignalStrength.equals(mLastSignalStrength)) {
    212                 try {
    213                     mPhoneBase.notifySignalStrength();
    214                     notified = true;
    215                 } catch (NullPointerException ex) {
    216                     loge("updateSignalStrength() Phone already destroyed: " + ex
    217                             + "SignalStrength not notified");
    218                 }
    219             }
    220         }
    221         return notified;
    222     }
    223 
    224     /**
    225      * Registration point for combined roaming on
    226      * combined roaming is true when roaming is true and ONS differs SPN
    227      *
    228      * @param h handler to notify
    229      * @param what what code of message when delivered
    230      * @param obj placed in Message.obj
    231      */
    232     public  void registerForRoamingOn(Handler h, int what, Object obj) {
    233         Registrant r = new Registrant(h, what, obj);
    234         mRoamingOnRegistrants.add(r);
    235 
    236         if (ss.getRoaming()) {
    237             r.notifyRegistrant();
    238         }
    239     }
    240 
    241     public  void unregisterForRoamingOn(Handler h) {
    242         mRoamingOnRegistrants.remove(h);
    243     }
    244 
    245     /**
    246      * Registration point for combined roaming off
    247      * combined roaming is true when roaming is true and ONS differs SPN
    248      *
    249      * @param h handler to notify
    250      * @param what what code of message when delivered
    251      * @param obj placed in Message.obj
    252      */
    253     public  void registerForRoamingOff(Handler h, int what, Object obj) {
    254         Registrant r = new Registrant(h, what, obj);
    255         mRoamingOffRegistrants.add(r);
    256 
    257         if (!ss.getRoaming()) {
    258             r.notifyRegistrant();
    259         }
    260     }
    261 
    262     public  void unregisterForRoamingOff(Handler h) {
    263         mRoamingOffRegistrants.remove(h);
    264     }
    265 
    266     /**
    267      * Re-register network by toggling preferred network type.
    268      * This is a work-around to deregister and register network since there is
    269      * no ril api to set COPS=2 (deregister) only.
    270      *
    271      * @param onComplete is dispatched when this is complete.  it will be
    272      * an AsyncResult, and onComplete.obj.exception will be non-null
    273      * on failure.
    274      */
    275     public void reRegisterNetwork(Message onComplete) {
    276         cm.getPreferredNetworkType(
    277                 obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete));
    278     }
    279 
    280     public void
    281     setRadioPower(boolean power) {
    282         mDesiredPowerState = power;
    283 
    284         setPowerStateToDesired();
    285     }
    286 
    287     /**
    288      * These two flags manage the behavior of the cell lock -- the
    289      * lock should be held if either flag is true.  The intention is
    290      * to allow temporary acquisition of the lock to get a single
    291      * update.  Such a lock grab and release can thus be made to not
    292      * interfere with more permanent lock holds -- in other words, the
    293      * lock will only be released if both flags are false, and so
    294      * releases by temporary users will only affect the lock state if
    295      * there is no continuous user.
    296      */
    297     private boolean mWantContinuousLocationUpdates;
    298     private boolean mWantSingleLocationUpdate;
    299 
    300     public void enableSingleLocationUpdate() {
    301         if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return;
    302         mWantSingleLocationUpdate = true;
    303         cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
    304     }
    305 
    306     public void enableLocationUpdates() {
    307         if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return;
    308         mWantContinuousLocationUpdates = true;
    309         cm.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
    310     }
    311 
    312     protected void disableSingleLocationUpdate() {
    313         mWantSingleLocationUpdate = false;
    314         if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) {
    315             cm.setLocationUpdates(false, null);
    316         }
    317     }
    318 
    319     public void disableLocationUpdates() {
    320         mWantContinuousLocationUpdates = false;
    321         if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) {
    322             cm.setLocationUpdates(false, null);
    323         }
    324     }
    325 
    326     @Override
    327     public void handleMessage(Message msg) {
    328         switch (msg.what) {
    329             case EVENT_SET_RADIO_POWER_OFF:
    330                 synchronized(this) {
    331                     if (mPendingRadioPowerOffAfterDataOff &&
    332                             (msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) {
    333                         if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
    334                         hangupAndPowerOff();
    335                         mPendingRadioPowerOffAfterDataOffTag += 1;
    336                         mPendingRadioPowerOffAfterDataOff = false;
    337                     } else {
    338                         log("EVENT_SET_RADIO_OFF is stale arg1=" + msg.arg1 +
    339                                 "!= tag=" + mPendingRadioPowerOffAfterDataOffTag);
    340                     }
    341                 }
    342                 break;
    343 
    344             case EVENT_ICC_CHANGED:
    345                 onUpdateIccAvailability();
    346                 break;
    347 
    348             default:
    349                 log("Unhandled message with number: " + msg.what);
    350                 break;
    351         }
    352     }
    353 
    354     protected abstract Phone getPhone();
    355     protected abstract void handlePollStateResult(int what, AsyncResult ar);
    356     protected abstract void updateSpnDisplay();
    357     protected abstract void setPowerStateToDesired();
    358     protected abstract void onUpdateIccAvailability();
    359     protected abstract void log(String s);
    360     protected abstract void loge(String s);
    361 
    362     public abstract int getCurrentDataConnectionState();
    363     public abstract boolean isConcurrentVoiceAndDataAllowed();
    364 
    365     /**
    366      * Registration point for transition into DataConnection attached.
    367      * @param h handler to notify
    368      * @param what what code of message when delivered
    369      * @param obj placed in Message.obj
    370      */
    371     public void registerForDataConnectionAttached(Handler h, int what, Object obj) {
    372         Registrant r = new Registrant(h, what, obj);
    373         mAttachedRegistrants.add(r);
    374 
    375         if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
    376             r.notifyRegistrant();
    377         }
    378     }
    379     public void unregisterForDataConnectionAttached(Handler h) {
    380         mAttachedRegistrants.remove(h);
    381     }
    382 
    383     /**
    384      * Registration point for transition into DataConnection detached.
    385      * @param h handler to notify
    386      * @param what what code of message when delivered
    387      * @param obj placed in Message.obj
    388      */
    389     public void registerForDataConnectionDetached(Handler h, int what, Object obj) {
    390         Registrant r = new Registrant(h, what, obj);
    391         mDetachedRegistrants.add(r);
    392 
    393         if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
    394             r.notifyRegistrant();
    395         }
    396     }
    397     public void unregisterForDataConnectionDetached(Handler h) {
    398         mDetachedRegistrants.remove(h);
    399     }
    400 
    401     /**
    402      * Registration point for transition into network attached.
    403      * @param h handler to notify
    404      * @param what what code of message when delivered
    405      * @param obj in Message.obj
    406      */
    407     public void registerForNetworkAttached(Handler h, int what, Object obj) {
    408         Registrant r = new Registrant(h, what, obj);
    409 
    410         mNetworkAttachedRegistrants.add(r);
    411         if (ss.getState() == ServiceState.STATE_IN_SERVICE) {
    412             r.notifyRegistrant();
    413         }
    414     }
    415     public void unregisterForNetworkAttached(Handler h) {
    416         mNetworkAttachedRegistrants.remove(h);
    417     }
    418 
    419     /**
    420      * Registration point for transition into packet service restricted zone.
    421      * @param h handler to notify
    422      * @param what what code of message when delivered
    423      * @param obj placed in Message.obj
    424      */
    425     public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
    426         Registrant r = new Registrant(h, what, obj);
    427         mPsRestrictEnabledRegistrants.add(r);
    428 
    429         if (mRestrictedState.isPsRestricted()) {
    430             r.notifyRegistrant();
    431         }
    432     }
    433 
    434     public void unregisterForPsRestrictedEnabled(Handler h) {
    435         mPsRestrictEnabledRegistrants.remove(h);
    436     }
    437 
    438     /**
    439      * Registration point for transition out of packet service restricted zone.
    440      * @param h handler to notify
    441      * @param what what code of message when delivered
    442      * @param obj placed in Message.obj
    443      */
    444     public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
    445         Registrant r = new Registrant(h, what, obj);
    446         mPsRestrictDisabledRegistrants.add(r);
    447 
    448         if (mRestrictedState.isPsRestricted()) {
    449             r.notifyRegistrant();
    450         }
    451     }
    452 
    453     public void unregisterForPsRestrictedDisabled(Handler h) {
    454         mPsRestrictDisabledRegistrants.remove(h);
    455     }
    456 
    457     /**
    458      * Clean up existing voice and data connection then turn off radio power.
    459      *
    460      * Hang up the existing voice calls to decrease call drop rate.
    461      */
    462     public void powerOffRadioSafely(DataConnectionTracker dcTracker) {
    463         synchronized (this) {
    464             if (!mPendingRadioPowerOffAfterDataOff) {
    465                 // To minimize race conditions we call cleanUpAllConnections on
    466                 // both if else paths instead of before this isDisconnected test.
    467                 if (dcTracker.isDisconnected()) {
    468                     // To minimize race conditions we do this after isDisconnected
    469                     dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
    470                     if (DBG) log("Data disconnected, turn off radio right away.");
    471                     hangupAndPowerOff();
    472                 } else {
    473                     dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF);
    474                     Message msg = Message.obtain(this);
    475                     msg.what = EVENT_SET_RADIO_POWER_OFF;
    476                     msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag;
    477                     if (sendMessageDelayed(msg, 30000)) {
    478                         if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio.");
    479                         mPendingRadioPowerOffAfterDataOff = true;
    480                     } else {
    481                         log("Cannot send delayed Msg, turn off radio right away.");
    482                         hangupAndPowerOff();
    483                     }
    484                 }
    485             }
    486         }
    487     }
    488 
    489     /**
    490      * process the pending request to turn radio off after data is disconnected
    491      *
    492      * return true if there is pending request to process; false otherwise.
    493      */
    494     public boolean processPendingRadioPowerOffAfterDataOff() {
    495         synchronized(this) {
    496             if (mPendingRadioPowerOffAfterDataOff) {
    497                 if (DBG) log("Process pending request to turn radio off.");
    498                 mPendingRadioPowerOffAfterDataOffTag += 1;
    499                 hangupAndPowerOff();
    500                 mPendingRadioPowerOffAfterDataOff = false;
    501                 return true;
    502             }
    503             return false;
    504         }
    505     }
    506 
    507     /**
    508      * send signal-strength-changed notification if changed Called both for
    509      * solicited and unsolicited signal strength updates
    510      *
    511      * @return true if the signal strength changed and a notification was sent.
    512      */
    513     protected boolean onSignalStrengthResult(AsyncResult ar, boolean isGsm) {
    514         SignalStrength oldSignalStrength = mSignalStrength;
    515 
    516         // This signal is used for both voice and data radio signal so parse
    517         // all fields
    518 
    519         if ((ar.exception == null) && (ar.result != null)) {
    520             mSignalStrength = (SignalStrength) ar.result;
    521             mSignalStrength.validateInput();
    522             mSignalStrength.setGsm(isGsm);
    523         } else {
    524             log("onSignalStrengthResult() Exception from RIL : " + ar.exception);
    525             mSignalStrength = new SignalStrength(isGsm);
    526         }
    527 
    528         return notifySignalStrength();
    529     }
    530 
    531     /**
    532      * Hang up all voice call and turn off radio. Implemented by derived class.
    533      */
    534     protected abstract void hangupAndPowerOff();
    535 
    536     /** Cancel a pending (if any) pollState() operation */
    537     protected void cancelPollState() {
    538         // This will effectively cancel the rest of the poll requests.
    539         pollingContext = new int[1];
    540     }
    541 
    542     /**
    543      * Return true if time zone needs fixing.
    544      *
    545      * @param phoneBase
    546      * @param operatorNumeric
    547      * @param prevOperatorNumeric
    548      * @param needToFixTimeZone
    549      * @return true if time zone needs to be fixed
    550      */
    551     protected boolean shouldFixTimeZoneNow(PhoneBase phoneBase, String operatorNumeric,
    552             String prevOperatorNumeric, boolean needToFixTimeZone) {
    553         // Return false if the mcc isn't valid as we don't know where we are.
    554         // Return true if we have an IccCard and the mcc changed or we
    555         // need to fix it because when the NITZ time came in we didn't
    556         // know the country code.
    557 
    558         // If mcc is invalid then we'll return false
    559         int mcc;
    560         try {
    561             mcc = Integer.parseInt(operatorNumeric.substring(0, 3));
    562         } catch (Exception e) {
    563             if (DBG) {
    564                 log("shouldFixTimeZoneNow: no mcc, operatorNumeric=" + operatorNumeric +
    565                         " retVal=false");
    566             }
    567             return false;
    568         }
    569 
    570         // If prevMcc is invalid will make it different from mcc
    571         // so we'll return true if the card exists.
    572         int prevMcc;
    573         try {
    574             prevMcc = Integer.parseInt(prevOperatorNumeric.substring(0, 3));
    575         } catch (Exception e) {
    576             prevMcc = mcc + 1;
    577         }
    578 
    579         // Determine if the Icc card exists
    580         boolean iccCardExist = false;
    581         if (mUiccApplcation != null) {
    582             iccCardExist = mUiccApplcation.getState() != AppState.APPSTATE_UNKNOWN;
    583         }
    584 
    585         // Determine retVal
    586         boolean retVal = ((iccCardExist && (mcc != prevMcc)) || needToFixTimeZone);
    587         if (DBG) {
    588             long ctm = System.currentTimeMillis();
    589             log("shouldFixTimeZoneNow: retVal=" + retVal +
    590                     " iccCardExist=" + iccCardExist +
    591                     " operatorNumeric=" + operatorNumeric + " mcc=" + mcc +
    592                     " prevOperatorNumeric=" + prevOperatorNumeric + " prevMcc=" + prevMcc +
    593                     " needToFixTimeZone=" + needToFixTimeZone +
    594                     " ltod=" + TimeUtils.logTimeOfDay(ctm));
    595         }
    596         return retVal;
    597     }
    598 
    599     /**
    600      * @return all available cell information or null if none.
    601      */
    602     public List<CellInfo> getAllCellInfo() {
    603         return null;
    604     }
    605 
    606     /**
    607      * @return signal strength
    608      */
    609     public SignalStrength getSignalStrength() {
    610         synchronized(mCellInfo) {
    611             return mSignalStrength;
    612         }
    613     }
    614 
    615     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    616         pw.println("ServiceStateTracker:");
    617         pw.println(" ss=" + ss);
    618         pw.println(" newSS=" + newSS);
    619         pw.println(" mCellInfo=" + mCellInfo);
    620         pw.println(" mRestrictedState=" + mRestrictedState);
    621         pw.println(" pollingContext=" + pollingContext);
    622         pw.println(" mDesiredPowerState=" + mDesiredPowerState);
    623         pw.println(" mRilRadioTechnology=" + mRilRadioTechnology);
    624         pw.println(" mNewRilRadioTechnology=" + mNewRilRadioTechnology);
    625         pw.println(" dontPollSignalStrength=" + dontPollSignalStrength);
    626         pw.println(" mPendingRadioPowerOffAfterDataOff=" + mPendingRadioPowerOffAfterDataOff);
    627         pw.println(" mPendingRadioPowerOffAfterDataOffTag=" + mPendingRadioPowerOffAfterDataOffTag);
    628     }
    629 
    630     /**
    631      * Verifies the current thread is the same as the thread originally
    632      * used in the initialization of this instance. Throws RuntimeException
    633      * if not.
    634      *
    635      * @exception RuntimeException if the current thread is not
    636      * the thread that originally obtained this PhoneBase instance.
    637      */
    638     protected void checkCorrectThread() {
    639         if (Thread.currentThread() != getLooper().getThread()) {
    640             throw new RuntimeException(
    641                     "ServiceStateTracker must be used from within one thread");
    642         }
    643     }
    644 }
    645