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