1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.telephony; 18 19import android.app.AlarmManager; 20import android.app.Notification; 21import android.app.NotificationManager; 22import android.app.PendingIntent; 23import android.content.BroadcastReceiver; 24import android.content.ContentResolver; 25import android.content.Context; 26import android.content.Intent; 27import android.content.IntentFilter; 28import android.content.SharedPreferences; 29import android.content.res.Resources; 30import android.database.ContentObserver; 31import android.os.AsyncResult; 32import android.os.BaseBundle; 33import android.os.Build; 34import android.os.Handler; 35import android.os.Looper; 36import android.os.Message; 37import android.os.PersistableBundle; 38import android.os.PowerManager; 39import android.os.Registrant; 40import android.os.RegistrantList; 41import android.os.RemoteException; 42import android.os.ServiceManager; 43import android.os.SystemClock; 44import android.os.SystemProperties; 45import android.os.UserHandle; 46import android.preference.PreferenceManager; 47import android.provider.Settings; 48import android.telephony.CarrierConfigManager; 49import android.telephony.CellIdentityGsm; 50import android.telephony.CellIdentityLte; 51import android.telephony.CellIdentityWcdma; 52import android.telephony.CellInfo; 53import android.telephony.CellInfoCdma; 54import android.telephony.CellInfoGsm; 55import android.telephony.CellInfoLte; 56import android.telephony.CellInfoWcdma; 57import android.telephony.CellLocation; 58import android.telephony.CellSignalStrengthLte; 59import android.telephony.Rlog; 60import android.telephony.ServiceState; 61import android.telephony.SignalStrength; 62import android.telephony.SubscriptionManager; 63import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 64import android.telephony.TelephonyManager; 65import android.telephony.cdma.CdmaCellLocation; 66import android.telephony.gsm.GsmCellLocation; 67import android.text.TextUtils; 68import android.util.EventLog; 69import android.util.LocalLog; 70import android.util.Pair; 71import android.util.TimeUtils; 72 73import java.io.FileDescriptor; 74import java.io.PrintWriter; 75import java.util.ArrayList; 76import java.util.Arrays; 77import java.util.Calendar; 78import java.util.Date; 79import java.util.List; 80import java.util.TimeZone; 81import java.util.concurrent.atomic.AtomicInteger; 82 83import com.android.internal.annotations.VisibleForTesting; 84import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 85import com.android.internal.telephony.cdma.EriInfo; 86import com.android.internal.telephony.dataconnection.DcTracker; 87import com.android.internal.telephony.metrics.TelephonyMetrics; 88import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 89import com.android.internal.telephony.uicc.IccRecords; 90import com.android.internal.telephony.uicc.RuimRecords; 91import com.android.internal.telephony.uicc.SIMRecords; 92import com.android.internal.telephony.uicc.UiccCardApplication; 93import com.android.internal.telephony.uicc.UiccController; 94import com.android.internal.util.IndentingPrintWriter; 95 96/** 97 * {@hide} 98 */ 99public class ServiceStateTracker extends Handler { 100 private static final String LOG_TAG = "SST"; 101 private static final boolean DBG = true; 102 private static final boolean VDBG = false; // STOPSHIP if true 103 104 private static final String PROP_FORCE_ROAMING = "telephony.test.forceRoaming"; 105 106 private CommandsInterface mCi; 107 private UiccController mUiccController = null; 108 private UiccCardApplication mUiccApplcation = null; 109 private IccRecords mIccRecords = null; 110 111 private boolean mVoiceCapable; 112 113 public ServiceState mSS; 114 private ServiceState mNewSS; 115 116 private static final long LAST_CELL_INFO_LIST_MAX_AGE_MS = 2000; 117 private long mLastCellInfoListTime; 118 private List<CellInfo> mLastCellInfoList = null; 119 120 private SignalStrength mSignalStrength; 121 122 // TODO - this should not be public, right now used externally GsmConnetion. 123 public RestrictedState mRestrictedState; 124 125 /* The otaspMode passed to PhoneStateListener#onOtaspChanged */ 126 static public final int OTASP_UNINITIALIZED = 0; 127 static public final int OTASP_UNKNOWN = 1; 128 static public final int OTASP_NEEDED = 2; 129 static public final int OTASP_NOT_NEEDED = 3; 130 /** 131 * OtaUtil has conflict enum 4: OtaUtils.OTASP_FAILURE_SPC_RETRIES 132 */ 133 static public final int OTASP_SIM_UNPROVISIONED = 5; 134 135 /** 136 * A unique identifier to track requests associated with a poll 137 * and ignore stale responses. The value is a count-down of 138 * expected responses in this pollingContext. 139 */ 140 private int[] mPollingContext; 141 private boolean mDesiredPowerState; 142 143 /** 144 * By default, strength polling is enabled. However, if we're 145 * getting unsolicited signal strength updates from the radio, set 146 * value to true and don't bother polling any more. 147 */ 148 private boolean mDontPollSignalStrength = false; 149 150 private RegistrantList mVoiceRoamingOnRegistrants = new RegistrantList(); 151 private RegistrantList mVoiceRoamingOffRegistrants = new RegistrantList(); 152 private RegistrantList mDataRoamingOnRegistrants = new RegistrantList(); 153 private RegistrantList mDataRoamingOffRegistrants = new RegistrantList(); 154 protected RegistrantList mAttachedRegistrants = new RegistrantList(); 155 protected RegistrantList mDetachedRegistrants = new RegistrantList(); 156 private RegistrantList mDataRegStateOrRatChangedRegistrants = new RegistrantList(); 157 private RegistrantList mNetworkAttachedRegistrants = new RegistrantList(); 158 private RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList(); 159 private RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList(); 160 161 /* Radio power off pending flag and tag counter */ 162 private boolean mPendingRadioPowerOffAfterDataOff = false; 163 private int mPendingRadioPowerOffAfterDataOffTag = 0; 164 165 /** Signal strength poll rate. */ 166 private static final int POLL_PERIOD_MILLIS = 20 * 1000; 167 168 /** Waiting period before recheck gprs and voice registration. */ 169 public static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000; 170 171 /** GSM events */ 172 protected static final int EVENT_RADIO_STATE_CHANGED = 1; 173 protected static final int EVENT_NETWORK_STATE_CHANGED = 2; 174 protected static final int EVENT_GET_SIGNAL_STRENGTH = 3; 175 protected static final int EVENT_POLL_STATE_REGISTRATION = 4; 176 protected static final int EVENT_POLL_STATE_GPRS = 5; 177 protected static final int EVENT_POLL_STATE_OPERATOR = 6; 178 protected static final int EVENT_POLL_SIGNAL_STRENGTH = 10; 179 protected static final int EVENT_NITZ_TIME = 11; 180 protected static final int EVENT_SIGNAL_STRENGTH_UPDATE = 12; 181 protected static final int EVENT_RADIO_AVAILABLE = 13; 182 protected static final int EVENT_POLL_STATE_NETWORK_SELECTION_MODE = 14; 183 protected static final int EVENT_GET_LOC_DONE = 15; 184 protected static final int EVENT_SIM_RECORDS_LOADED = 16; 185 protected static final int EVENT_SIM_READY = 17; 186 protected static final int EVENT_LOCATION_UPDATES_ENABLED = 18; 187 protected static final int EVENT_GET_PREFERRED_NETWORK_TYPE = 19; 188 protected static final int EVENT_SET_PREFERRED_NETWORK_TYPE = 20; 189 protected static final int EVENT_RESET_PREFERRED_NETWORK_TYPE = 21; 190 protected static final int EVENT_CHECK_REPORT_GPRS = 22; 191 protected static final int EVENT_RESTRICTED_STATE_CHANGED = 23; 192 193 /** CDMA events */ 194 protected static final int EVENT_RUIM_READY = 26; 195 protected static final int EVENT_RUIM_RECORDS_LOADED = 27; 196 protected static final int EVENT_POLL_STATE_CDMA_SUBSCRIPTION = 34; 197 protected static final int EVENT_NV_READY = 35; 198 protected static final int EVENT_ERI_FILE_LOADED = 36; 199 protected static final int EVENT_OTA_PROVISION_STATUS_CHANGE = 37; 200 protected static final int EVENT_SET_RADIO_POWER_OFF = 38; 201 protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 39; 202 protected static final int EVENT_CDMA_PRL_VERSION_CHANGED = 40; 203 204 protected static final int EVENT_RADIO_ON = 41; 205 public static final int EVENT_ICC_CHANGED = 42; 206 protected static final int EVENT_GET_CELL_INFO_LIST = 43; 207 protected static final int EVENT_UNSOL_CELL_INFO_LIST = 44; 208 protected static final int EVENT_CHANGE_IMS_STATE = 45; 209 protected static final int EVENT_IMS_STATE_CHANGED = 46; 210 protected static final int EVENT_IMS_STATE_DONE = 47; 211 protected static final int EVENT_IMS_CAPABILITY_CHANGED = 48; 212 protected static final int EVENT_ALL_DATA_DISCONNECTED = 49; 213 protected static final int EVENT_PHONE_TYPE_SWITCHED = 50; 214 215 protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone"; 216 217 /** 218 * List of ISO codes for countries that can have an offset of 219 * GMT+0 when not in daylight savings time. This ignores some 220 * small places such as the Canary Islands (Spain) and 221 * Danmarkshavn (Denmark). The list must be sorted by code. 222 */ 223 protected static final String[] GMT_COUNTRY_CODES = { 224 "bf", // Burkina Faso 225 "ci", // Cote d'Ivoire 226 "eh", // Western Sahara 227 "fo", // Faroe Islands, Denmark 228 "gb", // United Kingdom of Great Britain and Northern Ireland 229 "gh", // Ghana 230 "gm", // Gambia 231 "gn", // Guinea 232 "gw", // Guinea Bissau 233 "ie", // Ireland 234 "lr", // Liberia 235 "is", // Iceland 236 "ma", // Morocco 237 "ml", // Mali 238 "mr", // Mauritania 239 "pt", // Portugal 240 "sl", // Sierra Leone 241 "sn", // Senegal 242 "st", // Sao Tome and Principe 243 "tg", // Togo 244 }; 245 246 private class CellInfoResult { 247 List<CellInfo> list; 248 Object lockObj = new Object(); 249 } 250 251 /** Reason for registration denial. */ 252 protected static final String REGISTRATION_DENIED_GEN = "General"; 253 protected static final String REGISTRATION_DENIED_AUTH = "Authentication Failure"; 254 255 private boolean mImsRegistrationOnOff = false; 256 private boolean mAlarmSwitch = false; 257 /** Radio is disabled by carrier. Radio power will not be override if this field is set */ 258 private boolean mRadioDisabledByCarrier = false; 259 private PendingIntent mRadioOffIntent = null; 260 private static final String ACTION_RADIO_OFF = "android.intent.action.ACTION_RADIO_OFF"; 261 private boolean mPowerOffDelayNeed = true; 262 private boolean mDeviceShuttingDown = false; 263 /** Keep track of SPN display rules, so we only broadcast intent if something changes. */ 264 private boolean mSpnUpdatePending = false; 265 private String mCurSpn = null; 266 private String mCurDataSpn = null; 267 private String mCurPlmn = null; 268 private boolean mCurShowPlmn = false; 269 private boolean mCurShowSpn = false; 270 private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 271 272 private boolean mImsRegistered = false; 273 274 private SubscriptionManager mSubscriptionManager; 275 private SubscriptionController mSubscriptionController; 276 private final SstSubscriptionsChangedListener mOnSubscriptionsChangedListener = 277 new SstSubscriptionsChangedListener(); 278 279 280 private final RatRatcheter mRatRatcheter; 281 282 private final LocalLog mRoamingLog = new LocalLog(10); 283 private final LocalLog mAttachLog = new LocalLog(10); 284 private final LocalLog mPhoneTypeLog = new LocalLog(10); 285 private final LocalLog mRatLog = new LocalLog(20); 286 287 private class SstSubscriptionsChangedListener extends OnSubscriptionsChangedListener { 288 public final AtomicInteger mPreviousSubId = 289 new AtomicInteger(SubscriptionManager.INVALID_SUBSCRIPTION_ID); 290 291 /** 292 * Callback invoked when there is any change to any SubscriptionInfo. Typically 293 * this method would invoke {@link SubscriptionManager#getActiveSubscriptionInfoList} 294 */ 295 @Override 296 public void onSubscriptionsChanged() { 297 if (DBG) log("SubscriptionListener.onSubscriptionInfoChanged"); 298 // Set the network type, in case the radio does not restore it. 299 int subId = mPhone.getSubId(); 300 if (mPreviousSubId.getAndSet(subId) != subId) { 301 if (SubscriptionManager.isValidSubscriptionId(subId)) { 302 Context context = mPhone.getContext(); 303 304 mPhone.notifyPhoneStateChanged(); 305 mPhone.notifyCallForwardingIndicator(); 306 307 boolean restoreSelection = !context.getResources().getBoolean( 308 com.android.internal.R.bool.skip_restoring_network_selection); 309 mPhone.sendSubscriptionSettings(restoreSelection); 310 311 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, 312 ServiceState.rilRadioTechnologyToString( 313 mSS.getRilDataRadioTechnology())); 314 315 if (mSpnUpdatePending) { 316 mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(), mCurShowPlmn, 317 mCurPlmn, mCurShowSpn, mCurSpn); 318 mSpnUpdatePending = false; 319 } 320 321 // Remove old network selection sharedPreferences since SP key names are now 322 // changed to include subId. This will be done only once when upgrading from an 323 // older build that did not include subId in the names. 324 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences( 325 context); 326 String oldNetworkSelection = sp.getString( 327 Phone.NETWORK_SELECTION_KEY, ""); 328 String oldNetworkSelectionName = sp.getString( 329 Phone.NETWORK_SELECTION_NAME_KEY, ""); 330 String oldNetworkSelectionShort = sp.getString( 331 Phone.NETWORK_SELECTION_SHORT_KEY, ""); 332 if (!TextUtils.isEmpty(oldNetworkSelection) || 333 !TextUtils.isEmpty(oldNetworkSelectionName) || 334 !TextUtils.isEmpty(oldNetworkSelectionShort)) { 335 SharedPreferences.Editor editor = sp.edit(); 336 editor.putString(Phone.NETWORK_SELECTION_KEY + subId, 337 oldNetworkSelection); 338 editor.putString(Phone.NETWORK_SELECTION_NAME_KEY + subId, 339 oldNetworkSelectionName); 340 editor.putString(Phone.NETWORK_SELECTION_SHORT_KEY + subId, 341 oldNetworkSelectionShort); 342 editor.remove(Phone.NETWORK_SELECTION_KEY); 343 editor.remove(Phone.NETWORK_SELECTION_NAME_KEY); 344 editor.remove(Phone.NETWORK_SELECTION_SHORT_KEY); 345 editor.commit(); 346 } 347 348 // Once sub id becomes valid, we need to update the service provider name 349 // displayed on the UI again. The old SPN update intents sent to 350 // MobileSignalController earlier were actually ignored due to invalid sub id. 351 updateSpnDisplay(); 352 } 353 // update voicemail count and notify message waiting changed 354 mPhone.updateVoiceMail(); 355 } 356 } 357 }; 358 359 //Common 360 private GsmCdmaPhone mPhone; 361 public CellLocation mCellLoc; 362 private CellLocation mNewCellLoc; 363 public static final int MS_PER_HOUR = 60 * 60 * 1000; 364 /* Time stamp after 19 January 2038 is not supported under 32 bit */ 365 private static final int MAX_NITZ_YEAR = 2037; 366 /** 367 * Sometimes we get the NITZ time before we know what country we 368 * are in. Keep the time zone information from the NITZ string so 369 * we can fix the time zone once know the country. 370 */ 371 private boolean mNeedFixZoneAfterNitz = false; 372 private int mZoneOffset; 373 private boolean mZoneDst; 374 private long mZoneTime; 375 private boolean mGotCountryCode = false; 376 private String mSavedTimeZone; 377 private long mSavedTime; 378 private long mSavedAtTime; 379 /** Wake lock used while setting time of day. */ 380 private PowerManager.WakeLock mWakeLock; 381 public static final String WAKELOCK_TAG = "ServiceStateTracker"; 382 private ContentResolver mCr; 383 private ContentObserver mAutoTimeObserver = new ContentObserver(new Handler()) { 384 @Override 385 public void onChange(boolean selfChange) { 386 Rlog.i(LOG_TAG, "Auto time state changed"); 387 revertToNitzTime(); 388 } 389 }; 390 391 private ContentObserver mAutoTimeZoneObserver = new ContentObserver(new Handler()) { 392 @Override 393 public void onChange(boolean selfChange) { 394 Rlog.i(LOG_TAG, "Auto time zone state changed"); 395 revertToNitzTimeZone(); 396 } 397 }; 398 399 //GSM 400 private int mPreferredNetworkType; 401 private int mMaxDataCalls = 1; 402 private int mNewMaxDataCalls = 1; 403 private int mReasonDataDenied = -1; 404 private int mNewReasonDataDenied = -1; 405 /** 406 * GSM roaming status solely based on TS 27.007 7.2 CREG. Only used by 407 * handlePollStateResult to store CREG roaming result. 408 */ 409 private boolean mGsmRoaming = false; 410 /** 411 * Data roaming status solely based on TS 27.007 10.1.19 CGREG. Only used by 412 * handlePollStateResult to store CGREG roaming result. 413 */ 414 private boolean mDataRoaming = false; 415 /** 416 * Mark when service state is in emergency call only mode 417 */ 418 private boolean mEmergencyOnly = false; 419 /** Boolean is true is setTimeFromNITZString was called */ 420 private boolean mNitzUpdatedTime = false; 421 /** Started the recheck process after finding gprs should registered but not. */ 422 private boolean mStartedGprsRegCheck; 423 /** Already sent the event-log for no gprs register. */ 424 private boolean mReportedGprsNoReg; 425 /** 426 * The Notification object given to the NotificationManager. 427 */ 428 private Notification mNotification; 429 /** Notification type. */ 430 public static final int PS_ENABLED = 1001; // Access Control blocks data service 431 public static final int PS_DISABLED = 1002; // Access Control enables data service 432 public static final int CS_ENABLED = 1003; // Access Control blocks all voice/sms service 433 public static final int CS_DISABLED = 1004; // Access Control enables all voice/sms service 434 public static final int CS_NORMAL_ENABLED = 1005; // Access Control blocks normal voice/sms service 435 public static final int CS_EMERGENCY_ENABLED = 1006; // Access Control blocks emergency call service 436 /** Notification id. */ 437 public static final int PS_NOTIFICATION = 888; // Id to update and cancel PS restricted 438 public static final int CS_NOTIFICATION = 999; // Id to update and cancel CS restricted 439 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 440 @Override 441 public void onReceive(Context context, Intent intent) { 442 if (!mPhone.isPhoneTypeGsm()) { 443 loge("Ignoring intent " + intent + " received on CDMA phone"); 444 return; 445 } 446 447 if (intent.getAction().equals(Intent.ACTION_LOCALE_CHANGED)) { 448 // update emergency string whenever locale changed 449 updateSpnDisplay(); 450 } else if (intent.getAction().equals(ACTION_RADIO_OFF)) { 451 mAlarmSwitch = false; 452 DcTracker dcTracker = mPhone.mDcTracker; 453 powerOffRadioSafely(dcTracker); 454 } 455 } 456 }; 457 458 //CDMA 459 // Min values used to by getOtasp() 460 public static final String UNACTIVATED_MIN2_VALUE = "000000"; 461 public static final String UNACTIVATED_MIN_VALUE = "1111110111"; 462 // Current Otasp value 463 private int mCurrentOtaspMode = OTASP_UNINITIALIZED; 464 /** if time between NITZ updates is less than mNitzUpdateSpacing the update may be ignored. */ 465 public static final int NITZ_UPDATE_SPACING_DEFAULT = 1000 * 60 * 10; 466 private int mNitzUpdateSpacing = SystemProperties.getInt("ro.nitz_update_spacing", 467 NITZ_UPDATE_SPACING_DEFAULT); 468 /** If mNitzUpdateSpacing hasn't been exceeded but update is > mNitzUpdate do the update */ 469 public static final int NITZ_UPDATE_DIFF_DEFAULT = 2000; 470 private int mNitzUpdateDiff = SystemProperties.getInt("ro.nitz_update_diff", 471 NITZ_UPDATE_DIFF_DEFAULT); 472 private int mRoamingIndicator; 473 private boolean mIsInPrl; 474 private int mDefaultRoamingIndicator; 475 /** 476 * Initially assume no data connection. 477 */ 478 private int mRegistrationState = -1; 479 private RegistrantList mCdmaForSubscriptionInfoReadyRegistrants = new RegistrantList(); 480 private String mMdn; 481 private int mHomeSystemId[] = null; 482 private int mHomeNetworkId[] = null; 483 private String mMin; 484 private String mPrlVersion; 485 private boolean mIsMinInfoReady = false; 486 private boolean mIsEriTextLoaded = false; 487 private boolean mIsSubscriptionFromRuim = false; 488 private CdmaSubscriptionSourceManager mCdmaSSM; 489 public static final String INVALID_MCC = "000"; 490 public static final String DEFAULT_MNC = "00"; 491 private HbpcdUtils mHbpcdUtils = null; 492 /* Used only for debugging purposes. */ 493 private String mRegistrationDeniedReason; 494 private String mCurrentCarrier = null; 495 496 public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) { 497 mPhone = phone; 498 mCi = ci; 499 500 mRatRatcheter = new RatRatcheter(mPhone); 501 mVoiceCapable = mPhone.getContext().getResources().getBoolean( 502 com.android.internal.R.bool.config_voice_capable); 503 mUiccController = UiccController.getInstance(); 504 505 mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null); 506 mCi.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null); 507 mCi.registerForCellInfoList(this, EVENT_UNSOL_CELL_INFO_LIST, null); 508 509 mSubscriptionController = SubscriptionController.getInstance(); 510 mSubscriptionManager = SubscriptionManager.from(phone.getContext()); 511 mSubscriptionManager 512 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 513 514 mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null); 515 516 PowerManager powerManager = 517 (PowerManager)phone.getContext().getSystemService(Context.POWER_SERVICE); 518 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG); 519 520 mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); 521 mCi.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null); 522 mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null); 523 524 mCr = phone.getContext().getContentResolver(); 525 // system setting property AIRPLANE_MODE_ON is set in Settings. 526 int airplaneMode = Settings.Global.getInt(mCr, Settings.Global.AIRPLANE_MODE_ON, 0); 527 int enableCellularOnBoot = Settings.Global.getInt(mCr, 528 Settings.Global.ENABLE_CELLULAR_ON_BOOT, 1); 529 mDesiredPowerState = (enableCellularOnBoot > 0) && ! (airplaneMode > 0); 530 531 mCr.registerContentObserver( 532 Settings.Global.getUriFor(Settings.Global.AUTO_TIME), true, 533 mAutoTimeObserver); 534 mCr.registerContentObserver( 535 Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true, 536 mAutoTimeZoneObserver); 537 setSignalStrengthDefaultValues(); 538 539 // Monitor locale change 540 Context context = mPhone.getContext(); 541 IntentFilter filter = new IntentFilter(); 542 filter.addAction(Intent.ACTION_LOCALE_CHANGED); 543 context.registerReceiver(mIntentReceiver, filter); 544 filter = new IntentFilter(); 545 filter.addAction(ACTION_RADIO_OFF); 546 context.registerReceiver(mIntentReceiver, filter); 547 548 mPhone.notifyOtaspChanged(OTASP_UNINITIALIZED); 549 550 updatePhoneType(); 551 } 552 553 @VisibleForTesting 554 public void updatePhoneType() { 555 mSS = new ServiceState(); 556 mNewSS = new ServiceState(); 557 mLastCellInfoListTime = 0; 558 mLastCellInfoList = null; 559 mSignalStrength = new SignalStrength(); 560 mRestrictedState = new RestrictedState(); 561 mStartedGprsRegCheck = false; 562 mReportedGprsNoReg = false; 563 mMdn = null; 564 mMin = null; 565 mPrlVersion = null; 566 mIsMinInfoReady = false; 567 mNitzUpdatedTime = false; 568 569 //cancel any pending pollstate request on voice tech switching 570 cancelPollState(); 571 572 if (mPhone.isPhoneTypeGsm()) { 573 //clear CDMA registrations first 574 if (mCdmaSSM != null) { 575 mCdmaSSM.dispose(this); 576 } 577 578 mCi.unregisterForCdmaPrlChanged(this); 579 mPhone.unregisterForEriFileLoaded(this); 580 mCi.unregisterForCdmaOtaProvision(this); 581 mPhone.unregisterForSimRecordsLoaded(this); 582 583 mCellLoc = new GsmCellLocation(); 584 mNewCellLoc = new GsmCellLocation(); 585 mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 586 mCi.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null); 587 } else { 588 //clear GSM regsitrations first 589 mCi.unregisterForAvailable(this); 590 mCi.unSetOnRestrictedStateChanged(this); 591 592 if (mPhone.isPhoneTypeCdmaLte()) { 593 mPhone.registerForSimRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); 594 } 595 mCellLoc = new CdmaCellLocation(); 596 mNewCellLoc = new CdmaCellLocation(); 597 mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(mPhone.getContext(), mCi, this, 598 EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); 599 mIsSubscriptionFromRuim = (mCdmaSSM.getCdmaSubscriptionSource() == 600 CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM); 601 602 mCi.registerForCdmaPrlChanged(this, EVENT_CDMA_PRL_VERSION_CHANGED, null); 603 mPhone.registerForEriFileLoaded(this, EVENT_ERI_FILE_LOADED, null); 604 mCi.registerForCdmaOtaProvision(this, EVENT_OTA_PROVISION_STATUS_CHANGE, null); 605 606 mHbpcdUtils = new HbpcdUtils(mPhone.getContext()); 607 // update OTASP state in case previously set by another service 608 updateOtaspState(); 609 } 610 611 // This should be done after the technology specific initializations above since it relies 612 // on fields like mIsSubscriptionFromRuim (which is updated above) 613 onUpdateIccAvailability(); 614 615 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, 616 ServiceState.rilRadioTechnologyToString(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)); 617 // Query signal strength from the modem after service tracker is created (i.e. boot up, 618 // switching between GSM and CDMA phone), because the unsolicited signal strength 619 // information might come late or even never come. This will get the accurate signal 620 // strength information displayed on the UI. 621 mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH)); 622 sendMessage(obtainMessage(EVENT_PHONE_TYPE_SWITCHED)); 623 624 logPhoneTypeChange(); 625 626 // Tell everybody that we've thrown away state and are starting over with 627 // empty, detached ServiceStates. 628 mVoiceRoamingOffRegistrants.notifyRegistrants(); 629 mDataRoamingOffRegistrants.notifyRegistrants(); 630 mDetachedRegistrants.notifyRegistrants(); 631 notifyDataRegStateRilRadioTechnologyChanged(); 632 } 633 634 @VisibleForTesting 635 public void requestShutdown() { 636 if (mDeviceShuttingDown == true) return; 637 mDeviceShuttingDown = true; 638 mDesiredPowerState = false; 639 setPowerStateToDesired(); 640 } 641 642 public void dispose() { 643 mCi.unSetOnSignalStrengthUpdate(this); 644 mUiccController.unregisterForIccChanged(this); 645 mCi.unregisterForCellInfoList(this); 646 mSubscriptionManager 647 .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 648 mCi.unregisterForImsNetworkStateChanged(this); 649 } 650 651 public boolean getDesiredPowerState() { 652 return mDesiredPowerState; 653 } 654 public boolean getPowerStateFromCarrier() { return !mRadioDisabledByCarrier; } 655 656 private SignalStrength mLastSignalStrength = null; 657 protected boolean notifySignalStrength() { 658 boolean notified = false; 659 if (!mSignalStrength.equals(mLastSignalStrength)) { 660 try { 661 mPhone.notifySignalStrength(); 662 notified = true; 663 } catch (NullPointerException ex) { 664 loge("updateSignalStrength() Phone already destroyed: " + ex 665 + "SignalStrength not notified"); 666 } 667 } 668 return notified; 669 } 670 671 /** 672 * Notify all mDataConnectionRatChangeRegistrants using an 673 * AsyncResult in msg.obj where AsyncResult#result contains the 674 * new RAT as an Integer Object. 675 */ 676 protected void notifyDataRegStateRilRadioTechnologyChanged() { 677 int rat = mSS.getRilDataRadioTechnology(); 678 int drs = mSS.getDataRegState(); 679 if (DBG) log("notifyDataRegStateRilRadioTechnologyChanged: drs=" + drs + " rat=" + rat); 680 681 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, 682 ServiceState.rilRadioTechnologyToString(rat)); 683 mDataRegStateOrRatChangedRegistrants.notifyResult(new Pair<Integer, Integer>(drs, rat)); 684 } 685 686 /** 687 * Some operators have been known to report registration failure 688 * data only devices, to fix that use DataRegState. 689 */ 690 protected void useDataRegStateForDataOnlyDevices() { 691 if (mVoiceCapable == false) { 692 if (DBG) { 693 log("useDataRegStateForDataOnlyDevice: VoiceRegState=" + mNewSS.getVoiceRegState() 694 + " DataRegState=" + mNewSS.getDataRegState()); 695 } 696 // TODO: Consider not lying and instead have callers know the difference. 697 mNewSS.setVoiceRegState(mNewSS.getDataRegState()); 698 } 699 } 700 701 protected void updatePhoneObject() { 702 if (mPhone.getContext().getResources(). 703 getBoolean(com.android.internal.R.bool.config_switch_phone_on_voice_reg_state_change)) { 704 // If the phone is not registered on a network, no need to update. 705 boolean isRegistered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE || 706 mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY; 707 if (!isRegistered) { 708 log("updatePhoneObject: Ignore update"); 709 return; 710 } 711 mPhone.updatePhoneObject(mSS.getRilVoiceRadioTechnology()); 712 } 713 } 714 715 /** 716 * Registration point for combined roaming on of mobile voice 717 * combined roaming is true when roaming is true and ONS differs SPN 718 * 719 * @param h handler to notify 720 * @param what what code of message when delivered 721 * @param obj placed in Message.obj 722 */ 723 public void registerForVoiceRoamingOn(Handler h, int what, Object obj) { 724 Registrant r = new Registrant(h, what, obj); 725 mVoiceRoamingOnRegistrants.add(r); 726 727 if (mSS.getVoiceRoaming()) { 728 r.notifyRegistrant(); 729 } 730 } 731 732 public void unregisterForVoiceRoamingOn(Handler h) { 733 mVoiceRoamingOnRegistrants.remove(h); 734 } 735 736 /** 737 * Registration point for roaming off of mobile voice 738 * combined roaming is true when roaming is true and ONS differs SPN 739 * 740 * @param h handler to notify 741 * @param what what code of message when delivered 742 * @param obj placed in Message.obj 743 */ 744 public void registerForVoiceRoamingOff(Handler h, int what, Object obj) { 745 Registrant r = new Registrant(h, what, obj); 746 mVoiceRoamingOffRegistrants.add(r); 747 748 if (!mSS.getVoiceRoaming()) { 749 r.notifyRegistrant(); 750 } 751 } 752 753 public void unregisterForVoiceRoamingOff(Handler h) { 754 mVoiceRoamingOffRegistrants.remove(h); 755 } 756 757 /** 758 * Registration point for combined roaming on of mobile data 759 * combined roaming is true when roaming is true and ONS differs SPN 760 * 761 * @param h handler to notify 762 * @param what what code of message when delivered 763 * @param obj placed in Message.obj 764 */ 765 public void registerForDataRoamingOn(Handler h, int what, Object obj) { 766 Registrant r = new Registrant(h, what, obj); 767 mDataRoamingOnRegistrants.add(r); 768 769 if (mSS.getDataRoaming()) { 770 r.notifyRegistrant(); 771 } 772 } 773 774 public void unregisterForDataRoamingOn(Handler h) { 775 mDataRoamingOnRegistrants.remove(h); 776 } 777 778 /** 779 * Registration point for roaming off of mobile data 780 * combined roaming is true when roaming is true and ONS differs SPN 781 * 782 * @param h handler to notify 783 * @param what what code of message when delivered 784 * @param obj placed in Message.obj 785 */ 786 public void registerForDataRoamingOff(Handler h, int what, Object obj) { 787 Registrant r = new Registrant(h, what, obj); 788 mDataRoamingOffRegistrants.add(r); 789 790 if (!mSS.getDataRoaming()) { 791 r.notifyRegistrant(); 792 } 793 } 794 795 public void unregisterForDataRoamingOff(Handler h) { 796 mDataRoamingOffRegistrants.remove(h); 797 } 798 799 /** 800 * Re-register network by toggling preferred network type. 801 * This is a work-around to deregister and register network since there is 802 * no ril api to set COPS=2 (deregister) only. 803 * 804 * @param onComplete is dispatched when this is complete. it will be 805 * an AsyncResult, and onComplete.obj.exception will be non-null 806 * on failure. 807 */ 808 public void reRegisterNetwork(Message onComplete) { 809 mCi.getPreferredNetworkType( 810 obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE, onComplete)); 811 } 812 813 public void 814 setRadioPower(boolean power) { 815 mDesiredPowerState = power; 816 817 setPowerStateToDesired(); 818 } 819 820 /** 821 * Radio power set from carrier action. if set to false means carrier desire to turn radio off 822 * and radio wont be re-enabled unless carrier explicitly turn it back on. 823 * @param enable indicate if radio power is enabled or disabled from carrier action. 824 */ 825 public void setRadioPowerFromCarrier(boolean enable) { 826 mRadioDisabledByCarrier = !enable; 827 setPowerStateToDesired(); 828 } 829 830 /** 831 * These two flags manage the behavior of the cell lock -- the 832 * lock should be held if either flag is true. The intention is 833 * to allow temporary acquisition of the lock to get a single 834 * update. Such a lock grab and release can thus be made to not 835 * interfere with more permanent lock holds -- in other words, the 836 * lock will only be released if both flags are false, and so 837 * releases by temporary users will only affect the lock state if 838 * there is no continuous user. 839 */ 840 private boolean mWantContinuousLocationUpdates; 841 private boolean mWantSingleLocationUpdate; 842 843 public void enableSingleLocationUpdate() { 844 if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return; 845 mWantSingleLocationUpdate = true; 846 mCi.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED)); 847 } 848 849 public void enableLocationUpdates() { 850 if (mWantSingleLocationUpdate || mWantContinuousLocationUpdates) return; 851 mWantContinuousLocationUpdates = true; 852 mCi.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED)); 853 } 854 855 protected void disableSingleLocationUpdate() { 856 mWantSingleLocationUpdate = false; 857 if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) { 858 mCi.setLocationUpdates(false, null); 859 } 860 } 861 862 public void disableLocationUpdates() { 863 mWantContinuousLocationUpdates = false; 864 if (!mWantSingleLocationUpdate && !mWantContinuousLocationUpdates) { 865 mCi.setLocationUpdates(false, null); 866 } 867 } 868 869 @Override 870 public void handleMessage(Message msg) { 871 AsyncResult ar; 872 int[] ints; 873 Message message; 874 switch (msg.what) { 875 case EVENT_SET_RADIO_POWER_OFF: 876 synchronized(this) { 877 if (mPendingRadioPowerOffAfterDataOff && 878 (msg.arg1 == mPendingRadioPowerOffAfterDataOffTag)) { 879 if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now."); 880 hangupAndPowerOff(); 881 mPendingRadioPowerOffAfterDataOffTag += 1; 882 mPendingRadioPowerOffAfterDataOff = false; 883 } else { 884 log("EVENT_SET_RADIO_OFF is stale arg1=" + msg.arg1 + 885 "!= tag=" + mPendingRadioPowerOffAfterDataOffTag); 886 } 887 } 888 break; 889 890 case EVENT_ICC_CHANGED: 891 onUpdateIccAvailability(); 892 break; 893 894 case EVENT_GET_CELL_INFO_LIST: { 895 ar = (AsyncResult) msg.obj; 896 CellInfoResult result = (CellInfoResult) ar.userObj; 897 synchronized(result.lockObj) { 898 if (ar.exception != null) { 899 log("EVENT_GET_CELL_INFO_LIST: error ret null, e=" + ar.exception); 900 result.list = null; 901 } else { 902 result.list = (List<CellInfo>) ar.result; 903 904 if (VDBG) { 905 log("EVENT_GET_CELL_INFO_LIST: size=" + result.list.size() 906 + " list=" + result.list); 907 } 908 } 909 mLastCellInfoListTime = SystemClock.elapsedRealtime(); 910 mLastCellInfoList = result.list; 911 result.lockObj.notify(); 912 } 913 break; 914 } 915 916 case EVENT_UNSOL_CELL_INFO_LIST: { 917 ar = (AsyncResult) msg.obj; 918 if (ar.exception != null) { 919 log("EVENT_UNSOL_CELL_INFO_LIST: error ignoring, e=" + ar.exception); 920 } else { 921 List<CellInfo> list = (List<CellInfo>) ar.result; 922 if (VDBG) { 923 log("EVENT_UNSOL_CELL_INFO_LIST: size=" + list.size() + " list=" + list); 924 } 925 mLastCellInfoListTime = SystemClock.elapsedRealtime(); 926 mLastCellInfoList = list; 927 mPhone.notifyCellInfo(list); 928 } 929 break; 930 } 931 932 case EVENT_IMS_STATE_CHANGED: // received unsol 933 mCi.getImsRegistrationState(this.obtainMessage(EVENT_IMS_STATE_DONE)); 934 break; 935 936 case EVENT_IMS_STATE_DONE: 937 ar = (AsyncResult) msg.obj; 938 if (ar.exception == null) { 939 int[] responseArray = (int[])ar.result; 940 mImsRegistered = (responseArray[0] == 1) ? true : false; 941 } 942 break; 943 944 //GSM 945 case EVENT_RADIO_AVAILABLE: 946 //this is unnecessary 947 //setPowerStateToDesired(); 948 break; 949 950 case EVENT_SIM_READY: 951 // Reset the mPreviousSubId so we treat a SIM power bounce 952 // as a first boot. See b/19194287 953 mOnSubscriptionsChangedListener.mPreviousSubId.set(-1); 954 pollState(); 955 // Signal strength polling stops when radio is off 956 queueNextSignalStrengthPoll(); 957 break; 958 959 case EVENT_RADIO_STATE_CHANGED: 960 case EVENT_PHONE_TYPE_SWITCHED: 961 if(!mPhone.isPhoneTypeGsm() && 962 mCi.getRadioState() == CommandsInterface.RadioState.RADIO_ON) { 963 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource()); 964 965 // Signal strength polling stops when radio is off. 966 queueNextSignalStrengthPoll(); 967 } 968 // This will do nothing in the 'radio not available' case 969 setPowerStateToDesired(); 970 // These events are modem triggered, so pollState() needs to be forced 971 modemTriggeredPollState(); 972 break; 973 974 case EVENT_NETWORK_STATE_CHANGED: 975 modemTriggeredPollState(); 976 break; 977 978 case EVENT_GET_SIGNAL_STRENGTH: 979 // This callback is called when signal strength is polled 980 // all by itself 981 982 if (!(mCi.getRadioState().isOn())) { 983 // Polling will continue when radio turns back on 984 return; 985 } 986 ar = (AsyncResult) msg.obj; 987 onSignalStrengthResult(ar); 988 queueNextSignalStrengthPoll(); 989 990 break; 991 992 case EVENT_GET_LOC_DONE: 993 ar = (AsyncResult) msg.obj; 994 995 if (ar.exception == null) { 996 String states[] = (String[])ar.result; 997 if (mPhone.isPhoneTypeGsm()) { 998 int lac = -1; 999 int cid = -1; 1000 if (states.length >= 3) { 1001 try { 1002 if (states[1] != null && states[1].length() > 0) { 1003 lac = Integer.parseInt(states[1], 16); 1004 } 1005 if (states[2] != null && states[2].length() > 0) { 1006 cid = Integer.parseInt(states[2], 16); 1007 } 1008 } catch (NumberFormatException ex) { 1009 Rlog.w(LOG_TAG, "error parsing location: " + ex); 1010 } 1011 } 1012 ((GsmCellLocation)mCellLoc).setLacAndCid(lac, cid); 1013 } else { 1014 int baseStationId = -1; 1015 int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG; 1016 int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG; 1017 int systemId = -1; 1018 int networkId = -1; 1019 1020 if (states.length > 9) { 1021 try { 1022 if (states[4] != null) { 1023 baseStationId = Integer.parseInt(states[4]); 1024 } 1025 if (states[5] != null) { 1026 baseStationLatitude = Integer.parseInt(states[5]); 1027 } 1028 if (states[6] != null) { 1029 baseStationLongitude = Integer.parseInt(states[6]); 1030 } 1031 // Some carriers only return lat-lngs of 0,0 1032 if (baseStationLatitude == 0 && baseStationLongitude == 0) { 1033 baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG; 1034 baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG; 1035 } 1036 if (states[8] != null) { 1037 systemId = Integer.parseInt(states[8]); 1038 } 1039 if (states[9] != null) { 1040 networkId = Integer.parseInt(states[9]); 1041 } 1042 } catch (NumberFormatException ex) { 1043 loge("error parsing cell location data: " + ex); 1044 } 1045 } 1046 1047 ((CdmaCellLocation)mCellLoc).setCellLocationData(baseStationId, 1048 baseStationLatitude, baseStationLongitude, systemId, networkId); 1049 } 1050 mPhone.notifyLocationChanged(); 1051 } 1052 1053 // Release any temporary cell lock, which could have been 1054 // acquired to allow a single-shot location update. 1055 disableSingleLocationUpdate(); 1056 break; 1057 1058 case EVENT_POLL_STATE_REGISTRATION: 1059 case EVENT_POLL_STATE_GPRS: 1060 case EVENT_POLL_STATE_OPERATOR: 1061 ar = (AsyncResult) msg.obj; 1062 handlePollStateResult(msg.what, ar); 1063 break; 1064 1065 case EVENT_POLL_STATE_NETWORK_SELECTION_MODE: 1066 if (DBG) log("EVENT_POLL_STATE_NETWORK_SELECTION_MODE"); 1067 ar = (AsyncResult) msg.obj; 1068 if (mPhone.isPhoneTypeGsm()) { 1069 handlePollStateResult(msg.what, ar); 1070 } else { 1071 if (ar.exception == null && ar.result != null) { 1072 ints = (int[])ar.result; 1073 if (ints[0] == 1) { // Manual selection. 1074 mPhone.setNetworkSelectionModeAutomatic(null); 1075 } 1076 } else { 1077 log("Unable to getNetworkSelectionMode"); 1078 } 1079 } 1080 break; 1081 1082 case EVENT_POLL_SIGNAL_STRENGTH: 1083 // Just poll signal strength...not part of pollState() 1084 1085 mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH)); 1086 break; 1087 1088 case EVENT_NITZ_TIME: 1089 ar = (AsyncResult) msg.obj; 1090 1091 String nitzString = (String)((Object[])ar.result)[0]; 1092 long nitzReceiveTime = ((Long)((Object[])ar.result)[1]).longValue(); 1093 1094 setTimeFromNITZString(nitzString, nitzReceiveTime); 1095 break; 1096 1097 case EVENT_SIGNAL_STRENGTH_UPDATE: 1098 // This is a notification from CommandsInterface.setOnSignalStrengthUpdate 1099 1100 ar = (AsyncResult) msg.obj; 1101 1102 // The radio is telling us about signal strength changes 1103 // we don't have to ask it 1104 mDontPollSignalStrength = true; 1105 1106 onSignalStrengthResult(ar); 1107 break; 1108 1109 case EVENT_SIM_RECORDS_LOADED: 1110 log("EVENT_SIM_RECORDS_LOADED: what=" + msg.what); 1111 updatePhoneObject(); 1112 updateOtaspState(); 1113 if (mPhone.isPhoneTypeGsm()) { 1114 updateSpnDisplay(); 1115 } 1116 break; 1117 1118 case EVENT_LOCATION_UPDATES_ENABLED: 1119 ar = (AsyncResult) msg.obj; 1120 1121 if (ar.exception == null) { 1122 mCi.getVoiceRegistrationState(obtainMessage(EVENT_GET_LOC_DONE, null)); 1123 } 1124 break; 1125 1126 case EVENT_SET_PREFERRED_NETWORK_TYPE: 1127 ar = (AsyncResult) msg.obj; 1128 // Don't care the result, only use for dereg network (COPS=2) 1129 message = obtainMessage(EVENT_RESET_PREFERRED_NETWORK_TYPE, ar.userObj); 1130 mCi.setPreferredNetworkType(mPreferredNetworkType, message); 1131 break; 1132 1133 case EVENT_RESET_PREFERRED_NETWORK_TYPE: 1134 ar = (AsyncResult) msg.obj; 1135 if (ar.userObj != null) { 1136 AsyncResult.forMessage(((Message) ar.userObj)).exception 1137 = ar.exception; 1138 ((Message) ar.userObj).sendToTarget(); 1139 } 1140 break; 1141 1142 case EVENT_GET_PREFERRED_NETWORK_TYPE: 1143 ar = (AsyncResult) msg.obj; 1144 1145 if (ar.exception == null) { 1146 mPreferredNetworkType = ((int[])ar.result)[0]; 1147 } else { 1148 mPreferredNetworkType = RILConstants.NETWORK_MODE_GLOBAL; 1149 } 1150 1151 message = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE, ar.userObj); 1152 int toggledNetworkType = RILConstants.NETWORK_MODE_GLOBAL; 1153 1154 mCi.setPreferredNetworkType(toggledNetworkType, message); 1155 break; 1156 1157 case EVENT_CHECK_REPORT_GPRS: 1158 if (mPhone.isPhoneTypeGsm() && mSS != null && 1159 !isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) { 1160 1161 // Can't register data service while voice service is ok 1162 // i.e. CREG is ok while CGREG is not 1163 // possible a network or baseband side error 1164 GsmCellLocation loc = ((GsmCellLocation)mPhone.getCellLocation()); 1165 EventLog.writeEvent(EventLogTags.DATA_NETWORK_REGISTRATION_FAIL, 1166 mSS.getOperatorNumeric(), loc != null ? loc.getCid() : -1); 1167 mReportedGprsNoReg = true; 1168 } 1169 mStartedGprsRegCheck = false; 1170 break; 1171 1172 case EVENT_RESTRICTED_STATE_CHANGED: 1173 if (mPhone.isPhoneTypeGsm()) { 1174 // This is a notification from 1175 // CommandsInterface.setOnRestrictedStateChanged 1176 1177 if (DBG) log("EVENT_RESTRICTED_STATE_CHANGED"); 1178 1179 ar = (AsyncResult) msg.obj; 1180 1181 onRestrictedStateChanged(ar); 1182 } 1183 break; 1184 1185 case EVENT_ALL_DATA_DISCONNECTED: 1186 int dds = SubscriptionManager.getDefaultDataSubscriptionId(); 1187 ProxyController.getInstance().unregisterForAllDataDisconnected(dds, this); 1188 synchronized(this) { 1189 if (mPendingRadioPowerOffAfterDataOff) { 1190 if (DBG) log("EVENT_ALL_DATA_DISCONNECTED, turn radio off now."); 1191 hangupAndPowerOff(); 1192 mPendingRadioPowerOffAfterDataOff = false; 1193 } else { 1194 log("EVENT_ALL_DATA_DISCONNECTED is stale"); 1195 } 1196 } 1197 break; 1198 1199 case EVENT_CHANGE_IMS_STATE: 1200 if (DBG) log("EVENT_CHANGE_IMS_STATE:"); 1201 1202 setPowerStateToDesired(); 1203 break; 1204 1205 case EVENT_IMS_CAPABILITY_CHANGED: 1206 if (DBG) log("EVENT_IMS_CAPABILITY_CHANGED"); 1207 updateSpnDisplay(); 1208 break; 1209 1210 //CDMA 1211 case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED: 1212 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource()); 1213 break; 1214 1215 case EVENT_RUIM_READY: 1216 if (mPhone.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) { 1217 // Subscription will be read from SIM I/O 1218 if (DBG) log("Receive EVENT_RUIM_READY"); 1219 pollState(); 1220 } else { 1221 if (DBG) log("Receive EVENT_RUIM_READY and Send Request getCDMASubscription."); 1222 getSubscriptionInfoAndStartPollingThreads(); 1223 } 1224 1225 // Only support automatic selection mode in CDMA. 1226 mCi.getNetworkSelectionMode(obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE)); 1227 1228 break; 1229 1230 case EVENT_NV_READY: 1231 updatePhoneObject(); 1232 1233 // Only support automatic selection mode in CDMA. 1234 mCi.getNetworkSelectionMode(obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE)); 1235 1236 // For Non-RUIM phones, the subscription information is stored in 1237 // Non Volatile. Here when Non-Volatile is ready, we can poll the CDMA 1238 // subscription info. 1239 getSubscriptionInfoAndStartPollingThreads(); 1240 break; 1241 1242 case EVENT_POLL_STATE_CDMA_SUBSCRIPTION: // Handle RIL_CDMA_SUBSCRIPTION 1243 if (!mPhone.isPhoneTypeGsm()) { 1244 ar = (AsyncResult) msg.obj; 1245 1246 if (ar.exception == null) { 1247 String cdmaSubscription[] = (String[]) ar.result; 1248 if (cdmaSubscription != null && cdmaSubscription.length >= 5) { 1249 mMdn = cdmaSubscription[0]; 1250 parseSidNid(cdmaSubscription[1], cdmaSubscription[2]); 1251 1252 mMin = cdmaSubscription[3]; 1253 mPrlVersion = cdmaSubscription[4]; 1254 if (DBG) log("GET_CDMA_SUBSCRIPTION: MDN=" + mMdn); 1255 1256 mIsMinInfoReady = true; 1257 1258 updateOtaspState(); 1259 // Notify apps subscription info is ready 1260 notifyCdmaSubscriptionInfoReady(); 1261 1262 if (!mIsSubscriptionFromRuim && mIccRecords != null) { 1263 if (DBG) { 1264 log("GET_CDMA_SUBSCRIPTION set imsi in mIccRecords"); 1265 } 1266 mIccRecords.setImsi(getImsi()); 1267 } else { 1268 if (DBG) { 1269 log("GET_CDMA_SUBSCRIPTION either mIccRecords is null or NV " + 1270 "type device - not setting Imsi in mIccRecords"); 1271 } 1272 } 1273 } else { 1274 if (DBG) { 1275 log("GET_CDMA_SUBSCRIPTION: error parsing cdmaSubscription " + 1276 "params num=" + cdmaSubscription.length); 1277 } 1278 } 1279 } 1280 } 1281 break; 1282 1283 case EVENT_RUIM_RECORDS_LOADED: 1284 if (!mPhone.isPhoneTypeGsm()) { 1285 log("EVENT_RUIM_RECORDS_LOADED: what=" + msg.what); 1286 updatePhoneObject(); 1287 if (mPhone.isPhoneTypeCdma()) { 1288 updateSpnDisplay(); 1289 } else { 1290 RuimRecords ruim = (RuimRecords) mIccRecords; 1291 if (ruim != null) { 1292 if (ruim.isProvisioned()) { 1293 mMdn = ruim.getMdn(); 1294 mMin = ruim.getMin(); 1295 parseSidNid(ruim.getSid(), ruim.getNid()); 1296 mPrlVersion = ruim.getPrlVersion(); 1297 mIsMinInfoReady = true; 1298 } 1299 updateOtaspState(); 1300 // Notify apps subscription info is ready 1301 notifyCdmaSubscriptionInfoReady(); 1302 } 1303 // SID/NID/PRL is loaded. Poll service state 1304 // again to update to the roaming state with 1305 // the latest variables. 1306 pollState(); 1307 } 1308 } 1309 break; 1310 1311 case EVENT_ERI_FILE_LOADED: 1312 // Repoll the state once the ERI file has been loaded. 1313 if (DBG) log("ERI file has been loaded, repolling."); 1314 pollState(); 1315 break; 1316 1317 case EVENT_OTA_PROVISION_STATUS_CHANGE: 1318 ar = (AsyncResult)msg.obj; 1319 if (ar.exception == null) { 1320 ints = (int[]) ar.result; 1321 int otaStatus = ints[0]; 1322 if (otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED 1323 || otaStatus == Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED) { 1324 if (DBG) log("EVENT_OTA_PROVISION_STATUS_CHANGE: Complete, Reload MDN"); 1325 mCi.getCDMASubscription( obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION)); 1326 } 1327 } 1328 break; 1329 1330 case EVENT_CDMA_PRL_VERSION_CHANGED: 1331 ar = (AsyncResult)msg.obj; 1332 if (ar.exception == null) { 1333 ints = (int[]) ar.result; 1334 mPrlVersion = Integer.toString(ints[0]); 1335 } 1336 break; 1337 1338 default: 1339 log("Unhandled message with number: " + msg.what); 1340 break; 1341 } 1342 } 1343 1344 protected boolean isSidsAllZeros() { 1345 if (mHomeSystemId != null) { 1346 for (int i=0; i < mHomeSystemId.length; i++) { 1347 if (mHomeSystemId[i] != 0) { 1348 return false; 1349 } 1350 } 1351 } 1352 return true; 1353 } 1354 1355 /** 1356 * Check whether a specified system ID that matches one of the home system IDs. 1357 */ 1358 private boolean isHomeSid(int sid) { 1359 if (mHomeSystemId != null) { 1360 for (int i=0; i < mHomeSystemId.length; i++) { 1361 if (sid == mHomeSystemId[i]) { 1362 return true; 1363 } 1364 } 1365 } 1366 return false; 1367 } 1368 1369 public String getMdnNumber() { 1370 return mMdn; 1371 } 1372 1373 public String getCdmaMin() { 1374 return mMin; 1375 } 1376 1377 /** Returns null if NV is not yet ready */ 1378 public String getPrlVersion() { 1379 return mPrlVersion; 1380 } 1381 1382 /** 1383 * Returns IMSI as MCC + MNC + MIN 1384 */ 1385 public String getImsi() { 1386 // TODO: When RUIM is enabled, IMSI will come from RUIM not build-time props. 1387 String operatorNumeric = ((TelephonyManager) mPhone.getContext(). 1388 getSystemService(Context.TELEPHONY_SERVICE)). 1389 getSimOperatorNumericForPhone(mPhone.getPhoneId()); 1390 1391 if (!TextUtils.isEmpty(operatorNumeric) && getCdmaMin() != null) { 1392 return (operatorNumeric + getCdmaMin()); 1393 } else { 1394 return null; 1395 } 1396 } 1397 1398 /** 1399 * Check if subscription data has been assigned to mMin 1400 * 1401 * return true if MIN info is ready; false otherwise. 1402 */ 1403 public boolean isMinInfoReady() { 1404 return mIsMinInfoReady; 1405 } 1406 1407 /** 1408 * Returns OTASP_UNKNOWN, OTASP_UNINITIALIZED, OTASP_NEEDED or OTASP_NOT_NEEDED 1409 */ 1410 public int getOtasp() { 1411 int provisioningState; 1412 // if sim is not loaded, return otasp uninitialized 1413 if(!mPhone.getIccRecordsLoaded()) { 1414 if(DBG) log("getOtasp: otasp uninitialized due to sim not loaded"); 1415 return OTASP_UNINITIALIZED; 1416 } 1417 // if voice tech is Gsm, return otasp not needed 1418 if(mPhone.isPhoneTypeGsm()) { 1419 if(DBG) log("getOtasp: otasp not needed for GSM"); 1420 return OTASP_NOT_NEEDED; 1421 } 1422 // for ruim, min is null means require otasp. 1423 if (mIsSubscriptionFromRuim && mMin == null) { 1424 return OTASP_NEEDED; 1425 } 1426 if (mMin == null || (mMin.length() < 6)) { 1427 if (DBG) log("getOtasp: bad mMin='" + mMin + "'"); 1428 provisioningState = OTASP_UNKNOWN; 1429 } else { 1430 if ((mMin.equals(UNACTIVATED_MIN_VALUE) 1431 || mMin.substring(0,6).equals(UNACTIVATED_MIN2_VALUE)) 1432 || SystemProperties.getBoolean("test_cdma_setup", false)) { 1433 provisioningState = OTASP_NEEDED; 1434 } else { 1435 provisioningState = OTASP_NOT_NEEDED; 1436 } 1437 } 1438 if (DBG) log("getOtasp: state=" + provisioningState); 1439 return provisioningState; 1440 } 1441 1442 protected void parseSidNid (String sidStr, String nidStr) { 1443 if (sidStr != null) { 1444 String[] sid = sidStr.split(","); 1445 mHomeSystemId = new int[sid.length]; 1446 for (int i = 0; i < sid.length; i++) { 1447 try { 1448 mHomeSystemId[i] = Integer.parseInt(sid[i]); 1449 } catch (NumberFormatException ex) { 1450 loge("error parsing system id: " + ex); 1451 } 1452 } 1453 } 1454 if (DBG) log("CDMA_SUBSCRIPTION: SID=" + sidStr); 1455 1456 if (nidStr != null) { 1457 String[] nid = nidStr.split(","); 1458 mHomeNetworkId = new int[nid.length]; 1459 for (int i = 0; i < nid.length; i++) { 1460 try { 1461 mHomeNetworkId[i] = Integer.parseInt(nid[i]); 1462 } catch (NumberFormatException ex) { 1463 loge("CDMA_SUBSCRIPTION: error parsing network id: " + ex); 1464 } 1465 } 1466 } 1467 if (DBG) log("CDMA_SUBSCRIPTION: NID=" + nidStr); 1468 } 1469 1470 protected void updateOtaspState() { 1471 int otaspMode = getOtasp(); 1472 int oldOtaspMode = mCurrentOtaspMode; 1473 mCurrentOtaspMode = otaspMode; 1474 1475 if (oldOtaspMode != mCurrentOtaspMode) { 1476 if (DBG) { 1477 log("updateOtaspState: call notifyOtaspChanged old otaspMode=" + 1478 oldOtaspMode + " new otaspMode=" + mCurrentOtaspMode); 1479 } 1480 mPhone.notifyOtaspChanged(mCurrentOtaspMode); 1481 } 1482 } 1483 1484 protected Phone getPhone() { 1485 return mPhone; 1486 } 1487 1488 protected void handlePollStateResult(int what, AsyncResult ar) { 1489 // Ignore stale requests from last poll 1490 if (ar.userObj != mPollingContext) return; 1491 1492 if (ar.exception != null) { 1493 CommandException.Error err=null; 1494 1495 if (ar.exception instanceof CommandException) { 1496 err = ((CommandException)(ar.exception)).getCommandError(); 1497 } 1498 1499 if (err == CommandException.Error.RADIO_NOT_AVAILABLE) { 1500 // Radio has crashed or turned off 1501 cancelPollState(); 1502 return; 1503 } 1504 1505 if (err != CommandException.Error.OP_NOT_ALLOWED_BEFORE_REG_NW) { 1506 loge("RIL implementation has returned an error where it must succeed" + 1507 ar.exception); 1508 } 1509 } else try { 1510 handlePollStateResultMessage(what, ar); 1511 } catch (RuntimeException ex) { 1512 loge("Exception while polling service state. Probably malformed RIL response." + ex); 1513 } 1514 1515 mPollingContext[0]--; 1516 1517 if (mPollingContext[0] == 0) { 1518 if (mPhone.isPhoneTypeGsm()) { 1519 updateRoamingState(); 1520 mNewSS.setEmergencyOnly(mEmergencyOnly); 1521 } else { 1522 boolean namMatch = false; 1523 if (!isSidsAllZeros() && isHomeSid(mNewSS.getSystemId())) { 1524 namMatch = true; 1525 } 1526 1527 // Setting SS Roaming (general) 1528 if (mIsSubscriptionFromRuim) { 1529 mNewSS.setVoiceRoaming(isRoamingBetweenOperators(mNewSS.getVoiceRoaming(), mNewSS)); 1530 } 1531 // For CDMA, voice and data should have the same roaming status 1532 final boolean isVoiceInService = 1533 (mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE); 1534 final int dataRegType = mNewSS.getRilDataRadioTechnology(); 1535 if (isVoiceInService && ServiceState.isCdma(dataRegType)) { 1536 mNewSS.setDataRoaming(mNewSS.getVoiceRoaming()); 1537 } 1538 1539 // Setting SS CdmaRoamingIndicator and CdmaDefaultRoamingIndicator 1540 mNewSS.setCdmaDefaultRoamingIndicator(mDefaultRoamingIndicator); 1541 mNewSS.setCdmaRoamingIndicator(mRoamingIndicator); 1542 boolean isPrlLoaded = true; 1543 if (TextUtils.isEmpty(mPrlVersion)) { 1544 isPrlLoaded = false; 1545 } 1546 if (!isPrlLoaded || (mNewSS.getRilVoiceRadioTechnology() 1547 == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)) { 1548 log("Turn off roaming indicator if !isPrlLoaded or voice RAT is unknown"); 1549 mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF); 1550 } else if (!isSidsAllZeros()) { 1551 if (!namMatch && !mIsInPrl) { 1552 // Use default 1553 mNewSS.setCdmaRoamingIndicator(mDefaultRoamingIndicator); 1554 } else if (namMatch && !mIsInPrl) { 1555 // TODO this will be removed when we handle roaming on LTE on CDMA+LTE phones 1556 if (ServiceState.isLte(mNewSS.getRilVoiceRadioTechnology())) { 1557 log("Turn off roaming indicator as voice is LTE"); 1558 mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF); 1559 } else { 1560 mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_FLASH); 1561 } 1562 } else if (!namMatch && mIsInPrl) { 1563 // Use the one from PRL/ERI 1564 mNewSS.setCdmaRoamingIndicator(mRoamingIndicator); 1565 } else { 1566 // It means namMatch && mIsInPrl 1567 if ((mRoamingIndicator <= 2)) { 1568 mNewSS.setCdmaRoamingIndicator(EriInfo.ROAMING_INDICATOR_OFF); 1569 } else { 1570 // Use the one from PRL/ERI 1571 mNewSS.setCdmaRoamingIndicator(mRoamingIndicator); 1572 } 1573 } 1574 } 1575 1576 int roamingIndicator = mNewSS.getCdmaRoamingIndicator(); 1577 mNewSS.setCdmaEriIconIndex(mPhone.mEriManager.getCdmaEriIconIndex(roamingIndicator, 1578 mDefaultRoamingIndicator)); 1579 mNewSS.setCdmaEriIconMode(mPhone.mEriManager.getCdmaEriIconMode(roamingIndicator, 1580 mDefaultRoamingIndicator)); 1581 1582 // NOTE: Some operator may require overriding mCdmaRoaming 1583 // (set by the modem), depending on the mRoamingIndicator. 1584 1585 if (DBG) { 1586 log("Set CDMA Roaming Indicator to: " + mNewSS.getCdmaRoamingIndicator() 1587 + ". voiceRoaming = " + mNewSS.getVoiceRoaming() 1588 + ". dataRoaming = " + mNewSS.getDataRoaming() 1589 + ", isPrlLoaded = " + isPrlLoaded 1590 + ". namMatch = " + namMatch + " , mIsInPrl = " + mIsInPrl 1591 + ", mRoamingIndicator = " + mRoamingIndicator 1592 + ", mDefaultRoamingIndicator= " + mDefaultRoamingIndicator); 1593 } 1594 } 1595 pollStateDone(); 1596 } 1597 1598 } 1599 1600 /** 1601 * Set roaming state when cdmaRoaming is true and ons is different from spn 1602 * @param cdmaRoaming TS 27.007 7.2 CREG registered roaming 1603 * @param s ServiceState hold current ons 1604 * @return true for roaming state set 1605 */ 1606 private boolean isRoamingBetweenOperators(boolean cdmaRoaming, ServiceState s) { 1607 return cdmaRoaming && !isSameOperatorNameFromSimAndSS(s); 1608 } 1609 1610 void handlePollStateResultMessage(int what, AsyncResult ar) { 1611 int ints[]; 1612 String states[]; 1613 switch (what) { 1614 case EVENT_POLL_STATE_REGISTRATION: { 1615 if (mPhone.isPhoneTypeGsm()) { 1616 states = (String[]) ar.result; 1617 int lac = -1; 1618 int cid = -1; 1619 int type = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; 1620 int regState = ServiceState.RIL_REG_STATE_UNKNOWN; 1621 int reasonRegStateDenied = -1; 1622 int psc = -1; 1623 if (states.length > 0) { 1624 try { 1625 regState = Integer.parseInt(states[0]); 1626 if (states.length >= 3) { 1627 if (states[1] != null && states[1].length() > 0) { 1628 lac = Integer.parseInt(states[1], 16); 1629 } 1630 if (states[2] != null && states[2].length() > 0) { 1631 cid = Integer.parseInt(states[2], 16); 1632 } 1633 1634 // states[3] (if present) is the current radio technology 1635 if (states.length >= 4 && states[3] != null) { 1636 type = Integer.parseInt(states[3]); 1637 } 1638 } 1639 if (states.length > 14) { 1640 if (states[14] != null && states[14].length() > 0) { 1641 psc = Integer.parseInt(states[14], 16); 1642 } 1643 } 1644 } catch (NumberFormatException ex) { 1645 loge("error parsing RegistrationState: " + ex); 1646 } 1647 } 1648 1649 mGsmRoaming = regCodeIsRoaming(regState); 1650 mNewSS.setVoiceRegState(regCodeToServiceState(regState)); 1651 mNewSS.setRilVoiceRadioTechnology(type); 1652 1653 boolean isVoiceCapable = mPhone.getContext().getResources() 1654 .getBoolean(com.android.internal.R.bool.config_voice_capable); 1655 if ((regState == ServiceState.RIL_REG_STATE_DENIED_EMERGENCY_CALL_ENABLED 1656 || regState == ServiceState.RIL_REG_STATE_NOT_REG_EMERGENCY_CALL_ENABLED 1657 || regState == ServiceState.RIL_REG_STATE_SEARCHING_EMERGENCY_CALL_ENABLED 1658 || regState == ServiceState.RIL_REG_STATE_UNKNOWN_EMERGENCY_CALL_ENABLED) 1659 && isVoiceCapable) { 1660 mEmergencyOnly = true; 1661 } else { 1662 mEmergencyOnly = false; 1663 } 1664 1665 // LAC and CID are -1 if not avail 1666 ((GsmCellLocation)mNewCellLoc).setLacAndCid(lac, cid); 1667 ((GsmCellLocation)mNewCellLoc).setPsc(psc); 1668 } else { 1669 states = (String[])ar.result; 1670 1671 int registrationState = 4; //[0] registrationState 1672 int radioTechnology = -1; //[3] radioTechnology 1673 int baseStationId = -1; //[4] baseStationId 1674 //[5] baseStationLatitude 1675 int baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG; 1676 //[6] baseStationLongitude 1677 int baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG; 1678 int cssIndicator = 0; //[7] init with 0, because it is treated as a boolean 1679 int systemId = 0; //[8] systemId 1680 int networkId = 0; //[9] networkId 1681 int roamingIndicator = -1; //[10] Roaming indicator 1682 int systemIsInPrl = 0; //[11] Indicates if current system is in PRL 1683 int defaultRoamingIndicator = 0; //[12] Is default roaming indicator from PRL 1684 int reasonForDenial = 0; //[13] Denial reason if registrationState = 3 1685 1686 if (states.length >= 14) { 1687 try { 1688 if (states[0] != null) { 1689 registrationState = Integer.parseInt(states[0]); 1690 } 1691 if (states[3] != null) { 1692 radioTechnology = Integer.parseInt(states[3]); 1693 } 1694 if (states[4] != null) { 1695 baseStationId = Integer.parseInt(states[4]); 1696 } 1697 if (states[5] != null) { 1698 baseStationLatitude = Integer.parseInt(states[5]); 1699 } 1700 if (states[6] != null) { 1701 baseStationLongitude = Integer.parseInt(states[6]); 1702 } 1703 // Some carriers only return lat-lngs of 0,0 1704 if (baseStationLatitude == 0 && baseStationLongitude == 0) { 1705 baseStationLatitude = CdmaCellLocation.INVALID_LAT_LONG; 1706 baseStationLongitude = CdmaCellLocation.INVALID_LAT_LONG; 1707 } 1708 if (states[7] != null) { 1709 cssIndicator = Integer.parseInt(states[7]); 1710 } 1711 if (states[8] != null) { 1712 systemId = Integer.parseInt(states[8]); 1713 } 1714 if (states[9] != null) { 1715 networkId = Integer.parseInt(states[9]); 1716 } 1717 if (states[10] != null) { 1718 roamingIndicator = Integer.parseInt(states[10]); 1719 } 1720 if (states[11] != null) { 1721 systemIsInPrl = Integer.parseInt(states[11]); 1722 } 1723 if (states[12] != null) { 1724 defaultRoamingIndicator = Integer.parseInt(states[12]); 1725 } 1726 if (states[13] != null) { 1727 reasonForDenial = Integer.parseInt(states[13]); 1728 } 1729 } catch (NumberFormatException ex) { 1730 loge("EVENT_POLL_STATE_REGISTRATION_CDMA: error parsing: " + ex); 1731 } 1732 } else { 1733 throw new RuntimeException("Warning! Wrong number of parameters returned from " 1734 + "RIL_REQUEST_REGISTRATION_STATE: expected 14 or more " 1735 + "strings and got " + states.length + " strings"); 1736 } 1737 1738 mRegistrationState = registrationState; 1739 // When registration state is roaming and TSB58 1740 // roaming indicator is not in the carrier-specified 1741 // list of ERIs for home system, mCdmaRoaming is true. 1742 boolean cdmaRoaming = 1743 regCodeIsRoaming(registrationState) && !isRoamIndForHomeSystem(states[10]); 1744 mNewSS.setVoiceRoaming(cdmaRoaming); 1745 mNewSS.setVoiceRegState(regCodeToServiceState(registrationState)); 1746 1747 mNewSS.setRilVoiceRadioTechnology(radioTechnology); 1748 1749 mNewSS.setCssIndicator(cssIndicator); 1750 mNewSS.setSystemAndNetworkId(systemId, networkId); 1751 mRoamingIndicator = roamingIndicator; 1752 mIsInPrl = (systemIsInPrl == 0) ? false : true; 1753 mDefaultRoamingIndicator = defaultRoamingIndicator; 1754 1755 1756 // Values are -1 if not available. 1757 ((CdmaCellLocation)mNewCellLoc).setCellLocationData(baseStationId, 1758 baseStationLatitude, baseStationLongitude, systemId, networkId); 1759 1760 if (reasonForDenial == 0) { 1761 mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_GEN; 1762 } else if (reasonForDenial == 1) { 1763 mRegistrationDeniedReason = ServiceStateTracker.REGISTRATION_DENIED_AUTH; 1764 } else { 1765 mRegistrationDeniedReason = ""; 1766 } 1767 1768 if (mRegistrationState == 3) { 1769 if (DBG) log("Registration denied, " + mRegistrationDeniedReason); 1770 } 1771 } 1772 break; 1773 } 1774 1775 case EVENT_POLL_STATE_GPRS: { 1776 if (mPhone.isPhoneTypeGsm()) { 1777 states = (String[]) ar.result; 1778 1779 int type = 0; 1780 int regState = ServiceState.RIL_REG_STATE_UNKNOWN; 1781 mNewReasonDataDenied = -1; 1782 mNewMaxDataCalls = 1; 1783 if (states.length > 0) { 1784 try { 1785 regState = Integer.parseInt(states[0]); 1786 1787 // states[3] (if present) is the current radio technology 1788 if (states.length >= 4 && states[3] != null) { 1789 type = Integer.parseInt(states[3]); 1790 } 1791 if ((states.length >= 5) && 1792 (regState == ServiceState.RIL_REG_STATE_DENIED)) { 1793 mNewReasonDataDenied = Integer.parseInt(states[4]); 1794 } 1795 if (states.length >= 6) { 1796 mNewMaxDataCalls = Integer.parseInt(states[5]); 1797 } 1798 } catch (NumberFormatException ex) { 1799 loge("error parsing GprsRegistrationState: " + ex); 1800 } 1801 } 1802 int dataRegState = regCodeToServiceState(regState); 1803 mNewSS.setDataRegState(dataRegState); 1804 mDataRoaming = regCodeIsRoaming(regState); 1805 mNewSS.setRilDataRadioTechnology(type); 1806 if (DBG) { 1807 log("handlPollStateResultMessage: GsmSST setDataRegState=" + dataRegState 1808 + " regState=" + regState 1809 + " dataRadioTechnology=" + type); 1810 } 1811 } else if (mPhone.isPhoneTypeCdma()) { 1812 states = (String[])ar.result; 1813 if (DBG) { 1814 log("handlePollStateResultMessage: EVENT_POLL_STATE_GPRS states.length=" + 1815 states.length + " states=" + states); 1816 } 1817 1818 int regState = ServiceState.RIL_REG_STATE_UNKNOWN; 1819 int dataRadioTechnology = 0; 1820 1821 if (states.length > 0) { 1822 try { 1823 regState = Integer.parseInt(states[0]); 1824 1825 // states[3] (if present) is the current radio technology 1826 if (states.length >= 4 && states[3] != null) { 1827 dataRadioTechnology = Integer.parseInt(states[3]); 1828 } 1829 } catch (NumberFormatException ex) { 1830 loge("handlePollStateResultMessage: error parsing GprsRegistrationState: " 1831 + ex); 1832 } 1833 } 1834 1835 int dataRegState = regCodeToServiceState(regState); 1836 mNewSS.setDataRegState(dataRegState); 1837 mNewSS.setRilDataRadioTechnology(dataRadioTechnology); 1838 mNewSS.setDataRoaming(regCodeIsRoaming(regState)); 1839 if (DBG) { 1840 log("handlPollStateResultMessage: cdma setDataRegState=" + dataRegState 1841 + " regState=" + regState 1842 + " dataRadioTechnology=" + dataRadioTechnology); 1843 } 1844 } else { 1845 states = (String[])ar.result; 1846 if (DBG) { 1847 log("handlePollStateResultMessage: EVENT_POLL_STATE_GPRS states.length=" + 1848 states.length + " states=" + states); 1849 } 1850 1851 int newDataRAT = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; 1852 int regState = -1; 1853 if (states.length > 0) { 1854 try { 1855 regState = Integer.parseInt(states[0]); 1856 1857 // states[3] (if present) is the current radio technology 1858 if (states.length >= 4 && states[3] != null) { 1859 newDataRAT = Integer.parseInt(states[3]); 1860 } 1861 } catch (NumberFormatException ex) { 1862 loge("handlePollStateResultMessage: error parsing GprsRegistrationState: " 1863 + ex); 1864 } 1865 } 1866 1867 // If the unsolicited signal strength comes just before data RAT family changes 1868 // (i.e. from UNKNOWN to LTE, CDMA to LTE, LTE to CDMA), the signal bar might 1869 // display the wrong information until the next unsolicited signal strength 1870 // information coming from the modem, which might take a long time to come or 1871 // even not come at all. In order to provide the best user experience, we 1872 // query the latest signal information so it will show up on the UI on time. 1873 int oldDataRAT = mSS.getRilDataRadioTechnology(); 1874 if ((oldDataRAT == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN && 1875 newDataRAT != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) || 1876 (ServiceState.isCdma(oldDataRAT) && ServiceState.isLte(newDataRAT)) || 1877 (ServiceState.isLte(oldDataRAT) && ServiceState.isCdma(newDataRAT))) { 1878 mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH)); 1879 } 1880 1881 mNewSS.setRilDataRadioTechnology(newDataRAT); 1882 int dataRegState = regCodeToServiceState(regState); 1883 mNewSS.setDataRegState(dataRegState); 1884 // voice roaming state in done while handling EVENT_POLL_STATE_REGISTRATION_CDMA 1885 mNewSS.setDataRoaming(regCodeIsRoaming(regState)); 1886 if (DBG) { 1887 log("handlPollStateResultMessage: CdmaLteSST setDataRegState=" + dataRegState 1888 + " regState=" + regState 1889 + " dataRadioTechnology=" + newDataRAT); 1890 } 1891 } 1892 break; 1893 } 1894 1895 case EVENT_POLL_STATE_OPERATOR: { 1896 if (mPhone.isPhoneTypeGsm()) { 1897 String opNames[] = (String[]) ar.result; 1898 1899 if (opNames != null && opNames.length >= 3) { 1900 // FIXME: Giving brandOverride higher precedence, is this desired? 1901 String brandOverride = mUiccController.getUiccCard(getPhoneId()) != null ? 1902 mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() : null; 1903 if (brandOverride != null) { 1904 log("EVENT_POLL_STATE_OPERATOR: use brandOverride=" + brandOverride); 1905 mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]); 1906 } else { 1907 mNewSS.setOperatorName(opNames[0], opNames[1], opNames[2]); 1908 } 1909 } 1910 } else { 1911 String opNames[] = (String[])ar.result; 1912 1913 if (opNames != null && opNames.length >= 3) { 1914 // TODO: Do we care about overriding in this case. 1915 // If the NUMERIC field isn't valid use PROPERTY_CDMA_HOME_OPERATOR_NUMERIC 1916 if ((opNames[2] == null) || (opNames[2].length() < 5) 1917 || ("00000".equals(opNames[2]))) { 1918 opNames[2] = SystemProperties.get( 1919 GsmCdmaPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "00000"); 1920 if (DBG) { 1921 log("RIL_REQUEST_OPERATOR.response[2], the numeric, " + 1922 " is bad. Using SystemProperties '" + 1923 GsmCdmaPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC + 1924 "'= " + opNames[2]); 1925 } 1926 } 1927 1928 if (!mIsSubscriptionFromRuim) { 1929 // NV device (as opposed to CSIM) 1930 mNewSS.setOperatorName(opNames[0], opNames[1], opNames[2]); 1931 } else { 1932 String brandOverride = mUiccController.getUiccCard(getPhoneId()) != null ? 1933 mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() : null; 1934 if (brandOverride != null) { 1935 mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]); 1936 } else { 1937 mNewSS.setOperatorName(opNames[0], opNames[1], opNames[2]); 1938 } 1939 } 1940 } else { 1941 if (DBG) log("EVENT_POLL_STATE_OPERATOR_CDMA: error parsing opNames"); 1942 } 1943 } 1944 break; 1945 } 1946 1947 case EVENT_POLL_STATE_NETWORK_SELECTION_MODE: { 1948 ints = (int[])ar.result; 1949 mNewSS.setIsManualSelection(ints[0] == 1); 1950 if ((ints[0] == 1) && (!mPhone.isManualNetSelAllowed())) { 1951 /* 1952 * modem is currently in manual selection but manual 1953 * selection is not allowed in the current mode so 1954 * switch to automatic registration 1955 */ 1956 mPhone.setNetworkSelectionModeAutomatic (null); 1957 log(" Forcing Automatic Network Selection, " + 1958 "manual selection is not allowed"); 1959 } 1960 break; 1961 } 1962 1963 default: 1964 loge("handlePollStateResultMessage: Unexpected RIL response received: " + what); 1965 } 1966 } 1967 1968 /** 1969 * Determine whether a roaming indicator is in the carrier-specified list of ERIs for 1970 * home system 1971 * 1972 * @param roamInd roaming indicator in String 1973 * @return true if the roamInd is in the carrier-specified list of ERIs for home network 1974 */ 1975 private boolean isRoamIndForHomeSystem(String roamInd) { 1976 // retrieve the carrier-specified list of ERIs for home system 1977 String[] homeRoamIndicators = mPhone.getContext().getResources() 1978 .getStringArray(com.android.internal.R.array.config_cdma_home_system); 1979 1980 if (homeRoamIndicators != null) { 1981 // searches through the comma-separated list for a match, 1982 // return true if one is found. 1983 for (String homeRoamInd : homeRoamIndicators) { 1984 if (homeRoamInd.equals(roamInd)) { 1985 return true; 1986 } 1987 } 1988 // no matches found against the list! 1989 return false; 1990 } 1991 1992 // no system property found for the roaming indicators for home system 1993 return false; 1994 } 1995 1996 /** 1997 * Query the carrier configuration to determine if there any network overrides 1998 * for roaming or not roaming for the current service state. 1999 */ 2000 protected void updateRoamingState() { 2001 if (mPhone.isPhoneTypeGsm()) { 2002 /** 2003 * Since the roaming state of gsm service (from +CREG) and 2004 * data service (from +CGREG) could be different, the new SS 2005 * is set to roaming when either is true. 2006 * 2007 * There are exceptions for the above rule. 2008 * The new SS is not set as roaming while gsm service reports 2009 * roaming but indeed it is same operator. 2010 * And the operator is considered non roaming. 2011 * 2012 * The test for the operators is to handle special roaming 2013 * agreements and MVNO's. 2014 */ 2015 boolean roaming = (mGsmRoaming || mDataRoaming); 2016 if (mGsmRoaming && !isOperatorConsideredRoaming(mNewSS) && 2017 (isSameNamedOperators(mNewSS) || isOperatorConsideredNonRoaming(mNewSS))) { 2018 roaming = false; 2019 } 2020 2021 // Save the roaming state before carrier config possibly overrides it. 2022 mNewSS.setDataRoamingFromRegistration(roaming); 2023 2024 CarrierConfigManager configLoader = (CarrierConfigManager) 2025 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 2026 2027 if (configLoader != null) { 2028 try { 2029 PersistableBundle b = configLoader.getConfigForSubId(mPhone.getSubId()); 2030 2031 if (alwaysOnHomeNetwork(b)) { 2032 log("updateRoamingState: carrier config override always on home network"); 2033 roaming = false; 2034 } else if (isNonRoamingInGsmNetwork(b, mNewSS.getOperatorNumeric())) { 2035 log("updateRoamingState: carrier config override set non roaming:" 2036 + mNewSS.getOperatorNumeric()); 2037 roaming = false; 2038 } else if (isRoamingInGsmNetwork(b, mNewSS.getOperatorNumeric())) { 2039 log("updateRoamingState: carrier config override set roaming:" 2040 + mNewSS.getOperatorNumeric()); 2041 roaming = true; 2042 } 2043 } catch (Exception e) { 2044 loge("updateRoamingState: unable to access carrier config service"); 2045 } 2046 } else { 2047 log("updateRoamingState: no carrier config service available"); 2048 } 2049 2050 mNewSS.setVoiceRoaming(roaming); 2051 mNewSS.setDataRoaming(roaming); 2052 } else { 2053 // Save the roaming state before carrier config possibly overrides it. 2054 mNewSS.setDataRoamingFromRegistration(mNewSS.getDataRoaming()); 2055 2056 CarrierConfigManager configLoader = (CarrierConfigManager) 2057 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 2058 if (configLoader != null) { 2059 try { 2060 PersistableBundle b = configLoader.getConfigForSubId(mPhone.getSubId()); 2061 String systemId = Integer.toString(mNewSS.getSystemId()); 2062 2063 if (alwaysOnHomeNetwork(b)) { 2064 log("updateRoamingState: carrier config override always on home network"); 2065 setRoamingOff(); 2066 } else if (isNonRoamingInGsmNetwork(b, mNewSS.getOperatorNumeric()) 2067 || isNonRoamingInCdmaNetwork(b, systemId)) { 2068 log("updateRoamingState: carrier config override set non-roaming:" 2069 + mNewSS.getOperatorNumeric() + ", " + systemId); 2070 setRoamingOff(); 2071 } else if (isRoamingInGsmNetwork(b, mNewSS.getOperatorNumeric()) 2072 || isRoamingInCdmaNetwork(b, systemId)) { 2073 log("updateRoamingState: carrier config override set roaming:" 2074 + mNewSS.getOperatorNumeric() + ", " + systemId); 2075 setRoamingOn(); 2076 } 2077 } catch (Exception e) { 2078 loge("updateRoamingState: unable to access carrier config service"); 2079 } 2080 } else { 2081 log("updateRoamingState: no carrier config service available"); 2082 } 2083 2084 if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) { 2085 mNewSS.setVoiceRoaming(true); 2086 mNewSS.setDataRoaming(true); 2087 } 2088 } 2089 } 2090 2091 private void setRoamingOn() { 2092 mNewSS.setVoiceRoaming(true); 2093 mNewSS.setDataRoaming(true); 2094 mNewSS.setCdmaEriIconIndex(EriInfo.ROAMING_INDICATOR_ON); 2095 mNewSS.setCdmaEriIconMode(EriInfo.ROAMING_ICON_MODE_NORMAL); 2096 } 2097 2098 private void setRoamingOff() { 2099 mNewSS.setVoiceRoaming(false); 2100 mNewSS.setDataRoaming(false); 2101 mNewSS.setCdmaEriIconIndex(EriInfo.ROAMING_INDICATOR_OFF); 2102 } 2103 2104 protected void updateSpnDisplay() { 2105 updateOperatorNameFromEri(); 2106 2107 String wfcVoiceSpnFormat = null; 2108 String wfcDataSpnFormat = null; 2109 if (mPhone.getImsPhone() != null && mPhone.getImsPhone().isWifiCallingEnabled()) { 2110 // In Wi-Fi Calling mode show SPN+WiFi 2111 2112 String[] wfcSpnFormats = mPhone.getContext().getResources().getStringArray( 2113 com.android.internal.R.array.wfcSpnFormats); 2114 int voiceIdx = 0; 2115 int dataIdx = 0; 2116 CarrierConfigManager configLoader = (CarrierConfigManager) 2117 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 2118 if (configLoader != null) { 2119 try { 2120 PersistableBundle b = configLoader.getConfigForSubId(mPhone.getSubId()); 2121 if (b != null) { 2122 voiceIdx = b.getInt(CarrierConfigManager.KEY_WFC_SPN_FORMAT_IDX_INT); 2123 dataIdx = b.getInt( 2124 CarrierConfigManager.KEY_WFC_DATA_SPN_FORMAT_IDX_INT); 2125 } 2126 } catch (Exception e) { 2127 loge("updateSpnDisplay: carrier config error: " + e); 2128 } 2129 } 2130 2131 wfcVoiceSpnFormat = wfcSpnFormats[voiceIdx]; 2132 wfcDataSpnFormat = wfcSpnFormats[dataIdx]; 2133 } 2134 2135 if (mPhone.isPhoneTypeGsm()) { 2136 // The values of plmn/showPlmn change in different scenarios. 2137 // 1) No service but emergency call allowed -> expected 2138 // to show "Emergency call only" 2139 // EXTRA_SHOW_PLMN = true 2140 // EXTRA_PLMN = "Emergency call only" 2141 2142 // 2) No service at all --> expected to show "No service" 2143 // EXTRA_SHOW_PLMN = true 2144 // EXTRA_PLMN = "No service" 2145 2146 // 3) Normal operation in either home or roaming service 2147 // EXTRA_SHOW_PLMN = depending on IccRecords rule 2148 // EXTRA_PLMN = plmn 2149 2150 // 4) No service due to power off, aka airplane mode 2151 // EXTRA_SHOW_PLMN = false 2152 // EXTRA_PLMN = null 2153 2154 IccRecords iccRecords = mIccRecords; 2155 String plmn = null; 2156 boolean showPlmn = false; 2157 int rule = (iccRecords != null) ? iccRecords.getDisplayRule(mSS.getOperatorNumeric()) : 0; 2158 if (mSS.getVoiceRegState() == ServiceState.STATE_OUT_OF_SERVICE 2159 || mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY) { 2160 showPlmn = true; 2161 if (mEmergencyOnly) { 2162 // No service but emergency call allowed 2163 plmn = Resources.getSystem(). 2164 getText(com.android.internal.R.string.emergency_calls_only).toString(); 2165 } else { 2166 // No service at all 2167 plmn = Resources.getSystem(). 2168 getText(com.android.internal.R.string.lockscreen_carrier_default).toString(); 2169 } 2170 if (DBG) log("updateSpnDisplay: radio is on but out " + 2171 "of service, set plmn='" + plmn + "'"); 2172 } else if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 2173 // In either home or roaming service 2174 plmn = mSS.getOperatorAlphaLong(); 2175 showPlmn = !TextUtils.isEmpty(plmn) && 2176 ((rule & SIMRecords.SPN_RULE_SHOW_PLMN) 2177 == SIMRecords.SPN_RULE_SHOW_PLMN); 2178 } else { 2179 // Power off state, such as airplane mode, show plmn as "No service" 2180 showPlmn = true; 2181 plmn = Resources.getSystem(). 2182 getText(com.android.internal.R.string.lockscreen_carrier_default).toString(); 2183 if (DBG) log("updateSpnDisplay: radio is off w/ showPlmn=" 2184 + showPlmn + " plmn=" + plmn); 2185 } 2186 2187 // The value of spn/showSpn are same in different scenarios. 2188 // EXTRA_SHOW_SPN = depending on IccRecords rule and radio/IMS state 2189 // EXTRA_SPN = spn 2190 // EXTRA_DATA_SPN = dataSpn 2191 String spn = (iccRecords != null) ? iccRecords.getServiceProviderName() : ""; 2192 String dataSpn = spn; 2193 boolean showSpn = !TextUtils.isEmpty(spn) 2194 && ((rule & SIMRecords.SPN_RULE_SHOW_SPN) 2195 == SIMRecords.SPN_RULE_SHOW_SPN); 2196 2197 if (!TextUtils.isEmpty(spn) && !TextUtils.isEmpty(wfcVoiceSpnFormat) && 2198 !TextUtils.isEmpty(wfcDataSpnFormat)) { 2199 // In Wi-Fi Calling mode show SPN+WiFi 2200 2201 String originalSpn = spn.trim(); 2202 spn = String.format(wfcVoiceSpnFormat, originalSpn); 2203 dataSpn = String.format(wfcDataSpnFormat, originalSpn); 2204 showSpn = true; 2205 showPlmn = false; 2206 } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF 2207 || (showPlmn && TextUtils.equals(spn, plmn))) { 2208 // airplane mode or spn equals plmn, do not show spn 2209 spn = null; 2210 showSpn = false; 2211 } 2212 2213 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 2214 int[] subIds = SubscriptionManager.getSubId(mPhone.getPhoneId()); 2215 if (subIds != null && subIds.length > 0) { 2216 subId = subIds[0]; 2217 } 2218 2219 // Update SPN_STRINGS_UPDATED_ACTION IFF any value changes 2220 if (mSubId != subId || 2221 showPlmn != mCurShowPlmn 2222 || showSpn != mCurShowSpn 2223 || !TextUtils.equals(spn, mCurSpn) 2224 || !TextUtils.equals(dataSpn, mCurDataSpn) 2225 || !TextUtils.equals(plmn, mCurPlmn)) { 2226 if (DBG) { 2227 log(String.format("updateSpnDisplay: changed sending intent rule=" + rule + 2228 " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s' dataSpn='%s' " + 2229 "subId='%d'", showPlmn, plmn, showSpn, spn, dataSpn, subId)); 2230 } 2231 Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); 2232 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 2233 intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, showSpn); 2234 intent.putExtra(TelephonyIntents.EXTRA_SPN, spn); 2235 intent.putExtra(TelephonyIntents.EXTRA_DATA_SPN, dataSpn); 2236 intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn); 2237 intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn); 2238 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 2239 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); 2240 2241 if (!mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(), 2242 showPlmn, plmn, showSpn, spn)) { 2243 mSpnUpdatePending = true; 2244 } 2245 } 2246 2247 mSubId = subId; 2248 mCurShowSpn = showSpn; 2249 mCurShowPlmn = showPlmn; 2250 mCurSpn = spn; 2251 mCurDataSpn = dataSpn; 2252 mCurPlmn = plmn; 2253 } else { 2254 // mOperatorAlphaLong contains the ERI text 2255 String plmn = mSS.getOperatorAlphaLong(); 2256 boolean showPlmn = false; 2257 2258 showPlmn = plmn != null; 2259 2260 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 2261 int[] subIds = SubscriptionManager.getSubId(mPhone.getPhoneId()); 2262 if (subIds != null && subIds.length > 0) { 2263 subId = subIds[0]; 2264 } 2265 2266 if (!TextUtils.isEmpty(plmn) && !TextUtils.isEmpty(wfcVoiceSpnFormat)) { 2267 // In Wi-Fi Calling mode show SPN+WiFi 2268 2269 String originalPlmn = plmn.trim(); 2270 plmn = String.format(wfcVoiceSpnFormat, originalPlmn); 2271 } else if (mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) { 2272 // todo: temporary hack; should have a better fix. This is to avoid using operator 2273 // name from ServiceState (populated in resetServiceStateInIwlanMode()) until 2274 // wifi calling is actually enabled 2275 log("updateSpnDisplay: overwriting plmn from " + plmn + " to null as radio " + 2276 "state is off"); 2277 plmn = null; 2278 } 2279 2280 if (mSubId != subId || !TextUtils.equals(plmn, mCurPlmn)) { 2281 // Allow A blank plmn, "" to set showPlmn to true. Previously, we 2282 // would set showPlmn to true only if plmn was not empty, i.e. was not 2283 // null and not blank. But this would cause us to incorrectly display 2284 // "No Service". Now showPlmn is set to true for any non null string. 2285 if (DBG) { 2286 log(String.format("updateSpnDisplay: changed sending intent" + 2287 " showPlmn='%b' plmn='%s' subId='%d'", showPlmn, plmn, subId)); 2288 } 2289 Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); 2290 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 2291 intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, false); 2292 intent.putExtra(TelephonyIntents.EXTRA_SPN, ""); 2293 intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn); 2294 intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn); 2295 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId()); 2296 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); 2297 2298 if (!mSubscriptionController.setPlmnSpn(mPhone.getPhoneId(), 2299 showPlmn, plmn, false, "")) { 2300 mSpnUpdatePending = true; 2301 } 2302 } 2303 2304 mSubId = subId; 2305 mCurShowSpn = false; 2306 mCurShowPlmn = showPlmn; 2307 mCurSpn = ""; 2308 mCurPlmn = plmn; 2309 } 2310 } 2311 2312 protected void setPowerStateToDesired() { 2313 if (DBG) { 2314 log("mDeviceShuttingDown=" + mDeviceShuttingDown + 2315 ", mDesiredPowerState=" + mDesiredPowerState + 2316 ", getRadioState=" + mCi.getRadioState() + 2317 ", mPowerOffDelayNeed=" + mPowerOffDelayNeed + 2318 ", mAlarmSwitch=" + mAlarmSwitch + 2319 ", mRadioDisabledByCarrier=" + mRadioDisabledByCarrier); 2320 } 2321 2322 if (mPhone.isPhoneTypeGsm() && mAlarmSwitch) { 2323 if(DBG) log("mAlarmSwitch == true"); 2324 Context context = mPhone.getContext(); 2325 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 2326 am.cancel(mRadioOffIntent); 2327 mAlarmSwitch = false; 2328 } 2329 2330 // If we want it on and it's off, turn it on 2331 if (mDesiredPowerState && !mRadioDisabledByCarrier 2332 && mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) { 2333 mCi.setRadioPower(true, null); 2334 } else if ((!mDesiredPowerState || mRadioDisabledByCarrier) && mCi.getRadioState().isOn()) { 2335 // If it's on and available and we want it off gracefully 2336 if (mPhone.isPhoneTypeGsm() && mPowerOffDelayNeed) { 2337 if (mImsRegistrationOnOff && !mAlarmSwitch) { 2338 if(DBG) log("mImsRegistrationOnOff == true"); 2339 Context context = mPhone.getContext(); 2340 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 2341 2342 Intent intent = new Intent(ACTION_RADIO_OFF); 2343 mRadioOffIntent = PendingIntent.getBroadcast(context, 0, intent, 0); 2344 2345 mAlarmSwitch = true; 2346 if (DBG) log("Alarm setting"); 2347 am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 2348 SystemClock.elapsedRealtime() + 3000, mRadioOffIntent); 2349 } else { 2350 DcTracker dcTracker = mPhone.mDcTracker; 2351 powerOffRadioSafely(dcTracker); 2352 } 2353 } else { 2354 DcTracker dcTracker = mPhone.mDcTracker; 2355 powerOffRadioSafely(dcTracker); 2356 } 2357 } else if (mDeviceShuttingDown && mCi.getRadioState().isAvailable()) { 2358 mCi.requestShutdown(null); 2359 } 2360 } 2361 2362 protected void onUpdateIccAvailability() { 2363 if (mUiccController == null ) { 2364 return; 2365 } 2366 2367 UiccCardApplication newUiccApplication = getUiccCardApplication(); 2368 2369 if (mUiccApplcation != newUiccApplication) { 2370 if (mUiccApplcation != null) { 2371 log("Removing stale icc objects."); 2372 mUiccApplcation.unregisterForReady(this); 2373 if (mIccRecords != null) { 2374 mIccRecords.unregisterForRecordsLoaded(this); 2375 } 2376 mIccRecords = null; 2377 mUiccApplcation = null; 2378 } 2379 if (newUiccApplication != null) { 2380 log("New card found"); 2381 mUiccApplcation = newUiccApplication; 2382 mIccRecords = mUiccApplcation.getIccRecords(); 2383 if (mPhone.isPhoneTypeGsm()) { 2384 mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null); 2385 if (mIccRecords != null) { 2386 mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); 2387 } 2388 } else if (mIsSubscriptionFromRuim) { 2389 mUiccApplcation.registerForReady(this, EVENT_RUIM_READY, null); 2390 if (mIccRecords != null) { 2391 mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null); 2392 } 2393 } 2394 } 2395 } 2396 } 2397 2398 private void logRoamingChange() { 2399 mRoamingLog.log(mSS.toString()); 2400 } 2401 2402 private void logAttachChange() { 2403 mAttachLog.log(mSS.toString()); 2404 } 2405 2406 private void logPhoneTypeChange() { 2407 mPhoneTypeLog.log(Integer.toString(mPhone.getPhoneType())); 2408 } 2409 2410 private void logRatChange() { 2411 mRatLog.log(mSS.toString()); 2412 } 2413 2414 protected void log(String s) { 2415 Rlog.d(LOG_TAG, s); 2416 } 2417 2418 protected void loge(String s) { 2419 Rlog.e(LOG_TAG, s); 2420 } 2421 2422 /** 2423 * @return The current GPRS state. IN_SERVICE is the same as "attached" 2424 * and OUT_OF_SERVICE is the same as detached. 2425 */ 2426 public int getCurrentDataConnectionState() { 2427 return mSS.getDataRegState(); 2428 } 2429 2430 /** 2431 * @return true if phone is camping on a technology (eg UMTS) 2432 * that could support voice and data simultaneously. 2433 */ 2434 public boolean isConcurrentVoiceAndDataAllowed() { 2435 if (mPhone.isPhoneTypeGsm()) { 2436 return (mSS.getRilVoiceRadioTechnology() >= ServiceState.RIL_RADIO_TECHNOLOGY_UMTS); 2437 } else if (mPhone.isPhoneTypeCdma()) { 2438 // Note: it needs to be confirmed which CDMA network types 2439 // can support voice and data calls concurrently. 2440 // For the time-being, the return value will be false. 2441 return false; 2442 } else { 2443 // Using the Conncurrent Service Supported flag for CdmaLte devices. 2444 return mSS.getCssIndicator() == 1; 2445 } 2446 } 2447 2448 public void setImsRegistrationState(boolean registered) { 2449 log("ImsRegistrationState - registered : " + registered); 2450 2451 if (mImsRegistrationOnOff && !registered) { 2452 if (mAlarmSwitch) { 2453 mImsRegistrationOnOff = registered; 2454 2455 Context context = mPhone.getContext(); 2456 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 2457 am.cancel(mRadioOffIntent); 2458 mAlarmSwitch = false; 2459 2460 sendMessage(obtainMessage(EVENT_CHANGE_IMS_STATE)); 2461 return; 2462 } 2463 } 2464 mImsRegistrationOnOff = registered; 2465 } 2466 2467 public void onImsCapabilityChanged() { 2468 sendMessage(obtainMessage(EVENT_IMS_CAPABILITY_CHANGED)); 2469 } 2470 2471 public boolean isRadioOn() { 2472 return mCi.getRadioState() == CommandsInterface.RadioState.RADIO_ON; 2473 } 2474 2475 /** 2476 * A complete "service state" from our perspective is 2477 * composed of a handful of separate requests to the radio. 2478 * 2479 * We make all of these requests at once, but then abandon them 2480 * and start over again if the radio notifies us that some 2481 * event has changed 2482 */ 2483 public void pollState() { 2484 pollState(false); 2485 } 2486 /** 2487 * We insist on polling even if the radio says its off. 2488 * Used when we get a network changed notification 2489 * but the radio is off - part of iwlan hack 2490 */ 2491 private void modemTriggeredPollState() { 2492 pollState(true); 2493 } 2494 2495 public void pollState(boolean modemTriggered) { 2496 mPollingContext = new int[1]; 2497 mPollingContext[0] = 0; 2498 2499 switch (mCi.getRadioState()) { 2500 case RADIO_UNAVAILABLE: 2501 mNewSS.setStateOutOfService(); 2502 mNewCellLoc.setStateInvalid(); 2503 setSignalStrengthDefaultValues(); 2504 mGotCountryCode = false; 2505 mNitzUpdatedTime = false; 2506 pollStateDone(); 2507 break; 2508 2509 case RADIO_OFF: 2510 mNewSS.setStateOff(); 2511 mNewCellLoc.setStateInvalid(); 2512 setSignalStrengthDefaultValues(); 2513 mGotCountryCode = false; 2514 mNitzUpdatedTime = false; 2515 // don't poll for state when the radio is off 2516 // EXCEPT, if the poll was modemTrigged (they sent us new radio data) 2517 // or we're on IWLAN 2518 if (!modemTriggered && ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 2519 != mSS.getRilDataRadioTechnology()) { 2520 pollStateDone(); 2521 break; 2522 } 2523 2524 default: 2525 // Issue all poll-related commands at once then count down the responses, which 2526 // are allowed to arrive out-of-order 2527 mPollingContext[0]++; 2528 mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR, mPollingContext)); 2529 2530 mPollingContext[0]++; 2531 mCi.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS, mPollingContext)); 2532 2533 mPollingContext[0]++; 2534 mCi.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION, 2535 mPollingContext)); 2536 2537 if (mPhone.isPhoneTypeGsm()) { 2538 mPollingContext[0]++; 2539 mCi.getNetworkSelectionMode(obtainMessage( 2540 EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext)); 2541 } 2542 break; 2543 } 2544 } 2545 2546 //todo: try to merge pollstate functions 2547 private void pollStateDone() { 2548 if (mPhone.isPhoneTypeGsm()) { 2549 pollStateDoneGsm(); 2550 } else if (mPhone.isPhoneTypeCdma()) { 2551 pollStateDoneCdma(); 2552 } else { 2553 pollStateDoneCdmaLte(); 2554 } 2555 } 2556 2557 private void pollStateDoneGsm() { 2558 if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) { 2559 mNewSS.setVoiceRoaming(true); 2560 mNewSS.setDataRoaming(true); 2561 } 2562 useDataRegStateForDataOnlyDevices(); 2563 resetServiceStateInIwlanMode(); 2564 2565 if (DBG) { 2566 log("Poll ServiceState done: " + 2567 " oldSS=[" + mSS + "] newSS=[" + mNewSS + "]" + 2568 " oldMaxDataCalls=" + mMaxDataCalls + 2569 " mNewMaxDataCalls=" + mNewMaxDataCalls + 2570 " oldReasonDataDenied=" + mReasonDataDenied + 2571 " mNewReasonDataDenied=" + mNewReasonDataDenied); 2572 } 2573 2574 boolean hasRegistered = 2575 mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE 2576 && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE; 2577 2578 boolean hasDeregistered = 2579 mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE 2580 && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE; 2581 2582 boolean hasGprsAttached = 2583 mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE 2584 && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE; 2585 2586 boolean hasGprsDetached = 2587 mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE 2588 && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE; 2589 2590 boolean hasDataRegStateChanged = 2591 mSS.getDataRegState() != mNewSS.getDataRegState(); 2592 2593 boolean hasVoiceRegStateChanged = 2594 mSS.getVoiceRegState() != mNewSS.getVoiceRegState(); 2595 2596 boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc); 2597 2598 // ratchet the new tech up through it's rat family but don't drop back down 2599 // until cell change 2600 if (hasLocationChanged == false) { 2601 mRatRatcheter.ratchetRat(mSS, mNewSS); 2602 } 2603 2604 boolean hasRilVoiceRadioTechnologyChanged = 2605 mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology(); 2606 2607 boolean hasRilDataRadioTechnologyChanged = 2608 mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology(); 2609 2610 boolean hasChanged = !mNewSS.equals(mSS); 2611 2612 boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming(); 2613 2614 boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming(); 2615 2616 boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming(); 2617 2618 boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming(); 2619 2620 TelephonyManager tm = 2621 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE); 2622 2623 // Add an event log when connection state changes 2624 if (hasVoiceRegStateChanged || hasDataRegStateChanged) { 2625 EventLog.writeEvent(EventLogTags.GSM_SERVICE_STATE_CHANGE, 2626 mSS.getVoiceRegState(), mSS.getDataRegState(), 2627 mNewSS.getVoiceRegState(), mNewSS.getDataRegState()); 2628 } 2629 2630 // Add an event log when network type switched 2631 // TODO: we may add filtering to reduce the event logged, 2632 // i.e. check preferred network setting, only switch to 2G, etc 2633 if (hasRilVoiceRadioTechnologyChanged) { 2634 int cid = -1; 2635 GsmCellLocation loc = (GsmCellLocation)mNewCellLoc; 2636 if (loc != null) cid = loc.getCid(); 2637 // NOTE: this code was previously located after mSS and mNewSS are swapped, so 2638 // existing logs were incorrectly using the new state for "network_from" 2639 // and STATE_OUT_OF_SERVICE for "network_to". To avoid confusion, use a new log tag 2640 // to record the correct states. 2641 EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED_NEW, cid, 2642 mSS.getRilVoiceRadioTechnology(), 2643 mNewSS.getRilVoiceRadioTechnology()); 2644 if (DBG) { 2645 log("RAT switched " 2646 + ServiceState.rilRadioTechnologyToString(mSS.getRilVoiceRadioTechnology()) 2647 + " -> " 2648 + ServiceState.rilRadioTechnologyToString( 2649 mNewSS.getRilVoiceRadioTechnology()) + " at cell " + cid); 2650 } 2651 } 2652 2653 // swap mSS and mNewSS to put new state in mSS 2654 ServiceState tss = mSS; 2655 mSS = mNewSS; 2656 mNewSS = tss; 2657 // clean slate for next time 2658 mNewSS.setStateOutOfService(); 2659 2660 // swap mCellLoc and mNewCellLoc to put new state in mCellLoc 2661 GsmCellLocation tcl = (GsmCellLocation)mCellLoc; 2662 mCellLoc = mNewCellLoc; 2663 mNewCellLoc = tcl; 2664 2665 mReasonDataDenied = mNewReasonDataDenied; 2666 mMaxDataCalls = mNewMaxDataCalls; 2667 2668 if (hasRilVoiceRadioTechnologyChanged) { 2669 updatePhoneObject(); 2670 } 2671 2672 if (hasRilDataRadioTechnologyChanged) { 2673 tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilDataRadioTechnology()); 2674 2675 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 2676 == mSS.getRilDataRadioTechnology()) { 2677 log("pollStateDone: IWLAN enabled"); 2678 } 2679 } 2680 2681 if (hasRegistered) { 2682 mNetworkAttachedRegistrants.notifyRegistrants(); 2683 2684 if (DBG) { 2685 log("pollStateDone: registering current mNitzUpdatedTime=" + 2686 mNitzUpdatedTime + " changing to false"); 2687 } 2688 mNitzUpdatedTime = false; 2689 } 2690 2691 if (hasChanged) { 2692 String operatorNumeric; 2693 2694 updateSpnDisplay(); 2695 2696 tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlphaLong()); 2697 2698 String prevOperatorNumeric = tm.getNetworkOperatorForPhone(mPhone.getPhoneId()); 2699 operatorNumeric = mSS.getOperatorNumeric(); 2700 tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric); 2701 updateCarrierMccMncConfiguration(operatorNumeric, 2702 prevOperatorNumeric, mPhone.getContext()); 2703 if (operatorNumeric == null) { 2704 if (DBG) log("operatorNumeric is null"); 2705 tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), ""); 2706 mGotCountryCode = false; 2707 mNitzUpdatedTime = false; 2708 } else { 2709 String iso = ""; 2710 String mcc = ""; 2711 try{ 2712 mcc = operatorNumeric.substring(0, 3); 2713 iso = MccTable.countryCodeForMcc(Integer.parseInt(mcc)); 2714 } catch ( NumberFormatException ex){ 2715 loge("pollStateDone: countryCodeForMcc error" + ex); 2716 } catch ( StringIndexOutOfBoundsException ex) { 2717 loge("pollStateDone: countryCodeForMcc error" + ex); 2718 } 2719 2720 tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), iso); 2721 mGotCountryCode = true; 2722 2723 TimeZone zone = null; 2724 2725 if (!mNitzUpdatedTime && !mcc.equals("000") && !TextUtils.isEmpty(iso) && 2726 getAutoTimeZone()) { 2727 2728 // Test both paths if ignore nitz is true 2729 boolean testOneUniqueOffsetPath = SystemProperties.getBoolean( 2730 TelephonyProperties.PROPERTY_IGNORE_NITZ, false) && 2731 ((SystemClock.uptimeMillis() & 1) == 0); 2732 2733 ArrayList<TimeZone> uniqueZones = TimeUtils.getTimeZonesWithUniqueOffsets(iso); 2734 if ((uniqueZones.size() == 1) || testOneUniqueOffsetPath) { 2735 zone = uniqueZones.get(0); 2736 if (DBG) { 2737 log("pollStateDone: no nitz but one TZ for iso-cc=" + iso + 2738 " with zone.getID=" + zone.getID() + 2739 " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath); 2740 } 2741 setAndBroadcastNetworkSetTimeZone(zone.getID()); 2742 } else { 2743 if (DBG) { 2744 log("pollStateDone: there are " + uniqueZones.size() + 2745 " unique offsets for iso-cc='" + iso + 2746 " testOneUniqueOffsetPath=" + testOneUniqueOffsetPath + 2747 "', do nothing"); 2748 } 2749 } 2750 } 2751 2752 if (shouldFixTimeZoneNow(mPhone, operatorNumeric, prevOperatorNumeric, 2753 mNeedFixZoneAfterNitz)) { 2754 fixTimeZone(iso); 2755 } 2756 } 2757 2758 tm.setNetworkRoamingForPhone(mPhone.getPhoneId(), mSS.getVoiceRoaming()); 2759 2760 setRoamingType(mSS); 2761 log("Broadcasting ServiceState : " + mSS); 2762 mPhone.notifyServiceStateChanged(mSS); 2763 2764 TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS); 2765 } 2766 2767 if (hasGprsAttached || hasGprsDetached || hasRegistered || hasDeregistered) { 2768 logAttachChange(); 2769 } 2770 2771 if (hasGprsAttached) { 2772 mAttachedRegistrants.notifyRegistrants(); 2773 } 2774 2775 if (hasGprsDetached) { 2776 mDetachedRegistrants.notifyRegistrants(); 2777 } 2778 2779 if (hasRilDataRadioTechnologyChanged || hasRilVoiceRadioTechnologyChanged) { 2780 logRatChange(); 2781 } 2782 2783 if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) { 2784 notifyDataRegStateRilRadioTechnologyChanged(); 2785 2786 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 2787 == mSS.getRilDataRadioTechnology()) { 2788 mPhone.notifyDataConnection(Phone.REASON_IWLAN_AVAILABLE); 2789 } else { 2790 mPhone.notifyDataConnection(null); 2791 } 2792 } 2793 2794 if (hasVoiceRoamingOn || hasVoiceRoamingOff || hasDataRoamingOn || hasDataRoamingOff) { 2795 logRoamingChange(); 2796 } 2797 2798 if (hasVoiceRoamingOn) { 2799 mVoiceRoamingOnRegistrants.notifyRegistrants(); 2800 } 2801 2802 if (hasVoiceRoamingOff) { 2803 mVoiceRoamingOffRegistrants.notifyRegistrants(); 2804 } 2805 2806 if (hasDataRoamingOn) { 2807 mDataRoamingOnRegistrants.notifyRegistrants(); 2808 } 2809 2810 if (hasDataRoamingOff) { 2811 mDataRoamingOffRegistrants.notifyRegistrants(); 2812 } 2813 2814 if (hasLocationChanged) { 2815 mPhone.notifyLocationChanged(); 2816 } 2817 2818 if (!isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) { 2819 if (!mStartedGprsRegCheck && !mReportedGprsNoReg) { 2820 mStartedGprsRegCheck = true; 2821 2822 int check_period = Settings.Global.getInt( 2823 mPhone.getContext().getContentResolver(), 2824 Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS, 2825 DEFAULT_GPRS_CHECK_PERIOD_MILLIS); 2826 sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS), 2827 check_period); 2828 } 2829 } else { 2830 mReportedGprsNoReg = false; 2831 } 2832 } 2833 2834 protected void pollStateDoneCdma() { 2835 updateRoamingState(); 2836 2837 useDataRegStateForDataOnlyDevices(); 2838 resetServiceStateInIwlanMode(); 2839 if (DBG) log("pollStateDone: cdma oldSS=[" + mSS + "] newSS=[" + mNewSS + "]"); 2840 2841 boolean hasRegistered = 2842 mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE 2843 && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE; 2844 2845 boolean hasCdmaDataConnectionAttached = 2846 mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE 2847 && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE; 2848 2849 boolean hasCdmaDataConnectionDetached = 2850 mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE 2851 && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE; 2852 2853 boolean hasCdmaDataConnectionChanged = 2854 mSS.getDataRegState() != mNewSS.getDataRegState(); 2855 2856 boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc); 2857 2858 // ratchet the new tech up through it's rat family but don't drop back down 2859 // until cell change 2860 if (hasLocationChanged == false) { 2861 mRatRatcheter.ratchetRat(mSS, mNewSS); 2862 } 2863 2864 boolean hasRilVoiceRadioTechnologyChanged = 2865 mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology(); 2866 2867 boolean hasRilDataRadioTechnologyChanged = 2868 mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology(); 2869 2870 boolean hasChanged = !mNewSS.equals(mSS); 2871 2872 boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming(); 2873 2874 boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming(); 2875 2876 boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming(); 2877 2878 boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming(); 2879 2880 TelephonyManager tm = 2881 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE); 2882 2883 // Add an event log when connection state changes 2884 if (mSS.getVoiceRegState() != mNewSS.getVoiceRegState() || 2885 mSS.getDataRegState() != mNewSS.getDataRegState()) { 2886 EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, 2887 mSS.getVoiceRegState(), mSS.getDataRegState(), 2888 mNewSS.getVoiceRegState(), mNewSS.getDataRegState()); 2889 } 2890 2891 ServiceState tss; 2892 tss = mSS; 2893 mSS = mNewSS; 2894 mNewSS = tss; 2895 // clean slate for next time 2896 mNewSS.setStateOutOfService(); 2897 2898 CdmaCellLocation tcl = (CdmaCellLocation)mCellLoc; 2899 mCellLoc = mNewCellLoc; 2900 mNewCellLoc = tcl; 2901 2902 if (hasRilVoiceRadioTechnologyChanged) { 2903 updatePhoneObject(); 2904 } 2905 2906 if (hasRilDataRadioTechnologyChanged) { 2907 tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilDataRadioTechnology()); 2908 2909 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 2910 == mSS.getRilDataRadioTechnology()) { 2911 log("pollStateDone: IWLAN enabled"); 2912 } 2913 } 2914 2915 if (hasRegistered) { 2916 mNetworkAttachedRegistrants.notifyRegistrants(); 2917 } 2918 2919 if (hasChanged) { 2920 updateSpnDisplay(); 2921 2922 String operatorNumeric; 2923 2924 tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlphaLong()); 2925 2926 String prevOperatorNumeric = tm.getNetworkOperatorForPhone(mPhone.getPhoneId()); 2927 operatorNumeric = mSS.getOperatorNumeric(); 2928 2929 // try to fix the invalid Operator Numeric 2930 if (isInvalidOperatorNumeric(operatorNumeric)) { 2931 int sid = mSS.getSystemId(); 2932 operatorNumeric = fixUnknownMcc(operatorNumeric, sid); 2933 } 2934 2935 tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric); 2936 updateCarrierMccMncConfiguration(operatorNumeric, 2937 prevOperatorNumeric, mPhone.getContext()); 2938 2939 if (isInvalidOperatorNumeric(operatorNumeric)) { 2940 if (DBG) log("operatorNumeric "+ operatorNumeric +"is invalid"); 2941 tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), ""); 2942 mGotCountryCode = false; 2943 } else { 2944 String isoCountryCode = ""; 2945 String mcc = operatorNumeric.substring(0, 3); 2946 try{ 2947 isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt( 2948 operatorNumeric.substring(0, 3))); 2949 } catch ( NumberFormatException ex){ 2950 loge("pollStateDone: countryCodeForMcc error" + ex); 2951 } catch ( StringIndexOutOfBoundsException ex) { 2952 loge("pollStateDone: countryCodeForMcc error" + ex); 2953 } 2954 2955 tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), isoCountryCode); 2956 mGotCountryCode = true; 2957 2958 setOperatorIdd(operatorNumeric); 2959 2960 if (shouldFixTimeZoneNow(mPhone, operatorNumeric, prevOperatorNumeric, 2961 mNeedFixZoneAfterNitz)) { 2962 fixTimeZone(isoCountryCode); 2963 } 2964 } 2965 2966 tm.setNetworkRoamingForPhone(mPhone.getPhoneId(), 2967 (mSS.getVoiceRoaming() || mSS.getDataRoaming())); 2968 2969 // set roaming type 2970 setRoamingType(mSS); 2971 log("Broadcasting ServiceState : " + mSS); 2972 mPhone.notifyServiceStateChanged(mSS); 2973 2974 TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS); 2975 } 2976 2977 if (hasCdmaDataConnectionAttached || hasCdmaDataConnectionDetached || hasRegistered) { 2978 logAttachChange(); 2979 } 2980 2981 if (hasCdmaDataConnectionAttached) { 2982 mAttachedRegistrants.notifyRegistrants(); 2983 } 2984 2985 if (hasCdmaDataConnectionDetached) { 2986 mDetachedRegistrants.notifyRegistrants(); 2987 } 2988 2989 if (hasRilDataRadioTechnologyChanged || hasRilVoiceRadioTechnologyChanged) { 2990 logRatChange(); 2991 } 2992 2993 if (hasCdmaDataConnectionChanged || hasRilDataRadioTechnologyChanged) { 2994 notifyDataRegStateRilRadioTechnologyChanged(); 2995 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 2996 == mSS.getRilDataRadioTechnology()) { 2997 mPhone.notifyDataConnection(Phone.REASON_IWLAN_AVAILABLE); 2998 } else { 2999 mPhone.notifyDataConnection(null); 3000 } 3001 } 3002 3003 if (hasVoiceRoamingOn) { 3004 mVoiceRoamingOnRegistrants.notifyRegistrants(); 3005 } 3006 3007 if (hasVoiceRoamingOff) { 3008 mVoiceRoamingOffRegistrants.notifyRegistrants(); 3009 } 3010 3011 if (hasVoiceRoamingOn || hasVoiceRoamingOff || hasDataRoamingOn || hasDataRoamingOff) { 3012 logRoamingChange(); 3013 } 3014 3015 if (hasDataRoamingOn) { 3016 mDataRoamingOnRegistrants.notifyRegistrants(); 3017 } 3018 3019 if (hasDataRoamingOff) { 3020 mDataRoamingOffRegistrants.notifyRegistrants(); 3021 } 3022 3023 if (hasLocationChanged) { 3024 mPhone.notifyLocationChanged(); 3025 } 3026 // TODO: Add CdmaCellIdenity updating, see CdmaLteServiceStateTracker. 3027 } 3028 3029 protected void pollStateDoneCdmaLte() { 3030 updateRoamingState(); 3031 3032 if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) { 3033 mNewSS.setVoiceRoaming(true); 3034 mNewSS.setDataRoaming(true); 3035 } 3036 3037 useDataRegStateForDataOnlyDevices(); 3038 resetServiceStateInIwlanMode(); 3039 log("pollStateDone: lte 1 ss=[" + mSS + "] newSS=[" + mNewSS + "]"); 3040 3041 boolean hasRegistered = mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE 3042 && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE; 3043 3044 boolean hasDeregistered = mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE 3045 && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE; 3046 3047 boolean hasCdmaDataConnectionAttached = 3048 mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE 3049 && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE; 3050 3051 boolean hasCdmaDataConnectionDetached = 3052 mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE 3053 && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE; 3054 3055 boolean hasCdmaDataConnectionChanged = 3056 mSS.getDataRegState() != mNewSS.getDataRegState(); 3057 3058 boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc); 3059 3060 // ratchet the new tech up through it's rat family but don't drop back down 3061 // until cell change 3062 if (hasLocationChanged == false) { 3063 mRatRatcheter.ratchetRat(mSS, mNewSS); 3064 } 3065 3066 boolean hasVoiceRadioTechnologyChanged = mSS.getRilVoiceRadioTechnology() 3067 != mNewSS.getRilVoiceRadioTechnology(); 3068 3069 boolean hasDataRadioTechnologyChanged = mSS.getRilDataRadioTechnology() 3070 != mNewSS.getRilDataRadioTechnology(); 3071 3072 boolean hasChanged = !mNewSS.equals(mSS); 3073 3074 boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming(); 3075 3076 boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming(); 3077 3078 boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming(); 3079 3080 boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming(); 3081 3082 boolean has4gHandoff = 3083 mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE && 3084 ((ServiceState.isLte(mSS.getRilDataRadioTechnology()) && 3085 (mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) || 3086 ((mSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD) && 3087 ServiceState.isLte(mNewSS.getRilDataRadioTechnology()))); 3088 3089 boolean hasMultiApnSupport = 3090 ((ServiceState.isLte(mNewSS.getRilDataRadioTechnology()) || 3091 (mNewSS.getRilDataRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) && 3092 (!ServiceState.isLte(mSS.getRilDataRadioTechnology()) && 3093 (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))); 3094 3095 boolean hasLostMultiApnSupport = 3096 ((mNewSS.getRilDataRadioTechnology() >= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A) && 3097 (mNewSS.getRilDataRadioTechnology() <= ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)); 3098 3099 TelephonyManager tm = 3100 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE); 3101 3102 if (DBG) { 3103 log("pollStateDone:" 3104 + " hasRegistered=" + hasRegistered 3105 + " hasDeegistered=" + hasDeregistered 3106 + " hasCdmaDataConnectionAttached=" + hasCdmaDataConnectionAttached 3107 + " hasCdmaDataConnectionDetached=" + hasCdmaDataConnectionDetached 3108 + " hasCdmaDataConnectionChanged=" + hasCdmaDataConnectionChanged 3109 + " hasVoiceRadioTechnologyChanged= " + hasVoiceRadioTechnologyChanged 3110 + " hasDataRadioTechnologyChanged=" + hasDataRadioTechnologyChanged 3111 + " hasChanged=" + hasChanged 3112 + " hasVoiceRoamingOn=" + hasVoiceRoamingOn 3113 + " hasVoiceRoamingOff=" + hasVoiceRoamingOff 3114 + " hasDataRoamingOn=" + hasDataRoamingOn 3115 + " hasDataRoamingOff=" + hasDataRoamingOff 3116 + " hasLocationChanged=" + hasLocationChanged 3117 + " has4gHandoff = " + has4gHandoff 3118 + " hasMultiApnSupport=" + hasMultiApnSupport 3119 + " hasLostMultiApnSupport=" + hasLostMultiApnSupport); 3120 } 3121 // Add an event log when connection state changes 3122 if (mSS.getVoiceRegState() != mNewSS.getVoiceRegState() 3123 || mSS.getDataRegState() != mNewSS.getDataRegState()) { 3124 EventLog.writeEvent(EventLogTags.CDMA_SERVICE_STATE_CHANGE, mSS.getVoiceRegState(), 3125 mSS.getDataRegState(), mNewSS.getVoiceRegState(), mNewSS.getDataRegState()); 3126 } 3127 3128 ServiceState tss; 3129 tss = mSS; 3130 mSS = mNewSS; 3131 mNewSS = tss; 3132 // clean slate for next time 3133 mNewSS.setStateOutOfService(); 3134 3135 CdmaCellLocation tcl = (CdmaCellLocation)mCellLoc; 3136 mCellLoc = mNewCellLoc; 3137 mNewCellLoc = tcl; 3138 3139 mNewSS.setStateOutOfService(); // clean slate for next time 3140 3141 if (hasVoiceRadioTechnologyChanged) { 3142 updatePhoneObject(); 3143 } 3144 3145 if (hasDataRadioTechnologyChanged) { 3146 tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilDataRadioTechnology()); 3147 3148 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 3149 == mSS.getRilDataRadioTechnology()) { 3150 log("pollStateDone: IWLAN enabled"); 3151 } 3152 } 3153 3154 if (hasRegistered) { 3155 mNetworkAttachedRegistrants.notifyRegistrants(); 3156 } 3157 3158 if (hasChanged) { 3159 updateSpnDisplay(); 3160 3161 String operatorNumeric; 3162 3163 tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlphaLong()); 3164 3165 String prevOperatorNumeric = tm.getNetworkOperatorForPhone(mPhone.getPhoneId()); 3166 operatorNumeric = mSS.getOperatorNumeric(); 3167 // try to fix the invalid Operator Numeric 3168 if (isInvalidOperatorNumeric(operatorNumeric)) { 3169 int sid = mSS.getSystemId(); 3170 operatorNumeric = fixUnknownMcc(operatorNumeric, sid); 3171 } 3172 tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric); 3173 updateCarrierMccMncConfiguration(operatorNumeric, 3174 prevOperatorNumeric, mPhone.getContext()); 3175 3176 if (isInvalidOperatorNumeric(operatorNumeric)) { 3177 if (DBG) log("operatorNumeric is null"); 3178 tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), ""); 3179 mGotCountryCode = false; 3180 } else { 3181 String isoCountryCode = ""; 3182 String mcc = operatorNumeric.substring(0, 3); 3183 try { 3184 isoCountryCode = MccTable.countryCodeForMcc(Integer.parseInt(operatorNumeric 3185 .substring(0, 3))); 3186 } catch (NumberFormatException ex) { 3187 loge("countryCodeForMcc error" + ex); 3188 } catch (StringIndexOutOfBoundsException ex) { 3189 loge("countryCodeForMcc error" + ex); 3190 } 3191 3192 tm.setNetworkCountryIsoForPhone(mPhone.getPhoneId(), isoCountryCode); 3193 mGotCountryCode = true; 3194 3195 setOperatorIdd(operatorNumeric); 3196 3197 if (shouldFixTimeZoneNow(mPhone, operatorNumeric, prevOperatorNumeric, 3198 mNeedFixZoneAfterNitz)) { 3199 fixTimeZone(isoCountryCode); 3200 } 3201 } 3202 3203 tm.setNetworkRoamingForPhone(mPhone.getPhoneId(), 3204 (mSS.getVoiceRoaming() || mSS.getDataRoaming())); 3205 3206 setRoamingType(mSS); 3207 log("Broadcasting ServiceState : " + mSS); 3208 mPhone.notifyServiceStateChanged(mSS); 3209 3210 TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS); 3211 } 3212 3213 if (hasCdmaDataConnectionAttached || has4gHandoff || hasCdmaDataConnectionDetached || 3214 hasRegistered || hasDeregistered) { 3215 logAttachChange(); 3216 } 3217 3218 if (hasCdmaDataConnectionAttached || has4gHandoff) { 3219 mAttachedRegistrants.notifyRegistrants(); 3220 } 3221 3222 if (hasCdmaDataConnectionDetached) { 3223 mDetachedRegistrants.notifyRegistrants(); 3224 } 3225 3226 if (hasDataRadioTechnologyChanged || hasVoiceRadioTechnologyChanged) { 3227 logRatChange(); 3228 } 3229 3230 if ((hasCdmaDataConnectionChanged || hasDataRadioTechnologyChanged)) { 3231 notifyDataRegStateRilRadioTechnologyChanged(); 3232 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 3233 == mSS.getRilDataRadioTechnology()) { 3234 mPhone.notifyDataConnection(Phone.REASON_IWLAN_AVAILABLE); 3235 } else { 3236 mPhone.notifyDataConnection(null); 3237 } 3238 } 3239 3240 if (hasVoiceRoamingOn || hasVoiceRoamingOff || hasDataRoamingOn || hasDataRoamingOff) { 3241 logRoamingChange(); 3242 } 3243 3244 if (hasVoiceRoamingOn) { 3245 mVoiceRoamingOnRegistrants.notifyRegistrants(); 3246 } 3247 3248 if (hasVoiceRoamingOff) { 3249 mVoiceRoamingOffRegistrants.notifyRegistrants(); 3250 } 3251 3252 if (hasDataRoamingOn) { 3253 mDataRoamingOnRegistrants.notifyRegistrants(); 3254 } 3255 3256 if (hasDataRoamingOff) { 3257 mDataRoamingOffRegistrants.notifyRegistrants(); 3258 } 3259 3260 if (hasLocationChanged) { 3261 mPhone.notifyLocationChanged(); 3262 } 3263 } 3264 3265 private void updateOperatorNameFromEri() { 3266 if (mPhone.isPhoneTypeCdma()) { 3267 if ((mCi.getRadioState().isOn()) && (!mIsSubscriptionFromRuim)) { 3268 String eriText; 3269 // Now the Phone sees the new ServiceState so it can get the new ERI text 3270 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 3271 eriText = mPhone.getCdmaEriText(); 3272 } else { 3273 // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used for 3274 // mRegistrationState 0,2,3 and 4 3275 eriText = mPhone.getContext().getText( 3276 com.android.internal.R.string.roamingTextSearching).toString(); 3277 } 3278 mSS.setOperatorAlphaLong(eriText); 3279 } 3280 } else if (mPhone.isPhoneTypeCdmaLte()) { 3281 boolean hasBrandOverride = mUiccController.getUiccCard(getPhoneId()) != null && 3282 mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() != null; 3283 if (!hasBrandOverride && (mCi.getRadioState().isOn()) && (mPhone.isEriFileLoaded()) && 3284 (!ServiceState.isLte(mSS.getRilVoiceRadioTechnology()) || 3285 mPhone.getContext().getResources().getBoolean(com.android.internal.R. 3286 bool.config_LTE_eri_for_network_name))) { 3287 // Only when CDMA is in service, ERI will take effect 3288 String eriText = mSS.getOperatorAlphaLong(); 3289 // Now the Phone sees the new ServiceState so it can get the new ERI text 3290 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 3291 eriText = mPhone.getCdmaEriText(); 3292 } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF) { 3293 eriText = (mIccRecords != null) ? mIccRecords.getServiceProviderName() : null; 3294 if (TextUtils.isEmpty(eriText)) { 3295 // Sets operator alpha property by retrieving from 3296 // build-time system property 3297 eriText = SystemProperties.get("ro.cdma.home.operator.alpha"); 3298 } 3299 } else if (mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE) { 3300 // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used 3301 // for mRegistrationState 0,2,3 and 4 3302 eriText = mPhone.getContext() 3303 .getText(com.android.internal.R.string.roamingTextSearching).toString(); 3304 } 3305 mSS.setOperatorAlphaLong(eriText); 3306 } 3307 3308 if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY && 3309 mIccRecords != null && (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) 3310 && !ServiceState.isLte(mSS.getRilVoiceRadioTechnology())) { 3311 // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches 3312 // one configured in SIM, use operator name from CSIM record. Note that ERI, SID, 3313 // and NID are CDMA only, not applicable to LTE. 3314 boolean showSpn = 3315 ((RuimRecords) mIccRecords).getCsimSpnDisplayCondition(); 3316 int iconIndex = mSS.getCdmaEriIconIndex(); 3317 3318 if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) && 3319 isInHomeSidNid(mSS.getSystemId(), mSS.getNetworkId()) && 3320 mIccRecords != null) { 3321 mSS.setOperatorAlphaLong(mIccRecords.getServiceProviderName()); 3322 } 3323 } 3324 } 3325 } 3326 3327 /** 3328 * Check whether the specified SID and NID pair appears in the HOME SID/NID list 3329 * read from NV or SIM. 3330 * 3331 * @return true if provided sid/nid pair belongs to operator's home network. 3332 */ 3333 private boolean isInHomeSidNid(int sid, int nid) { 3334 // if SID/NID is not available, assume this is home network. 3335 if (isSidsAllZeros()) return true; 3336 3337 // length of SID/NID shold be same 3338 if (mHomeSystemId.length != mHomeNetworkId.length) return true; 3339 3340 if (sid == 0) return true; 3341 3342 for (int i = 0; i < mHomeSystemId.length; i++) { 3343 // Use SID only if NID is a reserved value. 3344 // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2) 3345 if ((mHomeSystemId[i] == sid) && 3346 ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) || 3347 (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) { 3348 return true; 3349 } 3350 } 3351 // SID/NID are not in the list. So device is not in home network 3352 return false; 3353 } 3354 3355 protected void setOperatorIdd(String operatorNumeric) { 3356 // Retrieve the current country information 3357 // with the MCC got from opeatorNumeric. 3358 String idd = mHbpcdUtils.getIddByMcc( 3359 Integer.parseInt(operatorNumeric.substring(0,3))); 3360 if (idd != null && !idd.isEmpty()) { 3361 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING, 3362 idd); 3363 } else { 3364 // use default "+", since we don't know the current IDP 3365 mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING, "+"); 3366 } 3367 } 3368 3369 protected boolean isInvalidOperatorNumeric(String operatorNumeric) { 3370 return operatorNumeric == null || operatorNumeric.length() < 5 || 3371 operatorNumeric.startsWith(INVALID_MCC); 3372 } 3373 3374 protected String fixUnknownMcc(String operatorNumeric, int sid) { 3375 if (sid <= 0) { 3376 // no cdma information is available, do nothing 3377 return operatorNumeric; 3378 } 3379 3380 // resolve the mcc from sid; 3381 // if mSavedTimeZone is null, TimeZone would get the default timeZone, 3382 // and the fixTimeZone couldn't help, because it depends on operator Numeric; 3383 // if the sid is conflict and timezone is unavailable, the mcc may be not right. 3384 boolean isNitzTimeZone = false; 3385 int timeZone = 0; 3386 TimeZone tzone = null; 3387 if (mSavedTimeZone != null) { 3388 timeZone = 3389 TimeZone.getTimeZone(mSavedTimeZone).getRawOffset()/MS_PER_HOUR; 3390 isNitzTimeZone = true; 3391 } else { 3392 tzone = getNitzTimeZone(mZoneOffset, mZoneDst, mZoneTime); 3393 if (tzone != null) 3394 timeZone = tzone.getRawOffset()/MS_PER_HOUR; 3395 } 3396 3397 int mcc = mHbpcdUtils.getMcc(sid, 3398 timeZone, (mZoneDst ? 1 : 0), isNitzTimeZone); 3399 if (mcc > 0) { 3400 operatorNumeric = Integer.toString(mcc) + DEFAULT_MNC; 3401 } 3402 return operatorNumeric; 3403 } 3404 3405 protected void fixTimeZone(String isoCountryCode) { 3406 TimeZone zone = null; 3407 // If the offset is (0, false) and the time zone property 3408 // is set, use the time zone property rather than GMT. 3409 String zoneName = SystemProperties.get(TIMEZONE_PROPERTY); 3410 if (DBG) { 3411 log("fixTimeZone zoneName='" + zoneName + 3412 "' mZoneOffset=" + mZoneOffset + " mZoneDst=" + mZoneDst + 3413 " iso-cc='" + isoCountryCode + 3414 "' iso-cc-idx=" + Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode)); 3415 } 3416 if ("".equals(isoCountryCode) && mNeedFixZoneAfterNitz) { 3417 // Country code not found. This is likely a test network. 3418 // Get a TimeZone based only on the NITZ parameters (best guess). 3419 zone = getNitzTimeZone(mZoneOffset, mZoneDst, mZoneTime); 3420 if (DBG) log("pollStateDone: using NITZ TimeZone"); 3421 } else if ((mZoneOffset == 0) && (mZoneDst == false) && (zoneName != null) 3422 && (zoneName.length() > 0) 3423 && (Arrays.binarySearch(GMT_COUNTRY_CODES, isoCountryCode) < 0)) { 3424 // For NITZ string without time zone, 3425 // need adjust time to reflect default time zone setting 3426 zone = TimeZone.getDefault(); 3427 if (mNeedFixZoneAfterNitz) { 3428 long ctm = System.currentTimeMillis(); 3429 long tzOffset = zone.getOffset(ctm); 3430 if (DBG) { 3431 log("fixTimeZone: tzOffset=" + tzOffset + 3432 " ltod=" + TimeUtils.logTimeOfDay(ctm)); 3433 } 3434 if (getAutoTime()) { 3435 long adj = ctm - tzOffset; 3436 if (DBG) log("fixTimeZone: adj ltod=" + TimeUtils.logTimeOfDay(adj)); 3437 setAndBroadcastNetworkSetTime(adj); 3438 } else { 3439 // Adjust the saved NITZ time to account for tzOffset. 3440 mSavedTime = mSavedTime - tzOffset; 3441 if (DBG) log("fixTimeZone: adj mSavedTime=" + mSavedTime); 3442 } 3443 } 3444 if (DBG) log("fixTimeZone: using default TimeZone"); 3445 } else { 3446 zone = TimeUtils.getTimeZone(mZoneOffset, mZoneDst, mZoneTime, isoCountryCode); 3447 if (DBG) log("fixTimeZone: using getTimeZone(off, dst, time, iso)"); 3448 } 3449 3450 mNeedFixZoneAfterNitz = false; 3451 3452 if (zone != null) { 3453 log("fixTimeZone: zone != null zone.getID=" + zone.getID()); 3454 if (getAutoTimeZone()) { 3455 setAndBroadcastNetworkSetTimeZone(zone.getID()); 3456 } else { 3457 log("fixTimeZone: skip changing zone as getAutoTimeZone was false"); 3458 } 3459 saveNitzTimeZone(zone.getID()); 3460 } else { 3461 log("fixTimeZone: zone == null, do nothing for zone"); 3462 } 3463 } 3464 3465 /** 3466 * Check if GPRS got registered while voice is registered. 3467 * 3468 * @param dataRegState i.e. CGREG in GSM 3469 * @param voiceRegState i.e. CREG in GSM 3470 * @return false if device only register to voice but not gprs 3471 */ 3472 private boolean isGprsConsistent(int dataRegState, int voiceRegState) { 3473 return !((voiceRegState == ServiceState.STATE_IN_SERVICE) && 3474 (dataRegState != ServiceState.STATE_IN_SERVICE)); 3475 } 3476 3477 /** 3478 * Returns a TimeZone object based only on parameters from the NITZ string. 3479 */ 3480 private TimeZone getNitzTimeZone(int offset, boolean dst, long when) { 3481 TimeZone guess = findTimeZone(offset, dst, when); 3482 if (guess == null) { 3483 // Couldn't find a proper timezone. Perhaps the DST data is wrong. 3484 guess = findTimeZone(offset, !dst, when); 3485 } 3486 if (DBG) log("getNitzTimeZone returning " + (guess == null ? guess : guess.getID())); 3487 return guess; 3488 } 3489 3490 private TimeZone findTimeZone(int offset, boolean dst, long when) { 3491 int rawOffset = offset; 3492 if (dst) { 3493 rawOffset -= MS_PER_HOUR; 3494 } 3495 String[] zones = TimeZone.getAvailableIDs(rawOffset); 3496 TimeZone guess = null; 3497 Date d = new Date(when); 3498 for (String zone : zones) { 3499 TimeZone tz = TimeZone.getTimeZone(zone); 3500 if (tz.getOffset(when) == offset && 3501 tz.inDaylightTime(d) == dst) { 3502 guess = tz; 3503 break; 3504 } 3505 } 3506 3507 return guess; 3508 } 3509 3510 /** code is registration state 0-5 from TS 27.007 7.2 */ 3511 private int regCodeToServiceState(int code) { 3512 switch (code) { 3513 case 0: 3514 case 2: // 2 is "searching" 3515 case 3: // 3 is "registration denied" 3516 case 4: // 4 is "unknown" no vaild in current baseband 3517 case 10:// same as 0, but indicates that emergency call is possible. 3518 case 12:// same as 2, but indicates that emergency call is possible. 3519 case 13:// same as 3, but indicates that emergency call is possible. 3520 case 14:// same as 4, but indicates that emergency call is possible. 3521 return ServiceState.STATE_OUT_OF_SERVICE; 3522 3523 case 1: 3524 case 5: // 5 is "registered, roaming" 3525 return ServiceState.STATE_IN_SERVICE; 3526 3527 default: 3528 loge("regCodeToServiceState: unexpected service state " + code); 3529 return ServiceState.STATE_OUT_OF_SERVICE; 3530 } 3531 } 3532 3533 /** 3534 * code is registration state 0-5 from TS 27.007 7.2 3535 * returns true if registered roam, false otherwise 3536 */ 3537 private boolean regCodeIsRoaming (int code) { 3538 return ServiceState.RIL_REG_STATE_ROAMING == code; 3539 } 3540 3541 private boolean isSameOperatorNameFromSimAndSS(ServiceState s) { 3542 String spn = ((TelephonyManager) mPhone.getContext(). 3543 getSystemService(Context.TELEPHONY_SERVICE)). 3544 getSimOperatorNameForPhone(getPhoneId()); 3545 3546 // NOTE: in case of RUIM we should completely ignore the ERI data file and 3547 // mOperatorAlphaLong is set from RIL_REQUEST_OPERATOR response 0 (alpha ONS) 3548 String onsl = s.getOperatorAlphaLong(); 3549 String onss = s.getOperatorAlphaShort(); 3550 3551 boolean equalsOnsl = !TextUtils.isEmpty(spn) && spn.equalsIgnoreCase(onsl); 3552 boolean equalsOnss = !TextUtils.isEmpty(spn) && spn.equalsIgnoreCase(onss); 3553 3554 return (equalsOnsl || equalsOnss); 3555 } 3556 3557 /** 3558 * Set roaming state if operator mcc is the same as sim mcc 3559 * and ons is not different from spn 3560 * 3561 * @param s ServiceState hold current ons 3562 * @return true if same operator 3563 */ 3564 private boolean isSameNamedOperators(ServiceState s) { 3565 return currentMccEqualsSimMcc(s) && isSameOperatorNameFromSimAndSS(s); 3566 } 3567 3568 /** 3569 * Compare SIM MCC with Operator MCC 3570 * 3571 * @param s ServiceState hold current ons 3572 * @return true if both are same 3573 */ 3574 private boolean currentMccEqualsSimMcc(ServiceState s) { 3575 String simNumeric = ((TelephonyManager) mPhone.getContext(). 3576 getSystemService(Context.TELEPHONY_SERVICE)). 3577 getSimOperatorNumericForPhone(getPhoneId()); 3578 String operatorNumeric = s.getOperatorNumeric(); 3579 boolean equalsMcc = true; 3580 3581 try { 3582 equalsMcc = simNumeric.substring(0, 3). 3583 equals(operatorNumeric.substring(0, 3)); 3584 } catch (Exception e){ 3585 } 3586 return equalsMcc; 3587 } 3588 3589 /** 3590 * Do not set roaming state in case of oprators considered non-roaming. 3591 * 3592 * Can use mcc or mcc+mnc as item of config_operatorConsideredNonRoaming. 3593 * For example, 302 or 21407. If mcc or mcc+mnc match with operator, 3594 * don't set roaming state. 3595 * 3596 * @param s ServiceState hold current ons 3597 * @return false for roaming state set 3598 */ 3599 private boolean isOperatorConsideredNonRoaming(ServiceState s) { 3600 String operatorNumeric = s.getOperatorNumeric(); 3601 String[] numericArray = mPhone.getContext().getResources().getStringArray( 3602 com.android.internal.R.array.config_operatorConsideredNonRoaming); 3603 3604 if (numericArray.length == 0 || operatorNumeric == null) { 3605 return false; 3606 } 3607 3608 for (String numeric : numericArray) { 3609 if (operatorNumeric.startsWith(numeric)) { 3610 return true; 3611 } 3612 } 3613 return false; 3614 } 3615 3616 private boolean isOperatorConsideredRoaming(ServiceState s) { 3617 String operatorNumeric = s.getOperatorNumeric(); 3618 String[] numericArray = mPhone.getContext().getResources().getStringArray( 3619 com.android.internal.R.array.config_sameNamedOperatorConsideredRoaming); 3620 3621 if (numericArray.length == 0 || operatorNumeric == null) { 3622 return false; 3623 } 3624 3625 for (String numeric : numericArray) { 3626 if (operatorNumeric.startsWith(numeric)) { 3627 return true; 3628 } 3629 } 3630 return false; 3631 } 3632 3633 /** 3634 * Set restricted state based on the OnRestrictedStateChanged notification 3635 * If any voice or packet restricted state changes, trigger a UI 3636 * notification and notify registrants when sim is ready. 3637 * 3638 * @param ar an int value of RIL_RESTRICTED_STATE_* 3639 */ 3640 private void onRestrictedStateChanged(AsyncResult ar) { 3641 RestrictedState newRs = new RestrictedState(); 3642 3643 if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState); 3644 3645 if (ar.exception == null) { 3646 int[] ints = (int[])ar.result; 3647 int state = ints[0]; 3648 3649 newRs.setCsEmergencyRestricted( 3650 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) || 3651 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); 3652 //ignore the normal call and data restricted state before SIM READY 3653 if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY) { 3654 newRs.setCsNormalRestricted( 3655 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) || 3656 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); 3657 newRs.setPsRestricted( 3658 (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0); 3659 } 3660 3661 if (DBG) log("onRestrictedStateChanged: new rs "+ newRs); 3662 3663 if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) { 3664 mPsRestrictEnabledRegistrants.notifyRegistrants(); 3665 setNotification(PS_ENABLED); 3666 } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) { 3667 mPsRestrictDisabledRegistrants.notifyRegistrants(); 3668 setNotification(PS_DISABLED); 3669 } 3670 3671 /** 3672 * There are two kind of cs restriction, normal and emergency. So 3673 * there are 4 x 4 combinations in current and new restricted states 3674 * and we only need to notify when state is changed. 3675 */ 3676 if (mRestrictedState.isCsRestricted()) { 3677 if (!newRs.isCsRestricted()) { 3678 // remove all restriction 3679 setNotification(CS_DISABLED); 3680 } else if (!newRs.isCsNormalRestricted()) { 3681 // remove normal restriction 3682 setNotification(CS_EMERGENCY_ENABLED); 3683 } else if (!newRs.isCsEmergencyRestricted()) { 3684 // remove emergency restriction 3685 setNotification(CS_NORMAL_ENABLED); 3686 } 3687 } else if (mRestrictedState.isCsEmergencyRestricted() && 3688 !mRestrictedState.isCsNormalRestricted()) { 3689 if (!newRs.isCsRestricted()) { 3690 // remove all restriction 3691 setNotification(CS_DISABLED); 3692 } else if (newRs.isCsRestricted()) { 3693 // enable all restriction 3694 setNotification(CS_ENABLED); 3695 } else if (newRs.isCsNormalRestricted()) { 3696 // remove emergency restriction and enable normal restriction 3697 setNotification(CS_NORMAL_ENABLED); 3698 } 3699 } else if (!mRestrictedState.isCsEmergencyRestricted() && 3700 mRestrictedState.isCsNormalRestricted()) { 3701 if (!newRs.isCsRestricted()) { 3702 // remove all restriction 3703 setNotification(CS_DISABLED); 3704 } else if (newRs.isCsRestricted()) { 3705 // enable all restriction 3706 setNotification(CS_ENABLED); 3707 } else if (newRs.isCsEmergencyRestricted()) { 3708 // remove normal restriction and enable emergency restriction 3709 setNotification(CS_EMERGENCY_ENABLED); 3710 } 3711 } else { 3712 if (newRs.isCsRestricted()) { 3713 // enable all restriction 3714 setNotification(CS_ENABLED); 3715 } else if (newRs.isCsEmergencyRestricted()) { 3716 // enable emergency restriction 3717 setNotification(CS_EMERGENCY_ENABLED); 3718 } else if (newRs.isCsNormalRestricted()) { 3719 // enable normal restriction 3720 setNotification(CS_NORMAL_ENABLED); 3721 } 3722 } 3723 3724 mRestrictedState = newRs; 3725 } 3726 log("onRestrictedStateChanged: X rs "+ mRestrictedState); 3727 } 3728 3729 /** 3730 * @return the current cell location information. Prefer Gsm location 3731 * information if available otherwise return LTE location information 3732 */ 3733 public CellLocation getCellLocation() { 3734 if (((GsmCellLocation)mCellLoc).getLac() >= 0 && 3735 ((GsmCellLocation)mCellLoc).getCid() >= 0) { 3736 if (DBG) log("getCellLocation(): X good mCellLoc=" + mCellLoc); 3737 return mCellLoc; 3738 } else { 3739 List<CellInfo> result = getAllCellInfo(); 3740 if (result != null) { 3741 // A hack to allow tunneling of LTE information via GsmCellLocation 3742 // so that older Network Location Providers can return some information 3743 // on LTE only networks, see bug 9228974. 3744 // 3745 // We'll search the return CellInfo array preferring GSM/WCDMA 3746 // data, but if there is none we'll tunnel the first LTE information 3747 // in the list. 3748 // 3749 // The tunnel'd LTE information is returned as follows: 3750 // LAC = TAC field 3751 // CID = CI field 3752 // PSC = 0. 3753 GsmCellLocation cellLocOther = new GsmCellLocation(); 3754 for (CellInfo ci : result) { 3755 if (ci instanceof CellInfoGsm) { 3756 CellInfoGsm cellInfoGsm = (CellInfoGsm)ci; 3757 CellIdentityGsm cellIdentityGsm = cellInfoGsm.getCellIdentity(); 3758 cellLocOther.setLacAndCid(cellIdentityGsm.getLac(), 3759 cellIdentityGsm.getCid()); 3760 cellLocOther.setPsc(cellIdentityGsm.getPsc()); 3761 if (DBG) log("getCellLocation(): X ret GSM info=" + cellLocOther); 3762 return cellLocOther; 3763 } else if (ci instanceof CellInfoWcdma) { 3764 CellInfoWcdma cellInfoWcdma = (CellInfoWcdma)ci; 3765 CellIdentityWcdma cellIdentityWcdma = cellInfoWcdma.getCellIdentity(); 3766 cellLocOther.setLacAndCid(cellIdentityWcdma.getLac(), 3767 cellIdentityWcdma.getCid()); 3768 cellLocOther.setPsc(cellIdentityWcdma.getPsc()); 3769 if (DBG) log("getCellLocation(): X ret WCDMA info=" + cellLocOther); 3770 return cellLocOther; 3771 } else if ((ci instanceof CellInfoLte) && 3772 ((cellLocOther.getLac() < 0) || (cellLocOther.getCid() < 0))) { 3773 // We'll return the first good LTE info we get if there is no better answer 3774 CellInfoLte cellInfoLte = (CellInfoLte)ci; 3775 CellIdentityLte cellIdentityLte = cellInfoLte.getCellIdentity(); 3776 if ((cellIdentityLte.getTac() != Integer.MAX_VALUE) 3777 && (cellIdentityLte.getCi() != Integer.MAX_VALUE)) { 3778 cellLocOther.setLacAndCid(cellIdentityLte.getTac(), 3779 cellIdentityLte.getCi()); 3780 cellLocOther.setPsc(0); 3781 if (DBG) { 3782 log("getCellLocation(): possible LTE cellLocOther=" + cellLocOther); 3783 } 3784 } 3785 } 3786 } 3787 if (DBG) { 3788 log("getCellLocation(): X ret best answer cellLocOther=" + cellLocOther); 3789 } 3790 return cellLocOther; 3791 } else { 3792 if (DBG) { 3793 log("getCellLocation(): X empty mCellLoc and CellInfo mCellLoc=" + mCellLoc); 3794 } 3795 return mCellLoc; 3796 } 3797 } 3798 } 3799 3800 /** 3801 * nitzReceiveTime is time_t that the NITZ time was posted 3802 */ 3803 private void setTimeFromNITZString (String nitz, long nitzReceiveTime) { 3804 // "yy/mm/dd,hh:mm:ss(+/-)tz" 3805 // tz is in number of quarter-hours 3806 3807 long start = SystemClock.elapsedRealtime(); 3808 if (DBG) {log("NITZ: " + nitz + "," + nitzReceiveTime + 3809 " start=" + start + " delay=" + (start - nitzReceiveTime)); 3810 } 3811 3812 try { 3813 /* NITZ time (hour:min:sec) will be in UTC but it supplies the timezone 3814 * offset as well (which we won't worry about until later) */ 3815 Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 3816 3817 c.clear(); 3818 c.set(Calendar.DST_OFFSET, 0); 3819 3820 String[] nitzSubs = nitz.split("[/:,+-]"); 3821 3822 int year = 2000 + Integer.parseInt(nitzSubs[0]); 3823 if (year > MAX_NITZ_YEAR) { 3824 if (DBG) loge("NITZ year: " + year + " exceeds limit, skip NITZ time update"); 3825 return; 3826 } 3827 c.set(Calendar.YEAR, year); 3828 3829 // month is 0 based! 3830 int month = Integer.parseInt(nitzSubs[1]) - 1; 3831 c.set(Calendar.MONTH, month); 3832 3833 int date = Integer.parseInt(nitzSubs[2]); 3834 c.set(Calendar.DATE, date); 3835 3836 int hour = Integer.parseInt(nitzSubs[3]); 3837 c.set(Calendar.HOUR, hour); 3838 3839 int minute = Integer.parseInt(nitzSubs[4]); 3840 c.set(Calendar.MINUTE, minute); 3841 3842 int second = Integer.parseInt(nitzSubs[5]); 3843 c.set(Calendar.SECOND, second); 3844 3845 boolean sign = (nitz.indexOf('-') == -1); 3846 3847 int tzOffset = Integer.parseInt(nitzSubs[6]); 3848 3849 int dst = (nitzSubs.length >= 8 ) ? Integer.parseInt(nitzSubs[7]) : 0; 3850 3851 // The zone offset received from NITZ is for current local time, 3852 // so DST correction is already applied. Don't add it again. 3853 // 3854 // tzOffset += dst * 4; 3855 // 3856 // We could unapply it if we wanted the raw offset. 3857 3858 tzOffset = (sign ? 1 : -1) * tzOffset * 15 * 60 * 1000; 3859 3860 TimeZone zone = null; 3861 3862 // As a special extension, the Android emulator appends the name of 3863 // the host computer's timezone to the nitz string. this is zoneinfo 3864 // timezone name of the form Area!Location or Area!Location!SubLocation 3865 // so we need to convert the ! into / 3866 if (nitzSubs.length >= 9) { 3867 String tzname = nitzSubs[8].replace('!','/'); 3868 zone = TimeZone.getTimeZone( tzname ); 3869 } 3870 3871 String iso = ((TelephonyManager) mPhone.getContext(). 3872 getSystemService(Context.TELEPHONY_SERVICE)). 3873 getNetworkCountryIsoForPhone(mPhone.getPhoneId()); 3874 3875 if (zone == null) { 3876 3877 if (mGotCountryCode) { 3878 if (iso != null && iso.length() > 0) { 3879 zone = TimeUtils.getTimeZone(tzOffset, dst != 0, 3880 c.getTimeInMillis(), 3881 iso); 3882 } else { 3883 // We don't have a valid iso country code. This is 3884 // most likely because we're on a test network that's 3885 // using a bogus MCC (eg, "001"), so get a TimeZone 3886 // based only on the NITZ parameters. 3887 zone = getNitzTimeZone(tzOffset, (dst != 0), c.getTimeInMillis()); 3888 } 3889 } 3890 } 3891 3892 if ((zone == null) || (mZoneOffset != tzOffset) || (mZoneDst != (dst != 0))){ 3893 // We got the time before the country or the zone has changed 3894 // so we don't know how to identify the DST rules yet. Save 3895 // the information and hope to fix it up later. 3896 3897 mNeedFixZoneAfterNitz = true; 3898 mZoneOffset = tzOffset; 3899 mZoneDst = dst != 0; 3900 mZoneTime = c.getTimeInMillis(); 3901 } 3902 if (DBG) { 3903 log("NITZ: tzOffset=" + tzOffset + " dst=" + dst + " zone=" + 3904 (zone!=null ? zone.getID() : "NULL") + 3905 " iso=" + iso + " mGotCountryCode=" + mGotCountryCode + 3906 " mNeedFixZoneAfterNitz=" + mNeedFixZoneAfterNitz); 3907 } 3908 3909 if (zone != null) { 3910 if (getAutoTimeZone()) { 3911 setAndBroadcastNetworkSetTimeZone(zone.getID()); 3912 } 3913 saveNitzTimeZone(zone.getID()); 3914 } 3915 3916 String ignore = SystemProperties.get("gsm.ignore-nitz"); 3917 if (ignore != null && ignore.equals("yes")) { 3918 log("NITZ: Not setting clock because gsm.ignore-nitz is set"); 3919 return; 3920 } 3921 3922 try { 3923 mWakeLock.acquire(); 3924 3925 if (!mPhone.isPhoneTypeGsm() || getAutoTime()) { 3926 long millisSinceNitzReceived 3927 = SystemClock.elapsedRealtime() - nitzReceiveTime; 3928 3929 if (millisSinceNitzReceived < 0) { 3930 // Sanity check: something is wrong 3931 if (DBG) { 3932 log("NITZ: not setting time, clock has rolled " 3933 + "backwards since NITZ time was received, " 3934 + nitz); 3935 } 3936 return; 3937 } 3938 3939 if (millisSinceNitzReceived > Integer.MAX_VALUE) { 3940 // If the time is this far off, something is wrong > 24 days! 3941 if (DBG) { 3942 log("NITZ: not setting time, processing has taken " 3943 + (millisSinceNitzReceived / (1000 * 60 * 60 * 24)) 3944 + " days"); 3945 } 3946 return; 3947 } 3948 3949 // Note: with range checks above, cast to int is safe 3950 c.add(Calendar.MILLISECOND, (int)millisSinceNitzReceived); 3951 3952 if (DBG) { 3953 log("NITZ: Setting time of day to " + c.getTime() 3954 + " NITZ receive delay(ms): " + millisSinceNitzReceived 3955 + " gained(ms): " 3956 + (c.getTimeInMillis() - System.currentTimeMillis()) 3957 + " from " + nitz); 3958 } 3959 if (mPhone.isPhoneTypeGsm()) { 3960 setAndBroadcastNetworkSetTime(c.getTimeInMillis()); 3961 Rlog.i(LOG_TAG, "NITZ: after Setting time of day"); 3962 } else { 3963 if (getAutoTime()) { 3964 /** 3965 * Update system time automatically 3966 */ 3967 long gained = c.getTimeInMillis() - System.currentTimeMillis(); 3968 long timeSinceLastUpdate = SystemClock.elapsedRealtime() - mSavedAtTime; 3969 int nitzUpdateSpacing = Settings.Global.getInt(mCr, 3970 Settings.Global.NITZ_UPDATE_SPACING, mNitzUpdateSpacing); 3971 int nitzUpdateDiff = Settings.Global.getInt(mCr, 3972 Settings.Global.NITZ_UPDATE_DIFF, mNitzUpdateDiff); 3973 3974 if ((mSavedAtTime == 0) || (timeSinceLastUpdate > nitzUpdateSpacing) 3975 || (Math.abs(gained) > nitzUpdateDiff)) { 3976 if (DBG) { 3977 log("NITZ: Auto updating time of day to " + c.getTime() 3978 + " NITZ receive delay=" + millisSinceNitzReceived 3979 + "ms gained=" + gained + "ms from " + nitz); 3980 } 3981 3982 setAndBroadcastNetworkSetTime(c.getTimeInMillis()); 3983 } else { 3984 if (DBG) { 3985 log("NITZ: ignore, a previous update was " 3986 + timeSinceLastUpdate + "ms ago and gained=" + gained + "ms"); 3987 } 3988 return; 3989 } 3990 } 3991 } 3992 } 3993 SystemProperties.set("gsm.nitz.time", String.valueOf(c.getTimeInMillis())); 3994 saveNitzTime(c.getTimeInMillis()); 3995 mNitzUpdatedTime = true; 3996 } finally { 3997 if (DBG) { 3998 long end = SystemClock.elapsedRealtime(); 3999 log("NITZ: end=" + end + " dur=" + (end - start)); 4000 } 4001 mWakeLock.release(); 4002 } 4003 } catch (RuntimeException ex) { 4004 loge("NITZ: Parsing NITZ time " + nitz + " ex=" + ex); 4005 } 4006 } 4007 4008 private boolean getAutoTime() { 4009 try { 4010 return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME) > 0; 4011 } catch (Settings.SettingNotFoundException snfe) { 4012 return true; 4013 } 4014 } 4015 4016 private boolean getAutoTimeZone() { 4017 try { 4018 return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE) > 0; 4019 } catch (Settings.SettingNotFoundException snfe) { 4020 return true; 4021 } 4022 } 4023 4024 private void saveNitzTimeZone(String zoneId) { 4025 mSavedTimeZone = zoneId; 4026 } 4027 4028 private void saveNitzTime(long time) { 4029 mSavedTime = time; 4030 mSavedAtTime = SystemClock.elapsedRealtime(); 4031 } 4032 4033 /** 4034 * Set the timezone and send out a sticky broadcast so the system can 4035 * determine if the timezone was set by the carrier. 4036 * 4037 * @param zoneId timezone set by carrier 4038 */ 4039 private void setAndBroadcastNetworkSetTimeZone(String zoneId) { 4040 if (DBG) log("setAndBroadcastNetworkSetTimeZone: setTimeZone=" + zoneId); 4041 AlarmManager alarm = 4042 (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); 4043 alarm.setTimeZone(zoneId); 4044 Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE); 4045 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 4046 intent.putExtra("time-zone", zoneId); 4047 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4048 if (DBG) { 4049 log("setAndBroadcastNetworkSetTimeZone: call alarm.setTimeZone and broadcast zoneId=" + 4050 zoneId); 4051 } 4052 } 4053 4054 /** 4055 * Set the time and Send out a sticky broadcast so the system can determine 4056 * if the time was set by the carrier. 4057 * 4058 * @param time time set by network 4059 */ 4060 private void setAndBroadcastNetworkSetTime(long time) { 4061 if (DBG) log("setAndBroadcastNetworkSetTime: time=" + time + "ms"); 4062 SystemClock.setCurrentTimeMillis(time); 4063 Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIME); 4064 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 4065 intent.putExtra("time", time); 4066 mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); 4067 4068 TelephonyMetrics.getInstance().writeNITZEvent(mPhone.getPhoneId(), time); 4069 } 4070 4071 private void revertToNitzTime() { 4072 if (Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME, 0) == 0) { 4073 return; 4074 } 4075 if (DBG) { 4076 log("Reverting to NITZ Time: mSavedTime=" + mSavedTime + " mSavedAtTime=" + 4077 mSavedAtTime); 4078 } 4079 if (mSavedTime != 0 && mSavedAtTime != 0) { 4080 setAndBroadcastNetworkSetTime(mSavedTime 4081 + (SystemClock.elapsedRealtime() - mSavedAtTime)); 4082 } 4083 } 4084 4085 private void revertToNitzTimeZone() { 4086 if (Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE, 0) == 0) { 4087 return; 4088 } 4089 if (DBG) log("Reverting to NITZ TimeZone: tz='" + mSavedTimeZone); 4090 if (mSavedTimeZone != null) { 4091 setAndBroadcastNetworkSetTimeZone(mSavedTimeZone); 4092 } 4093 } 4094 4095 /** 4096 * Post a notification to NotificationManager for restricted state 4097 * 4098 * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE 4099 */ 4100 private void setNotification(int notifyType) { 4101 if (DBG) log("setNotification: create notification " + notifyType); 4102 4103 // Needed because sprout RIL sends these when they shouldn't? 4104 boolean isSetNotification = mPhone.getContext().getResources().getBoolean( 4105 com.android.internal.R.bool.config_user_notification_of_restrictied_mobile_access); 4106 if (!isSetNotification) { 4107 if (DBG) log("Ignore all the notifications"); 4108 return; 4109 } 4110 4111 Context context = mPhone.getContext(); 4112 4113 4114 CharSequence details = ""; 4115 CharSequence title = context.getText(com.android.internal.R.string.RestrictedOnData); 4116 int notificationId = CS_NOTIFICATION; 4117 4118 switch (notifyType) { 4119 case PS_ENABLED: 4120 long dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 4121 if (dataSubId != mPhone.getSubId()) { 4122 return; 4123 } 4124 notificationId = PS_NOTIFICATION; 4125 details = context.getText(com.android.internal.R.string.RestrictedOnData); 4126 break; 4127 case PS_DISABLED: 4128 notificationId = PS_NOTIFICATION; 4129 break; 4130 case CS_ENABLED: 4131 details = context.getText(com.android.internal.R.string.RestrictedOnAllVoice); 4132 break; 4133 case CS_NORMAL_ENABLED: 4134 details = context.getText(com.android.internal.R.string.RestrictedOnNormal); 4135 break; 4136 case CS_EMERGENCY_ENABLED: 4137 details = context.getText(com.android.internal.R.string.RestrictedOnEmergency); 4138 break; 4139 case CS_DISABLED: 4140 // do nothing and cancel the notification later 4141 break; 4142 } 4143 4144 if (DBG) log("setNotification: put notification " + title + " / " +details); 4145 mNotification = new Notification.Builder(context) 4146 .setWhen(System.currentTimeMillis()) 4147 .setAutoCancel(true) 4148 .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning) 4149 .setTicker(title) 4150 .setColor(context.getResources().getColor( 4151 com.android.internal.R.color.system_notification_accent_color)) 4152 .setContentTitle(title) 4153 .setContentText(details) 4154 .build(); 4155 4156 NotificationManager notificationManager = (NotificationManager) 4157 context.getSystemService(Context.NOTIFICATION_SERVICE); 4158 4159 if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) { 4160 // cancel previous post notification 4161 notificationManager.cancel(notificationId); 4162 } else { 4163 // update restricted state notification 4164 notificationManager.notify(notificationId, mNotification); 4165 } 4166 } 4167 4168 private UiccCardApplication getUiccCardApplication() { 4169 if (mPhone.isPhoneTypeGsm()) { 4170 return mUiccController.getUiccCardApplication(mPhone.getPhoneId(), 4171 UiccController.APP_FAM_3GPP); 4172 } else { 4173 return mUiccController.getUiccCardApplication(mPhone.getPhoneId(), 4174 UiccController.APP_FAM_3GPP2); 4175 } 4176 } 4177 4178 private void queueNextSignalStrengthPoll() { 4179 if (mDontPollSignalStrength) { 4180 // The radio is telling us about signal strength changes 4181 // we don't have to ask it 4182 return; 4183 } 4184 4185 Message msg; 4186 4187 msg = obtainMessage(); 4188 msg.what = EVENT_POLL_SIGNAL_STRENGTH; 4189 4190 long nextTime; 4191 4192 // TODO Don't poll signal strength if screen is off 4193 sendMessageDelayed(msg, POLL_PERIOD_MILLIS); 4194 } 4195 4196 private void notifyCdmaSubscriptionInfoReady() { 4197 if (mCdmaForSubscriptionInfoReadyRegistrants != null) { 4198 if (DBG) log("CDMA_SUBSCRIPTION: call notifyRegistrants()"); 4199 mCdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants(); 4200 } 4201 } 4202 4203 /** 4204 * Registration point for transition into DataConnection attached. 4205 * @param h handler to notify 4206 * @param what what code of message when delivered 4207 * @param obj placed in Message.obj 4208 */ 4209 public void registerForDataConnectionAttached(Handler h, int what, Object obj) { 4210 Registrant r = new Registrant(h, what, obj); 4211 mAttachedRegistrants.add(r); 4212 4213 if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) { 4214 r.notifyRegistrant(); 4215 } 4216 } 4217 public void unregisterForDataConnectionAttached(Handler h) { 4218 mAttachedRegistrants.remove(h); 4219 } 4220 4221 /** 4222 * Registration point for transition into DataConnection detached. 4223 * @param h handler to notify 4224 * @param what what code of message when delivered 4225 * @param obj placed in Message.obj 4226 */ 4227 public void registerForDataConnectionDetached(Handler h, int what, Object obj) { 4228 Registrant r = new Registrant(h, what, obj); 4229 mDetachedRegistrants.add(r); 4230 4231 if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) { 4232 r.notifyRegistrant(); 4233 } 4234 } 4235 public void unregisterForDataConnectionDetached(Handler h) { 4236 mDetachedRegistrants.remove(h); 4237 } 4238 4239 /** 4240 * Registration for DataConnection RIL Data Radio Technology changing. The 4241 * new radio technology will be returned AsyncResult#result as an Integer Object. 4242 * The AsyncResult will be in the notification Message#obj. 4243 * 4244 * @param h handler to notify 4245 * @param what what code of message when delivered 4246 * @param obj placed in Message.obj 4247 */ 4248 public void registerForDataRegStateOrRatChanged(Handler h, int what, Object obj) { 4249 Registrant r = new Registrant(h, what, obj); 4250 mDataRegStateOrRatChangedRegistrants.add(r); 4251 notifyDataRegStateRilRadioTechnologyChanged(); 4252 } 4253 public void unregisterForDataRegStateOrRatChanged(Handler h) { 4254 mDataRegStateOrRatChangedRegistrants.remove(h); 4255 } 4256 4257 /** 4258 * Registration point for transition into network attached. 4259 * @param h handler to notify 4260 * @param what what code of message when delivered 4261 * @param obj in Message.obj 4262 */ 4263 public void registerForNetworkAttached(Handler h, int what, Object obj) { 4264 Registrant r = new Registrant(h, what, obj); 4265 4266 mNetworkAttachedRegistrants.add(r); 4267 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 4268 r.notifyRegistrant(); 4269 } 4270 } 4271 public void unregisterForNetworkAttached(Handler h) { 4272 mNetworkAttachedRegistrants.remove(h); 4273 } 4274 4275 /** 4276 * Registration point for transition into packet service restricted zone. 4277 * @param h handler to notify 4278 * @param what what code of message when delivered 4279 * @param obj placed in Message.obj 4280 */ 4281 public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) { 4282 Registrant r = new Registrant(h, what, obj); 4283 mPsRestrictEnabledRegistrants.add(r); 4284 4285 if (mRestrictedState.isPsRestricted()) { 4286 r.notifyRegistrant(); 4287 } 4288 } 4289 4290 public void unregisterForPsRestrictedEnabled(Handler h) { 4291 mPsRestrictEnabledRegistrants.remove(h); 4292 } 4293 4294 /** 4295 * Registration point for transition out of packet service restricted zone. 4296 * @param h handler to notify 4297 * @param what what code of message when delivered 4298 * @param obj placed in Message.obj 4299 */ 4300 public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) { 4301 Registrant r = new Registrant(h, what, obj); 4302 mPsRestrictDisabledRegistrants.add(r); 4303 4304 if (mRestrictedState.isPsRestricted()) { 4305 r.notifyRegistrant(); 4306 } 4307 } 4308 4309 public void unregisterForPsRestrictedDisabled(Handler h) { 4310 mPsRestrictDisabledRegistrants.remove(h); 4311 } 4312 4313 /** 4314 * Clean up existing voice and data connection then turn off radio power. 4315 * 4316 * Hang up the existing voice calls to decrease call drop rate. 4317 */ 4318 public void powerOffRadioSafely(DcTracker dcTracker) { 4319 synchronized (this) { 4320 if (!mPendingRadioPowerOffAfterDataOff) { 4321 if (mPhone.isPhoneTypeGsm() || mPhone.isPhoneTypeCdmaLte()) { 4322 int dds = SubscriptionManager.getDefaultDataSubscriptionId(); 4323 // To minimize race conditions we call cleanUpAllConnections on 4324 // both if else paths instead of before this isDisconnected test. 4325 if (dcTracker.isDisconnected() 4326 && (dds == mPhone.getSubId() 4327 || (dds != mPhone.getSubId() 4328 && ProxyController.getInstance().isDataDisconnected(dds)))) { 4329 // To minimize race conditions we do this after isDisconnected 4330 dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF); 4331 if (DBG) log("Data disconnected, turn off radio right away."); 4332 hangupAndPowerOff(); 4333 } else { 4334 // hang up all active voice calls first 4335 if (mPhone.isPhoneTypeGsm() && mPhone.isInCall()) { 4336 mPhone.mCT.mRingingCall.hangupIfAlive(); 4337 mPhone.mCT.mBackgroundCall.hangupIfAlive(); 4338 mPhone.mCT.mForegroundCall.hangupIfAlive(); 4339 } 4340 dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF); 4341 if (dds != mPhone.getSubId() 4342 && !ProxyController.getInstance().isDataDisconnected(dds)) { 4343 if (DBG) log("Data is active on DDS. Wait for all data disconnect"); 4344 // Data is not disconnected on DDS. Wait for the data disconnect complete 4345 // before sending the RADIO_POWER off. 4346 ProxyController.getInstance().registerForAllDataDisconnected(dds, this, 4347 EVENT_ALL_DATA_DISCONNECTED, null); 4348 mPendingRadioPowerOffAfterDataOff = true; 4349 } 4350 Message msg = Message.obtain(this); 4351 msg.what = EVENT_SET_RADIO_POWER_OFF; 4352 msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag; 4353 if (sendMessageDelayed(msg, 30000)) { 4354 if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio."); 4355 mPendingRadioPowerOffAfterDataOff = true; 4356 } else { 4357 log("Cannot send delayed Msg, turn off radio right away."); 4358 hangupAndPowerOff(); 4359 mPendingRadioPowerOffAfterDataOff = false; 4360 } 4361 } 4362 } else { 4363 // In some network, deactivate PDP connection cause releasing of RRC connection, 4364 // which MM/IMSI detaching request needs. Without this detaching, network can 4365 // not release the network resources previously attached. 4366 // So we are avoiding data detaching on these networks. 4367 String[] networkNotClearData = mPhone.getContext().getResources() 4368 .getStringArray(com.android.internal.R.array.networks_not_clear_data); 4369 String currentNetwork = mSS.getOperatorNumeric(); 4370 if ((networkNotClearData != null) && (currentNetwork != null)) { 4371 for (int i = 0; i < networkNotClearData.length; i++) { 4372 if (currentNetwork.equals(networkNotClearData[i])) { 4373 // Don't clear data connection for this carrier 4374 if (DBG) 4375 log("Not disconnecting data for " + currentNetwork); 4376 hangupAndPowerOff(); 4377 return; 4378 } 4379 } 4380 } 4381 // To minimize race conditions we call cleanUpAllConnections on 4382 // both if else paths instead of before this isDisconnected test. 4383 if (dcTracker.isDisconnected()) { 4384 // To minimize race conditions we do this after isDisconnected 4385 dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF); 4386 if (DBG) log("Data disconnected, turn off radio right away."); 4387 hangupAndPowerOff(); 4388 } else { 4389 dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF); 4390 Message msg = Message.obtain(this); 4391 msg.what = EVENT_SET_RADIO_POWER_OFF; 4392 msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag; 4393 if (sendMessageDelayed(msg, 30000)) { 4394 if (DBG) 4395 log("Wait upto 30s for data to disconnect, then turn off radio."); 4396 mPendingRadioPowerOffAfterDataOff = true; 4397 } else { 4398 log("Cannot send delayed Msg, turn off radio right away."); 4399 hangupAndPowerOff(); 4400 } 4401 } 4402 } 4403 } 4404 } 4405 } 4406 4407 /** 4408 * process the pending request to turn radio off after data is disconnected 4409 * 4410 * return true if there is pending request to process; false otherwise. 4411 */ 4412 public boolean processPendingRadioPowerOffAfterDataOff() { 4413 synchronized(this) { 4414 if (mPendingRadioPowerOffAfterDataOff) { 4415 if (DBG) log("Process pending request to turn radio off."); 4416 mPendingRadioPowerOffAfterDataOffTag += 1; 4417 hangupAndPowerOff(); 4418 mPendingRadioPowerOffAfterDataOff = false; 4419 return true; 4420 } 4421 return false; 4422 } 4423 } 4424 4425 /** 4426 * send signal-strength-changed notification if changed Called both for 4427 * solicited and unsolicited signal strength updates 4428 * 4429 * @return true if the signal strength changed and a notification was sent. 4430 */ 4431 protected boolean onSignalStrengthResult(AsyncResult ar) { 4432 boolean isGsm = false; 4433 //override isGsm for CDMA LTE 4434 if (mPhone.isPhoneTypeGsm() || 4435 (mPhone.isPhoneTypeCdmaLte() && 4436 ServiceState.isLte(mSS.getRilDataRadioTechnology()))) { 4437 isGsm = true; 4438 } 4439 4440 // This signal is used for both voice and data radio signal so parse 4441 // all fields 4442 4443 if ((ar.exception == null) && (ar.result != null)) { 4444 mSignalStrength = (SignalStrength) ar.result; 4445 mSignalStrength.validateInput(); 4446 mSignalStrength.setGsm(isGsm); 4447 } else { 4448 log("onSignalStrengthResult() Exception from RIL : " + ar.exception); 4449 mSignalStrength = new SignalStrength(isGsm); 4450 } 4451 4452 boolean ssChanged = notifySignalStrength(); 4453 4454 return ssChanged; 4455 } 4456 4457 /** 4458 * Hang up all voice call and turn off radio. Implemented by derived class. 4459 */ 4460 protected void hangupAndPowerOff() { 4461 // hang up all active voice calls 4462 if (!mPhone.isPhoneTypeGsm() || mPhone.isInCall()) { 4463 mPhone.mCT.mRingingCall.hangupIfAlive(); 4464 mPhone.mCT.mBackgroundCall.hangupIfAlive(); 4465 mPhone.mCT.mForegroundCall.hangupIfAlive(); 4466 } 4467 4468 mCi.setRadioPower(false, null); 4469 4470 } 4471 4472 /** Cancel a pending (if any) pollState() operation */ 4473 protected void cancelPollState() { 4474 // This will effectively cancel the rest of the poll requests. 4475 mPollingContext = new int[1]; 4476 } 4477 4478 /** 4479 * Return true if time zone needs fixing. 4480 * 4481 * @param phone 4482 * @param operatorNumeric 4483 * @param prevOperatorNumeric 4484 * @param needToFixTimeZone 4485 * @return true if time zone needs to be fixed 4486 */ 4487 protected boolean shouldFixTimeZoneNow(Phone phone, String operatorNumeric, 4488 String prevOperatorNumeric, boolean needToFixTimeZone) { 4489 // Return false if the mcc isn't valid as we don't know where we are. 4490 // Return true if we have an IccCard and the mcc changed or we 4491 // need to fix it because when the NITZ time came in we didn't 4492 // know the country code. 4493 4494 // If mcc is invalid then we'll return false 4495 int mcc; 4496 try { 4497 mcc = Integer.parseInt(operatorNumeric.substring(0, 3)); 4498 } catch (Exception e) { 4499 if (DBG) { 4500 log("shouldFixTimeZoneNow: no mcc, operatorNumeric=" + operatorNumeric + 4501 " retVal=false"); 4502 } 4503 return false; 4504 } 4505 4506 // If prevMcc is invalid will make it different from mcc 4507 // so we'll return true if the card exists. 4508 int prevMcc; 4509 try { 4510 prevMcc = Integer.parseInt(prevOperatorNumeric.substring(0, 3)); 4511 } catch (Exception e) { 4512 prevMcc = mcc + 1; 4513 } 4514 4515 // Determine if the Icc card exists 4516 boolean iccCardExist = false; 4517 if (mUiccApplcation != null) { 4518 iccCardExist = mUiccApplcation.getState() != AppState.APPSTATE_UNKNOWN; 4519 } 4520 4521 // Determine retVal 4522 boolean retVal = ((iccCardExist && (mcc != prevMcc)) || needToFixTimeZone); 4523 if (DBG) { 4524 long ctm = System.currentTimeMillis(); 4525 log("shouldFixTimeZoneNow: retVal=" + retVal + 4526 " iccCardExist=" + iccCardExist + 4527 " operatorNumeric=" + operatorNumeric + " mcc=" + mcc + 4528 " prevOperatorNumeric=" + prevOperatorNumeric + " prevMcc=" + prevMcc + 4529 " needToFixTimeZone=" + needToFixTimeZone + 4530 " ltod=" + TimeUtils.logTimeOfDay(ctm)); 4531 } 4532 return retVal; 4533 } 4534 4535 public String getSystemProperty(String property, String defValue) { 4536 return TelephonyManager.getTelephonyProperty(mPhone.getPhoneId(), property, defValue); 4537 } 4538 4539 /** 4540 * @return all available cell information or null if none. 4541 */ 4542 public List<CellInfo> getAllCellInfo() { 4543 CellInfoResult result = new CellInfoResult(); 4544 if (VDBG) log("SST.getAllCellInfo(): E"); 4545 int ver = mCi.getRilVersion(); 4546 if (ver >= 8) { 4547 if (isCallerOnDifferentThread()) { 4548 if ((SystemClock.elapsedRealtime() - mLastCellInfoListTime) 4549 > LAST_CELL_INFO_LIST_MAX_AGE_MS) { 4550 Message msg = obtainMessage(EVENT_GET_CELL_INFO_LIST, result); 4551 synchronized(result.lockObj) { 4552 result.list = null; 4553 mCi.getCellInfoList(msg); 4554 try { 4555 result.lockObj.wait(5000); 4556 } catch (InterruptedException e) { 4557 e.printStackTrace(); 4558 } 4559 } 4560 } else { 4561 if (DBG) log("SST.getAllCellInfo(): return last, back to back calls"); 4562 result.list = mLastCellInfoList; 4563 } 4564 } else { 4565 if (DBG) log("SST.getAllCellInfo(): return last, same thread can't block"); 4566 result.list = mLastCellInfoList; 4567 } 4568 } else { 4569 if (DBG) log("SST.getAllCellInfo(): not implemented"); 4570 result.list = null; 4571 } 4572 synchronized(result.lockObj) { 4573 if (result.list != null) { 4574 if (VDBG) log("SST.getAllCellInfo(): X size=" + result.list.size() 4575 + " list=" + result.list); 4576 return result.list; 4577 } else { 4578 if (DBG) log("SST.getAllCellInfo(): X size=0 list=null"); 4579 return null; 4580 } 4581 } 4582 } 4583 4584 /** 4585 * @return signal strength 4586 */ 4587 public SignalStrength getSignalStrength() { 4588 return mSignalStrength; 4589 } 4590 4591 /** 4592 * Registration point for subscription info ready 4593 * @param h handler to notify 4594 * @param what what code of message when delivered 4595 * @param obj placed in Message.obj 4596 */ 4597 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) { 4598 Registrant r = new Registrant(h, what, obj); 4599 mCdmaForSubscriptionInfoReadyRegistrants.add(r); 4600 4601 if (isMinInfoReady()) { 4602 r.notifyRegistrant(); 4603 } 4604 } 4605 4606 public void unregisterForSubscriptionInfoReady(Handler h) { 4607 mCdmaForSubscriptionInfoReadyRegistrants.remove(h); 4608 } 4609 4610 /** 4611 * Save current source of cdma subscription 4612 * @param source - 1 for NV, 0 for RUIM 4613 */ 4614 private void saveCdmaSubscriptionSource(int source) { 4615 log("Storing cdma subscription source: " + source); 4616 Settings.Global.putInt(mPhone.getContext().getContentResolver(), 4617 Settings.Global.CDMA_SUBSCRIPTION_MODE, 4618 source); 4619 log("Read from settings: " + Settings.Global.getInt(mPhone.getContext().getContentResolver(), 4620 Settings.Global.CDMA_SUBSCRIPTION_MODE, -1)); 4621 } 4622 4623 private void getSubscriptionInfoAndStartPollingThreads() { 4624 mCi.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION)); 4625 4626 // Get Registration Information 4627 pollState(); 4628 } 4629 4630 private void handleCdmaSubscriptionSource(int newSubscriptionSource) { 4631 log("Subscription Source : " + newSubscriptionSource); 4632 mIsSubscriptionFromRuim = 4633 (newSubscriptionSource == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM); 4634 log("isFromRuim: " + mIsSubscriptionFromRuim); 4635 saveCdmaSubscriptionSource(newSubscriptionSource); 4636 if (!mIsSubscriptionFromRuim) { 4637 // NV is ready when subscription source is NV 4638 sendMessage(obtainMessage(EVENT_NV_READY)); 4639 } 4640 } 4641 4642 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4643 pw.println("ServiceStateTracker:"); 4644 pw.println(" mSubId=" + mSubId); 4645 pw.println(" mSS=" + mSS); 4646 pw.println(" mNewSS=" + mNewSS); 4647 pw.println(" mVoiceCapable=" + mVoiceCapable); 4648 pw.println(" mRestrictedState=" + mRestrictedState); 4649 pw.println(" mPollingContext=" + mPollingContext + " - " + 4650 (mPollingContext != null ? mPollingContext[0] : "")); 4651 pw.println(" mDesiredPowerState=" + mDesiredPowerState); 4652 pw.println(" mDontPollSignalStrength=" + mDontPollSignalStrength); 4653 pw.println(" mSignalStrength=" + mSignalStrength); 4654 pw.println(" mLastSignalStrength=" + mLastSignalStrength); 4655 pw.println(" mRestrictedState=" + mRestrictedState); 4656 pw.println(" mPendingRadioPowerOffAfterDataOff=" + mPendingRadioPowerOffAfterDataOff); 4657 pw.println(" mPendingRadioPowerOffAfterDataOffTag=" + mPendingRadioPowerOffAfterDataOffTag); 4658 pw.println(" mCellLoc=" + mCellLoc); 4659 pw.println(" mNewCellLoc=" + mNewCellLoc); 4660 pw.println(" mLastCellInfoListTime=" + mLastCellInfoListTime); 4661 pw.println(" mPreferredNetworkType=" + mPreferredNetworkType); 4662 pw.println(" mMaxDataCalls=" + mMaxDataCalls); 4663 pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls); 4664 pw.println(" mReasonDataDenied=" + mReasonDataDenied); 4665 pw.println(" mNewReasonDataDenied=" + mNewReasonDataDenied); 4666 pw.println(" mGsmRoaming=" + mGsmRoaming); 4667 pw.println(" mDataRoaming=" + mDataRoaming); 4668 pw.println(" mEmergencyOnly=" + mEmergencyOnly); 4669 pw.println(" mNeedFixZoneAfterNitz=" + mNeedFixZoneAfterNitz); 4670 pw.flush(); 4671 pw.println(" mZoneOffset=" + mZoneOffset); 4672 pw.println(" mZoneDst=" + mZoneDst); 4673 pw.println(" mZoneTime=" + mZoneTime); 4674 pw.println(" mGotCountryCode=" + mGotCountryCode); 4675 pw.println(" mNitzUpdatedTime=" + mNitzUpdatedTime); 4676 pw.println(" mSavedTimeZone=" + mSavedTimeZone); 4677 pw.println(" mSavedTime=" + mSavedTime); 4678 pw.println(" mSavedAtTime=" + mSavedAtTime); 4679 pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck); 4680 pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg); 4681 pw.println(" mNotification=" + mNotification); 4682 pw.println(" mWakeLock=" + mWakeLock); 4683 pw.println(" mCurSpn=" + mCurSpn); 4684 pw.println(" mCurDataSpn=" + mCurDataSpn); 4685 pw.println(" mCurShowSpn=" + mCurShowSpn); 4686 pw.println(" mCurPlmn=" + mCurPlmn); 4687 pw.println(" mCurShowPlmn=" + mCurShowPlmn); 4688 pw.flush(); 4689 pw.println(" mCurrentOtaspMode=" + mCurrentOtaspMode); 4690 pw.println(" mRoamingIndicator=" + mRoamingIndicator); 4691 pw.println(" mIsInPrl=" + mIsInPrl); 4692 pw.println(" mDefaultRoamingIndicator=" + mDefaultRoamingIndicator); 4693 pw.println(" mRegistrationState=" + mRegistrationState); 4694 pw.println(" mMdn=" + mMdn); 4695 pw.println(" mHomeSystemId=" + mHomeSystemId); 4696 pw.println(" mHomeNetworkId=" + mHomeNetworkId); 4697 pw.println(" mMin=" + mMin); 4698 pw.println(" mPrlVersion=" + mPrlVersion); 4699 pw.println(" mIsMinInfoReady=" + mIsMinInfoReady); 4700 pw.println(" mIsEriTextLoaded=" + mIsEriTextLoaded); 4701 pw.println(" mIsSubscriptionFromRuim=" + mIsSubscriptionFromRuim); 4702 pw.println(" mCdmaSSM=" + mCdmaSSM); 4703 pw.println(" mRegistrationDeniedReason=" + mRegistrationDeniedReason); 4704 pw.println(" mCurrentCarrier=" + mCurrentCarrier); 4705 pw.flush(); 4706 pw.println(" mImsRegistered=" + mImsRegistered); 4707 pw.println(" mImsRegistrationOnOff=" + mImsRegistrationOnOff); 4708 pw.println(" mAlarmSwitch=" + mAlarmSwitch); 4709 pw.println(" mRadioDisabledByCarrier" + mRadioDisabledByCarrier); 4710 pw.println(" mPowerOffDelayNeed=" + mPowerOffDelayNeed); 4711 pw.println(" mDeviceShuttingDown=" + mDeviceShuttingDown); 4712 pw.println(" mSpnUpdatePending=" + mSpnUpdatePending); 4713 4714 pw.println(" Roaming Log:"); 4715 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 4716 ipw.increaseIndent(); 4717 mRoamingLog.dump(fd, ipw, args); 4718 ipw.decreaseIndent(); 4719 4720 ipw.println(" Attach Log:"); 4721 ipw.increaseIndent(); 4722 mAttachLog.dump(fd, ipw, args); 4723 ipw.decreaseIndent(); 4724 4725 ipw.println(" Phone Change Log:"); 4726 ipw.increaseIndent(); 4727 mPhoneTypeLog.dump(fd, ipw, args); 4728 ipw.decreaseIndent(); 4729 4730 ipw.println(" Rat Change Log:"); 4731 ipw.increaseIndent(); 4732 mRatLog.dump(fd, ipw, args); 4733 ipw.decreaseIndent(); 4734 } 4735 4736 public boolean isImsRegistered() { 4737 return mImsRegistered; 4738 } 4739 /** 4740 * Verifies the current thread is the same as the thread originally 4741 * used in the initialization of this instance. Throws RuntimeException 4742 * if not. 4743 * 4744 * @exception RuntimeException if the current thread is not 4745 * the thread that originally obtained this Phone instance. 4746 */ 4747 protected void checkCorrectThread() { 4748 if (Thread.currentThread() != getLooper().getThread()) { 4749 throw new RuntimeException( 4750 "ServiceStateTracker must be used from within one thread"); 4751 } 4752 } 4753 4754 protected boolean isCallerOnDifferentThread() { 4755 boolean value = Thread.currentThread() != getLooper().getThread(); 4756 if (VDBG) log("isCallerOnDifferentThread: " + value); 4757 return value; 4758 } 4759 4760 protected void updateCarrierMccMncConfiguration(String newOp, String oldOp, Context context) { 4761 // if we have a change in operator, notify wifi (even to/from none) 4762 if (((newOp == null) && (TextUtils.isEmpty(oldOp) == false)) || 4763 ((newOp != null) && (newOp.equals(oldOp) == false))) { 4764 log("update mccmnc=" + newOp + " fromServiceState=true"); 4765 MccTable.updateMccMncConfiguration(context, newOp, true); 4766 } 4767 } 4768 4769 /** 4770 * Check ISO country by MCC to see if phone is roaming in same registered country 4771 */ 4772 protected boolean inSameCountry(String operatorNumeric) { 4773 if (TextUtils.isEmpty(operatorNumeric) || (operatorNumeric.length() < 5)) { 4774 // Not a valid network 4775 return false; 4776 } 4777 final String homeNumeric = getHomeOperatorNumeric(); 4778 if (TextUtils.isEmpty(homeNumeric) || (homeNumeric.length() < 5)) { 4779 // Not a valid SIM MCC 4780 return false; 4781 } 4782 boolean inSameCountry = true; 4783 final String networkMCC = operatorNumeric.substring(0, 3); 4784 final String homeMCC = homeNumeric.substring(0, 3); 4785 final String networkCountry = MccTable.countryCodeForMcc(Integer.parseInt(networkMCC)); 4786 final String homeCountry = MccTable.countryCodeForMcc(Integer.parseInt(homeMCC)); 4787 if (networkCountry.isEmpty() || homeCountry.isEmpty()) { 4788 // Not a valid country 4789 return false; 4790 } 4791 inSameCountry = homeCountry.equals(networkCountry); 4792 if (inSameCountry) { 4793 return inSameCountry; 4794 } 4795 // special same country cases 4796 if ("us".equals(homeCountry) && "vi".equals(networkCountry)) { 4797 inSameCountry = true; 4798 } else if ("vi".equals(homeCountry) && "us".equals(networkCountry)) { 4799 inSameCountry = true; 4800 } 4801 return inSameCountry; 4802 } 4803 4804 /** 4805 * Set both voice and data roaming type, 4806 * judging from the ISO country of SIM VS network. 4807 */ 4808 protected void setRoamingType(ServiceState currentServiceState) { 4809 final boolean isVoiceInService = 4810 (currentServiceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE); 4811 if (isVoiceInService) { 4812 if (currentServiceState.getVoiceRoaming()) { 4813 if (mPhone.isPhoneTypeGsm()) { 4814 // check roaming type by MCC 4815 if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) { 4816 currentServiceState.setVoiceRoamingType( 4817 ServiceState.ROAMING_TYPE_DOMESTIC); 4818 } else { 4819 currentServiceState.setVoiceRoamingType( 4820 ServiceState.ROAMING_TYPE_INTERNATIONAL); 4821 } 4822 } else { 4823 // some carrier defines international roaming by indicator 4824 int[] intRoamingIndicators = mPhone.getContext().getResources().getIntArray( 4825 com.android.internal.R.array.config_cdma_international_roaming_indicators); 4826 if ((intRoamingIndicators != null) && (intRoamingIndicators.length > 0)) { 4827 // It's domestic roaming at least now 4828 currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC); 4829 int curRoamingIndicator = currentServiceState.getCdmaRoamingIndicator(); 4830 for (int i = 0; i < intRoamingIndicators.length; i++) { 4831 if (curRoamingIndicator == intRoamingIndicators[i]) { 4832 currentServiceState.setVoiceRoamingType( 4833 ServiceState.ROAMING_TYPE_INTERNATIONAL); 4834 break; 4835 } 4836 } 4837 } else { 4838 // check roaming type by MCC 4839 if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) { 4840 currentServiceState.setVoiceRoamingType( 4841 ServiceState.ROAMING_TYPE_DOMESTIC); 4842 } else { 4843 currentServiceState.setVoiceRoamingType( 4844 ServiceState.ROAMING_TYPE_INTERNATIONAL); 4845 } 4846 } 4847 } 4848 } else { 4849 currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING); 4850 } 4851 } 4852 final boolean isDataInService = 4853 (currentServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE); 4854 final int dataRegType = currentServiceState.getRilDataRadioTechnology(); 4855 if (isDataInService) { 4856 if (!currentServiceState.getDataRoaming()) { 4857 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING); 4858 } else { 4859 if (mPhone.isPhoneTypeGsm()) { 4860 if (ServiceState.isGsm(dataRegType)) { 4861 if (isVoiceInService) { 4862 // GSM data should have the same state as voice 4863 currentServiceState.setDataRoamingType(currentServiceState 4864 .getVoiceRoamingType()); 4865 } else { 4866 // we can not decide GSM data roaming type without voice 4867 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN); 4868 } 4869 } else { 4870 // we can not decide 3gpp2 roaming state here 4871 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN); 4872 } 4873 } else { 4874 if (ServiceState.isCdma(dataRegType)) { 4875 if (isVoiceInService) { 4876 // CDMA data should have the same state as voice 4877 currentServiceState.setDataRoamingType(currentServiceState 4878 .getVoiceRoamingType()); 4879 } else { 4880 // we can not decide CDMA data roaming type without voice 4881 // set it as same as last time 4882 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN); 4883 } 4884 } else { 4885 // take it as 3GPP roaming 4886 if (inSameCountry(currentServiceState.getDataOperatorNumeric())) { 4887 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC); 4888 } else { 4889 currentServiceState.setDataRoamingType( 4890 ServiceState.ROAMING_TYPE_INTERNATIONAL); 4891 } 4892 } 4893 } 4894 } 4895 } 4896 } 4897 4898 private void setSignalStrengthDefaultValues() { 4899 mSignalStrength = new SignalStrength(true); 4900 } 4901 4902 protected String getHomeOperatorNumeric() { 4903 String numeric = ((TelephonyManager) mPhone.getContext(). 4904 getSystemService(Context.TELEPHONY_SERVICE)). 4905 getSimOperatorNumericForPhone(mPhone.getPhoneId()); 4906 if (!mPhone.isPhoneTypeGsm() && TextUtils.isEmpty(numeric)) { 4907 numeric = SystemProperties.get(GsmCdmaPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, ""); 4908 } 4909 return numeric; 4910 } 4911 4912 protected int getPhoneId() { 4913 return mPhone.getPhoneId(); 4914 } 4915 4916 /* Reset Service state when IWLAN is enabled as polling in airplane mode 4917 * causes state to go to OUT_OF_SERVICE state instead of STATE_OFF 4918 */ 4919 protected void resetServiceStateInIwlanMode() { 4920 if (mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) { 4921 boolean resetIwlanRatVal = false; 4922 log("set service state as POWER_OFF"); 4923 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 4924 == mNewSS.getRilDataRadioTechnology()) { 4925 log("pollStateDone: mNewSS = " + mNewSS); 4926 log("pollStateDone: reset iwlan RAT value"); 4927 resetIwlanRatVal = true; 4928 } 4929 // operator info should be kept in SS 4930 String operator = mNewSS.getOperatorAlphaLong(); 4931 mNewSS.setStateOff(); 4932 if (resetIwlanRatVal) { 4933 mNewSS.setRilDataRadioTechnology(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN); 4934 mNewSS.setDataRegState(ServiceState.STATE_IN_SERVICE); 4935 mNewSS.setOperatorAlphaLong(operator); 4936 log("pollStateDone: mNewSS = " + mNewSS); 4937 } 4938 } 4939 } 4940 4941 /** 4942 * Check if device is non-roaming and always on home network. 4943 * 4944 * @param b carrier config bundle obtained from CarrierConfigManager 4945 * @return true if network is always on home network, false otherwise 4946 * @see CarrierConfigManager 4947 */ 4948 protected final boolean alwaysOnHomeNetwork(BaseBundle b) { 4949 return b.getBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL); 4950 } 4951 4952 /** 4953 * Check if the network identifier has membership in the set of 4954 * network identifiers stored in the carrier config bundle. 4955 * 4956 * @param b carrier config bundle obtained from CarrierConfigManager 4957 * @param network The network identifier to check network existence in bundle 4958 * @param key The key to index into the bundle presenting a string array of 4959 * networks to check membership 4960 * @return true if network has membership in bundle networks, false otherwise 4961 * @see CarrierConfigManager 4962 */ 4963 private boolean isInNetwork(BaseBundle b, String network, String key) { 4964 String[] networks = b.getStringArray(key); 4965 4966 if (networks != null && Arrays.asList(networks).contains(network)) { 4967 return true; 4968 } 4969 return false; 4970 } 4971 4972 protected final boolean isRoamingInGsmNetwork(BaseBundle b, String network) { 4973 return isInNetwork(b, network, CarrierConfigManager.KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY); 4974 } 4975 4976 protected final boolean isNonRoamingInGsmNetwork(BaseBundle b, String network) { 4977 return isInNetwork(b, network, CarrierConfigManager.KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY); 4978 } 4979 4980 protected final boolean isRoamingInCdmaNetwork(BaseBundle b, String network) { 4981 return isInNetwork(b, network, CarrierConfigManager.KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY); 4982 } 4983 4984 protected final boolean isNonRoamingInCdmaNetwork(BaseBundle b, String network) { 4985 return isInNetwork(b, network, CarrierConfigManager.KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY); 4986 } 4987 4988 /** Check if the device is shutting down. */ 4989 public boolean isDeviceShuttingDown() { 4990 return mDeviceShuttingDown; 4991 } 4992} 4993