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