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