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