• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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