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