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