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