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