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