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