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