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