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