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