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