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( 2502 context, 0, intent, PendingIntent.FLAG_IMMUTABLE); 2503 2504 mAlarmSwitch = true; 2505 if (DBG) log("Alarm setting"); 2506 am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 2507 SystemClock.elapsedRealtime() + 3000, mRadioOffIntent); 2508 } else { 2509 DcTracker dcTracker = mPhone.mDcTracker; 2510 powerOffRadioSafely(dcTracker); 2511 } 2512 } else { 2513 DcTracker dcTracker = mPhone.mDcTracker; 2514 powerOffRadioSafely(dcTracker); 2515 } 2516 } else if (mDeviceShuttingDown && mCi.getRadioState().isAvailable()) { 2517 mCi.requestShutdown(null); 2518 } 2519 } 2520 onUpdateIccAvailability()2521 protected void onUpdateIccAvailability() { 2522 if (mUiccController == null ) { 2523 return; 2524 } 2525 2526 UiccCardApplication newUiccApplication = getUiccCardApplication(); 2527 2528 if (mUiccApplcation != newUiccApplication) { 2529 if (mUiccApplcation != null) { 2530 log("Removing stale icc objects."); 2531 mUiccApplcation.unregisterForReady(this); 2532 if (mIccRecords != null) { 2533 mIccRecords.unregisterForRecordsLoaded(this); 2534 } 2535 mIccRecords = null; 2536 mUiccApplcation = null; 2537 } 2538 if (newUiccApplication != null) { 2539 log("New card found"); 2540 mUiccApplcation = newUiccApplication; 2541 mIccRecords = mUiccApplcation.getIccRecords(); 2542 if (mPhone.isPhoneTypeGsm()) { 2543 mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null); 2544 if (mIccRecords != null) { 2545 mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null); 2546 } 2547 } else if (mIsSubscriptionFromRuim) { 2548 mUiccApplcation.registerForReady(this, EVENT_RUIM_READY, null); 2549 if (mIccRecords != null) { 2550 mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null); 2551 } 2552 } 2553 } 2554 } 2555 } 2556 logRoamingChange()2557 private void logRoamingChange() { 2558 mRoamingLog.log(mSS.toString()); 2559 } 2560 logAttachChange()2561 private void logAttachChange() { 2562 mAttachLog.log(mSS.toString()); 2563 } 2564 logPhoneTypeChange()2565 private void logPhoneTypeChange() { 2566 mPhoneTypeLog.log(Integer.toString(mPhone.getPhoneType())); 2567 } 2568 logRatChange()2569 private void logRatChange() { 2570 mRatLog.log(mSS.toString()); 2571 } 2572 log(String s)2573 protected final void log(String s) { 2574 Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "] " + s); 2575 } 2576 loge(String s)2577 protected final void loge(String s) { 2578 Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "] " + s); 2579 } 2580 2581 /** 2582 * @return The current GPRS state. IN_SERVICE is the same as "attached" 2583 * and OUT_OF_SERVICE is the same as detached. 2584 */ getCurrentDataConnectionState()2585 public int getCurrentDataConnectionState() { 2586 return mSS.getDataRegState(); 2587 } 2588 2589 /** 2590 * @return true if phone is camping on a technology (eg UMTS) 2591 * that could support voice and data simultaneously. 2592 */ isConcurrentVoiceAndDataAllowed()2593 public boolean isConcurrentVoiceAndDataAllowed() { 2594 if (mSS.getCssIndicator() == 1) { 2595 // Checking the Concurrent Service Supported flag first for all phone types. 2596 return true; 2597 } else if (mPhone.isPhoneTypeGsm()) { 2598 return (mSS.getRilDataRadioTechnology() >= ServiceState.RIL_RADIO_TECHNOLOGY_UMTS); 2599 } else { 2600 return false; 2601 } 2602 } 2603 2604 /** Called when the service state of ImsPhone is changed. */ onImsServiceStateChanged()2605 public void onImsServiceStateChanged() { 2606 sendMessage(obtainMessage(EVENT_IMS_SERVICE_STATE_CHANGED)); 2607 } 2608 setImsRegistrationState(boolean registered)2609 public void setImsRegistrationState(boolean registered) { 2610 log("ImsRegistrationState - registered : " + registered); 2611 2612 if (mImsRegistrationOnOff && !registered) { 2613 if (mAlarmSwitch) { 2614 mImsRegistrationOnOff = registered; 2615 2616 Context context = mPhone.getContext(); 2617 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 2618 am.cancel(mRadioOffIntent); 2619 mAlarmSwitch = false; 2620 2621 sendMessage(obtainMessage(EVENT_CHANGE_IMS_STATE)); 2622 return; 2623 } 2624 } 2625 mImsRegistrationOnOff = registered; 2626 } 2627 onImsCapabilityChanged()2628 public void onImsCapabilityChanged() { 2629 sendMessage(obtainMessage(EVENT_IMS_CAPABILITY_CHANGED)); 2630 } 2631 isRadioOn()2632 public boolean isRadioOn() { 2633 return mCi.getRadioState() == CommandsInterface.RadioState.RADIO_ON; 2634 } 2635 2636 /** 2637 * A complete "service state" from our perspective is 2638 * composed of a handful of separate requests to the radio. 2639 * 2640 * We make all of these requests at once, but then abandon them 2641 * and start over again if the radio notifies us that some 2642 * event has changed 2643 */ pollState()2644 public void pollState() { 2645 pollState(false); 2646 } 2647 /** 2648 * We insist on polling even if the radio says its off. 2649 * Used when we get a network changed notification 2650 * but the radio is off - part of iwlan hack 2651 */ modemTriggeredPollState()2652 private void modemTriggeredPollState() { 2653 pollState(true); 2654 } 2655 pollState(boolean modemTriggered)2656 public void pollState(boolean modemTriggered) { 2657 mPollingContext = new int[1]; 2658 mPollingContext[0] = 0; 2659 2660 log("pollState: modemTriggered=" + modemTriggered); 2661 2662 switch (mCi.getRadioState()) { 2663 case RADIO_UNAVAILABLE: 2664 mNewSS.setStateOutOfService(); 2665 mNewCellLoc.setStateInvalid(); 2666 setSignalStrengthDefaultValues(); 2667 mNitzState.handleNetworkUnavailable(); 2668 pollStateDone(); 2669 break; 2670 2671 case RADIO_OFF: 2672 mNewSS.setStateOff(); 2673 mNewCellLoc.setStateInvalid(); 2674 setSignalStrengthDefaultValues(); 2675 mNitzState.handleNetworkUnavailable(); 2676 // don't poll when device is shutting down or the poll was not modemTrigged 2677 // (they sent us new radio data) and current network is not IWLAN 2678 if (mDeviceShuttingDown || 2679 (!modemTriggered && ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 2680 != mSS.getRilDataRadioTechnology())) { 2681 pollStateDone(); 2682 break; 2683 } 2684 2685 default: 2686 // Issue all poll-related commands at once then count down the responses, which 2687 // are allowed to arrive out-of-order 2688 // TODO: Add WLAN support. 2689 mPollingContext[0]++; 2690 mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR, mPollingContext)); 2691 2692 mPollingContext[0]++; 2693 mRegStateManagers.get(AccessNetworkConstants.TransportType.WWAN) 2694 .getNetworkRegistrationState(NetworkRegistrationState.DOMAIN_PS, 2695 obtainMessage(EVENT_POLL_STATE_GPRS, mPollingContext)); 2696 2697 mPollingContext[0]++; 2698 mRegStateManagers.get(AccessNetworkConstants.TransportType.WWAN) 2699 .getNetworkRegistrationState(NetworkRegistrationState.DOMAIN_CS, 2700 obtainMessage(EVENT_POLL_STATE_REGISTRATION, mPollingContext)); 2701 2702 if (mPhone.isPhoneTypeGsm()) { 2703 mPollingContext[0]++; 2704 mCi.getNetworkSelectionMode(obtainMessage( 2705 EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext)); 2706 } 2707 break; 2708 } 2709 } 2710 pollStateDone()2711 private void pollStateDone() { 2712 if (!mPhone.isPhoneTypeGsm()) { 2713 updateRoamingState(); 2714 } 2715 2716 if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) { 2717 mNewSS.setVoiceRoaming(true); 2718 mNewSS.setDataRoaming(true); 2719 } 2720 useDataRegStateForDataOnlyDevices(); 2721 resetServiceStateInIwlanMode(); 2722 2723 if (Build.IS_DEBUGGABLE && mPhone.mTelephonyTester != null) { 2724 mPhone.mTelephonyTester.overrideServiceState(mNewSS); 2725 } 2726 2727 if (DBG) { 2728 log("Poll ServiceState done: " 2729 + " oldSS=[" + mSS + "] newSS=[" + mNewSS + "]" 2730 + " oldMaxDataCalls=" + mMaxDataCalls 2731 + " mNewMaxDataCalls=" + mNewMaxDataCalls 2732 + " oldReasonDataDenied=" + mReasonDataDenied 2733 + " mNewReasonDataDenied=" + mNewReasonDataDenied); 2734 } 2735 2736 boolean hasRegistered = 2737 mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE 2738 && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE; 2739 2740 boolean hasDeregistered = 2741 mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE 2742 && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE; 2743 2744 boolean hasDataAttached = 2745 mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE 2746 && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE; 2747 2748 boolean hasDataDetached = 2749 mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE 2750 && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE; 2751 2752 boolean hasDataRegStateChanged = 2753 mSS.getDataRegState() != mNewSS.getDataRegState(); 2754 2755 boolean hasVoiceRegStateChanged = 2756 mSS.getVoiceRegState() != mNewSS.getVoiceRegState(); 2757 2758 boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc); 2759 2760 // ratchet the new tech up through its rat family but don't drop back down 2761 // until cell change or device is OOS 2762 boolean isDataInService = mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE; 2763 2764 if (isDataInService) { 2765 mRatRatcheter.ratchet(mSS, mNewSS, hasLocationChanged); 2766 } 2767 2768 boolean hasRilVoiceRadioTechnologyChanged = 2769 mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology(); 2770 2771 boolean hasRilDataRadioTechnologyChanged = 2772 mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology(); 2773 2774 boolean hasChanged = !mNewSS.equals(mSS); 2775 2776 boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming(); 2777 2778 boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming(); 2779 2780 boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming(); 2781 2782 boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming(); 2783 2784 boolean hasRejectCauseChanged = mRejectCode != mNewRejectCode; 2785 2786 boolean hasCssIndicatorChanged = (mSS.getCssIndicator() != mNewSS.getCssIndicator()); 2787 2788 boolean has4gHandoff = false; 2789 boolean hasMultiApnSupport = false; 2790 boolean hasLostMultiApnSupport = false; 2791 if (mPhone.isPhoneTypeCdmaLte()) { 2792 has4gHandoff = mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE 2793 && ((ServiceState.isLte(mSS.getRilDataRadioTechnology()) 2794 && (mNewSS.getRilDataRadioTechnology() 2795 == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) 2796 || 2797 ((mSS.getRilDataRadioTechnology() 2798 == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD) 2799 && ServiceState.isLte(mNewSS.getRilDataRadioTechnology()))); 2800 2801 hasMultiApnSupport = ((ServiceState.isLte(mNewSS.getRilDataRadioTechnology()) 2802 || (mNewSS.getRilDataRadioTechnology() 2803 == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)) 2804 && 2805 (!ServiceState.isLte(mSS.getRilDataRadioTechnology()) 2806 && (mSS.getRilDataRadioTechnology() 2807 != ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))); 2808 2809 hasLostMultiApnSupport = 2810 ((mNewSS.getRilDataRadioTechnology() 2811 >= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A) 2812 && (mNewSS.getRilDataRadioTechnology() 2813 <= ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)); 2814 } 2815 2816 if (DBG) { 2817 log("pollStateDone:" 2818 + " hasRegistered=" + hasRegistered 2819 + " hasDeregistered=" + hasDeregistered 2820 + " hasDataAttached=" + hasDataAttached 2821 + " hasDataDetached=" + hasDataDetached 2822 + " hasDataRegStateChanged=" + hasDataRegStateChanged 2823 + " hasRilVoiceRadioTechnologyChanged= " + hasRilVoiceRadioTechnologyChanged 2824 + " hasRilDataRadioTechnologyChanged=" + hasRilDataRadioTechnologyChanged 2825 + " hasChanged=" + hasChanged 2826 + " hasVoiceRoamingOn=" + hasVoiceRoamingOn 2827 + " hasVoiceRoamingOff=" + hasVoiceRoamingOff 2828 + " hasDataRoamingOn=" + hasDataRoamingOn 2829 + " hasDataRoamingOff=" + hasDataRoamingOff 2830 + " hasLocationChanged=" + hasLocationChanged 2831 + " has4gHandoff = " + has4gHandoff 2832 + " hasMultiApnSupport=" + hasMultiApnSupport 2833 + " hasLostMultiApnSupport=" + hasLostMultiApnSupport 2834 + " hasCssIndicatorChanged=" + hasCssIndicatorChanged); 2835 } 2836 2837 // Add an event log when connection state changes 2838 if (hasVoiceRegStateChanged || hasDataRegStateChanged) { 2839 EventLog.writeEvent(mPhone.isPhoneTypeGsm() ? EventLogTags.GSM_SERVICE_STATE_CHANGE : 2840 EventLogTags.CDMA_SERVICE_STATE_CHANGE, 2841 mSS.getVoiceRegState(), mSS.getDataRegState(), 2842 mNewSS.getVoiceRegState(), mNewSS.getDataRegState()); 2843 } 2844 2845 if (mPhone.isPhoneTypeGsm()) { 2846 // Add an event log when network type switched 2847 // TODO: we may add filtering to reduce the event logged, 2848 // i.e. check preferred network setting, only switch to 2G, etc 2849 if (hasRilVoiceRadioTechnologyChanged) { 2850 int cid = -1; 2851 GsmCellLocation loc = (GsmCellLocation) mNewCellLoc; 2852 if (loc != null) cid = loc.getCid(); 2853 // NOTE: this code was previously located after mSS and mNewSS are swapped, so 2854 // existing logs were incorrectly using the new state for "network_from" 2855 // and STATE_OUT_OF_SERVICE for "network_to". To avoid confusion, use a new log tag 2856 // to record the correct states. 2857 EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED_NEW, cid, 2858 mSS.getRilVoiceRadioTechnology(), 2859 mNewSS.getRilVoiceRadioTechnology()); 2860 if (DBG) { 2861 log("RAT switched " 2862 + ServiceState.rilRadioTechnologyToString( 2863 mSS.getRilVoiceRadioTechnology()) 2864 + " -> " 2865 + ServiceState.rilRadioTechnologyToString( 2866 mNewSS.getRilVoiceRadioTechnology()) + " at cell " + cid); 2867 } 2868 } 2869 2870 if (hasCssIndicatorChanged) { 2871 mPhone.notifyDataConnection(Phone.REASON_CSS_INDICATOR_CHANGED); 2872 } 2873 2874 mReasonDataDenied = mNewReasonDataDenied; 2875 mMaxDataCalls = mNewMaxDataCalls; 2876 mRejectCode = mNewRejectCode; 2877 } 2878 2879 ServiceState oldMergedSS = mPhone.getServiceState(); 2880 2881 // swap mSS and mNewSS to put new state in mSS 2882 ServiceState tss = mSS; 2883 mSS = mNewSS; 2884 mNewSS = tss; 2885 // clean slate for next time 2886 mNewSS.setStateOutOfService(); 2887 2888 // swap mCellLoc and mNewCellLoc to put new state in mCellLoc 2889 CellLocation tcl = mCellLoc; 2890 mCellLoc = mNewCellLoc; 2891 mNewCellLoc = tcl; 2892 2893 if (hasRilVoiceRadioTechnologyChanged) { 2894 updatePhoneObject(); 2895 } 2896 2897 TelephonyManager tm = 2898 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE); 2899 2900 if (hasRilDataRadioTechnologyChanged) { 2901 tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilDataRadioTechnology()); 2902 StatsLog.write(StatsLog.MOBILE_RADIO_TECHNOLOGY_CHANGED, 2903 ServiceState.rilRadioTechnologyToNetworkType(mSS.getRilDataRadioTechnology()), 2904 mPhone.getPhoneId()); 2905 2906 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 2907 == mSS.getRilDataRadioTechnology()) { 2908 log("pollStateDone: IWLAN enabled"); 2909 } 2910 } 2911 2912 if (hasRegistered) { 2913 mNetworkAttachedRegistrants.notifyRegistrants(); 2914 mNitzState.handleNetworkAvailable(); 2915 } 2916 2917 if (hasDeregistered) { 2918 mNetworkDetachedRegistrants.notifyRegistrants(); 2919 mNitzState.handleNetworkUnavailable(); 2920 } 2921 2922 if (hasRejectCauseChanged) { 2923 setNotification(CS_REJECT_CAUSE_ENABLED); 2924 } 2925 2926 if (hasChanged) { 2927 updateSpnDisplay(); 2928 2929 tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlpha()); 2930 2931 String prevOperatorNumeric = tm.getNetworkOperatorForPhone(mPhone.getPhoneId()); 2932 String prevCountryIsoCode = tm.getNetworkCountryIso(mPhone.getPhoneId()); 2933 String operatorNumeric = mSS.getOperatorNumeric(); 2934 2935 if (!mPhone.isPhoneTypeGsm()) { 2936 // try to fix the invalid Operator Numeric 2937 if (isInvalidOperatorNumeric(operatorNumeric)) { 2938 int sid = mSS.getCdmaSystemId(); 2939 operatorNumeric = fixUnknownMcc(operatorNumeric, sid); 2940 } 2941 } 2942 2943 tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric); 2944 2945 if (isInvalidOperatorNumeric(operatorNumeric)) { 2946 if (DBG) log("operatorNumeric " + operatorNumeric + " is invalid"); 2947 // Passing empty string is important for the first update. The initial value of 2948 // operator numeric in locale tracker is null. The async update will allow getting 2949 // cell info from the modem instead of using the cached one. 2950 mLocaleTracker.updateOperatorNumericAsync(""); 2951 mNitzState.handleNetworkUnavailable(); 2952 } else if (mSS.getRilDataRadioTechnology() != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN) { 2953 // If the device is on IWLAN, modems manufacture a ServiceState with the MCC/MNC of 2954 // the SIM as if we were talking to towers. Telephony code then uses that with 2955 // mccTable to suggest a timezone. We shouldn't do that if the MCC/MNC is from IWLAN 2956 2957 // Update IDD. 2958 if (!mPhone.isPhoneTypeGsm()) { 2959 setOperatorIdd(operatorNumeric); 2960 } 2961 2962 mLocaleTracker.updateOperatorNumericSync(operatorNumeric); 2963 String countryIsoCode = mLocaleTracker.getCurrentCountry(); 2964 2965 // Update Time Zone. 2966 boolean iccCardExists = iccCardExists(); 2967 boolean networkIsoChanged = 2968 networkCountryIsoChanged(countryIsoCode, prevCountryIsoCode); 2969 2970 // Determine countryChanged: networkIso is only reliable if there's an ICC card. 2971 boolean countryChanged = iccCardExists && networkIsoChanged; 2972 if (DBG) { 2973 long ctm = System.currentTimeMillis(); 2974 log("Before handleNetworkCountryCodeKnown:" 2975 + " countryChanged=" + countryChanged 2976 + " iccCardExist=" + iccCardExists 2977 + " countryIsoChanged=" + networkIsoChanged 2978 + " operatorNumeric=" + operatorNumeric 2979 + " prevOperatorNumeric=" + prevOperatorNumeric 2980 + " countryIsoCode=" + countryIsoCode 2981 + " prevCountryIsoCode=" + prevCountryIsoCode 2982 + " ltod=" + TimeUtils.logTimeOfDay(ctm)); 2983 } 2984 mNitzState.handleNetworkCountryCodeSet(countryChanged); 2985 } 2986 2987 tm.setNetworkRoamingForPhone(mPhone.getPhoneId(), 2988 mPhone.isPhoneTypeGsm() ? mSS.getVoiceRoaming() : 2989 (mSS.getVoiceRoaming() || mSS.getDataRoaming())); 2990 2991 setRoamingType(mSS); 2992 log("Broadcasting ServiceState : " + mSS); 2993 // notify using PhoneStateListener and the legacy intent ACTION_SERVICE_STATE_CHANGED 2994 // notify service state changed only if the merged service state is changed. 2995 if (!oldMergedSS.equals(mPhone.getServiceState())) { 2996 mPhone.notifyServiceStateChanged(mPhone.getServiceState()); 2997 } 2998 2999 // insert into ServiceStateProvider. This will trigger apps to wake through JobScheduler 3000 mPhone.getContext().getContentResolver() 3001 .insert(getUriForSubscriptionId(mPhone.getSubId()), 3002 getContentValuesForServiceState(mSS)); 3003 3004 TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS); 3005 } 3006 3007 if (hasDataAttached || has4gHandoff || hasDataDetached || hasRegistered 3008 || hasDeregistered) { 3009 logAttachChange(); 3010 } 3011 3012 if (hasDataAttached || has4gHandoff) { 3013 mAttachedRegistrants.notifyRegistrants(); 3014 } 3015 3016 if (hasDataDetached) { 3017 mDetachedRegistrants.notifyRegistrants(); 3018 } 3019 3020 if (hasRilDataRadioTechnologyChanged || hasRilVoiceRadioTechnologyChanged) { 3021 logRatChange(); 3022 } 3023 3024 if (hasDataRegStateChanged || hasRilDataRadioTechnologyChanged) { 3025 notifyDataRegStateRilRadioTechnologyChanged(); 3026 3027 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 3028 == mSS.getRilDataRadioTechnology()) { 3029 mPhone.notifyDataConnection(Phone.REASON_IWLAN_AVAILABLE); 3030 } else { 3031 mPhone.notifyDataConnection(null); 3032 } 3033 } 3034 3035 if (hasVoiceRoamingOn || hasVoiceRoamingOff || hasDataRoamingOn || hasDataRoamingOff) { 3036 logRoamingChange(); 3037 } 3038 3039 if (hasVoiceRoamingOn) { 3040 mVoiceRoamingOnRegistrants.notifyRegistrants(); 3041 } 3042 3043 if (hasVoiceRoamingOff) { 3044 mVoiceRoamingOffRegistrants.notifyRegistrants(); 3045 } 3046 3047 if (hasDataRoamingOn) { 3048 mDataRoamingOnRegistrants.notifyRegistrants(); 3049 } 3050 3051 if (hasDataRoamingOff) { 3052 mDataRoamingOffRegistrants.notifyRegistrants(); 3053 } 3054 3055 if (hasLocationChanged) { 3056 mPhone.notifyLocationChanged(); 3057 } 3058 3059 if (mPhone.isPhoneTypeGsm()) { 3060 if (!isGprsConsistent(mSS.getDataRegState(), mSS.getVoiceRegState())) { 3061 if (!mStartedGprsRegCheck && !mReportedGprsNoReg) { 3062 mStartedGprsRegCheck = true; 3063 3064 int check_period = Settings.Global.getInt( 3065 mPhone.getContext().getContentResolver(), 3066 Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS, 3067 DEFAULT_GPRS_CHECK_PERIOD_MILLIS); 3068 sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS), 3069 check_period); 3070 } 3071 } else { 3072 mReportedGprsNoReg = false; 3073 } 3074 } 3075 } 3076 updateOperatorNameFromEri()3077 private void updateOperatorNameFromEri() { 3078 if (mPhone.isPhoneTypeCdma()) { 3079 if ((mCi.getRadioState().isOn()) && (!mIsSubscriptionFromRuim)) { 3080 String eriText; 3081 // Now the Phone sees the new ServiceState so it can get the new ERI text 3082 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 3083 eriText = mPhone.getCdmaEriText(); 3084 } else { 3085 // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used for 3086 // mRegistrationState 0,2,3 and 4 3087 eriText = mPhone.getContext().getText( 3088 com.android.internal.R.string.roamingTextSearching).toString(); 3089 } 3090 mSS.setOperatorAlphaLong(eriText); 3091 } 3092 } else if (mPhone.isPhoneTypeCdmaLte()) { 3093 boolean hasBrandOverride = mUiccController.getUiccCard(getPhoneId()) != null && 3094 mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() != null; 3095 if (!hasBrandOverride && (mCi.getRadioState().isOn()) && (mPhone.isEriFileLoaded()) && 3096 (!ServiceState.isLte(mSS.getRilVoiceRadioTechnology()) || 3097 mPhone.getContext().getResources().getBoolean(com.android.internal.R. 3098 bool.config_LTE_eri_for_network_name))) { 3099 // Only when CDMA is in service, ERI will take effect 3100 String eriText = mSS.getOperatorAlpha(); 3101 // Now the Phone sees the new ServiceState so it can get the new ERI text 3102 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 3103 eriText = mPhone.getCdmaEriText(); 3104 } else if (mSS.getVoiceRegState() == ServiceState.STATE_POWER_OFF) { 3105 eriText = (mIccRecords != null) ? mIccRecords.getServiceProviderName() : null; 3106 if (TextUtils.isEmpty(eriText)) { 3107 // Sets operator alpha property by retrieving from 3108 // build-time system property 3109 eriText = SystemProperties.get("ro.cdma.home.operator.alpha"); 3110 } 3111 } else if (mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE) { 3112 // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used 3113 // for mRegistrationState 0,2,3 and 4 3114 eriText = mPhone.getContext() 3115 .getText(com.android.internal.R.string.roamingTextSearching).toString(); 3116 } 3117 mSS.setOperatorAlphaLong(eriText); 3118 } 3119 3120 if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY && 3121 mIccRecords != null && getCombinedRegState() == ServiceState.STATE_IN_SERVICE 3122 && !ServiceState.isLte(mSS.getRilVoiceRadioTechnology())) { 3123 // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches 3124 // one configured in SIM, use operator name from CSIM record. Note that ERI, SID, 3125 // and NID are CDMA only, not applicable to LTE. 3126 boolean showSpn = 3127 ((RuimRecords) mIccRecords).getCsimSpnDisplayCondition(); 3128 int iconIndex = mSS.getCdmaEriIconIndex(); 3129 3130 if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF) 3131 && isInHomeSidNid(mSS.getCdmaSystemId(), mSS.getCdmaNetworkId()) 3132 && mIccRecords != null) { 3133 mSS.setOperatorAlphaLong(mIccRecords.getServiceProviderName()); 3134 } 3135 } 3136 } 3137 } 3138 3139 /** 3140 * Check whether the specified SID and NID pair appears in the HOME SID/NID list 3141 * read from NV or SIM. 3142 * 3143 * @return true if provided sid/nid pair belongs to operator's home network. 3144 */ isInHomeSidNid(int sid, int nid)3145 private boolean isInHomeSidNid(int sid, int nid) { 3146 // if SID/NID is not available, assume this is home network. 3147 if (isSidsAllZeros()) return true; 3148 3149 // length of SID/NID shold be same 3150 if (mHomeSystemId.length != mHomeNetworkId.length) return true; 3151 3152 if (sid == 0) return true; 3153 3154 for (int i = 0; i < mHomeSystemId.length; i++) { 3155 // Use SID only if NID is a reserved value. 3156 // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2) 3157 if ((mHomeSystemId[i] == sid) && 3158 ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) || 3159 (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) { 3160 return true; 3161 } 3162 } 3163 // SID/NID are not in the list. So device is not in home network 3164 return false; 3165 } 3166 setOperatorIdd(String operatorNumeric)3167 protected void setOperatorIdd(String operatorNumeric) { 3168 // Retrieve the current country information 3169 // with the MCC got from opeatorNumeric. 3170 String idd = mHbpcdUtils.getIddByMcc( 3171 Integer.parseInt(operatorNumeric.substring(0,3))); 3172 if (idd != null && !idd.isEmpty()) { 3173 mPhone.setGlobalSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING, 3174 idd); 3175 } else { 3176 // use default "+", since we don't know the current IDP 3177 mPhone.setGlobalSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING, "+"); 3178 } 3179 } 3180 isInvalidOperatorNumeric(String operatorNumeric)3181 private boolean isInvalidOperatorNumeric(String operatorNumeric) { 3182 return operatorNumeric == null || operatorNumeric.length() < 5 || 3183 operatorNumeric.startsWith(INVALID_MCC); 3184 } 3185 fixUnknownMcc(String operatorNumeric, int sid)3186 private String fixUnknownMcc(String operatorNumeric, int sid) { 3187 if (sid <= 0) { 3188 // no cdma information is available, do nothing 3189 return operatorNumeric; 3190 } 3191 3192 // resolve the mcc from sid; 3193 // if mNitzState.getSavedTimeZoneId() is null, TimeZone would get the default timeZone, 3194 // and the mNitzState.fixTimeZone() couldn't help, because it depends on operator Numeric; 3195 // if the sid is conflict and timezone is unavailable, the mcc may be not right. 3196 boolean isNitzTimeZone; 3197 TimeZone tzone; 3198 if (mNitzState.getSavedTimeZoneId() != null) { 3199 tzone = TimeZone.getTimeZone(mNitzState.getSavedTimeZoneId()); 3200 isNitzTimeZone = true; 3201 } else { 3202 NitzData lastNitzData = mNitzState.getCachedNitzData(); 3203 if (lastNitzData == null) { 3204 tzone = null; 3205 } else { 3206 tzone = TimeZoneLookupHelper.guessZoneByNitzStatic(lastNitzData); 3207 if (ServiceStateTracker.DBG) { 3208 log("fixUnknownMcc(): guessNitzTimeZone returned " 3209 + (tzone == null ? tzone : tzone.getID())); 3210 } 3211 } 3212 isNitzTimeZone = false; 3213 } 3214 3215 int utcOffsetHours = 0; 3216 if (tzone != null) { 3217 utcOffsetHours = tzone.getRawOffset() / MS_PER_HOUR; 3218 } 3219 3220 NitzData nitzData = mNitzState.getCachedNitzData(); 3221 boolean isDst = nitzData != null && nitzData.isDst(); 3222 int mcc = mHbpcdUtils.getMcc(sid, utcOffsetHours, (isDst ? 1 : 0), isNitzTimeZone); 3223 if (mcc > 0) { 3224 operatorNumeric = Integer.toString(mcc) + DEFAULT_MNC; 3225 } 3226 return operatorNumeric; 3227 } 3228 3229 /** 3230 * Check if GPRS got registered while voice is registered. 3231 * 3232 * @param dataRegState i.e. CGREG in GSM 3233 * @param voiceRegState i.e. CREG in GSM 3234 * @return false if device only register to voice but not gprs 3235 */ isGprsConsistent(int dataRegState, int voiceRegState)3236 private boolean isGprsConsistent(int dataRegState, int voiceRegState) { 3237 return !((voiceRegState == ServiceState.STATE_IN_SERVICE) && 3238 (dataRegState != ServiceState.STATE_IN_SERVICE)); 3239 } 3240 3241 /** convert ServiceState registration code 3242 * to service state */ regCodeToServiceState(int code)3243 private int regCodeToServiceState(int code) { 3244 switch (code) { 3245 case NetworkRegistrationState.REG_STATE_HOME: 3246 case NetworkRegistrationState.REG_STATE_ROAMING: 3247 return ServiceState.STATE_IN_SERVICE; 3248 default: 3249 return ServiceState.STATE_OUT_OF_SERVICE; 3250 } 3251 } 3252 3253 /** 3254 * code is registration state 0-5 from TS 27.007 7.2 3255 * returns true if registered roam, false otherwise 3256 */ regCodeIsRoaming(int code)3257 private boolean regCodeIsRoaming (int code) { 3258 return NetworkRegistrationState.REG_STATE_ROAMING == code; 3259 } 3260 isSameOperatorNameFromSimAndSS(ServiceState s)3261 private boolean isSameOperatorNameFromSimAndSS(ServiceState s) { 3262 String spn = ((TelephonyManager) mPhone.getContext(). 3263 getSystemService(Context.TELEPHONY_SERVICE)). 3264 getSimOperatorNameForPhone(getPhoneId()); 3265 3266 // NOTE: in case of RUIM we should completely ignore the ERI data file and 3267 // mOperatorAlphaLong is set from RIL_REQUEST_OPERATOR response 0 (alpha ONS) 3268 String onsl = s.getOperatorAlphaLong(); 3269 String onss = s.getOperatorAlphaShort(); 3270 3271 boolean equalsOnsl = !TextUtils.isEmpty(spn) && spn.equalsIgnoreCase(onsl); 3272 boolean equalsOnss = !TextUtils.isEmpty(spn) && spn.equalsIgnoreCase(onss); 3273 3274 return (equalsOnsl || equalsOnss); 3275 } 3276 3277 /** 3278 * Set roaming state if operator mcc is the same as sim mcc 3279 * and ons is not different from spn 3280 * 3281 * @param s ServiceState hold current ons 3282 * @return true if same operator 3283 */ isSameNamedOperators(ServiceState s)3284 private boolean isSameNamedOperators(ServiceState s) { 3285 return currentMccEqualsSimMcc(s) && isSameOperatorNameFromSimAndSS(s); 3286 } 3287 3288 /** 3289 * Compare SIM MCC with Operator MCC 3290 * 3291 * @param s ServiceState hold current ons 3292 * @return true if both are same 3293 */ currentMccEqualsSimMcc(ServiceState s)3294 private boolean currentMccEqualsSimMcc(ServiceState s) { 3295 String simNumeric = ((TelephonyManager) mPhone.getContext(). 3296 getSystemService(Context.TELEPHONY_SERVICE)). 3297 getSimOperatorNumericForPhone(getPhoneId()); 3298 String operatorNumeric = s.getOperatorNumeric(); 3299 boolean equalsMcc = true; 3300 3301 try { 3302 equalsMcc = simNumeric.substring(0, 3). 3303 equals(operatorNumeric.substring(0, 3)); 3304 } catch (Exception e){ 3305 } 3306 return equalsMcc; 3307 } 3308 3309 /** 3310 * Do not set roaming state in case of oprators considered non-roaming. 3311 * 3312 * Can use mcc or mcc+mnc as item of 3313 * {@link CarrierConfigManager#KEY_NON_ROAMING_OPERATOR_STRING_ARRAY}. 3314 * For example, 302 or 21407. If mcc or mcc+mnc match with operator, 3315 * don't set roaming state. 3316 * 3317 * @param s ServiceState hold current ons 3318 * @return false for roaming state set 3319 */ isOperatorConsideredNonRoaming(ServiceState s)3320 private boolean isOperatorConsideredNonRoaming(ServiceState s) { 3321 String operatorNumeric = s.getOperatorNumeric(); 3322 final CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 3323 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 3324 String[] numericArray = null; 3325 if (configManager != null) { 3326 PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId()); 3327 if (config != null) { 3328 numericArray = config.getStringArray( 3329 CarrierConfigManager.KEY_NON_ROAMING_OPERATOR_STRING_ARRAY); 3330 } 3331 } 3332 if (ArrayUtils.isEmpty(numericArray) || operatorNumeric == null) { 3333 return false; 3334 } 3335 3336 for (String numeric : numericArray) { 3337 if (!TextUtils.isEmpty(numeric) && operatorNumeric.startsWith(numeric)) { 3338 return true; 3339 } 3340 } 3341 return false; 3342 } 3343 isOperatorConsideredRoaming(ServiceState s)3344 private boolean isOperatorConsideredRoaming(ServiceState s) { 3345 String operatorNumeric = s.getOperatorNumeric(); 3346 final CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 3347 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 3348 String[] numericArray = null; 3349 if (configManager != null) { 3350 PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId()); 3351 if (config != null) { 3352 numericArray = config.getStringArray( 3353 CarrierConfigManager.KEY_ROAMING_OPERATOR_STRING_ARRAY); 3354 } 3355 } 3356 if (ArrayUtils.isEmpty(numericArray) || operatorNumeric == null) { 3357 return false; 3358 } 3359 3360 for (String numeric : numericArray) { 3361 if (!TextUtils.isEmpty(numeric) && operatorNumeric.startsWith(numeric)) { 3362 return true; 3363 } 3364 } 3365 return false; 3366 } 3367 3368 /** 3369 * Set restricted state based on the OnRestrictedStateChanged notification 3370 * If any voice or packet restricted state changes, trigger a UI 3371 * notification and notify registrants when sim is ready. 3372 * 3373 * @param ar an int value of RIL_RESTRICTED_STATE_* 3374 */ onRestrictedStateChanged(AsyncResult ar)3375 private void onRestrictedStateChanged(AsyncResult ar) { 3376 RestrictedState newRs = new RestrictedState(); 3377 3378 if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState); 3379 3380 if (ar.exception == null && ar.result != null) { 3381 int state = (int)ar.result; 3382 3383 newRs.setCsEmergencyRestricted( 3384 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) || 3385 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); 3386 //ignore the normal call and data restricted state before SIM READY 3387 if (mUiccApplcation != null && mUiccApplcation.getState() == AppState.APPSTATE_READY) { 3388 newRs.setCsNormalRestricted( 3389 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) || 3390 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) ); 3391 newRs.setPsRestricted( 3392 (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0); 3393 } 3394 3395 if (DBG) log("onRestrictedStateChanged: new rs "+ newRs); 3396 3397 if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) { 3398 mPsRestrictEnabledRegistrants.notifyRegistrants(); 3399 setNotification(PS_ENABLED); 3400 } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) { 3401 mPsRestrictDisabledRegistrants.notifyRegistrants(); 3402 setNotification(PS_DISABLED); 3403 } 3404 3405 /** 3406 * There are two kind of cs restriction, normal and emergency. So 3407 * there are 4 x 4 combinations in current and new restricted states 3408 * and we only need to notify when state is changed. 3409 */ 3410 if (mRestrictedState.isCsRestricted()) { 3411 if (!newRs.isAnyCsRestricted()) { 3412 // remove all restriction 3413 setNotification(CS_DISABLED); 3414 } else if (!newRs.isCsNormalRestricted()) { 3415 // remove normal restriction 3416 setNotification(CS_EMERGENCY_ENABLED); 3417 } else if (!newRs.isCsEmergencyRestricted()) { 3418 // remove emergency restriction 3419 setNotification(CS_NORMAL_ENABLED); 3420 } 3421 } else if (mRestrictedState.isCsEmergencyRestricted() && 3422 !mRestrictedState.isCsNormalRestricted()) { 3423 if (!newRs.isAnyCsRestricted()) { 3424 // remove all restriction 3425 setNotification(CS_DISABLED); 3426 } else if (newRs.isCsRestricted()) { 3427 // enable all restriction 3428 setNotification(CS_ENABLED); 3429 } else if (newRs.isCsNormalRestricted()) { 3430 // remove emergency restriction and enable normal restriction 3431 setNotification(CS_NORMAL_ENABLED); 3432 } 3433 } else if (!mRestrictedState.isCsEmergencyRestricted() && 3434 mRestrictedState.isCsNormalRestricted()) { 3435 if (!newRs.isAnyCsRestricted()) { 3436 // remove all restriction 3437 setNotification(CS_DISABLED); 3438 } else if (newRs.isCsRestricted()) { 3439 // enable all restriction 3440 setNotification(CS_ENABLED); 3441 } else if (newRs.isCsEmergencyRestricted()) { 3442 // remove normal restriction and enable emergency restriction 3443 setNotification(CS_EMERGENCY_ENABLED); 3444 } 3445 } else { 3446 if (newRs.isCsRestricted()) { 3447 // enable all restriction 3448 setNotification(CS_ENABLED); 3449 } else if (newRs.isCsEmergencyRestricted()) { 3450 // enable emergency restriction 3451 setNotification(CS_EMERGENCY_ENABLED); 3452 } else if (newRs.isCsNormalRestricted()) { 3453 // enable normal restriction 3454 setNotification(CS_NORMAL_ENABLED); 3455 } 3456 } 3457 3458 mRestrictedState = newRs; 3459 } 3460 log("onRestrictedStateChanged: X rs "+ mRestrictedState); 3461 } 3462 3463 /** 3464 * @param workSource calling WorkSource 3465 * @return the current cell location information. Prefer Gsm location 3466 * information if available otherwise return LTE location information 3467 */ getCellLocation(WorkSource workSource)3468 public CellLocation getCellLocation(WorkSource workSource) { 3469 if (((GsmCellLocation)mCellLoc).getLac() >= 0 && 3470 ((GsmCellLocation)mCellLoc).getCid() >= 0) { 3471 if (VDBG) log("getCellLocation(): X good mCellLoc=" + mCellLoc); 3472 return mCellLoc; 3473 } else { 3474 List<CellInfo> result = getAllCellInfo(workSource); 3475 if (result != null) { 3476 // A hack to allow tunneling of LTE information via GsmCellLocation 3477 // so that older Network Location Providers can return some information 3478 // on LTE only networks, see bug 9228974. 3479 // 3480 // We'll search the return CellInfo array preferring GSM/WCDMA 3481 // data, but if there is none we'll tunnel the first LTE information 3482 // in the list. 3483 // 3484 // The tunnel'd LTE information is returned as follows: 3485 // LAC = TAC field 3486 // CID = CI field 3487 // PSC = 0. 3488 GsmCellLocation cellLocOther = new GsmCellLocation(); 3489 for (CellInfo ci : result) { 3490 if (ci instanceof CellInfoGsm) { 3491 CellInfoGsm cellInfoGsm = (CellInfoGsm)ci; 3492 CellIdentityGsm cellIdentityGsm = cellInfoGsm.getCellIdentity(); 3493 cellLocOther.setLacAndCid(cellIdentityGsm.getLac(), 3494 cellIdentityGsm.getCid()); 3495 cellLocOther.setPsc(cellIdentityGsm.getPsc()); 3496 if (VDBG) log("getCellLocation(): X ret GSM info=" + cellLocOther); 3497 return cellLocOther; 3498 } else if (ci instanceof CellInfoWcdma) { 3499 CellInfoWcdma cellInfoWcdma = (CellInfoWcdma)ci; 3500 CellIdentityWcdma cellIdentityWcdma = cellInfoWcdma.getCellIdentity(); 3501 cellLocOther.setLacAndCid(cellIdentityWcdma.getLac(), 3502 cellIdentityWcdma.getCid()); 3503 cellLocOther.setPsc(cellIdentityWcdma.getPsc()); 3504 if (VDBG) log("getCellLocation(): X ret WCDMA info=" + cellLocOther); 3505 return cellLocOther; 3506 } else if ((ci instanceof CellInfoLte) && 3507 ((cellLocOther.getLac() < 0) || (cellLocOther.getCid() < 0))) { 3508 // We'll return the first good LTE info we get if there is no better answer 3509 CellInfoLte cellInfoLte = (CellInfoLte)ci; 3510 CellIdentityLte cellIdentityLte = cellInfoLte.getCellIdentity(); 3511 if ((cellIdentityLte.getTac() != Integer.MAX_VALUE) 3512 && (cellIdentityLte.getCi() != Integer.MAX_VALUE)) { 3513 cellLocOther.setLacAndCid(cellIdentityLte.getTac(), 3514 cellIdentityLte.getCi()); 3515 cellLocOther.setPsc(0); 3516 if (VDBG) { 3517 log("getCellLocation(): possible LTE cellLocOther=" + cellLocOther); 3518 } 3519 } 3520 } 3521 } 3522 if (VDBG) { 3523 log("getCellLocation(): X ret best answer cellLocOther=" + cellLocOther); 3524 } 3525 return cellLocOther; 3526 } else { 3527 if (VDBG) { 3528 log("getCellLocation(): X empty mCellLoc and CellInfo mCellLoc=" + mCellLoc); 3529 } 3530 return mCellLoc; 3531 } 3532 } 3533 } 3534 3535 /** 3536 * nitzReceiveTime is time_t that the NITZ time was posted 3537 */ setTimeFromNITZString(String nitzString, long nitzReceiveTime)3538 private void setTimeFromNITZString(String nitzString, long nitzReceiveTime) { 3539 long start = SystemClock.elapsedRealtime(); 3540 if (DBG) { 3541 Rlog.d(LOG_TAG, "NITZ: " + nitzString + "," + nitzReceiveTime 3542 + " start=" + start + " delay=" + (start - nitzReceiveTime)); 3543 } 3544 NitzData newNitzData = NitzData.parse(nitzString); 3545 if (newNitzData != null) { 3546 try { 3547 TimeStampedValue<NitzData> nitzSignal = 3548 new TimeStampedValue<>(newNitzData, nitzReceiveTime); 3549 mNitzState.handleNitzReceived(nitzSignal); 3550 } finally { 3551 if (DBG) { 3552 long end = SystemClock.elapsedRealtime(); 3553 Rlog.d(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start)); 3554 } 3555 } 3556 } 3557 } 3558 3559 /** 3560 * Cancels all notifications posted to NotificationManager for this subId. These notifications 3561 * for restricted state and rejection cause for cs registration are no longer valid after the 3562 * SIM has been removed. 3563 */ cancelAllNotifications()3564 private void cancelAllNotifications() { 3565 if (DBG) log("cancelAllNotifications: mPrevSubId=" + mPrevSubId); 3566 NotificationManager notificationManager = (NotificationManager) 3567 mPhone.getContext().getSystemService(Context.NOTIFICATION_SERVICE); 3568 if (SubscriptionManager.isValidSubscriptionId(mPrevSubId)) { 3569 notificationManager.cancel(Integer.toString(mPrevSubId), PS_NOTIFICATION); 3570 notificationManager.cancel(Integer.toString(mPrevSubId), CS_NOTIFICATION); 3571 notificationManager.cancel(Integer.toString(mPrevSubId), CS_REJECT_CAUSE_NOTIFICATION); 3572 } 3573 } 3574 3575 /** 3576 * Post a notification to NotificationManager for restricted state and 3577 * rejection cause for cs registration 3578 * 3579 * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE 3580 */ 3581 @VisibleForTesting setNotification(int notifyType)3582 public void setNotification(int notifyType) { 3583 if (DBG) log("setNotification: create notification " + notifyType); 3584 3585 if (!SubscriptionManager.isValidSubscriptionId(mSubId)) { 3586 // notifications are posted per-sub-id, so return if current sub-id is invalid 3587 loge("cannot setNotification on invalid subid mSubId=" + mSubId); 3588 return; 3589 } 3590 3591 // Needed because sprout RIL sends these when they shouldn't? 3592 boolean isSetNotification = mPhone.getContext().getResources().getBoolean( 3593 com.android.internal.R.bool.config_user_notification_of_restrictied_mobile_access); 3594 if (!isSetNotification) { 3595 if (DBG) log("Ignore all the notifications"); 3596 return; 3597 } 3598 3599 Context context = mPhone.getContext(); 3600 3601 CarrierConfigManager configManager = (CarrierConfigManager) 3602 context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 3603 if (configManager != null) { 3604 PersistableBundle bundle = configManager.getConfig(); 3605 if (bundle != null) { 3606 boolean disableVoiceBarringNotification = bundle.getBoolean( 3607 CarrierConfigManager.KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL, false); 3608 if(disableVoiceBarringNotification && (notifyType == CS_ENABLED 3609 || notifyType == CS_NORMAL_ENABLED 3610 || notifyType == CS_EMERGENCY_ENABLED)) { 3611 if (DBG) log("Voice/emergency call barred notification disabled"); 3612 return; 3613 } 3614 } 3615 } 3616 3617 CharSequence details = ""; 3618 CharSequence title = ""; 3619 int notificationId = CS_NOTIFICATION; 3620 int icon = com.android.internal.R.drawable.stat_sys_warning; 3621 3622 final boolean multipleSubscriptions = (((TelephonyManager) mPhone.getContext() 3623 .getSystemService(Context.TELEPHONY_SERVICE)).getPhoneCount() > 1); 3624 final int simNumber = mSubscriptionController.getSlotIndex(mSubId) + 1; 3625 3626 switch (notifyType) { 3627 case PS_ENABLED: 3628 long dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 3629 if (dataSubId != mPhone.getSubId()) { 3630 return; 3631 } 3632 notificationId = PS_NOTIFICATION; 3633 title = context.getText(com.android.internal.R.string.RestrictedOnDataTitle); 3634 details = multipleSubscriptions 3635 ? context.getString( 3636 com.android.internal.R.string.RestrictedStateContentMsimTemplate, 3637 simNumber) : 3638 context.getText(com.android.internal.R.string.RestrictedStateContent); 3639 break; 3640 case PS_DISABLED: 3641 notificationId = PS_NOTIFICATION; 3642 break; 3643 case CS_ENABLED: 3644 title = context.getText(com.android.internal.R.string.RestrictedOnAllVoiceTitle); 3645 details = multipleSubscriptions 3646 ? context.getString( 3647 com.android.internal.R.string.RestrictedStateContentMsimTemplate, 3648 simNumber) : 3649 context.getText(com.android.internal.R.string.RestrictedStateContent); 3650 break; 3651 case CS_NORMAL_ENABLED: 3652 title = context.getText(com.android.internal.R.string.RestrictedOnNormalTitle); 3653 details = multipleSubscriptions 3654 ? context.getString( 3655 com.android.internal.R.string.RestrictedStateContentMsimTemplate, 3656 simNumber) : 3657 context.getText(com.android.internal.R.string.RestrictedStateContent); 3658 break; 3659 case CS_EMERGENCY_ENABLED: 3660 title = context.getText(com.android.internal.R.string.RestrictedOnEmergencyTitle); 3661 details = multipleSubscriptions 3662 ? context.getString( 3663 com.android.internal.R.string.RestrictedStateContentMsimTemplate, 3664 simNumber) : 3665 context.getText(com.android.internal.R.string.RestrictedStateContent); 3666 break; 3667 case CS_DISABLED: 3668 // do nothing and cancel the notification later 3669 break; 3670 case CS_REJECT_CAUSE_ENABLED: 3671 notificationId = CS_REJECT_CAUSE_NOTIFICATION; 3672 int resId = selectResourceForRejectCode(mRejectCode, multipleSubscriptions); 3673 if (0 == resId) { 3674 loge("setNotification: mRejectCode=" + mRejectCode + " is not handled."); 3675 return; 3676 } else { 3677 icon = com.android.internal.R.drawable.stat_notify_mmcc_indication_icn; 3678 // if using the single SIM resource, mSubId will be ignored 3679 title = context.getString(resId, mSubId); 3680 details = null; 3681 } 3682 break; 3683 } 3684 3685 if (DBG) { 3686 log("setNotification, create notification, notifyType: " + notifyType 3687 + ", title: " + title + ", details: " + details + ", subId: " + mSubId); 3688 } 3689 3690 mNotification = new Notification.Builder(context) 3691 .setWhen(System.currentTimeMillis()) 3692 .setAutoCancel(true) 3693 .setSmallIcon(icon) 3694 .setTicker(title) 3695 .setColor(context.getResources().getColor( 3696 com.android.internal.R.color.system_notification_accent_color)) 3697 .setContentTitle(title) 3698 .setStyle(new Notification.BigTextStyle().bigText(details)) 3699 .setContentText(details) 3700 .setChannel(NotificationChannelController.CHANNEL_ID_ALERT) 3701 .build(); 3702 3703 NotificationManager notificationManager = (NotificationManager) 3704 context.getSystemService(Context.NOTIFICATION_SERVICE); 3705 3706 if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) { 3707 // cancel previous post notification 3708 notificationManager.cancel(Integer.toString(mSubId), notificationId); 3709 } else { 3710 boolean show = false; 3711 if (mSS.isEmergencyOnly() && notifyType == CS_EMERGENCY_ENABLED) { 3712 // if reg state is emergency only, always show restricted emergency notification. 3713 show = true; 3714 } else if (notifyType == CS_REJECT_CAUSE_ENABLED) { 3715 // always show notification due to CS reject irrespective of service state. 3716 show = true; 3717 } else if (mSS.getState() == ServiceState.STATE_IN_SERVICE) { 3718 // for non in service states, we have system UI and signal bar to indicate limited 3719 // service. No need to show notification again. This also helps to mitigate the 3720 // issue if phone go to OOS and camp to other networks and received restricted ind. 3721 show = true; 3722 } 3723 // update restricted state notification for this subId 3724 if (show) { 3725 notificationManager.notify(Integer.toString(mSubId), notificationId, mNotification); 3726 } 3727 } 3728 } 3729 3730 /** 3731 * Selects the resource ID, which depends on rejection cause that is sent by the network when CS 3732 * registration is rejected. 3733 * 3734 * @param rejCode should be compatible with TS 24.008. 3735 */ selectResourceForRejectCode(int rejCode, boolean multipleSubscriptions)3736 private int selectResourceForRejectCode(int rejCode, boolean multipleSubscriptions) { 3737 int rejResourceId = 0; 3738 switch (rejCode) { 3739 case 1:// Authentication reject 3740 rejResourceId = multipleSubscriptions 3741 ? com.android.internal.R.string.mmcc_authentication_reject_msim_template : 3742 com.android.internal.R.string.mmcc_authentication_reject; 3743 break; 3744 case 2:// IMSI unknown in HLR 3745 rejResourceId = multipleSubscriptions 3746 ? com.android.internal.R.string.mmcc_imsi_unknown_in_hlr_msim_template : 3747 com.android.internal.R.string.mmcc_imsi_unknown_in_hlr; 3748 break; 3749 case 3:// Illegal MS 3750 rejResourceId = multipleSubscriptions 3751 ? com.android.internal.R.string.mmcc_illegal_ms_msim_template : 3752 com.android.internal.R.string.mmcc_illegal_ms; 3753 break; 3754 case 6:// Illegal ME 3755 rejResourceId = multipleSubscriptions 3756 ? com.android.internal.R.string.mmcc_illegal_me_msim_template : 3757 com.android.internal.R.string.mmcc_illegal_me; 3758 break; 3759 default: 3760 // The other codes are not defined or not required by operators till now. 3761 break; 3762 } 3763 return rejResourceId; 3764 } 3765 getUiccCardApplication()3766 private UiccCardApplication getUiccCardApplication() { 3767 if (mPhone.isPhoneTypeGsm()) { 3768 return mUiccController.getUiccCardApplication(mPhone.getPhoneId(), 3769 UiccController.APP_FAM_3GPP); 3770 } else { 3771 return mUiccController.getUiccCardApplication(mPhone.getPhoneId(), 3772 UiccController.APP_FAM_3GPP2); 3773 } 3774 } 3775 queueNextSignalStrengthPoll()3776 private void queueNextSignalStrengthPoll() { 3777 if (mDontPollSignalStrength) { 3778 // The radio is telling us about signal strength changes 3779 // we don't have to ask it 3780 return; 3781 } 3782 3783 Message msg; 3784 3785 msg = obtainMessage(); 3786 msg.what = EVENT_POLL_SIGNAL_STRENGTH; 3787 3788 long nextTime; 3789 3790 // TODO Don't poll signal strength if screen is off 3791 sendMessageDelayed(msg, POLL_PERIOD_MILLIS); 3792 } 3793 notifyCdmaSubscriptionInfoReady()3794 private void notifyCdmaSubscriptionInfoReady() { 3795 if (mCdmaForSubscriptionInfoReadyRegistrants != null) { 3796 if (DBG) log("CDMA_SUBSCRIPTION: call notifyRegistrants()"); 3797 mCdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants(); 3798 } 3799 } 3800 3801 /** 3802 * Registration point for transition into DataConnection attached. 3803 * @param h handler to notify 3804 * @param what what code of message when delivered 3805 * @param obj placed in Message.obj 3806 */ registerForDataConnectionAttached(Handler h, int what, Object obj)3807 public void registerForDataConnectionAttached(Handler h, int what, Object obj) { 3808 Registrant r = new Registrant(h, what, obj); 3809 mAttachedRegistrants.add(r); 3810 3811 if (getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) { 3812 r.notifyRegistrant(); 3813 } 3814 } unregisterForDataConnectionAttached(Handler h)3815 public void unregisterForDataConnectionAttached(Handler h) { 3816 mAttachedRegistrants.remove(h); 3817 } 3818 3819 /** 3820 * Registration point for transition into DataConnection detached. 3821 * @param h handler to notify 3822 * @param what what code of message when delivered 3823 * @param obj placed in Message.obj 3824 */ registerForDataConnectionDetached(Handler h, int what, Object obj)3825 public void registerForDataConnectionDetached(Handler h, int what, Object obj) { 3826 Registrant r = new Registrant(h, what, obj); 3827 mDetachedRegistrants.add(r); 3828 3829 if (getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) { 3830 r.notifyRegistrant(); 3831 } 3832 } unregisterForDataConnectionDetached(Handler h)3833 public void unregisterForDataConnectionDetached(Handler h) { 3834 mDetachedRegistrants.remove(h); 3835 } 3836 3837 /** 3838 * Registration for DataConnection RIL Data Radio Technology changing. The 3839 * new radio technology will be returned AsyncResult#result as an Integer Object. 3840 * The AsyncResult will be in the notification Message#obj. 3841 * 3842 * @param h handler to notify 3843 * @param what what code of message when delivered 3844 * @param obj placed in Message.obj 3845 */ registerForDataRegStateOrRatChanged(Handler h, int what, Object obj)3846 public void registerForDataRegStateOrRatChanged(Handler h, int what, Object obj) { 3847 Registrant r = new Registrant(h, what, obj); 3848 mDataRegStateOrRatChangedRegistrants.add(r); 3849 notifyDataRegStateRilRadioTechnologyChanged(); 3850 } unregisterForDataRegStateOrRatChanged(Handler h)3851 public void unregisterForDataRegStateOrRatChanged(Handler h) { 3852 mDataRegStateOrRatChangedRegistrants.remove(h); 3853 } 3854 3855 /** 3856 * Registration point for transition into network attached. 3857 * @param h handler to notify 3858 * @param what what code of message when delivered 3859 * @param obj in Message.obj 3860 */ registerForNetworkAttached(Handler h, int what, Object obj)3861 public void registerForNetworkAttached(Handler h, int what, Object obj) { 3862 Registrant r = new Registrant(h, what, obj); 3863 3864 mNetworkAttachedRegistrants.add(r); 3865 if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { 3866 r.notifyRegistrant(); 3867 } 3868 } 3869 unregisterForNetworkAttached(Handler h)3870 public void unregisterForNetworkAttached(Handler h) { 3871 mNetworkAttachedRegistrants.remove(h); 3872 } 3873 3874 /** 3875 * Registration point for transition into network detached. 3876 * @param h handler to notify 3877 * @param what what code of message when delivered 3878 * @param obj in Message.obj 3879 */ registerForNetworkDetached(Handler h, int what, Object obj)3880 public void registerForNetworkDetached(Handler h, int what, Object obj) { 3881 Registrant r = new Registrant(h, what, obj); 3882 3883 mNetworkDetachedRegistrants.add(r); 3884 if (mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE) { 3885 r.notifyRegistrant(); 3886 } 3887 } 3888 unregisterForNetworkDetached(Handler h)3889 public void unregisterForNetworkDetached(Handler h) { 3890 mNetworkDetachedRegistrants.remove(h); 3891 } 3892 3893 /** 3894 * Registration point for transition into packet service restricted zone. 3895 * @param h handler to notify 3896 * @param what what code of message when delivered 3897 * @param obj placed in Message.obj 3898 */ registerForPsRestrictedEnabled(Handler h, int what, Object obj)3899 public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) { 3900 Registrant r = new Registrant(h, what, obj); 3901 mPsRestrictEnabledRegistrants.add(r); 3902 3903 if (mRestrictedState.isPsRestricted()) { 3904 r.notifyRegistrant(); 3905 } 3906 } 3907 unregisterForPsRestrictedEnabled(Handler h)3908 public void unregisterForPsRestrictedEnabled(Handler h) { 3909 mPsRestrictEnabledRegistrants.remove(h); 3910 } 3911 3912 /** 3913 * Registration point for transition out of packet service restricted zone. 3914 * @param h handler to notify 3915 * @param what what code of message when delivered 3916 * @param obj placed in Message.obj 3917 */ registerForPsRestrictedDisabled(Handler h, int what, Object obj)3918 public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) { 3919 Registrant r = new Registrant(h, what, obj); 3920 mPsRestrictDisabledRegistrants.add(r); 3921 3922 if (mRestrictedState.isPsRestricted()) { 3923 r.notifyRegistrant(); 3924 } 3925 } 3926 unregisterForPsRestrictedDisabled(Handler h)3927 public void unregisterForPsRestrictedDisabled(Handler h) { 3928 mPsRestrictDisabledRegistrants.remove(h); 3929 } 3930 3931 /** 3932 * Clean up existing voice and data connection then turn off radio power. 3933 * 3934 * Hang up the existing voice calls to decrease call drop rate. 3935 */ powerOffRadioSafely(DcTracker dcTracker)3936 public void powerOffRadioSafely(DcTracker dcTracker) { 3937 synchronized (this) { 3938 if (!mPendingRadioPowerOffAfterDataOff) { 3939 int dds = SubscriptionManager.getDefaultDataSubscriptionId(); 3940 // To minimize race conditions we call cleanUpAllConnections on 3941 // both if else paths instead of before this isDisconnected test. 3942 if (dcTracker.isDisconnected() 3943 && (dds == mPhone.getSubId() 3944 || (dds != mPhone.getSubId() 3945 && ProxyController.getInstance().isDataDisconnected(dds)))) { 3946 // To minimize race conditions we do this after isDisconnected 3947 dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF); 3948 if (DBG) log("Data disconnected, turn off radio right away."); 3949 hangupAndPowerOff(); 3950 } else { 3951 // hang up all active voice calls first 3952 if (mPhone.isPhoneTypeGsm() && mPhone.isInCall()) { 3953 mPhone.mCT.mRingingCall.hangupIfAlive(); 3954 mPhone.mCT.mBackgroundCall.hangupIfAlive(); 3955 mPhone.mCT.mForegroundCall.hangupIfAlive(); 3956 } 3957 dcTracker.cleanUpAllConnections(Phone.REASON_RADIO_TURNED_OFF); 3958 if (dds != mPhone.getSubId() 3959 && !ProxyController.getInstance().isDataDisconnected(dds)) { 3960 if (DBG) log("Data is active on DDS. Wait for all data disconnect"); 3961 // Data is not disconnected on DDS. Wait for the data disconnect complete 3962 // before sending the RADIO_POWER off. 3963 ProxyController.getInstance().registerForAllDataDisconnected(dds, this, 3964 EVENT_ALL_DATA_DISCONNECTED, null); 3965 mPendingRadioPowerOffAfterDataOff = true; 3966 } 3967 Message msg = Message.obtain(this); 3968 msg.what = EVENT_SET_RADIO_POWER_OFF; 3969 msg.arg1 = ++mPendingRadioPowerOffAfterDataOffTag; 3970 if (sendMessageDelayed(msg, 30000)) { 3971 if (DBG) log("Wait upto 30s for data to disconnect, then turn off radio."); 3972 mPendingRadioPowerOffAfterDataOff = true; 3973 } else { 3974 log("Cannot send delayed Msg, turn off radio right away."); 3975 hangupAndPowerOff(); 3976 mPendingRadioPowerOffAfterDataOff = false; 3977 } 3978 } 3979 } 3980 } 3981 } 3982 3983 /** 3984 * process the pending request to turn radio off after data is disconnected 3985 * 3986 * return true if there is pending request to process; false otherwise. 3987 */ processPendingRadioPowerOffAfterDataOff()3988 public boolean processPendingRadioPowerOffAfterDataOff() { 3989 synchronized(this) { 3990 if (mPendingRadioPowerOffAfterDataOff) { 3991 if (DBG) log("Process pending request to turn radio off."); 3992 mPendingRadioPowerOffAfterDataOffTag += 1; 3993 hangupAndPowerOff(); 3994 mPendingRadioPowerOffAfterDataOff = false; 3995 return true; 3996 } 3997 return false; 3998 } 3999 } 4000 4001 /** 4002 * Checks if the provided earfcn falls withing the range of earfcns. 4003 * 4004 * return true if earfcn falls within the provided range; false otherwise. 4005 */ containsEarfcnInEarfcnRange(ArrayList<Pair<Integer, Integer>> earfcnPairList, int earfcn)4006 private boolean containsEarfcnInEarfcnRange(ArrayList<Pair<Integer, Integer>> earfcnPairList, 4007 int earfcn) { 4008 if (earfcnPairList != null) { 4009 for (Pair<Integer, Integer> earfcnPair : earfcnPairList) { 4010 if ((earfcn >= earfcnPair.first) && (earfcn <= earfcnPair.second)) { 4011 return true; 4012 } 4013 } 4014 } 4015 4016 return false; 4017 } 4018 4019 /** 4020 * Convert the earfcnStringArray to list of pairs. 4021 * 4022 * Format of the earfcnsList is expected to be {"erafcn1_start-earfcn1_end", 4023 * "earfcn2_start-earfcn2_end" ... } 4024 */ convertEarfcnStringArrayToPairList(String[] earfcnsList)4025 ArrayList<Pair<Integer, Integer>> convertEarfcnStringArrayToPairList(String[] earfcnsList) { 4026 ArrayList<Pair<Integer, Integer>> earfcnPairList = new ArrayList<Pair<Integer, Integer>>(); 4027 4028 if (earfcnsList != null) { 4029 int earfcnStart; 4030 int earfcnEnd; 4031 for (int i = 0; i < earfcnsList.length; i++) { 4032 try { 4033 String[] earfcns = earfcnsList[i].split("-"); 4034 if (earfcns.length != 2) { 4035 if (VDBG) { 4036 log("Invalid earfcn range format"); 4037 } 4038 return null; 4039 } 4040 4041 earfcnStart = Integer.parseInt(earfcns[0]); 4042 earfcnEnd = Integer.parseInt(earfcns[1]); 4043 4044 if (earfcnStart > earfcnEnd) { 4045 if (VDBG) { 4046 log("Invalid earfcn range format"); 4047 } 4048 return null; 4049 } 4050 4051 earfcnPairList.add(new Pair<Integer, Integer>(earfcnStart, earfcnEnd)); 4052 } catch (PatternSyntaxException pse) { 4053 if (VDBG) { 4054 log("Invalid earfcn range format"); 4055 } 4056 return null; 4057 } catch (NumberFormatException nfe) { 4058 if (VDBG) { 4059 log("Invalid earfcn number format"); 4060 } 4061 return null; 4062 } 4063 } 4064 } 4065 4066 return earfcnPairList; 4067 } 4068 onCarrierConfigChanged()4069 private void onCarrierConfigChanged() { 4070 CarrierConfigManager configManager = (CarrierConfigManager) 4071 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 4072 PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId()); 4073 4074 if (config != null) { 4075 updateLteEarfcnLists(config); 4076 updateReportingCriteria(config); 4077 } 4078 } 4079 updateLteEarfcnLists(PersistableBundle config)4080 private void updateLteEarfcnLists(PersistableBundle config) { 4081 synchronized (mLteRsrpBoostLock) { 4082 mLteRsrpBoost = config.getInt(CarrierConfigManager.KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0); 4083 String[] earfcnsStringArrayForRsrpBoost = config.getStringArray( 4084 CarrierConfigManager.KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY); 4085 mEarfcnPairListForRsrpBoost = convertEarfcnStringArrayToPairList( 4086 earfcnsStringArrayForRsrpBoost); 4087 } 4088 } 4089 updateReportingCriteria(PersistableBundle config)4090 private void updateReportingCriteria(PersistableBundle config) { 4091 mPhone.setSignalStrengthReportingCriteria( 4092 config.getIntArray(CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY), 4093 AccessNetworkType.EUTRAN); 4094 mPhone.setSignalStrengthReportingCriteria( 4095 config.getIntArray(CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY), 4096 AccessNetworkType.UTRAN); 4097 } 4098 updateServiceStateLteEarfcnBoost(ServiceState serviceState, int lteEarfcn)4099 private void updateServiceStateLteEarfcnBoost(ServiceState serviceState, int lteEarfcn) { 4100 synchronized (mLteRsrpBoostLock) { 4101 if ((lteEarfcn != INVALID_LTE_EARFCN) 4102 && containsEarfcnInEarfcnRange(mEarfcnPairListForRsrpBoost, lteEarfcn)) { 4103 serviceState.setLteEarfcnRsrpBoost(mLteRsrpBoost); 4104 } else { 4105 serviceState.setLteEarfcnRsrpBoost(0); 4106 } 4107 } 4108 } 4109 4110 /** 4111 * send signal-strength-changed notification if changed Called both for 4112 * solicited and unsolicited signal strength updates 4113 * 4114 * @return true if the signal strength changed and a notification was sent. 4115 */ onSignalStrengthResult(AsyncResult ar)4116 protected boolean onSignalStrengthResult(AsyncResult ar) { 4117 boolean isGsm = false; 4118 int dataRat = mSS.getRilDataRadioTechnology(); 4119 int voiceRat = mSS.getRilVoiceRadioTechnology(); 4120 4121 // Override isGsm based on currently camped data and voice RATs 4122 // Set isGsm to true if the RAT belongs to GSM family and not IWLAN 4123 if ((dataRat != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 4124 && ServiceState.isGsm(dataRat)) 4125 || (voiceRat != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 4126 && ServiceState.isGsm(voiceRat))) { 4127 isGsm = true; 4128 } 4129 4130 // This signal is used for both voice and data radio signal so parse 4131 // all fields 4132 4133 if ((ar.exception == null) && (ar.result != null)) { 4134 mSignalStrength = (SignalStrength) ar.result; 4135 mSignalStrength.validateInput(); 4136 if (dataRat == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN 4137 && voiceRat == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) { 4138 mSignalStrength.fixType(); 4139 } else { 4140 mSignalStrength.setGsm(isGsm); 4141 } 4142 mSignalStrength.setLteRsrpBoost(mSS.getLteEarfcnRsrpBoost()); 4143 4144 PersistableBundle config = getCarrierConfig(); 4145 mSignalStrength.setUseOnlyRsrpForLteLevel(config.getBoolean( 4146 CarrierConfigManager.KEY_USE_ONLY_RSRP_FOR_LTE_SIGNAL_BAR_BOOL)); 4147 mSignalStrength.setLteRsrpThresholds(config.getIntArray( 4148 CarrierConfigManager.KEY_LTE_RSRP_THRESHOLDS_INT_ARRAY)); 4149 mSignalStrength.setWcdmaDefaultSignalMeasurement(config.getString( 4150 CarrierConfigManager.KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING)); 4151 mSignalStrength.setWcdmaRscpThresholds(config.getIntArray( 4152 CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY)); 4153 } else { 4154 log("onSignalStrengthResult() Exception from RIL : " + ar.exception); 4155 mSignalStrength = new SignalStrength(isGsm); 4156 } 4157 4158 boolean ssChanged = notifySignalStrength(); 4159 4160 return ssChanged; 4161 } 4162 4163 /** 4164 * Hang up all voice call and turn off radio. Implemented by derived class. 4165 */ hangupAndPowerOff()4166 protected void hangupAndPowerOff() { 4167 // hang up all active voice calls 4168 if (!mPhone.isPhoneTypeGsm() || mPhone.isInCall()) { 4169 mPhone.mCT.mRingingCall.hangupIfAlive(); 4170 mPhone.mCT.mBackgroundCall.hangupIfAlive(); 4171 mPhone.mCT.mForegroundCall.hangupIfAlive(); 4172 } 4173 4174 mCi.setRadioPower(false, obtainMessage(EVENT_RADIO_POWER_OFF_DONE)); 4175 4176 } 4177 4178 /** Cancel a pending (if any) pollState() operation */ cancelPollState()4179 protected void cancelPollState() { 4180 // This will effectively cancel the rest of the poll requests. 4181 mPollingContext = new int[1]; 4182 } 4183 4184 /** 4185 * Return true if the network operator's country code changed. 4186 */ networkCountryIsoChanged(String newCountryIsoCode, String prevCountryIsoCode)4187 private boolean networkCountryIsoChanged(String newCountryIsoCode, String prevCountryIsoCode) { 4188 // Return false if the new ISO code isn't valid as we don't know where we are. 4189 // Return true if the previous ISO code wasn't valid, or if it was and the new one differs. 4190 4191 // If newCountryIsoCode is invalid then we'll return false 4192 if (TextUtils.isEmpty(newCountryIsoCode)) { 4193 if (DBG) { 4194 log("countryIsoChanged: no new country ISO code"); 4195 } 4196 return false; 4197 } 4198 4199 if (TextUtils.isEmpty(prevCountryIsoCode)) { 4200 if (DBG) { 4201 log("countryIsoChanged: no previous country ISO code"); 4202 } 4203 return true; 4204 } 4205 return !newCountryIsoCode.equals(prevCountryIsoCode); 4206 } 4207 4208 // Determine if the Icc card exists iccCardExists()4209 private boolean iccCardExists() { 4210 boolean iccCardExist = false; 4211 if (mUiccApplcation != null) { 4212 iccCardExist = mUiccApplcation.getState() != AppState.APPSTATE_UNKNOWN; 4213 } 4214 return iccCardExist; 4215 } 4216 getSystemProperty(String property, String defValue)4217 public String getSystemProperty(String property, String defValue) { 4218 return TelephonyManager.getTelephonyProperty(mPhone.getPhoneId(), property, defValue); 4219 } 4220 4221 /** 4222 * @return all available cell information or null if none. 4223 */ getAllCellInfo(WorkSource workSource)4224 public List<CellInfo> getAllCellInfo(WorkSource workSource) { 4225 CellInfoResult result = new CellInfoResult(); 4226 if (VDBG) log("SST.getAllCellInfo(): E"); 4227 int ver = mCi.getRilVersion(); 4228 if (ver >= 8) { 4229 if (isCallerOnDifferentThread()) { 4230 if ((SystemClock.elapsedRealtime() - mLastCellInfoListTime) 4231 > LAST_CELL_INFO_LIST_MAX_AGE_MS) { 4232 Message msg = obtainMessage(EVENT_GET_CELL_INFO_LIST, result); 4233 synchronized(result.lockObj) { 4234 result.list = null; 4235 mCi.getCellInfoList(msg, workSource); 4236 try { 4237 result.lockObj.wait(5000); 4238 } catch (InterruptedException e) { 4239 e.printStackTrace(); 4240 } 4241 } 4242 } else { 4243 if (DBG) log("SST.getAllCellInfo(): return last, back to back calls"); 4244 result.list = mLastCellInfoList; 4245 } 4246 } else { 4247 if (DBG) log("SST.getAllCellInfo(): return last, same thread can't block"); 4248 result.list = mLastCellInfoList; 4249 } 4250 } else { 4251 if (DBG) log("SST.getAllCellInfo(): not implemented"); 4252 result.list = null; 4253 } 4254 synchronized(result.lockObj) { 4255 if (result.list != null) { 4256 if (VDBG) log("SST.getAllCellInfo(): X size=" + result.list.size() 4257 + " list=" + result.list); 4258 return result.list; 4259 } else { 4260 if (DBG) log("SST.getAllCellInfo(): X size=0 list=null"); 4261 return null; 4262 } 4263 } 4264 } 4265 4266 /** 4267 * @return signal strength 4268 */ getSignalStrength()4269 public SignalStrength getSignalStrength() { 4270 return mSignalStrength; 4271 } 4272 4273 /** 4274 * Registration point for subscription info ready 4275 * @param h handler to notify 4276 * @param what what code of message when delivered 4277 * @param obj placed in Message.obj 4278 */ registerForSubscriptionInfoReady(Handler h, int what, Object obj)4279 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) { 4280 Registrant r = new Registrant(h, what, obj); 4281 mCdmaForSubscriptionInfoReadyRegistrants.add(r); 4282 4283 if (isMinInfoReady()) { 4284 r.notifyRegistrant(); 4285 } 4286 } 4287 unregisterForSubscriptionInfoReady(Handler h)4288 public void unregisterForSubscriptionInfoReady(Handler h) { 4289 mCdmaForSubscriptionInfoReadyRegistrants.remove(h); 4290 } 4291 4292 /** 4293 * Save current source of cdma subscription 4294 * @param source - 1 for NV, 0 for RUIM 4295 */ saveCdmaSubscriptionSource(int source)4296 private void saveCdmaSubscriptionSource(int source) { 4297 log("Storing cdma subscription source: " + source); 4298 Settings.Global.putInt(mPhone.getContext().getContentResolver(), 4299 Settings.Global.CDMA_SUBSCRIPTION_MODE, 4300 source); 4301 log("Read from settings: " + Settings.Global.getInt(mPhone.getContext().getContentResolver(), 4302 Settings.Global.CDMA_SUBSCRIPTION_MODE, -1)); 4303 } 4304 getSubscriptionInfoAndStartPollingThreads()4305 private void getSubscriptionInfoAndStartPollingThreads() { 4306 mCi.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION)); 4307 4308 // Get Registration Information 4309 pollState(); 4310 } 4311 handleCdmaSubscriptionSource(int newSubscriptionSource)4312 private void handleCdmaSubscriptionSource(int newSubscriptionSource) { 4313 log("Subscription Source : " + newSubscriptionSource); 4314 mIsSubscriptionFromRuim = 4315 (newSubscriptionSource == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM); 4316 log("isFromRuim: " + mIsSubscriptionFromRuim); 4317 saveCdmaSubscriptionSource(newSubscriptionSource); 4318 if (!mIsSubscriptionFromRuim) { 4319 // NV is ready when subscription source is NV 4320 sendMessage(obtainMessage(EVENT_NV_READY)); 4321 } 4322 } 4323 dumpEarfcnPairList(PrintWriter pw)4324 private void dumpEarfcnPairList(PrintWriter pw) { 4325 pw.print(" mEarfcnPairListForRsrpBoost={"); 4326 if (mEarfcnPairListForRsrpBoost != null) { 4327 int i = mEarfcnPairListForRsrpBoost.size(); 4328 for (Pair<Integer, Integer> earfcnPair : mEarfcnPairListForRsrpBoost) { 4329 pw.print("("); 4330 pw.print(earfcnPair.first); 4331 pw.print(","); 4332 pw.print(earfcnPair.second); 4333 pw.print(")"); 4334 if ((--i) != 0) { 4335 pw.print(","); 4336 } 4337 } 4338 } 4339 pw.println("}"); 4340 } 4341 dumpCellInfoList(PrintWriter pw)4342 private void dumpCellInfoList(PrintWriter pw) { 4343 pw.print(" mLastCellInfoList={"); 4344 if(mLastCellInfoList != null) { 4345 boolean first = true; 4346 for(CellInfo info : mLastCellInfoList) { 4347 if(first == false) { 4348 pw.print(","); 4349 } 4350 first = false; 4351 pw.print(info.toString()); 4352 } 4353 } 4354 pw.println("}"); 4355 } 4356 dump(FileDescriptor fd, PrintWriter pw, String[] args)4357 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4358 pw.println("ServiceStateTracker:"); 4359 pw.println(" mSubId=" + mSubId); 4360 pw.println(" mSS=" + mSS); 4361 pw.println(" mNewSS=" + mNewSS); 4362 pw.println(" mVoiceCapable=" + mVoiceCapable); 4363 pw.println(" mRestrictedState=" + mRestrictedState); 4364 pw.println(" mPollingContext=" + mPollingContext + " - " + 4365 (mPollingContext != null ? mPollingContext[0] : "")); 4366 pw.println(" mDesiredPowerState=" + mDesiredPowerState); 4367 pw.println(" mDontPollSignalStrength=" + mDontPollSignalStrength); 4368 pw.println(" mSignalStrength=" + mSignalStrength); 4369 pw.println(" mLastSignalStrength=" + mLastSignalStrength); 4370 pw.println(" mRestrictedState=" + mRestrictedState); 4371 pw.println(" mPendingRadioPowerOffAfterDataOff=" + mPendingRadioPowerOffAfterDataOff); 4372 pw.println(" mPendingRadioPowerOffAfterDataOffTag=" + mPendingRadioPowerOffAfterDataOffTag); 4373 pw.println(" mCellLoc=" + Rlog.pii(VDBG, mCellLoc)); 4374 pw.println(" mNewCellLoc=" + Rlog.pii(VDBG, mNewCellLoc)); 4375 pw.println(" mLastCellInfoListTime=" + mLastCellInfoListTime); 4376 dumpCellInfoList(pw); 4377 pw.flush(); 4378 pw.println(" mPreferredNetworkType=" + mPreferredNetworkType); 4379 pw.println(" mMaxDataCalls=" + mMaxDataCalls); 4380 pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls); 4381 pw.println(" mReasonDataDenied=" + mReasonDataDenied); 4382 pw.println(" mNewReasonDataDenied=" + mNewReasonDataDenied); 4383 pw.println(" mGsmRoaming=" + mGsmRoaming); 4384 pw.println(" mDataRoaming=" + mDataRoaming); 4385 pw.println(" mEmergencyOnly=" + mEmergencyOnly); 4386 pw.flush(); 4387 mNitzState.dumpState(pw); 4388 pw.flush(); 4389 pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck); 4390 pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg); 4391 pw.println(" mNotification=" + mNotification); 4392 pw.println(" mCurSpn=" + mCurSpn); 4393 pw.println(" mCurDataSpn=" + mCurDataSpn); 4394 pw.println(" mCurShowSpn=" + mCurShowSpn); 4395 pw.println(" mCurPlmn=" + mCurPlmn); 4396 pw.println(" mCurShowPlmn=" + mCurShowPlmn); 4397 pw.flush(); 4398 pw.println(" mCurrentOtaspMode=" + mCurrentOtaspMode); 4399 pw.println(" mRoamingIndicator=" + mRoamingIndicator); 4400 pw.println(" mIsInPrl=" + mIsInPrl); 4401 pw.println(" mDefaultRoamingIndicator=" + mDefaultRoamingIndicator); 4402 pw.println(" mRegistrationState=" + mRegistrationState); 4403 pw.println(" mMdn=" + mMdn); 4404 pw.println(" mHomeSystemId=" + mHomeSystemId); 4405 pw.println(" mHomeNetworkId=" + mHomeNetworkId); 4406 pw.println(" mMin=" + mMin); 4407 pw.println(" mPrlVersion=" + mPrlVersion); 4408 pw.println(" mIsMinInfoReady=" + mIsMinInfoReady); 4409 pw.println(" mIsEriTextLoaded=" + mIsEriTextLoaded); 4410 pw.println(" mIsSubscriptionFromRuim=" + mIsSubscriptionFromRuim); 4411 pw.println(" mCdmaSSM=" + mCdmaSSM); 4412 pw.println(" mRegistrationDeniedReason=" + mRegistrationDeniedReason); 4413 pw.println(" mCurrentCarrier=" + mCurrentCarrier); 4414 pw.flush(); 4415 pw.println(" mImsRegistered=" + mImsRegistered); 4416 pw.println(" mImsRegistrationOnOff=" + mImsRegistrationOnOff); 4417 pw.println(" mAlarmSwitch=" + mAlarmSwitch); 4418 pw.println(" mRadioDisabledByCarrier" + mRadioDisabledByCarrier); 4419 pw.println(" mPowerOffDelayNeed=" + mPowerOffDelayNeed); 4420 pw.println(" mDeviceShuttingDown=" + mDeviceShuttingDown); 4421 pw.println(" mSpnUpdatePending=" + mSpnUpdatePending); 4422 pw.println(" mLteRsrpBoost=" + mLteRsrpBoost); 4423 dumpEarfcnPairList(pw); 4424 4425 mLocaleTracker.dump(fd, pw, args); 4426 4427 pw.println(" Roaming Log:"); 4428 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 4429 ipw.increaseIndent(); 4430 mRoamingLog.dump(fd, ipw, args); 4431 ipw.decreaseIndent(); 4432 4433 ipw.println(" Attach Log:"); 4434 ipw.increaseIndent(); 4435 mAttachLog.dump(fd, ipw, args); 4436 ipw.decreaseIndent(); 4437 4438 ipw.println(" Phone Change Log:"); 4439 ipw.increaseIndent(); 4440 mPhoneTypeLog.dump(fd, ipw, args); 4441 ipw.decreaseIndent(); 4442 4443 ipw.println(" Rat Change Log:"); 4444 ipw.increaseIndent(); 4445 mRatLog.dump(fd, ipw, args); 4446 ipw.decreaseIndent(); 4447 4448 ipw.println(" Radio power Log:"); 4449 ipw.increaseIndent(); 4450 mRadioPowerLog.dump(fd, ipw, args); 4451 4452 mNitzState.dumpLogs(fd, ipw, args); 4453 } 4454 isImsRegistered()4455 public boolean isImsRegistered() { 4456 return mImsRegistered; 4457 } 4458 /** 4459 * Verifies the current thread is the same as the thread originally 4460 * used in the initialization of this instance. Throws RuntimeException 4461 * if not. 4462 * 4463 * @exception RuntimeException if the current thread is not 4464 * the thread that originally obtained this Phone instance. 4465 */ checkCorrectThread()4466 protected void checkCorrectThread() { 4467 if (Thread.currentThread() != getLooper().getThread()) { 4468 throw new RuntimeException( 4469 "ServiceStateTracker must be used from within one thread"); 4470 } 4471 } 4472 isCallerOnDifferentThread()4473 protected boolean isCallerOnDifferentThread() { 4474 boolean value = Thread.currentThread() != getLooper().getThread(); 4475 if (VDBG) log("isCallerOnDifferentThread: " + value); 4476 return value; 4477 } 4478 updateCarrierMccMncConfiguration(String newOp, String oldOp, Context context)4479 protected void updateCarrierMccMncConfiguration(String newOp, String oldOp, Context context) { 4480 // if we have a change in operator, notify wifi (even to/from none) 4481 if (((newOp == null) && (TextUtils.isEmpty(oldOp) == false)) || 4482 ((newOp != null) && (newOp.equals(oldOp) == false))) { 4483 log("update mccmnc=" + newOp + " fromServiceState=true"); 4484 MccTable.updateMccMncConfiguration(context, newOp, true); 4485 } 4486 } 4487 4488 /** 4489 * Check ISO country by MCC to see if phone is roaming in same registered country 4490 */ inSameCountry(String operatorNumeric)4491 protected boolean inSameCountry(String operatorNumeric) { 4492 if (TextUtils.isEmpty(operatorNumeric) || (operatorNumeric.length() < 5)) { 4493 // Not a valid network 4494 return false; 4495 } 4496 final String homeNumeric = getHomeOperatorNumeric(); 4497 if (TextUtils.isEmpty(homeNumeric) || (homeNumeric.length() < 5)) { 4498 // Not a valid SIM MCC 4499 return false; 4500 } 4501 boolean inSameCountry = true; 4502 final String networkMCC = operatorNumeric.substring(0, 3); 4503 final String homeMCC = homeNumeric.substring(0, 3); 4504 final String networkCountry = MccTable.countryCodeForMcc(Integer.parseInt(networkMCC)); 4505 final String homeCountry = MccTable.countryCodeForMcc(Integer.parseInt(homeMCC)); 4506 if (networkCountry.isEmpty() || homeCountry.isEmpty()) { 4507 // Not a valid country 4508 return false; 4509 } 4510 inSameCountry = homeCountry.equals(networkCountry); 4511 if (inSameCountry) { 4512 return inSameCountry; 4513 } 4514 // special same country cases 4515 if ("us".equals(homeCountry) && "vi".equals(networkCountry)) { 4516 inSameCountry = true; 4517 } else if ("vi".equals(homeCountry) && "us".equals(networkCountry)) { 4518 inSameCountry = true; 4519 } 4520 return inSameCountry; 4521 } 4522 4523 /** 4524 * Set both voice and data roaming type, 4525 * judging from the ISO country of SIM VS network. 4526 */ setRoamingType(ServiceState currentServiceState)4527 protected void setRoamingType(ServiceState currentServiceState) { 4528 final boolean isVoiceInService = 4529 (currentServiceState.getVoiceRegState() == ServiceState.STATE_IN_SERVICE); 4530 if (isVoiceInService) { 4531 if (currentServiceState.getVoiceRoaming()) { 4532 if (mPhone.isPhoneTypeGsm()) { 4533 // check roaming type by MCC 4534 if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) { 4535 currentServiceState.setVoiceRoamingType( 4536 ServiceState.ROAMING_TYPE_DOMESTIC); 4537 } else { 4538 currentServiceState.setVoiceRoamingType( 4539 ServiceState.ROAMING_TYPE_INTERNATIONAL); 4540 } 4541 } else { 4542 // some carrier defines international roaming by indicator 4543 int[] intRoamingIndicators = mPhone.getContext().getResources().getIntArray( 4544 com.android.internal.R.array.config_cdma_international_roaming_indicators); 4545 if ((intRoamingIndicators != null) && (intRoamingIndicators.length > 0)) { 4546 // It's domestic roaming at least now 4547 currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC); 4548 int curRoamingIndicator = currentServiceState.getCdmaRoamingIndicator(); 4549 for (int i = 0; i < intRoamingIndicators.length; i++) { 4550 if (curRoamingIndicator == intRoamingIndicators[i]) { 4551 currentServiceState.setVoiceRoamingType( 4552 ServiceState.ROAMING_TYPE_INTERNATIONAL); 4553 break; 4554 } 4555 } 4556 } else { 4557 // check roaming type by MCC 4558 if (inSameCountry(currentServiceState.getVoiceOperatorNumeric())) { 4559 currentServiceState.setVoiceRoamingType( 4560 ServiceState.ROAMING_TYPE_DOMESTIC); 4561 } else { 4562 currentServiceState.setVoiceRoamingType( 4563 ServiceState.ROAMING_TYPE_INTERNATIONAL); 4564 } 4565 } 4566 } 4567 } else { 4568 currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING); 4569 } 4570 } 4571 final boolean isDataInService = 4572 (currentServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE); 4573 final int dataRegType = currentServiceState.getRilDataRadioTechnology(); 4574 if (isDataInService) { 4575 if (!currentServiceState.getDataRoaming()) { 4576 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING); 4577 } else { 4578 if (mPhone.isPhoneTypeGsm()) { 4579 if (ServiceState.isGsm(dataRegType)) { 4580 if (isVoiceInService) { 4581 // GSM data should have the same state as voice 4582 currentServiceState.setDataRoamingType(currentServiceState 4583 .getVoiceRoamingType()); 4584 } else { 4585 // we can not decide GSM data roaming type without voice 4586 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN); 4587 } 4588 } else { 4589 // we can not decide 3gpp2 roaming state here 4590 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN); 4591 } 4592 } else { 4593 if (ServiceState.isCdma(dataRegType)) { 4594 if (isVoiceInService) { 4595 // CDMA data should have the same state as voice 4596 currentServiceState.setDataRoamingType(currentServiceState 4597 .getVoiceRoamingType()); 4598 } else { 4599 // we can not decide CDMA data roaming type without voice 4600 // set it as same as last time 4601 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN); 4602 } 4603 } else { 4604 // take it as 3GPP roaming 4605 if (inSameCountry(currentServiceState.getDataOperatorNumeric())) { 4606 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC); 4607 } else { 4608 currentServiceState.setDataRoamingType( 4609 ServiceState.ROAMING_TYPE_INTERNATIONAL); 4610 } 4611 } 4612 } 4613 } 4614 } 4615 } 4616 setSignalStrengthDefaultValues()4617 private void setSignalStrengthDefaultValues() { 4618 mSignalStrength = new SignalStrength(true); 4619 } 4620 getHomeOperatorNumeric()4621 protected String getHomeOperatorNumeric() { 4622 String numeric = ((TelephonyManager) mPhone.getContext(). 4623 getSystemService(Context.TELEPHONY_SERVICE)). 4624 getSimOperatorNumericForPhone(mPhone.getPhoneId()); 4625 if (!mPhone.isPhoneTypeGsm() && TextUtils.isEmpty(numeric)) { 4626 numeric = SystemProperties.get(GsmCdmaPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, ""); 4627 } 4628 return numeric; 4629 } 4630 getPhoneId()4631 protected int getPhoneId() { 4632 return mPhone.getPhoneId(); 4633 } 4634 4635 /* Reset Service state when IWLAN is enabled as polling in airplane mode 4636 * causes state to go to OUT_OF_SERVICE state instead of STATE_OFF 4637 */ resetServiceStateInIwlanMode()4638 protected void resetServiceStateInIwlanMode() { 4639 if (mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) { 4640 boolean resetIwlanRatVal = false; 4641 log("set service state as POWER_OFF"); 4642 if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN 4643 == mNewSS.getRilDataRadioTechnology()) { 4644 log("pollStateDone: mNewSS = " + mNewSS); 4645 log("pollStateDone: reset iwlan RAT value"); 4646 resetIwlanRatVal = true; 4647 } 4648 // operator info should be kept in SS 4649 String operator = mNewSS.getOperatorAlphaLong(); 4650 mNewSS.setStateOff(); 4651 if (resetIwlanRatVal) { 4652 mNewSS.setRilDataRadioTechnology(ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN); 4653 mNewSS.setDataRegState(ServiceState.STATE_IN_SERVICE); 4654 mNewSS.setOperatorAlphaLong(operator); 4655 log("pollStateDone: mNewSS = " + mNewSS); 4656 } 4657 } 4658 } 4659 4660 /** 4661 * Check if device is non-roaming and always on home network. 4662 * 4663 * @param b carrier config bundle obtained from CarrierConfigManager 4664 * @return true if network is always on home network, false otherwise 4665 * @see CarrierConfigManager 4666 */ alwaysOnHomeNetwork(BaseBundle b)4667 protected final boolean alwaysOnHomeNetwork(BaseBundle b) { 4668 return b.getBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL); 4669 } 4670 4671 /** 4672 * Check if the network identifier has membership in the set of 4673 * network identifiers stored in the carrier config bundle. 4674 * 4675 * @param b carrier config bundle obtained from CarrierConfigManager 4676 * @param network The network identifier to check network existence in bundle 4677 * @param key The key to index into the bundle presenting a string array of 4678 * networks to check membership 4679 * @return true if network has membership in bundle networks, false otherwise 4680 * @see CarrierConfigManager 4681 */ isInNetwork(BaseBundle b, String network, String key)4682 private boolean isInNetwork(BaseBundle b, String network, String key) { 4683 String[] networks = b.getStringArray(key); 4684 4685 if (networks != null && Arrays.asList(networks).contains(network)) { 4686 return true; 4687 } 4688 return false; 4689 } 4690 isRoamingInGsmNetwork(BaseBundle b, String network)4691 protected final boolean isRoamingInGsmNetwork(BaseBundle b, String network) { 4692 return isInNetwork(b, network, CarrierConfigManager.KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY); 4693 } 4694 isNonRoamingInGsmNetwork(BaseBundle b, String network)4695 protected final boolean isNonRoamingInGsmNetwork(BaseBundle b, String network) { 4696 return isInNetwork(b, network, CarrierConfigManager.KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY); 4697 } 4698 isRoamingInCdmaNetwork(BaseBundle b, String network)4699 protected final boolean isRoamingInCdmaNetwork(BaseBundle b, String network) { 4700 return isInNetwork(b, network, CarrierConfigManager.KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY); 4701 } 4702 isNonRoamingInCdmaNetwork(BaseBundle b, String network)4703 protected final boolean isNonRoamingInCdmaNetwork(BaseBundle b, String network) { 4704 return isInNetwork(b, network, CarrierConfigManager.KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY); 4705 } 4706 4707 /** Check if the device is shutting down. */ isDeviceShuttingDown()4708 public boolean isDeviceShuttingDown() { 4709 return mDeviceShuttingDown; 4710 } 4711 4712 /** 4713 * Consider dataRegState if voiceRegState is OOS to determine SPN to be displayed 4714 */ getCombinedRegState()4715 protected int getCombinedRegState() { 4716 int regState = mSS.getVoiceRegState(); 4717 int dataRegState = mSS.getDataRegState(); 4718 if ((regState == ServiceState.STATE_OUT_OF_SERVICE 4719 || regState == ServiceState.STATE_POWER_OFF) 4720 && (dataRegState == ServiceState.STATE_IN_SERVICE)) { 4721 log("getCombinedRegState: return STATE_IN_SERVICE as Data is in service"); 4722 regState = dataRegState; 4723 } 4724 return regState; 4725 } 4726 4727 /** 4728 * Gets the carrier configuration values for a particular subscription. 4729 * 4730 * @return A {@link PersistableBundle} containing the config for the given subId, 4731 * or default values for an invalid subId. 4732 */ getCarrierConfig()4733 private PersistableBundle getCarrierConfig() { 4734 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 4735 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 4736 if (configManager != null) { 4737 // If an invalid subId is used, this bundle will contain default values. 4738 PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId()); 4739 if (config != null) { 4740 return config; 4741 } 4742 } 4743 // Return static default defined in CarrierConfigManager. 4744 return CarrierConfigManager.getDefaultConfig(); 4745 } 4746 getLocaleTracker()4747 public LocaleTracker getLocaleTracker() { 4748 return mLocaleTracker; 4749 } 4750 } 4751