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