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