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