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