• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony;
18 
19 import static android.provider.Telephony.ServiceStateTable.getUriForSubscriptionId;
20 
21 import static com.android.internal.telephony.CarrierActionAgent.CARRIER_ACTION_SET_RADIO_ENABLED;
22 import static com.android.internal.telephony.uicc.IccRecords.CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN;
23 import static com.android.internal.telephony.uicc.IccRecords.CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN;
24 
25 import android.annotation.IntDef;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.app.Notification;
29 import android.app.NotificationManager;
30 import android.compat.annotation.UnsupportedAppUsage;
31 import android.content.BroadcastReceiver;
32 import android.content.ContentResolver;
33 import android.content.ContentValues;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.IntentFilter;
37 import android.content.SharedPreferences;
38 import android.content.res.Resources;
39 import android.hardware.radio.V1_0.CellInfoType;
40 import android.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                 // Need to show both plmn and spn if both are not same.
2805                 if (!Objects.equals(spn, plmn)) {
2806                     String separator = mPhone.getContext().getString(
2807                             com.android.internal.R.string.kg_text_message_separator).toString();
2808                     carrierName = new StringBuilder().append(carrierName).append(separator)
2809                             .append(spn).toString();
2810                 }
2811             }
2812         } else if (showSpn) {
2813             carrierName = spn;
2814         }
2815         return carrierName;
2816     }
2817 
updateSpnDisplayCdnr()2818     private void updateSpnDisplayCdnr() {
2819         log("updateSpnDisplayCdnr+");
2820         CarrierDisplayNameData data = mCdnr.getCarrierDisplayNameData();
2821         notifySpnDisplayUpdate(data);
2822         log("updateSpnDisplayCdnr-");
2823     }
2824 
2825     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2826     @VisibleForTesting
updateSpnDisplay()2827     public void updateSpnDisplay() {
2828         if (mCarrierConfig.getBoolean(
2829                 CarrierConfigManager.KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL)) {
2830             updateSpnDisplayCdnr();
2831         } else {
2832             updateSpnDisplayLegacy();
2833         }
2834     }
2835 
updateSpnDisplayLegacy()2836     private void updateSpnDisplayLegacy() {
2837         log("updateSpnDisplayLegacy+");
2838 
2839         String spn = null;
2840         String dataSpn = null;
2841         boolean showSpn = false;
2842         String plmn;
2843         boolean showPlmn;
2844 
2845         String wfcVoiceSpnFormat = null;
2846         String wfcDataSpnFormat = null;
2847         String wfcFlightSpnFormat = null;
2848         int combinedRegState = getCombinedRegState(mSS);
2849         if (mPhone.getImsPhone() != null && mPhone.getImsPhone().isWifiCallingEnabled()
2850                 && mPhone.isImsRegistered()
2851                 && (combinedRegState == ServiceState.STATE_IN_SERVICE
2852                 && mSS.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_IWLAN)) {
2853             // In Wi-Fi Calling mode (connected to WiFi and WFC enabled),
2854             // show SPN or PLMN + WiFi Calling
2855             //
2856             // 1) Show SPN + Wi-Fi Calling If SIM has SPN and SPN display condition
2857             //    is satisfied or SPN override is enabled for this carrier
2858             //
2859             // 2) Show PLMN + Wi-Fi Calling if there is no valid SPN in case 1
2860 
2861             int voiceIdx;
2862             int dataIdx;
2863             int flightModeIdx;
2864             boolean useRootLocale;
2865 
2866             voiceIdx = mCarrierConfig.getInt(CarrierConfigManager.KEY_WFC_SPN_FORMAT_IDX_INT);
2867             dataIdx = mCarrierConfig.getInt(CarrierConfigManager.KEY_WFC_DATA_SPN_FORMAT_IDX_INT);
2868             flightModeIdx = mCarrierConfig.getInt(
2869                     CarrierConfigManager.KEY_WFC_FLIGHT_MODE_SPN_FORMAT_IDX_INT);
2870             useRootLocale =
2871                     mCarrierConfig.getBoolean(CarrierConfigManager.KEY_WFC_SPN_USE_ROOT_LOCALE);
2872 
2873             String[] wfcSpnFormats = SubscriptionManager.getResourcesForSubId(mPhone.getContext(),
2874                     mPhone.getSubId(), useRootLocale)
2875                     .getStringArray(com.android.internal.R.array.wfcSpnFormats);
2876 
2877             if (voiceIdx < 0 || voiceIdx >= wfcSpnFormats.length) {
2878                 loge("updateSpnDisplay: KEY_WFC_SPN_FORMAT_IDX_INT out of bounds: " + voiceIdx);
2879                 voiceIdx = 0;
2880             }
2881             if (dataIdx < 0 || dataIdx >= wfcSpnFormats.length) {
2882                 loge("updateSpnDisplay: KEY_WFC_DATA_SPN_FORMAT_IDX_INT out of bounds: "
2883                         + dataIdx);
2884                 dataIdx = 0;
2885             }
2886             if (flightModeIdx < 0 || flightModeIdx >= wfcSpnFormats.length) {
2887                 // KEY_WFC_FLIGHT_MODE_SPN_FORMAT_IDX_INT out of bounds. Use the value from
2888                 // voiceIdx.
2889                 flightModeIdx = voiceIdx;
2890             }
2891 
2892             wfcVoiceSpnFormat = wfcSpnFormats[voiceIdx];
2893             wfcDataSpnFormat = wfcSpnFormats[dataIdx];
2894             wfcFlightSpnFormat = wfcSpnFormats[flightModeIdx];
2895         }
2896 
2897         String crossSimSpnFormat = null;
2898         if (mPhone.getImsPhone() != null
2899                 && (mPhone.getImsPhone() != null)
2900                 && (mPhone.getImsPhone().getImsRegistrationTech()
2901                 == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM)) {
2902             // In Cross SIM Calling mode show SPN or PLMN + Cross SIM Calling
2903             //
2904             // 1) Show SPN + Cross SIM Calling If SIM has SPN and SPN display condition
2905             //    is satisfied or SPN override is enabled for this carrier
2906             //
2907             // 2) Show PLMN + Cross SIM Calling if there is no valid SPN in case 1
2908             int crossSimSpnFormatIdx =
2909                     mCarrierConfig.getInt(CarrierConfigManager.KEY_CROSS_SIM_SPN_FORMAT_INT);
2910             boolean useRootLocale =
2911                     mCarrierConfig.getBoolean(CarrierConfigManager.KEY_WFC_SPN_USE_ROOT_LOCALE);
2912 
2913             String[] crossSimSpnFormats = SubscriptionManager.getResourcesForSubId(
2914                     mPhone.getContext(), mPhone.getSubId(), useRootLocale)
2915                     .getStringArray(R.array.crossSimSpnFormats);
2916 
2917             if (crossSimSpnFormatIdx < 0 || crossSimSpnFormatIdx >= crossSimSpnFormats.length) {
2918                 loge("updateSpnDisplay: KEY_CROSS_SIM_SPN_FORMAT_INT out of bounds: "
2919                         + crossSimSpnFormatIdx);
2920                 crossSimSpnFormatIdx = 0;
2921             }
2922             crossSimSpnFormat = crossSimSpnFormats[crossSimSpnFormatIdx];
2923         }
2924 
2925         if (mPhone.isPhoneTypeGsm()) {
2926             // The values of plmn/showPlmn change in different scenarios.
2927             // 1) No service but emergency call allowed -> expected
2928             //    to show "Emergency call only"
2929             //    EXTRA_SHOW_PLMN = true
2930             //    EXTRA_PLMN = "Emergency call only"
2931 
2932             // 2) No service at all --> expected to show "No service"
2933             //    EXTRA_SHOW_PLMN = true
2934             //    EXTRA_PLMN = "No service"
2935 
2936             // 3) Normal operation in either home or roaming service
2937             //    EXTRA_SHOW_PLMN = depending on IccRecords rule
2938             //    EXTRA_PLMN = plmn
2939 
2940             // 4) No service due to power off, aka airplane mode
2941             //    EXTRA_SHOW_PLMN = true
2942             //    EXTRA_PLMN = null
2943 
2944             int rule = getCarrierNameDisplayBitmask(mSS);
2945             boolean noService = false;
2946             if (combinedRegState == ServiceState.STATE_OUT_OF_SERVICE
2947                     || combinedRegState == ServiceState.STATE_EMERGENCY_ONLY) {
2948                 showPlmn = true;
2949 
2950                 // Force display no service
2951                 final boolean forceDisplayNoService = shouldForceDisplayNoService() && !mIsSimReady;
2952                 if (!forceDisplayNoService && (mEmergencyOnly || Phone.isEmergencyCallOnly())) {
2953                     // The slot is emc only or the slot is masked as oos due to device is emc only
2954                     plmn = Resources.getSystem()
2955                             .getText(com.android.internal.R.string.emergency_calls_only).toString();
2956                 } else {
2957                     // No service at all
2958                     plmn = Resources.getSystem()
2959                             .getText(com.android.internal.R.string.lockscreen_carrier_default)
2960                             .toString();
2961                     noService = true;
2962                 }
2963                 if (DBG) log("updateSpnDisplay: radio is on but out " +
2964                         "of service, set plmn='" + plmn + "'");
2965             } else if (combinedRegState == ServiceState.STATE_IN_SERVICE) {
2966                 // In either home or roaming service
2967                 plmn = mSS.getOperatorAlpha();
2968                 showPlmn = !TextUtils.isEmpty(plmn) &&
2969                         ((rule & CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN)
2970                                 == CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN);
2971                 if (DBG) log("updateSpnDisplay: rawPlmn = " + plmn);
2972             } else {
2973                 // Power off state, such as airplane mode, show plmn as null
2974                 showPlmn = true;
2975                 plmn = null;
2976                 if (DBG) log("updateSpnDisplay: radio is off w/ showPlmn="
2977                         + showPlmn + " plmn=" + plmn);
2978             }
2979 
2980             // The value of spn/showSpn are same in different scenarios.
2981             //    EXTRA_SHOW_SPN = depending on IccRecords rule and radio/IMS state
2982             //    EXTRA_SPN = spn
2983             //    EXTRA_DATA_SPN = dataSpn
2984             spn = getServiceProviderName();
2985             dataSpn = spn;
2986             showSpn = !noService && !TextUtils.isEmpty(spn)
2987                     && ((rule & CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN)
2988                     == CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN);
2989             if (DBG) log("updateSpnDisplay: rawSpn = " + spn);
2990             if (!TextUtils.isEmpty(crossSimSpnFormat)) {
2991                 if (!TextUtils.isEmpty(spn)) {
2992                     // Show SPN + Cross-SIM Calling If SIM has SPN and SPN display condition
2993                     // is satisfied or SPN override is enabled for this carrier.
2994                     String originalSpn = spn.trim();
2995                     spn = String.format(crossSimSpnFormat, originalSpn);
2996                     dataSpn = spn;
2997                     showSpn = true;
2998                     showPlmn = false;
2999                 } else if (!TextUtils.isEmpty(plmn)) {
3000                     // Show PLMN + Cross-SIM Calling if there is no valid SPN in the above case
3001                     String originalPlmn = plmn.trim();
3002                     if (mIccRecords != null && mCarrierConfig.getBoolean(
3003                             CarrierConfigManager.KEY_WFC_CARRIER_NAME_OVERRIDE_BY_PNN_BOOL)) {
3004                         originalPlmn = mIccRecords.getPnnHomeName();
3005                     }
3006                     plmn = String.format(crossSimSpnFormat, originalPlmn);
3007                 }
3008             } else if (!TextUtils.isEmpty(spn) && !TextUtils.isEmpty(wfcVoiceSpnFormat)
3009                     && !TextUtils.isEmpty(wfcDataSpnFormat)) {
3010                 // Show SPN + Wi-Fi Calling If SIM has SPN and SPN display condition
3011                 // is satisfied or SPN override is enabled for this carrier.
3012 
3013                 // Handle Flight Mode
3014                 if (mSS.getState() == ServiceState.STATE_POWER_OFF) {
3015                     wfcVoiceSpnFormat = wfcFlightSpnFormat;
3016                 }
3017 
3018                 String originalSpn = spn.trim();
3019                 spn = String.format(wfcVoiceSpnFormat, originalSpn);
3020                 dataSpn = String.format(wfcDataSpnFormat, originalSpn);
3021                 showSpn = true;
3022                 showPlmn = false;
3023             } else if (!TextUtils.isEmpty(plmn) && !TextUtils.isEmpty(wfcVoiceSpnFormat)) {
3024                 // Show PLMN + Wi-Fi Calling if there is no valid SPN in the above case
3025                 String originalPlmn = plmn.trim();
3026 
3027                 if (mIccRecords != null && mCarrierConfig.getBoolean(
3028                         CarrierConfigManager.KEY_WFC_CARRIER_NAME_OVERRIDE_BY_PNN_BOOL)) {
3029                     originalPlmn = mIccRecords.getPnnHomeName();
3030                 }
3031 
3032                 plmn = String.format(wfcVoiceSpnFormat, originalPlmn);
3033             } else if (mSS.getState() == ServiceState.STATE_POWER_OFF
3034                     || (showPlmn && TextUtils.equals(spn, plmn))) {
3035                 // airplane mode or spn equals plmn, do not show spn
3036                 spn = null;
3037                 showSpn = false;
3038             }
3039         } else {
3040             String eriText = getOperatorNameFromEri();
3041             if (eriText != null) mSS.setOperatorAlphaLong(eriText);
3042 
3043             // carrier config gets a priority over ERI
3044             updateOperatorNameFromCarrierConfig();
3045 
3046             // mOperatorAlpha contains the ERI text
3047             plmn = mSS.getOperatorAlpha();
3048             if (DBG) log("updateSpnDisplay: cdma rawPlmn = " + plmn);
3049 
3050             showPlmn = plmn != null;
3051 
3052             if (!TextUtils.isEmpty(plmn) && !TextUtils.isEmpty(wfcVoiceSpnFormat)) {
3053                 // In Wi-Fi Calling mode show SPN+WiFi
3054                 String originalPlmn = plmn.trim();
3055                 plmn = String.format(wfcVoiceSpnFormat, originalPlmn);
3056             } else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
3057                 // todo: temporary hack; should have a better fix. This is to avoid using operator
3058                 // name from ServiceState (populated in processIwlanRegistrationInfo()) until
3059                 // wifi calling is actually enabled
3060                 log("updateSpnDisplay: overwriting plmn from " + plmn + " to null as radio " +
3061                         "state is off");
3062                 plmn = null;
3063             }
3064 
3065             if (combinedRegState == ServiceState.STATE_OUT_OF_SERVICE) {
3066                 plmn = Resources.getSystem().getText(com.android.internal.R.string
3067                         .lockscreen_carrier_default).toString();
3068                 if (DBG) {
3069                     log("updateSpnDisplay: radio is on but out of svc, set plmn='" + plmn + "'");
3070                 }
3071             }
3072 
3073         }
3074 
3075         notifySpnDisplayUpdate(new CarrierDisplayNameData.Builder()
3076                 .setSpn(spn)
3077                 .setDataSpn(dataSpn)
3078                 .setShowSpn(showSpn)
3079                 .setPlmn(plmn)
3080                 .setShowPlmn(showPlmn)
3081                 .build());
3082         log("updateSpnDisplayLegacy-");
3083     }
3084 
3085     /**
3086      * Returns whether out-of-service will be displayed as "no service" to the user.
3087      */
shouldForceDisplayNoService()3088     public boolean shouldForceDisplayNoService() {
3089         String[] countriesWithNoService = mPhone.getContext().getResources().getStringArray(
3090                 com.android.internal.R.array.config_display_no_service_when_sim_unready);
3091         if (ArrayUtils.isEmpty(countriesWithNoService)) {
3092             return false;
3093         }
3094         mLastKnownNetworkCountry = mLocaleTracker.getLastKnownCountryIso();
3095         for (String country : countriesWithNoService) {
3096             if (country.equalsIgnoreCase(mLastKnownNetworkCountry)) {
3097                 return true;
3098             }
3099         }
3100         return false;
3101     }
3102 
setPowerStateToDesired()3103     protected void setPowerStateToDesired() {
3104         setPowerStateToDesired(false, false, false);
3105     }
3106 
setPowerStateToDesired(boolean forEmergencyCall, boolean isSelectedPhoneForEmergencyCall, boolean forceApply)3107     protected void setPowerStateToDesired(boolean forEmergencyCall,
3108             boolean isSelectedPhoneForEmergencyCall, boolean forceApply) {
3109         if (DBG) {
3110             String tmpLog = "setPowerStateToDesired: mDeviceShuttingDown=" + mDeviceShuttingDown
3111                     + ", mDesiredPowerState=" + mDesiredPowerState
3112                     + ", getRadioState=" + mCi.getRadioState()
3113                     + ", mRadioPowerOffReasons=" + mRadioPowerOffReasons
3114                     + ", IMS reg state=" + mImsRegistrationOnOff
3115                     + ", pending radio off=" + hasMessages(EVENT_POWER_OFF_RADIO_IMS_DEREG_TIMEOUT);
3116             log(tmpLog);
3117             mRadioPowerLog.log(tmpLog);
3118         }
3119 
3120         if (mDesiredPowerState && mDeviceShuttingDown) {
3121             log("setPowerStateToDesired powering on of radio failed because the device is " +
3122                     "powering off");
3123             return;
3124         }
3125 
3126         // If we want it on and it's off, turn it on
3127         if (mDesiredPowerState && mRadioPowerOffReasons.isEmpty()
3128                 && (forceApply || mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF)) {
3129             mCi.setRadioPower(true, forEmergencyCall, isSelectedPhoneForEmergencyCall, null);
3130         } else if ((!mDesiredPowerState || !mRadioPowerOffReasons.isEmpty()) && mCi.getRadioState()
3131                 == TelephonyManager.RADIO_POWER_ON) {
3132             if (DBG) log("setPowerStateToDesired: powerOffRadioSafely()");
3133             powerOffRadioSafely();
3134         } else if (mDeviceShuttingDown
3135                 && (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE)) {
3136             // !mDesiredPowerState condition above will happen first if the radio is on, so we will
3137             // see the following: (delay for IMS dereg) -> RADIO_POWER_OFF ->
3138             // RADIO_POWER_UNAVAILABLE
3139             mCi.requestShutdown(null);
3140         }
3141         // Cancel any pending timeouts because the state has been re-evaluated.
3142         cancelDelayRadioOffWaitingForImsDeregTimeout();
3143     }
3144 
3145     /**
3146      * Cancel the EVENT_POWER_OFF_RADIO_DELAYED event if it is currently pending to be completed.
3147      */
cancelDelayRadioOffWaitingForImsDeregTimeout()3148     private void cancelDelayRadioOffWaitingForImsDeregTimeout() {
3149         if (hasMessages(EVENT_POWER_OFF_RADIO_IMS_DEREG_TIMEOUT)) {
3150             if (DBG) log("cancelDelayRadioOffWaitingForImsDeregTimeout: cancelling.");
3151             removeMessages(EVENT_POWER_OFF_RADIO_IMS_DEREG_TIMEOUT);
3152         }
3153     }
3154 
onUpdateIccAvailability()3155     protected void onUpdateIccAvailability() {
3156         if (mUiccController == null ) {
3157             return;
3158         }
3159 
3160         UiccCardApplication newUiccApplication = getUiccCardApplication();
3161 
3162         if (mUiccApplication != newUiccApplication) {
3163 
3164             // Remove the EF records that come from UICC
3165             if (mIccRecords instanceof SIMRecords) {
3166                 mCdnr.updateEfFromUsim(null /* usim */);
3167             } else if (mIccRecords instanceof RuimRecords) {
3168                 mCdnr.updateEfFromRuim(null /* ruim */);
3169             }
3170 
3171             if (mUiccApplication != null) {
3172                 log("Removing stale icc objects.");
3173                 mUiccApplication.unregisterForReady(this);
3174                 if (mIccRecords != null) {
3175                     mIccRecords.unregisterForRecordsLoaded(this);
3176                 }
3177                 mIccRecords = null;
3178                 mUiccApplication = null;
3179             }
3180             if (newUiccApplication != null) {
3181                 log("New card found");
3182                 mUiccApplication = newUiccApplication;
3183                 mIccRecords = mUiccApplication.getIccRecords();
3184                 if (mPhone.isPhoneTypeGsm()) {
3185                     mUiccApplication.registerForReady(this, EVENT_SIM_READY, null);
3186                     if (mIccRecords != null) {
3187                         mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
3188                     }
3189                 } else if (mIsSubscriptionFromRuim) {
3190                     mUiccApplication.registerForReady(this, EVENT_RUIM_READY, null);
3191                     if (mIccRecords != null) {
3192                         mIccRecords.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
3193                     }
3194                 }
3195             }
3196         }
3197     }
3198 
logRoamingChange()3199     private void logRoamingChange() {
3200         mRoamingLog.log(mSS.toString());
3201     }
3202 
logAttachChange()3203     private void logAttachChange() {
3204         mAttachLog.log(mSS.toString());
3205     }
3206 
logPhoneTypeChange()3207     private void logPhoneTypeChange() {
3208         mPhoneTypeLog.log(Integer.toString(mPhone.getPhoneType()));
3209     }
3210 
logRatChange()3211     private void logRatChange() {
3212         mRatLog.log(mSS.toString());
3213     }
3214 
3215     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
log(String s)3216     protected final void log(String s) {
3217         Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "] " + s);
3218     }
3219 
3220     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
loge(String s)3221     protected final void loge(String s) {
3222         Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "] " + s);
3223     }
3224 
3225     /**
3226      * @return The current GPRS state. IN_SERVICE is the same as "attached"
3227      * and OUT_OF_SERVICE is the same as detached.
3228      */
3229     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getCurrentDataConnectionState()3230     public int getCurrentDataConnectionState() {
3231         return mSS.getDataRegistrationState();
3232     }
3233 
3234     /**
3235      * @return true if phone is camping on a technology (eg UMTS)
3236      * that could support voice and data simultaneously.
3237      */
3238     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isConcurrentVoiceAndDataAllowed()3239     public boolean isConcurrentVoiceAndDataAllowed() {
3240         if (mSS.getCssIndicator() == 1) {
3241             // Checking the Concurrent Service Supported flag first for all phone types.
3242             return true;
3243         } else if (mPhone.isPhoneTypeGsm()) {
3244             int radioTechnology = mSS.getRilDataRadioTechnology();
3245             // There are cases where we we would setup data connection even data is not yet
3246             // attached. In these cases we check voice rat.
3247             if (radioTechnology == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN
3248                     && mSS.getDataRegistrationState() != ServiceState.STATE_IN_SERVICE) {
3249                 radioTechnology = mSS.getRilVoiceRadioTechnology();
3250             }
3251             // Concurrent voice and data is not allowed for 2G technologies. It's allowed in other
3252             // rats e.g. UMTS, LTE, etc.
3253             return radioTechnology != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN
3254                     && ServiceState.rilRadioTechnologyToAccessNetworkType(radioTechnology)
3255                         != AccessNetworkType.GERAN;
3256         } else {
3257             return false;
3258         }
3259     }
3260 
3261     /** Called when the service state of ImsPhone is changed. */
onImsServiceStateChanged()3262     public void onImsServiceStateChanged() {
3263         sendMessage(obtainMessage(EVENT_IMS_SERVICE_STATE_CHANGED));
3264     }
3265 
3266     /**
3267      * Sets the Ims registration state.  If the 3 second shut down timer has begun and the state
3268      * is set to unregistered, the timer is cancelled and the radio is shutdown immediately.
3269      *
3270      * @param registered whether ims is registered
3271      */
setImsRegistrationState(final boolean registered)3272     public void setImsRegistrationState(final boolean registered) {
3273         log("setImsRegistrationState: {registered=" + registered
3274                 + " mImsRegistrationOnOff=" + mImsRegistrationOnOff
3275                 + "}");
3276 
3277         if (mImsRegistrationOnOff && !registered) {
3278             // moving to deregistered, only send this event if we need to re-evaluate
3279             if (getRadioPowerOffDelayTimeoutForImsRegistration() > 0) {
3280                 // only send this event if the power off delay for IMS deregistration feature is
3281                 // enabled.
3282                 sendMessage(obtainMessage(EVENT_CHANGE_IMS_STATE));
3283             } else {
3284                 log("setImsRegistrationState: EVENT_CHANGE_IMS_STATE not sent because power off "
3285                         + "delay for IMS deregistration is not enabled.");
3286             }
3287         }
3288         mImsRegistrationOnOff = registered;
3289 
3290         // It's possible ServiceState changes did not trigger SPN display update; we update it here.
3291         updateSpnDisplay();
3292     }
3293 
onImsCapabilityChanged()3294     public void onImsCapabilityChanged() {
3295         sendMessage(obtainMessage(EVENT_IMS_CAPABILITY_CHANGED));
3296     }
3297 
isRadioOn()3298     public boolean isRadioOn() {
3299         return mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON;
3300     }
3301 
3302     /**
3303      * A complete "service state" from our perspective is
3304      * composed of a handful of separate requests to the radio.
3305      *
3306      * We make all of these requests at once, but then abandon them
3307      * and start over again if the radio notifies us that some
3308      * event has changed
3309      */
3310     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
pollState()3311     public void pollState() {
3312         sendEmptyMessage(EVENT_POLL_STATE_REQUEST);
3313     }
3314 
pollStateInternal(boolean modemTriggered)3315     private void pollStateInternal(boolean modemTriggered) {
3316         mPollingContext = new int[1];
3317 
3318         log("pollState: modemTriggered=" + modemTriggered + ", radioState=" + mCi.getRadioState());
3319 
3320         switch (mCi.getRadioState()) {
3321             case TelephonyManager.RADIO_POWER_UNAVAILABLE:
3322                 handlePollStateInternalForRadioOffOrUnavailable(false);
3323                 pollStateDone();
3324                 break;
3325 
3326             case TelephonyManager.RADIO_POWER_OFF:
3327                 handlePollStateInternalForRadioOffOrUnavailable(true);
3328                 // Don't poll when device is shutting down or the poll was not modemTriggered
3329                 // (they sent us new radio data) and the current network is not IWLAN
3330                 if (mDeviceShuttingDown ||
3331                         (!modemTriggered && ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
3332                         != mSS.getRilDataRadioTechnology())) {
3333                     pollStateDone();
3334                     break;
3335                 }
3336 
3337             default:
3338                 // Issue all poll-related commands at once then count down the responses, which
3339                 // are allowed to arrive out-of-order
3340                 mPollingContext[0]++;
3341                 mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR, mPollingContext));
3342 
3343                 mPollingContext[0]++;
3344                 mRegStateManagers.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
3345                         .requestNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
3346                                 obtainMessage(EVENT_POLL_STATE_PS_CELLULAR_REGISTRATION,
3347                                         mPollingContext));
3348 
3349                 mPollingContext[0]++;
3350                 mRegStateManagers.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
3351                         .requestNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
3352                         obtainMessage(EVENT_POLL_STATE_CS_CELLULAR_REGISTRATION, mPollingContext));
3353 
3354                 if (mRegStateManagers.get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN) != null) {
3355                     mPollingContext[0]++;
3356                     mRegStateManagers.get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
3357                             .requestNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
3358                                     obtainMessage(EVENT_POLL_STATE_PS_IWLAN_REGISTRATION,
3359                                             mPollingContext));
3360                 }
3361 
3362                 if (mPhone.isPhoneTypeGsm()) {
3363                     mPollingContext[0]++;
3364                     mCi.getNetworkSelectionMode(obtainMessage(
3365                             EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext));
3366                 }
3367                 break;
3368         }
3369     }
3370 
handlePollStateInternalForRadioOffOrUnavailable(boolean radioOff)3371     private void handlePollStateInternalForRadioOffOrUnavailable(boolean radioOff) {
3372         // Preserve the IWLAN registration state, which should not be affected by radio availability
3373         NetworkRegistrationInfo nri = mNewSS.getNetworkRegistrationInfo(
3374                 NetworkRegistrationInfo.DOMAIN_PS,
3375                 AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
3376         mNewSS.setOutOfService(radioOff);
3377         // Add the IWLAN registration info back to service state.
3378         if (nri != null) {
3379             mNewSS.addNetworkRegistrationInfo(nri);
3380         }
3381         mPhone.getSignalStrengthController().setSignalStrengthDefaultValues();
3382         mLastNitzData = null;
3383         mNitzState.handleNetworkUnavailable();
3384     }
3385 
3386     /**
3387      * Get the highest-priority CellIdentity for a provided ServiceState.
3388      *
3389      * Choose a CellIdentity for ServiceState using the following rules:
3390      * 1) WWAN only (WLAN is excluded)
3391      * 2) Registered > Camped
3392      * 3) CS > PS
3393      *
3394      * @param ss a Non-Null ServiceState object
3395      *
3396      * @return a list of CellIdentity objects in *decreasing* order of preference.
3397      */
getPrioritizedCellIdentities( @onNull final ServiceState ss)3398     @VisibleForTesting public static @NonNull List<CellIdentity> getPrioritizedCellIdentities(
3399             @NonNull final ServiceState ss) {
3400         final List<NetworkRegistrationInfo> regInfos = ss.getNetworkRegistrationInfoList();
3401         if (regInfos.isEmpty()) return Collections.emptyList();
3402 
3403         return regInfos.stream()
3404             .filter(nri -> nri.getCellIdentity() != null)
3405             .filter(nri -> nri.getTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
3406             .sorted(Comparator
3407                     .comparing(NetworkRegistrationInfo::isRegistered)
3408                     .thenComparing((nri) -> nri.getDomain() & NetworkRegistrationInfo.DOMAIN_CS)
3409                     .reversed())
3410             .map(nri -> nri.getCellIdentity())
3411             .distinct()
3412             .collect(Collectors.toList());
3413     }
3414 
pollStateDone()3415     private void pollStateDone() {
3416         if (!mPhone.isPhoneTypeGsm()) {
3417             updateRoamingState();
3418         }
3419 
3420         if (TelephonyUtils.IS_DEBUGGABLE
3421                 && SystemProperties.getBoolean(PROP_FORCE_ROAMING, false)) {
3422             mNewSS.setRoaming(true);
3423         }
3424         useDataRegStateForDataOnlyDevices();
3425         processIwlanRegistrationInfo();
3426 
3427         updateNrFrequencyRangeFromPhysicalChannelConfigs(mLastPhysicalChannelConfigList, mNewSS);
3428         updateNrStateFromPhysicalChannelConfigs(mLastPhysicalChannelConfigList, mNewSS);
3429         updateNtnCapability();
3430 
3431         if (TelephonyUtils.IS_DEBUGGABLE && mPhone.getTelephonyTester() != null) {
3432             mPhone.getTelephonyTester().overrideServiceState(mNewSS);
3433         }
3434 
3435         NetworkRegistrationInfo networkRegState = mNewSS.getNetworkRegistrationInfo(
3436                 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
3437         setPhyCellInfoFromCellIdentity(mNewSS, networkRegState.getCellIdentity());
3438 
3439         if (DBG) {
3440             log("Poll ServiceState done: oldSS=" + mSS);
3441             log("Poll ServiceState done: newSS=" + mNewSS);
3442             log("Poll ServiceState done: oldMaxDataCalls=" + mMaxDataCalls
3443                     + " mNewMaxDataCalls=" + mNewMaxDataCalls
3444                     + " oldReasonDataDenied=" + mReasonDataDenied
3445                     + " mNewReasonDataDenied=" + mNewReasonDataDenied);
3446         }
3447 
3448         boolean hasRegistered =
3449                 mSS.getState() != ServiceState.STATE_IN_SERVICE
3450                         && mNewSS.getState() == ServiceState.STATE_IN_SERVICE;
3451 
3452         boolean hasDeregistered =
3453                 mSS.getState() == ServiceState.STATE_IN_SERVICE
3454                         && mNewSS.getState() != ServiceState.STATE_IN_SERVICE;
3455 
3456         boolean hasAirplaneModeOnChanged =
3457                 mSS.getState() != ServiceState.STATE_POWER_OFF
3458                         && mNewSS.getState() == ServiceState.STATE_POWER_OFF;
3459         boolean hasAirplaneModeOffChanged =
3460                 mSS.getState() == ServiceState.STATE_POWER_OFF
3461                         && mNewSS.getState() != ServiceState.STATE_POWER_OFF;
3462 
3463         SparseBooleanArray hasDataAttached = new SparseBooleanArray();
3464         SparseBooleanArray hasDataDetached = new SparseBooleanArray();
3465         SparseBooleanArray hasRilDataRadioTechnologyChanged = new SparseBooleanArray();
3466         SparseBooleanArray hasDataRegStateChanged = new SparseBooleanArray();
3467         boolean anyDataRegChanged = false;
3468         boolean anyDataRatChanged = false;
3469         boolean hasAlphaRawChanged =
3470                 !TextUtils.equals(mSS.getOperatorAlphaLongRaw(), mNewSS.getOperatorAlphaLongRaw())
3471                         || !TextUtils.equals(mSS.getOperatorAlphaShortRaw(),
3472                         mNewSS.getOperatorAlphaShortRaw());
3473 
3474         for (int transport : mAccessNetworksManager.getAvailableTransports()) {
3475             NetworkRegistrationInfo oldNrs = mSS.getNetworkRegistrationInfo(
3476                     NetworkRegistrationInfo.DOMAIN_PS, transport);
3477             NetworkRegistrationInfo newNrs = mNewSS.getNetworkRegistrationInfo(
3478                     NetworkRegistrationInfo.DOMAIN_PS, transport);
3479 
3480             boolean changed = (oldNrs == null || !oldNrs.isInService() || hasAirplaneModeOnChanged)
3481                     && (newNrs != null && newNrs.isInService());
3482             hasDataAttached.put(transport, changed);
3483 
3484             changed = (oldNrs != null && oldNrs.isInService())
3485                     && (newNrs == null || !newNrs.isInService());
3486             hasDataDetached.put(transport, changed);
3487 
3488             int oldRAT = oldNrs != null ? oldNrs.getAccessNetworkTechnology()
3489                     : TelephonyManager.NETWORK_TYPE_UNKNOWN;
3490             int newRAT = newNrs != null ? newNrs.getAccessNetworkTechnology()
3491                     : TelephonyManager.NETWORK_TYPE_UNKNOWN;
3492 
3493             boolean isOldCA = oldNrs != null ? oldNrs.isUsingCarrierAggregation() : false;
3494             boolean isNewCA = newNrs != null ? newNrs.isUsingCarrierAggregation() : false;
3495 
3496             // If the carrier enable KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING and the operator name
3497             // match this pattern, the data rat display LteAdvanced indicator.
3498             hasRilDataRadioTechnologyChanged.put(transport,
3499                     oldRAT != newRAT || isOldCA != isNewCA || hasAlphaRawChanged);
3500             if (oldRAT != newRAT) {
3501                 anyDataRatChanged = true;
3502             }
3503 
3504             int oldRegState = oldNrs != null ? oldNrs.getNetworkRegistrationState()
3505                     : NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
3506             int newRegState = newNrs != null ? newNrs.getNetworkRegistrationState()
3507                     : NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
3508             hasDataRegStateChanged.put(transport, oldRegState != newRegState);
3509             if (oldRegState != newRegState) {
3510                 anyDataRegChanged = true;
3511             }
3512         }
3513 
3514         // Filter out per transport data RAT changes, only want to track changes based on
3515         // transport preference changes (WWAN to WLAN, for example).
3516         boolean hasDataTransportPreferenceChanged = !anyDataRatChanged
3517                 && (mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology());
3518 
3519         boolean hasVoiceRegStateChanged =
3520                 mSS.getState() != mNewSS.getState();
3521 
3522         boolean hasNrFrequencyRangeChanged =
3523                 mSS.getNrFrequencyRange() != mNewSS.getNrFrequencyRange();
3524 
3525         boolean hasNrStateChanged = mSS.getNrState() != mNewSS.getNrState();
3526 
3527         final List<CellIdentity> prioritizedCids = getPrioritizedCellIdentities(mNewSS);
3528 
3529         final CellIdentity primaryCellIdentity = prioritizedCids.isEmpty()
3530                 ? null : prioritizedCids.get(0);
3531 
3532         boolean hasLocationChanged = mCellIdentity == null
3533                 ? primaryCellIdentity != null : !mCellIdentity.isSameCell(primaryCellIdentity);
3534 
3535         boolean isRegisteredOnWwan = false;
3536         for (NetworkRegistrationInfo nri : mNewSS.getNetworkRegistrationInfoListForTransportType(
3537                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
3538             isRegisteredOnWwan |= nri.isRegistered();
3539         }
3540 
3541         // Ratchet if the device is in service on the same cell
3542         if (isRegisteredOnWwan && !hasLocationChanged) {
3543             mRatRatcheter.ratchet(mSS, mNewSS);
3544         }
3545 
3546         boolean hasRilVoiceRadioTechnologyChanged =
3547                 mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology();
3548 
3549         boolean hasChanged = !mNewSS.equals(mSS);
3550 
3551         boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming();
3552 
3553         boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming();
3554 
3555         boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming();
3556 
3557         boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming();
3558 
3559         boolean hasRejectCauseChanged = mRejectCode != mNewRejectCode;
3560 
3561         boolean hasCssIndicatorChanged = (mSS.getCssIndicator() != mNewSS.getCssIndicator());
3562 
3563         boolean has4gHandoff = false;
3564         boolean hasMultiApnSupport = false;
3565         boolean hasLostMultiApnSupport = false;
3566         if (mPhone.isPhoneTypeCdmaLte()) {
3567             final int wwanDataRat = getRilDataRadioTechnologyForWwan(mSS);
3568             final int newWwanDataRat = getRilDataRadioTechnologyForWwan(mNewSS);
3569             has4gHandoff = mNewSS.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE
3570                     && ((ServiceState.isPsOnlyTech(wwanDataRat)
3571                     && (newWwanDataRat == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))
3572                     || ((wwanDataRat == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)
3573                     && ServiceState.isPsOnlyTech(newWwanDataRat)));
3574 
3575             hasMultiApnSupport = ((ServiceState.isPsOnlyTech(newWwanDataRat)
3576                     || (newWwanDataRat == ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD))
3577                     && (!ServiceState.isPsOnlyTech(wwanDataRat)
3578                     && (wwanDataRat != ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD)));
3579 
3580             hasLostMultiApnSupport = ((newWwanDataRat >= ServiceState.RIL_RADIO_TECHNOLOGY_IS95A)
3581                     && (newWwanDataRat <= ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A));
3582         }
3583 
3584         if (DBG) {
3585             log("pollStateDone:"
3586                     + " hasRegistered = " + hasRegistered
3587                     + " hasDeregistered = " + hasDeregistered
3588                     + " hasDataAttached = " + hasDataAttached
3589                     + " hasDataDetached = " + hasDataDetached
3590                     + " hasDataRegStateChanged = " + hasDataRegStateChanged
3591                     + " hasRilVoiceRadioTechnologyChanged = " + hasRilVoiceRadioTechnologyChanged
3592                     + " hasRilDataRadioTechnologyChanged = " + hasRilDataRadioTechnologyChanged
3593                     + " hasDataTransportPreferenceChanged = " + hasDataTransportPreferenceChanged
3594                     + " hasChanged = " + hasChanged
3595                     + " hasVoiceRoamingOn = " + hasVoiceRoamingOn
3596                     + " hasVoiceRoamingOff = " + hasVoiceRoamingOff
3597                     + " hasDataRoamingOn =" + hasDataRoamingOn
3598                     + " hasDataRoamingOff = " + hasDataRoamingOff
3599                     + " hasLocationChanged = " + hasLocationChanged
3600                     + " has4gHandoff = " + has4gHandoff
3601                     + " hasMultiApnSupport = " + hasMultiApnSupport
3602                     + " hasLostMultiApnSupport = " + hasLostMultiApnSupport
3603                     + " hasCssIndicatorChanged = " + hasCssIndicatorChanged
3604                     + " hasNrFrequencyRangeChanged = " + hasNrFrequencyRangeChanged
3605                     + " hasNrStateChanged = " + hasNrStateChanged
3606                     + " hasAirplaneModeOnlChanged = " + hasAirplaneModeOnChanged);
3607         }
3608 
3609         // Add an event log when connection state changes
3610         if (hasVoiceRegStateChanged || anyDataRegChanged) {
3611             EventLog.writeEvent(mPhone.isPhoneTypeGsm() ? EventLogTags.GSM_SERVICE_STATE_CHANGE :
3612                             EventLogTags.CDMA_SERVICE_STATE_CHANGE,
3613                     mSS.getState(), mSS.getDataRegistrationState(),
3614                     mNewSS.getState(), mNewSS.getDataRegistrationState());
3615         }
3616 
3617         if (mPhone.isPhoneTypeGsm()) {
3618             // Add an event log when network type switched
3619             // TODO: we may add filtering to reduce the event logged,
3620             // i.e. check preferred network setting, only switch to 2G, etc
3621             if (hasRilVoiceRadioTechnologyChanged) {
3622                 long cid = getCidFromCellIdentity(primaryCellIdentity);
3623                 // NOTE: this code was previously located after mSS and mNewSS are swapped, so
3624                 // existing logs were incorrectly using the new state for "network_from"
3625                 // and STATE_OUT_OF_SERVICE for "network_to". To avoid confusion, use a new log tag
3626                 // to record the correct states.
3627                 EventLog.writeEvent(EventLogTags.GSM_RAT_SWITCHED_NEW, cid,
3628                         mSS.getRilVoiceRadioTechnology(),
3629                         mNewSS.getRilVoiceRadioTechnology());
3630                 if (DBG) {
3631                     log("RAT switched "
3632                             + ServiceState.rilRadioTechnologyToString(
3633                             mSS.getRilVoiceRadioTechnology())
3634                             + " -> "
3635                             + ServiceState.rilRadioTechnologyToString(
3636                             mNewSS.getRilVoiceRadioTechnology()) + " at cell " + cid);
3637                 }
3638             }
3639 
3640             mReasonDataDenied = mNewReasonDataDenied;
3641             mMaxDataCalls = mNewMaxDataCalls;
3642             mRejectCode = mNewRejectCode;
3643         }
3644 
3645         if (!Objects.equals(mSS, mNewSS)) {
3646             mServiceStateChangedRegistrants.notifyRegistrants();
3647         }
3648 
3649         ServiceState oldMergedSS = new ServiceState(mPhone.getServiceState());
3650         mSS = new ServiceState(mNewSS);
3651 
3652         mNewSS.setOutOfService(false);
3653 
3654         mCellIdentity = primaryCellIdentity;
3655         if (mSS.getState() == ServiceState.STATE_IN_SERVICE && primaryCellIdentity != null) {
3656             mLastKnownCellIdentity = mCellIdentity;
3657             removeMessages(EVENT_RESET_LAST_KNOWN_CELL_IDENTITY);
3658         }
3659 
3660         if (hasDeregistered && !hasMessages(EVENT_RESET_LAST_KNOWN_CELL_IDENTITY)) {
3661             sendEmptyMessageDelayed(EVENT_RESET_LAST_KNOWN_CELL_IDENTITY,
3662                     TimeUnit.DAYS.toMillis(1));
3663         }
3664 
3665         int areaCode = getAreaCodeFromCellIdentity(mCellIdentity);
3666         if (areaCode != mLastKnownAreaCode && areaCode != CellInfo.UNAVAILABLE) {
3667             mLastKnownAreaCode = areaCode;
3668             mAreaCodeChangedRegistrants.notifyRegistrants();
3669         }
3670 
3671         if (hasRilVoiceRadioTechnologyChanged) {
3672             updatePhoneObject();
3673         }
3674 
3675         TelephonyManager tm = (TelephonyManager) mPhone.getContext().getSystemService(
3676                 Context.TELEPHONY_SERVICE);
3677         if (anyDataRatChanged) {
3678             tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilDataRadioTechnology());
3679             TelephonyStatsLog.write(TelephonyStatsLog.MOBILE_RADIO_TECHNOLOGY_CHANGED,
3680                     ServiceState.rilRadioTechnologyToNetworkType(
3681                             mSS.getRilDataRadioTechnology()), mPhone.getPhoneId());
3682         }
3683 
3684         if (hasRegistered) {
3685             mNetworkAttachedRegistrants.notifyRegistrants();
3686             mNitzState.handleNetworkAvailable();
3687         }
3688 
3689         if (hasDeregistered) {
3690             mNetworkDetachedRegistrants.notifyRegistrants();
3691             mNitzState.handleNetworkUnavailable();
3692         }
3693 
3694         if (hasCssIndicatorChanged) {
3695             mCssIndicatorChangedRegistrants.notifyRegistrants();
3696         }
3697 
3698         if (hasRejectCauseChanged) {
3699             setNotification(CS_REJECT_CAUSE_ENABLED);
3700         }
3701 
3702         String eriText = mPhone.getCdmaEriText();
3703         boolean hasEriChanged = !TextUtils.equals(mEriText, eriText);
3704         mEriText = eriText;
3705         // Trigger updateSpnDisplay when
3706         // 1. Service state is changed.
3707         // 2. phone type is Cdma or CdmaLte and ERI text has changed.
3708         if (hasChanged || (!mPhone.isPhoneTypeGsm() && hasEriChanged)) {
3709             updateSpnDisplay();
3710         }
3711 
3712         if (hasChanged) {
3713             tm.setNetworkOperatorNameForPhone(mPhone.getPhoneId(), mSS.getOperatorAlpha());
3714             String operatorNumeric = mSS.getOperatorNumeric();
3715 
3716             if (!mPhone.isPhoneTypeGsm()) {
3717                 // try to fix the invalid Operator Numeric
3718                 if (isInvalidOperatorNumeric(operatorNumeric)) {
3719                     int sid = mSS.getCdmaSystemId();
3720                     operatorNumeric = fixUnknownMcc(operatorNumeric, sid);
3721                 }
3722             }
3723 
3724             tm.setNetworkOperatorNumericForPhone(mPhone.getPhoneId(), operatorNumeric);
3725 
3726             // If the OPERATOR command hasn't returned a valid operator or the device is on IWLAN (
3727             // because operatorNumeric would be SIM's mcc/mnc when device is on IWLAN), but if the
3728             // device has camped on a cell either to attempt registration or for emergency services,
3729             // then for purposes of setting the locale, we don't care if registration fails or is
3730             // incomplete. Additionally, if there is no cellular service and ims is registered over
3731             // the IWLAN, the locale will not be updated.
3732             // CellIdentity can return a null MCC and MNC in CDMA
3733             String localeOperator = operatorNumeric;
3734             int dataNetworkType = mSS.getDataNetworkType();
3735             if (dataNetworkType == TelephonyManager.NETWORK_TYPE_IWLAN
3736                     || (dataNetworkType == TelephonyManager.NETWORK_TYPE_UNKNOWN
3737                             && getImsRegistrationTech()
3738                                     == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)) {
3739                 // TODO(b/333346537#comment10): Complete solution would be ignore mcc/mnc reported
3740                 //  by the unsolicited indication OPERATOR from RIL, but only relies on MCC/MNC from
3741                 //  data registration or voice registration.
3742                 localeOperator = null;
3743             }
3744             if (isInvalidOperatorNumeric(localeOperator)) {
3745                 for (CellIdentity cid : prioritizedCids) {
3746                     if (!TextUtils.isEmpty(cid.getPlmn())) {
3747                         localeOperator = cid.getPlmn();
3748                         break;
3749                     }
3750                 }
3751             }
3752 
3753             if (isInvalidOperatorNumeric(localeOperator)) {
3754                 if (DBG) log("localeOperator " + localeOperator + " is invalid");
3755                 // Passing empty string is important for the first update. The initial value of
3756                 // operator numeric in locale tracker is null. The async update will allow getting
3757                 // cell info from the modem instead of using the cached one.
3758                 mLocaleTracker.updateOperatorNumeric("");
3759             } else {
3760                 if (!mPhone.isPhoneTypeGsm()) {
3761                     setOperatorIdd(localeOperator);
3762                 }
3763                 mLocaleTracker.updateOperatorNumeric(localeOperator);
3764             }
3765 
3766             tm.setNetworkRoamingForPhone(mPhone.getPhoneId(),
3767                     mPhone.isPhoneTypeGsm() ? mSS.getVoiceRoaming() :
3768                             (mSS.getVoiceRoaming() || mSS.getDataRoaming()));
3769 
3770             setRoamingType(mSS);
3771             log("Broadcasting ServiceState : " + mSS);
3772             // notify using PhoneStateListener and the legacy intent ACTION_SERVICE_STATE_CHANGED
3773             // notify service state changed only if the merged service state is changed.
3774             if (!oldMergedSS.equals(mPhone.getServiceState())) {
3775                 mPhone.notifyServiceStateChanged(mPhone.getServiceState());
3776             }
3777 
3778             updateServiceStateToDb(mPhone.getServiceState());
3779 
3780             TelephonyMetrics.getInstance().writeServiceStateChanged(mPhone.getPhoneId(), mSS);
3781             mPhone.getVoiceCallSessionStats().onServiceStateChanged(mSS);
3782             ImsPhone imsPhone = (ImsPhone) mPhone.getImsPhone();
3783             if (imsPhone != null) {
3784                 imsPhone.getImsStats().onServiceStateChanged(mSS);
3785             }
3786             mServiceStateStats.onServiceStateChanged(mSS);
3787         }
3788 
3789         boolean shouldLogAttachedChange = false;
3790         boolean shouldLogRatChange = false;
3791 
3792         if (hasRegistered || hasDeregistered) {
3793             shouldLogAttachedChange = true;
3794         }
3795 
3796         if (has4gHandoff) {
3797             mAttachedRegistrants.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
3798                     .notifyRegistrants();
3799             shouldLogAttachedChange = true;
3800         }
3801 
3802         if (hasRilVoiceRadioTechnologyChanged) {
3803             shouldLogRatChange = true;
3804             // TODO(b/178429976): Remove the dependency on SSC. Double check if the SS broadcast
3805             // is really needed when CS/PS RAT change.
3806             mPhone.getSignalStrengthController().notifySignalStrength();
3807         }
3808 
3809         for (int transport : mAccessNetworksManager.getAvailableTransports()) {
3810             if (hasRilDataRadioTechnologyChanged.get(transport)) {
3811                 shouldLogRatChange = true;
3812                 mPhone.getSignalStrengthController().notifySignalStrength();
3813             }
3814 
3815             if (hasDataRegStateChanged.get(transport)
3816                     || hasRilDataRadioTechnologyChanged.get(transport)
3817                     // Update all transports if preference changed so that consumers can be notified
3818                     // that ServiceState#getRilDataRadioTechnology has changed.
3819                     || hasDataTransportPreferenceChanged) {
3820                 setDataNetworkTypeForPhone(mSS.getRilDataRadioTechnology());
3821                 notifyDataRegStateRilRadioTechnologyChanged(transport);
3822             }
3823 
3824             if (hasDataAttached.get(transport)) {
3825                 shouldLogAttachedChange = true;
3826                 if (mAttachedRegistrants.get(transport) != null) {
3827                     mAttachedRegistrants.get(transport).notifyRegistrants();
3828                 }
3829             }
3830             if (hasDataDetached.get(transport)) {
3831                 shouldLogAttachedChange = true;
3832                 if (mDetachedRegistrants.get(transport) != null) {
3833                     mDetachedRegistrants.get(transport).notifyRegistrants();
3834                 }
3835             }
3836         }
3837 
3838         // Before starting to poll network state, the signal strength will be
3839         // reset under radio power off, so here expects to query it again
3840         // because the signal strength might come earlier RAT and radio state
3841         // changed.
3842         if (hasAirplaneModeOffChanged) {
3843             // TODO(b/178429976): Remove the dependency on SSC. This should be done in SSC.
3844             mPhone.getSignalStrengthController().getSignalStrengthFromCi();
3845         }
3846 
3847         if (shouldLogAttachedChange) {
3848             logAttachChange();
3849         }
3850         if (shouldLogRatChange) {
3851             logRatChange();
3852         }
3853 
3854         if (hasVoiceRegStateChanged || hasRilVoiceRadioTechnologyChanged) {
3855             notifyVoiceRegStateRilRadioTechnologyChanged();
3856         }
3857 
3858         if (hasVoiceRoamingOn || hasVoiceRoamingOff || hasDataRoamingOn || hasDataRoamingOff) {
3859             logRoamingChange();
3860         }
3861 
3862         if (hasVoiceRoamingOn) {
3863             mVoiceRoamingOnRegistrants.notifyRegistrants();
3864         }
3865 
3866         if (hasVoiceRoamingOff) {
3867             mVoiceRoamingOffRegistrants.notifyRegistrants();
3868         }
3869 
3870         if (hasDataRoamingOn) {
3871             mDataRoamingOnRegistrants.notifyRegistrants();
3872         }
3873 
3874         if (hasDataRoamingOff) {
3875             mDataRoamingOffRegistrants.notifyRegistrants();
3876         }
3877 
3878         if (hasLocationChanged) {
3879             mPhone.notifyLocationChanged(getCellIdentity());
3880         }
3881 
3882         if (hasNrStateChanged) {
3883             mNrStateChangedRegistrants.notifyRegistrants();
3884         }
3885 
3886         if (hasNrFrequencyRangeChanged) {
3887             mNrFrequencyChangedRegistrants.notifyRegistrants();
3888         }
3889 
3890         if (mPhone.isPhoneTypeGsm()) {
3891             if (!isGprsConsistent(mSS.getDataRegistrationState(), mSS.getState())) {
3892                 if (!mStartedGprsRegCheck && !mReportedGprsNoReg) {
3893                     mStartedGprsRegCheck = true;
3894 
3895                     int check_period = Settings.Global.getInt(
3896                             mPhone.getContext().getContentResolver(),
3897                             Settings.Global.GPRS_REGISTER_CHECK_PERIOD_MS,
3898                             DEFAULT_GPRS_CHECK_PERIOD_MILLIS);
3899                     sendMessageDelayed(obtainMessage(EVENT_CHECK_REPORT_GPRS),
3900                             check_period);
3901                 }
3902             } else {
3903                 mReportedGprsNoReg = false;
3904             }
3905         }
3906     }
3907 
3908     /**
3909      * Insert SS information into ServiceStateProvider DB table for a sub id.
3910      * This will trigger apps to wake through JobScheduler
3911      */
updateServiceStateToDb(ServiceState serviceState)3912     private void updateServiceStateToDb(ServiceState serviceState) {
3913         mPhone.getContext().getContentResolver()
3914                 .insert(getUriForSubscriptionId(mPhone.getSubId()),
3915                         getContentValuesForServiceState(serviceState));
3916     }
3917 
getOperatorNameFromEri()3918     private String getOperatorNameFromEri() {
3919         String eriText = null;
3920         if (mPhone.isPhoneTypeCdma()) {
3921             if ((mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON)
3922                     && (!mIsSubscriptionFromRuim)) {
3923                 // Now the Phone sees the new ServiceState so it can get the new ERI text
3924                 if (mSS.getState() == ServiceState.STATE_IN_SERVICE) {
3925                     eriText = mPhone.getCdmaEriText();
3926                 } else {
3927                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used for
3928                     // mRegistrationState 0,2,3 and 4
3929                     eriText = mPhone.getContext().getText(
3930                             com.android.internal.R.string.roamingTextSearching).toString();
3931                 }
3932             }
3933         } else if (mPhone.isPhoneTypeCdmaLte()) {
3934             boolean hasBrandOverride = mUiccController.getUiccPort(getPhoneId()) != null
3935                     && mUiccController.getUiccPort(getPhoneId()).getOperatorBrandOverride() != null;
3936             if (!hasBrandOverride && (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON)
3937                     && (mEriManager != null && mEriManager.isEriFileLoaded())
3938                     && (!ServiceState.isPsOnlyTech(mSS.getRilVoiceRadioTechnology())
3939                     || mPhone.getContext().getResources().getBoolean(com.android.internal.R
3940                     .bool.config_LTE_eri_for_network_name))) {
3941                 // Only when CDMA is in service, ERI will take effect
3942                 eriText = mSS.getOperatorAlpha();
3943                 // Now the Phone sees the new ServiceState so it can get the new ERI text
3944                 if (mSS.getState() == ServiceState.STATE_IN_SERVICE) {
3945                     eriText = mPhone.getCdmaEriText();
3946                 } else if (mSS.getState() == ServiceState.STATE_POWER_OFF) {
3947                     eriText = getServiceProviderName();
3948                     if (TextUtils.isEmpty(eriText)) {
3949                         // Sets operator alpha property by retrieving from
3950                         // build-time system property
3951                         eriText = SystemProperties.get("ro.cdma.home.operator.alpha");
3952                     }
3953                 } else if (mSS.getDataRegistrationState() != ServiceState.STATE_IN_SERVICE) {
3954                     // Note that ServiceState.STATE_OUT_OF_SERVICE is valid used
3955                     // for mRegistrationState 0,2,3 and 4
3956                     eriText = mPhone.getContext()
3957                             .getText(com.android.internal.R.string.roamingTextSearching).toString();
3958                 }
3959             }
3960 
3961             if (mUiccApplication != null && mUiccApplication.getState() == AppState.APPSTATE_READY
3962                     && mIccRecords != null
3963                     && getCombinedRegState(mSS) == ServiceState.STATE_IN_SERVICE
3964                     && !ServiceState.isPsOnlyTech(mSS.getRilVoiceRadioTechnology())) {
3965                 // SIM is found on the device. If ERI roaming is OFF, and SID/NID matches
3966                 // one configured in SIM, use operator name from CSIM record. Note that ERI, SID,
3967                 // and NID are CDMA only, not applicable to LTE.
3968                 boolean showSpn =
3969                         ((RuimRecords) mIccRecords).getCsimSpnDisplayCondition();
3970                 int iconIndex = mSS.getCdmaEriIconIndex();
3971 
3972                 if (showSpn && (iconIndex == EriInfo.ROAMING_INDICATOR_OFF)
3973                         && isInHomeSidNid(mSS.getCdmaSystemId(), mSS.getCdmaNetworkId())
3974                         && mIccRecords != null) {
3975                     eriText = getServiceProviderName();
3976                 }
3977             }
3978         }
3979         return eriText;
3980     }
3981 
3982     /**
3983      * Get the service provider name with highest priority among various source.
3984      * @return service provider name.
3985      */
getServiceProviderName()3986     public String getServiceProviderName() {
3987         // BrandOverride has higher priority than the carrier config
3988         String operatorBrandOverride = getOperatorBrandOverride();
3989         if (!TextUtils.isEmpty(operatorBrandOverride)) {
3990             return operatorBrandOverride;
3991         }
3992 
3993         String carrierName = mIccRecords != null ? mIccRecords.getServiceProviderName() : "";
3994         if (mCarrierConfig.getBoolean(CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL)
3995                 || TextUtils.isEmpty(carrierName)) {
3996             return mCarrierConfig.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
3997         }
3998 
3999         return carrierName;
4000     }
4001 
4002     /**
4003      * Get the resolved carrier name display condition bitmask.
4004      *
4005      * <p> Show service provider name if only if {@link #CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN}
4006      * is set.
4007      *
4008      * <p> Show PLMN network name if only if {@link #CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN} is set.
4009      *
4010      * @param ss service state
4011      * @return carrier name display bitmask.
4012      */
4013     @CarrierNameDisplayBitmask
getCarrierNameDisplayBitmask(ServiceState ss)4014     public int getCarrierNameDisplayBitmask(ServiceState ss) {
4015         if (!TextUtils.isEmpty(getOperatorBrandOverride())) {
4016             // If the operator has been overridden, all PLMNs will be considered HOME PLMNs, only
4017             // show SPN.
4018             return CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN;
4019         } else if (TextUtils.isEmpty(getServiceProviderName())) {
4020             // If SPN is null or empty, we should show plmn.
4021             // This is a hack from IccRecords#getServiceProviderName().
4022             return CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN;
4023         } else {
4024             boolean useRoamingFromServiceState = mCarrierConfig.getBoolean(
4025                     CarrierConfigManager.KEY_SPN_DISPLAY_RULE_USE_ROAMING_FROM_SERVICE_STATE_BOOL);
4026             int carrierDisplayNameConditionFromSim =
4027                     mIccRecords == null ? 0 : mIccRecords.getCarrierNameDisplayCondition();
4028 
4029             boolean isRoaming;
4030             if (useRoamingFromServiceState) {
4031                 isRoaming = ss.getRoaming();
4032             } else {
4033                 String[] hplmns = mIccRecords != null ? mIccRecords.getHomePlmns() : null;
4034                 isRoaming = !ArrayUtils.contains(hplmns, ss.getOperatorNumeric());
4035             }
4036             int rule;
4037             if (isRoaming) {
4038                 // Show PLMN when roaming.
4039                 rule = CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN;
4040 
4041                 // Check if show SPN is required when roaming.
4042                 if ((carrierDisplayNameConditionFromSim
4043                         & CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN)
4044                         == CARRIER_NAME_DISPLAY_CONDITION_BITMASK_SPN) {
4045                     rule |= CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN;
4046                 }
4047             } else {
4048                 // Show SPN when not roaming.
4049                 rule = CARRIER_NAME_DISPLAY_BITMASK_SHOW_SPN;
4050 
4051                 // Check if show PLMN is required when not roaming.
4052                 if ((carrierDisplayNameConditionFromSim
4053                         & CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN)
4054                         == CARRIER_NAME_DISPLAY_CONDITION_BITMASK_PLMN) {
4055                     rule |= CARRIER_NAME_DISPLAY_BITMASK_SHOW_PLMN;
4056                 }
4057             }
4058             return rule;
4059         }
4060     }
4061 
getOperatorBrandOverride()4062     private String getOperatorBrandOverride() {
4063         UiccPort uiccPort = mPhone.getUiccPort();
4064         if (uiccPort == null) return null;
4065         UiccProfile profile = uiccPort.getUiccProfile();
4066         if (profile == null) return null;
4067         return profile.getOperatorBrandOverride();
4068     }
4069 
4070     /**
4071      * Check whether the specified SID and NID pair appears in the HOME SID/NID list
4072      * read from NV or SIM.
4073      *
4074      * @return true if provided sid/nid pair belongs to operator's home network.
4075      */
4076     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInHomeSidNid(int sid, int nid)4077     private boolean isInHomeSidNid(int sid, int nid) {
4078         // if SID/NID is not available, assume this is home network.
4079         if (isSidsAllZeros()) return true;
4080 
4081         // length of SID/NID shold be same
4082         if (mHomeSystemId.length != mHomeNetworkId.length) return true;
4083 
4084         if (sid == 0) return true;
4085 
4086         for (int i = 0; i < mHomeSystemId.length; i++) {
4087             // Use SID only if NID is a reserved value.
4088             // SID 0 and NID 0 and 65535 are reserved. (C.0005 2.6.5.2)
4089             if ((mHomeSystemId[i] == sid) &&
4090                     ((mHomeNetworkId[i] == 0) || (mHomeNetworkId[i] == 65535) ||
4091                             (nid == 0) || (nid == 65535) || (mHomeNetworkId[i] == nid))) {
4092                 return true;
4093             }
4094         }
4095         // SID/NID are not in the list. So device is not in home network
4096         return false;
4097     }
4098 
4099     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setOperatorIdd(String operatorNumeric)4100     protected void setOperatorIdd(String operatorNumeric) {
4101         if (mPhone.getUnitTestMode()) {
4102             return;
4103         }
4104 
4105         // Retrieve the current country information
4106         // with the MCC got from operatorNumeric.
4107         String idd = mHbpcdUtils.getIddByMcc(
4108                 Integer.parseInt(operatorNumeric.substring(0,3)));
4109         if (idd != null && !idd.isEmpty()) {
4110             TelephonyProperties.operator_idp_string(idd);
4111         } else {
4112             // use default "+", since we don't know the current IDP
4113             TelephonyProperties.operator_idp_string("+");
4114         }
4115     }
4116 
4117     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInvalidOperatorNumeric(String operatorNumeric)4118     private boolean isInvalidOperatorNumeric(String operatorNumeric) {
4119         return operatorNumeric == null || operatorNumeric.length() < 5 ||
4120                 operatorNumeric.startsWith(INVALID_MCC);
4121     }
4122 
4123     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
fixUnknownMcc(String operatorNumeric, int sid)4124     private String fixUnknownMcc(String operatorNumeric, int sid) {
4125         if (sid <= 0) {
4126             // no cdma information is available, do nothing
4127             return operatorNumeric;
4128         }
4129 
4130         // resolve the mcc from sid, using time zone information from the latest NITZ signal when
4131         // available.
4132         int utcOffsetHours = 0;
4133         boolean isDst = false;
4134         boolean isNitzTimeZone = false;
4135         NitzData lastNitzData = mLastNitzData;
4136         if (lastNitzData != null) {
4137             utcOffsetHours = lastNitzData.getLocalOffsetMillis() / MS_PER_HOUR;
4138             Integer dstAdjustmentMillis = lastNitzData.getDstAdjustmentMillis();
4139             isDst = (dstAdjustmentMillis != null) && (dstAdjustmentMillis != 0);
4140             isNitzTimeZone = true;
4141         }
4142         int mcc = mHbpcdUtils.getMcc(sid, utcOffsetHours, (isDst ? 1 : 0), isNitzTimeZone);
4143         if (mcc > 0) {
4144             operatorNumeric = mcc + DEFAULT_MNC;
4145         }
4146         return operatorNumeric;
4147     }
4148 
4149     /**
4150      * Check if GPRS got registered while voice is registered.
4151      *
4152      * @param dataRegState i.e. CGREG in GSM
4153      * @param voiceRegState i.e. CREG in GSM
4154      * @return false if device only register to voice but not gprs
4155      */
4156     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isGprsConsistent(int dataRegState, int voiceRegState)4157     private boolean isGprsConsistent(int dataRegState, int voiceRegState) {
4158         return !((voiceRegState == ServiceState.STATE_IN_SERVICE) &&
4159                 (dataRegState != ServiceState.STATE_IN_SERVICE));
4160     }
4161 
4162     /** convert ServiceState registration code
4163      * to service state */
regCodeToServiceState(int code)4164     private int regCodeToServiceState(int code) {
4165         switch (code) {
4166             case NetworkRegistrationInfo.REGISTRATION_STATE_HOME:
4167             case NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING:
4168                 return ServiceState.STATE_IN_SERVICE;
4169             default:
4170                 return ServiceState.STATE_OUT_OF_SERVICE;
4171         }
4172     }
4173 
4174     /**
4175      * code is registration state 0-5 from TS 27.007 7.2
4176      * returns true if registered roam, false otherwise
4177      */
regCodeIsRoaming(int code)4178     private boolean regCodeIsRoaming (int code) {
4179         return NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING == code;
4180     }
4181 
isSameOperatorNameFromSimAndSS(ServiceState s)4182     private boolean isSameOperatorNameFromSimAndSS(ServiceState s) {
4183         String spn = ((TelephonyManager) mPhone.getContext().
4184                 getSystemService(Context.TELEPHONY_SERVICE)).
4185                 getSimOperatorNameForPhone(getPhoneId());
4186 
4187         // NOTE: in case of RUIM we should completely ignore the ERI data file and
4188         // mOperatorAlphaLong is set from RIL_REQUEST_OPERATOR response 0 (alpha ONS)
4189         String onsl = s.getOperatorAlphaLong();
4190         String onss = s.getOperatorAlphaShort();
4191 
4192         boolean equalsOnsl = !TextUtils.isEmpty(spn) && spn.equalsIgnoreCase(onsl);
4193         boolean equalsOnss = !TextUtils.isEmpty(spn) && spn.equalsIgnoreCase(onss);
4194 
4195         return (equalsOnsl || equalsOnss);
4196     }
4197 
4198     /**
4199      * Set roaming state if operator mcc is the same as sim mcc
4200      * and ons is not different from spn
4201      *
4202      * @param s ServiceState hold current ons
4203      * @return true if same operator
4204      */
isSameNamedOperators(ServiceState s)4205     private boolean isSameNamedOperators(ServiceState s) {
4206         return currentMccEqualsSimMcc(s) && isSameOperatorNameFromSimAndSS(s);
4207     }
4208 
4209     /**
4210      * Compare SIM MCC with Operator MCC
4211      *
4212      * @param s ServiceState hold current ons
4213      * @return true if both are same
4214      */
currentMccEqualsSimMcc(ServiceState s)4215     private boolean currentMccEqualsSimMcc(ServiceState s) {
4216         String simNumeric = ((TelephonyManager) mPhone.getContext().
4217                 getSystemService(Context.TELEPHONY_SERVICE)).
4218                 getSimOperatorNumericForPhone(getPhoneId());
4219         String operatorNumeric = s.getOperatorNumeric();
4220         boolean equalsMcc = true;
4221 
4222         try {
4223             equalsMcc = simNumeric.substring(0, 3).
4224                     equals(operatorNumeric.substring(0, 3));
4225         } catch (Exception e){
4226         }
4227         return equalsMcc;
4228     }
4229 
4230     /**
4231      * Do not set roaming state in case of operators considered non-roaming.
4232      *
4233      * Can use mcc or mcc+mnc as item of
4234      * {@link CarrierConfigManager#KEY_NON_ROAMING_OPERATOR_STRING_ARRAY}.
4235      * For example, 302 or 21407. If mcc or mcc+mnc match with operator,
4236      * don't set roaming state.
4237      *
4238      * @param s ServiceState hold current ons
4239      * @return false for roaming state set
4240      */
isOperatorConsideredNonRoaming(ServiceState s)4241     private boolean isOperatorConsideredNonRoaming(ServiceState s) {
4242         String operatorNumeric = s.getOperatorNumeric();
4243 
4244         String[] numericArray = mCarrierConfig.getStringArray(
4245                 CarrierConfigManager.KEY_NON_ROAMING_OPERATOR_STRING_ARRAY);
4246 
4247         if (ArrayUtils.isEmpty(numericArray) || operatorNumeric == null) {
4248             return false;
4249         }
4250 
4251         for (String numeric : numericArray) {
4252             if (!TextUtils.isEmpty(numeric) && operatorNumeric.startsWith(numeric)) {
4253                 return true;
4254             }
4255         }
4256         return false;
4257     }
4258 
isOperatorConsideredRoaming(ServiceState s)4259     private boolean isOperatorConsideredRoaming(ServiceState s) {
4260         String operatorNumeric = s.getOperatorNumeric();
4261         String[] numericArray = mCarrierConfig.getStringArray(
4262                 CarrierConfigManager.KEY_ROAMING_OPERATOR_STRING_ARRAY);
4263         if (ArrayUtils.isEmpty(numericArray) || operatorNumeric == null) {
4264             return false;
4265         }
4266 
4267         for (String numeric : numericArray) {
4268             if (!TextUtils.isEmpty(numeric) && operatorNumeric.startsWith(numeric)) {
4269                 return true;
4270             }
4271         }
4272         return false;
4273     }
4274 
4275     /**
4276      * Set restricted state based on the OnRestrictedStateChanged notification
4277      * If any voice or packet restricted state changes, trigger a UI
4278      * notification and notify registrants when sim is ready.
4279      *
4280      * @param ar an int value of RIL_RESTRICTED_STATE_*
4281      */
onRestrictedStateChanged(AsyncResult ar)4282     private void onRestrictedStateChanged(AsyncResult ar) {
4283         RestrictedState newRs = new RestrictedState();
4284 
4285         if (DBG) log("onRestrictedStateChanged: E rs "+ mRestrictedState);
4286 
4287         if (ar.exception == null && ar.result != null) {
4288             int state = (int)ar.result;
4289 
4290             newRs.setCsEmergencyRestricted(
4291                     ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
4292                             ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
4293             //ignore the normal call and data restricted state before SIM READY
4294             if (mUiccApplication != null
4295                     && mUiccApplication.getState() == AppState.APPSTATE_READY) {
4296                 newRs.setCsNormalRestricted(
4297                         ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
4298                                 ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
4299                 newRs.setPsRestricted((state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL) != 0);
4300             }
4301 
4302             if (DBG) log("onRestrictedStateChanged: new rs "+ newRs);
4303 
4304             if (!mRestrictedState.isPsRestricted() && newRs.isPsRestricted()) {
4305                 mPsRestrictEnabledRegistrants.notifyRegistrants();
4306                 setNotification(PS_ENABLED);
4307             } else if (mRestrictedState.isPsRestricted() && !newRs.isPsRestricted()) {
4308                 mPsRestrictDisabledRegistrants.notifyRegistrants();
4309                 setNotification(PS_DISABLED);
4310             }
4311 
4312             /**
4313              * There are two kind of cs restriction, normal and emergency. So
4314              * there are 4 x 4 combinations in current and new restricted states
4315              * and we only need to notify when state is changed.
4316              */
4317             if (mRestrictedState.isCsRestricted()) {
4318                 if (!newRs.isAnyCsRestricted()) {
4319                     // remove all restriction
4320                     setNotification(CS_DISABLED);
4321                 } else if (!newRs.isCsNormalRestricted()) {
4322                     // remove normal restriction
4323                     setNotification(CS_EMERGENCY_ENABLED);
4324                 } else if (!newRs.isCsEmergencyRestricted()) {
4325                     // remove emergency restriction
4326                     setNotification(CS_NORMAL_ENABLED);
4327                 }
4328             } else if (mRestrictedState.isCsEmergencyRestricted() &&
4329                     !mRestrictedState.isCsNormalRestricted()) {
4330                 if (!newRs.isAnyCsRestricted()) {
4331                     // remove all restriction
4332                     setNotification(CS_DISABLED);
4333                 } else if (newRs.isCsRestricted()) {
4334                     // enable all restriction
4335                     setNotification(CS_ENABLED);
4336                 } else if (newRs.isCsNormalRestricted()) {
4337                     // remove emergency restriction and enable normal restriction
4338                     setNotification(CS_NORMAL_ENABLED);
4339                 }
4340             } else if (!mRestrictedState.isCsEmergencyRestricted() &&
4341                     mRestrictedState.isCsNormalRestricted()) {
4342                 if (!newRs.isAnyCsRestricted()) {
4343                     // remove all restriction
4344                     setNotification(CS_DISABLED);
4345                 } else if (newRs.isCsRestricted()) {
4346                     // enable all restriction
4347                     setNotification(CS_ENABLED);
4348                 } else if (newRs.isCsEmergencyRestricted()) {
4349                     // remove normal restriction and enable emergency restriction
4350                     setNotification(CS_EMERGENCY_ENABLED);
4351                 }
4352             } else {
4353                 if (newRs.isCsRestricted()) {
4354                     // enable all restriction
4355                     setNotification(CS_ENABLED);
4356                 } else if (newRs.isCsEmergencyRestricted()) {
4357                     // enable emergency restriction
4358                     setNotification(CS_EMERGENCY_ENABLED);
4359                 } else if (newRs.isCsNormalRestricted()) {
4360                     // enable normal restriction
4361                     setNotification(CS_NORMAL_ENABLED);
4362                 }
4363             }
4364 
4365             mRestrictedState = newRs;
4366         }
4367         log("onRestrictedStateChanged: X rs "+ mRestrictedState);
4368     }
4369 
4370     /**
4371      * Get CellIdentity from the ServiceState if available or guess from cached
4372      *
4373      * Get the CellIdentity by first checking if ServiceState has a current CID. If so
4374      * then return that info. Otherwise, check the latest List<CellInfo> and return the first GSM or
4375      * WCDMA result that appears. If no GSM or WCDMA results, then return an LTE result. The
4376      * behavior is kept consistent for backwards compatibility; (do not apply logic to determine
4377      * why the behavior is this way).
4378      *
4379      * @return the current cell location if known or a non-null "empty" cell location
4380      */
4381     @NonNull
getCellIdentity()4382     public CellIdentity getCellIdentity() {
4383         if (mCellIdentity != null) return mCellIdentity;
4384 
4385         CellIdentity ci = getCellIdentityFromCellInfo(getAllCellInfo());
4386         if (ci != null) return ci;
4387 
4388         return mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA
4389                 ? new CellIdentityCdma() : new CellIdentityGsm();
4390     }
4391 
4392     /**
4393      * Get CellIdentity from the ServiceState if available or guess from CellInfo
4394      *
4395      * Get the CellLocation by first checking if ServiceState has a current CID. If so
4396      * then return that info. Otherwise, query AllCellInfo and return the first GSM or
4397      * WCDMA result that appears. If no GSM or WCDMA results, then return an LTE result.
4398      * The behavior is kept consistent for backwards compatibility; (do not apply logic
4399      * to determine why the behavior is this way).
4400      *
4401      * @param workSource calling WorkSource
4402      * @param rspMsg the response message which must be non-null
4403      */
requestCellIdentity(WorkSource workSource, Message rspMsg)4404     public void requestCellIdentity(WorkSource workSource, Message rspMsg) {
4405         if (mCellIdentity != null) {
4406             AsyncResult.forMessage(rspMsg, mCellIdentity, null);
4407             rspMsg.sendToTarget();
4408             return;
4409         }
4410 
4411         Message cellLocRsp = obtainMessage(EVENT_CELL_LOCATION_RESPONSE, rspMsg);
4412         requestAllCellInfo(workSource, cellLocRsp);
4413     }
4414 
4415     /* Find and return a CellIdentity from CellInfo
4416      *
4417      * This method returns the first GSM or WCDMA result that appears in List<CellInfo>. If no GSM
4418      * or  WCDMA results are found, then it returns an LTE result. The behavior is kept consistent
4419      * for backwards compatibility; (do not apply logic to determine why the behavior is this way).
4420      *
4421      * @return the current CellIdentity from CellInfo or null
4422      */
getCellIdentityFromCellInfo(List<CellInfo> info)4423     private static CellIdentity getCellIdentityFromCellInfo(List<CellInfo> info) {
4424         CellIdentity cl = null;
4425         if (info != null && info.size() > 0) {
4426             CellIdentity fallbackLteCid = null; // We prefer not to use LTE
4427             for (CellInfo ci : info) {
4428                 CellIdentity c = ci.getCellIdentity();
4429                 if (c instanceof CellIdentityLte && fallbackLteCid == null) {
4430                     if (getCidFromCellIdentity(c) != -1) fallbackLteCid = c;
4431                     continue;
4432                 }
4433                 if (getCidFromCellIdentity(c) != -1) {
4434                     cl = c;
4435                     break;
4436                 }
4437             }
4438             if (cl == null && fallbackLteCid != null) {
4439                 cl = fallbackLteCid;
4440             }
4441         }
4442         return cl;
4443     }
4444 
4445     /**
4446      * Handle the NITZ string from the modem
4447      *
4448      * @param nitzString NITZ time string in the form "yy/mm/dd,hh:mm:ss(+/-)tz,dt"
4449      * @param nitzReceiveTimeMs time according to {@link android.os.SystemClock#elapsedRealtime()}
4450      *        when the RIL sent the NITZ time to the framework
4451      * @param ageMs time in milliseconds indicating how long NITZ was cached in RIL and modem
4452      */
setTimeFromNITZString(String nitzString, long nitzReceiveTimeMs, long ageMs)4453     private void setTimeFromNITZString(String nitzString, long nitzReceiveTimeMs, long ageMs) {
4454         long start = SystemClock.elapsedRealtime();
4455         if (DBG) {
4456             Rlog.d(LOG_TAG, "NITZ: " + nitzString + "," + nitzReceiveTimeMs + ", ageMs=" + ageMs
4457                     + " start=" + start + " delay=" + (start - nitzReceiveTimeMs));
4458         }
4459         NitzData newNitzData = NitzData.parse(nitzString);
4460         mLastNitzData = newNitzData;
4461         if (newNitzData != null) {
4462             try {
4463                 NitzSignal nitzSignal = new NitzSignal(nitzReceiveTimeMs, newNitzData, ageMs);
4464                 mNitzState.handleNitzReceived(nitzSignal);
4465             } finally {
4466                 if (DBG) {
4467                     long end = SystemClock.elapsedRealtime();
4468                     Rlog.d(LOG_TAG, "NITZ: end=" + end + " dur=" + (end - start));
4469                 }
4470             }
4471         }
4472     }
4473 
4474     /**
4475      * Cancels all notifications posted to NotificationManager for this subId. These notifications
4476      * for restricted state and rejection cause for cs registration are no longer valid after the
4477      * SIM has been removed.
4478      */
cancelAllNotifications()4479     private void cancelAllNotifications() {
4480         if (DBG) log("cancelAllNotifications: mPrevSubId=" + mPrevSubId);
4481         NotificationManager notificationManager = (NotificationManager)
4482                 mPhone.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
4483         if (SubscriptionManager.isValidSubscriptionId(mPrevSubId)) {
4484             notificationManager.cancel(Integer.toString(mPrevSubId), PS_NOTIFICATION);
4485             notificationManager.cancel(Integer.toString(mPrevSubId), CS_NOTIFICATION);
4486             notificationManager.cancel(Integer.toString(mPrevSubId), CS_REJECT_CAUSE_NOTIFICATION);
4487 
4488             // Cancel Emergency call warning and network preference notifications
4489             notificationManager.cancel(
4490                     CarrierServiceStateTracker.EMERGENCY_NOTIFICATION_TAG, mPrevSubId);
4491             notificationManager.cancel(
4492                     CarrierServiceStateTracker.PREF_NETWORK_NOTIFICATION_TAG, mPrevSubId);
4493         }
4494     }
4495 
4496     /**
4497      * Post a notification to NotificationManager for restricted state and
4498      * rejection cause for cs registration
4499      *
4500      * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE
4501      */
4502     @VisibleForTesting
setNotification(int notifyType)4503     public void setNotification(int notifyType) {
4504         if (DBG) log("setNotification: create notification " + notifyType);
4505 
4506         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
4507             // notifications are posted per-sub-id, so return if current sub-id is invalid
4508             loge("cannot setNotification on invalid subid mSubId=" + mSubId);
4509             return;
4510         }
4511         Context context = mPhone.getContext();
4512 
4513         SubscriptionInfoInternal subInfo = mSubscriptionManagerService
4514                 .getSubscriptionInfoInternal(mPhone.getSubId());
4515         if (subInfo == null || !subInfo.isVisible()) {
4516             log("cannot setNotification on invisible subid mSubId=" + mSubId);
4517             return;
4518         }
4519 
4520         // Needed because sprout RIL sends these when they shouldn't?
4521         boolean isSetNotification = context.getResources().getBoolean(
4522                 com.android.internal.R.bool.config_user_notification_of_restrictied_mobile_access);
4523         if (!isSetNotification) {
4524             if (DBG) log("Ignore all the notifications");
4525             return;
4526         }
4527 
4528         boolean autoCancelCsRejectNotification;
4529         boolean disableVoiceBarringNotification = mCarrierConfig.getBoolean(
4530                 CarrierConfigManager.KEY_DISABLE_VOICE_BARRING_NOTIFICATION_BOOL, false);
4531         if (disableVoiceBarringNotification && (notifyType == CS_ENABLED
4532                 || notifyType == CS_NORMAL_ENABLED
4533                 || notifyType == CS_EMERGENCY_ENABLED)) {
4534             if (DBG) log("Voice/emergency call barred notification disabled");
4535             return;
4536         }
4537         autoCancelCsRejectNotification = mCarrierConfig.getBoolean(
4538                 CarrierConfigManager.KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION, false);
4539 
4540         CharSequence details = "";
4541         CharSequence title = "";
4542         int notificationId = CS_NOTIFICATION;
4543         int icon = com.android.internal.R.drawable.stat_sys_warning;
4544 
4545         final boolean multipleSubscriptions = (((TelephonyManager) mPhone.getContext()
4546                   .getSystemService(Context.TELEPHONY_SERVICE)).getPhoneCount() > 1);
4547         int simNumber = SubscriptionManager.getSlotIndex(mSubId) + 1;
4548 
4549         switch (notifyType) {
4550             case PS_ENABLED:
4551                 long dataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
4552                 if (dataSubId != mPhone.getSubId()) {
4553                     return;
4554                 }
4555                 notificationId = PS_NOTIFICATION;
4556                 title = context.getText(com.android.internal.R.string.RestrictedOnDataTitle);
4557                 details = multipleSubscriptions
4558                         ? context.getString(
4559                                 com.android.internal.R.string.RestrictedStateContentMsimTemplate,
4560                                 simNumber) :
4561                         context.getText(com.android.internal.R.string.RestrictedStateContent);
4562                 break;
4563             case PS_DISABLED:
4564                 notificationId = PS_NOTIFICATION;
4565                 break;
4566             case CS_ENABLED:
4567                 title = context.getText(com.android.internal.R.string.RestrictedOnAllVoiceTitle);
4568                 details = multipleSubscriptions
4569                         ? context.getString(
4570                                 com.android.internal.R.string.RestrictedStateContentMsimTemplate,
4571                                 simNumber) :
4572                         context.getText(com.android.internal.R.string.RestrictedStateContent);
4573                 break;
4574             case CS_NORMAL_ENABLED:
4575                 title = context.getText(com.android.internal.R.string.RestrictedOnNormalTitle);
4576                 details = multipleSubscriptions
4577                         ? context.getString(
4578                                 com.android.internal.R.string.RestrictedStateContentMsimTemplate,
4579                                 simNumber) :
4580                         context.getText(com.android.internal.R.string.RestrictedStateContent);
4581                 break;
4582             case CS_EMERGENCY_ENABLED:
4583                 title = context.getText(com.android.internal.R.string.RestrictedOnEmergencyTitle);
4584                 details = multipleSubscriptions
4585                         ? context.getString(
4586                                 com.android.internal.R.string.RestrictedStateContentMsimTemplate,
4587                                 simNumber) :
4588                         context.getText(com.android.internal.R.string.RestrictedStateContent);
4589                 break;
4590             case CS_DISABLED:
4591                 // do nothing and cancel the notification later
4592                 break;
4593             case CS_REJECT_CAUSE_ENABLED:
4594                 notificationId = CS_REJECT_CAUSE_NOTIFICATION;
4595                 int resId = selectResourceForRejectCode(mRejectCode, multipleSubscriptions);
4596                 if (0 == resId) {
4597                     if (autoCancelCsRejectNotification) {
4598                         notifyType = CS_REJECT_CAUSE_DISABLED;
4599                     } else {
4600                         loge("setNotification: mRejectCode=" + mRejectCode + " is not handled.");
4601                         return;
4602                     }
4603                 } else {
4604                     icon = com.android.internal.R.drawable.stat_notify_mmcc_indication_icn;
4605                     // if using the single SIM resource, simNumber will be ignored
4606                     title = context.getString(resId, simNumber);
4607                     details = null;
4608                 }
4609                 break;
4610         }
4611 
4612         if (DBG) {
4613             log("setNotification, create notification, notifyType: " + notifyType
4614                     + ", title: " + title + ", details: " + details + ", subId: " + mSubId);
4615         }
4616 
4617         mNotification = new Notification.Builder(context)
4618                 .setWhen(System.currentTimeMillis())
4619                 .setAutoCancel(true)
4620                 .setSmallIcon(icon)
4621                 .setTicker(title)
4622                 .setColor(context.getResources().getColor(
4623                         com.android.internal.R.color.system_notification_accent_color))
4624                 .setContentTitle(title)
4625                 .setStyle(new Notification.BigTextStyle().bigText(details))
4626                 .setContentText(details)
4627                 .setChannelId(NotificationChannelController.CHANNEL_ID_ALERT)
4628                 .build();
4629 
4630         NotificationManager notificationManager = (NotificationManager)
4631                 context.getSystemService(Context.NOTIFICATION_SERVICE);
4632 
4633         if (notifyType == PS_DISABLED || notifyType == CS_DISABLED
4634                 || notifyType == CS_REJECT_CAUSE_DISABLED) {
4635             // cancel previous post notification
4636             notificationManager.cancel(Integer.toString(mSubId), notificationId);
4637         } else {
4638             boolean show = false;
4639             if (mSS.isEmergencyOnly() && notifyType == CS_EMERGENCY_ENABLED) {
4640                 // if reg state is emergency only, always show restricted emergency notification.
4641                 show = true;
4642             } else if (notifyType == CS_REJECT_CAUSE_ENABLED) {
4643                 // always show notification due to CS reject irrespective of service state.
4644                 show = true;
4645             } else if (mSS.getState() == ServiceState.STATE_IN_SERVICE) {
4646                 // for non in service states, we have system UI and signal bar to indicate limited
4647                 // service. No need to show notification again. This also helps to mitigate the
4648                 // issue if phone go to OOS and camp to other networks and received restricted ind.
4649                 show = true;
4650             }
4651             // update restricted state notification for this subId
4652             if (show) {
4653                 notificationManager.notify(Integer.toString(mSubId), notificationId, mNotification);
4654             }
4655         }
4656     }
4657 
4658     /**
4659      * Selects the resource ID, which depends on rejection cause that is sent by the network when CS
4660      * registration is rejected.
4661      *
4662      * @param rejCode should be compatible with TS 24.008.
4663      */
selectResourceForRejectCode(int rejCode, boolean multipleSubscriptions)4664     private int selectResourceForRejectCode(int rejCode, boolean multipleSubscriptions) {
4665         int rejResourceId = 0;
4666         switch (rejCode) {
4667             case 1:// Authentication reject
4668                 rejResourceId = multipleSubscriptions
4669                         ? com.android.internal.R.string.mmcc_authentication_reject_msim_template :
4670                         com.android.internal.R.string.mmcc_authentication_reject;
4671                 break;
4672             case 2:// IMSI unknown in HLR
4673                 rejResourceId = multipleSubscriptions
4674                         ? com.android.internal.R.string.mmcc_imsi_unknown_in_hlr_msim_template :
4675                         com.android.internal.R.string.mmcc_imsi_unknown_in_hlr;
4676                 break;
4677             case 3:// Illegal MS
4678                 rejResourceId = multipleSubscriptions
4679                         ? com.android.internal.R.string.mmcc_illegal_ms_msim_template :
4680                         com.android.internal.R.string.mmcc_illegal_ms;
4681                 break;
4682             case 6:// Illegal ME
4683                 rejResourceId = multipleSubscriptions
4684                         ? com.android.internal.R.string.mmcc_illegal_me_msim_template :
4685                         com.android.internal.R.string.mmcc_illegal_me;
4686                 break;
4687             default:
4688                 // The other codes are not defined or not required by operators till now.
4689                 break;
4690         }
4691         return rejResourceId;
4692     }
4693 
getUiccCardApplication()4694     private UiccCardApplication getUiccCardApplication() {
4695         if (mPhone.isPhoneTypeGsm()) {
4696             return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
4697                     UiccController.APP_FAM_3GPP);
4698         } else {
4699             return mUiccController.getUiccCardApplication(mPhone.getPhoneId(),
4700                     UiccController.APP_FAM_3GPP2);
4701         }
4702     }
4703 
notifyCdmaSubscriptionInfoReady()4704     private void notifyCdmaSubscriptionInfoReady() {
4705         if (mCdmaForSubscriptionInfoReadyRegistrants != null) {
4706             if (DBG) log("CDMA_SUBSCRIPTION: call notifyRegistrants()");
4707             mCdmaForSubscriptionInfoReadyRegistrants.notifyRegistrants();
4708         }
4709     }
4710 
4711     /**
4712      * Registration point for transition into DataConnection attached.
4713      * @param transport Transport type
4714      * @param h handler to notify
4715      * @param what what code of message when delivered
4716      * @param obj placed in Message.obj
4717      */
registerForDataConnectionAttached(@ransportType int transport, Handler h, int what, Object obj)4718     public void registerForDataConnectionAttached(@TransportType int transport, Handler h, int what,
4719                                                   Object obj) {
4720         Registrant r = new Registrant(h, what, obj);
4721         if (mAttachedRegistrants.get(transport) == null) {
4722             mAttachedRegistrants.put(transport, new RegistrantList());
4723         }
4724         mAttachedRegistrants.get(transport).add(r);
4725 
4726         if (mSS != null) {
4727             NetworkRegistrationInfo netRegState = mSS.getNetworkRegistrationInfo(
4728                     NetworkRegistrationInfo.DOMAIN_PS, transport);
4729             if (netRegState == null || netRegState.isInService()) {
4730                 r.notifyRegistrant();
4731             }
4732         }
4733     }
4734 
4735     /**
4736      * Unregister for data attached event
4737      *
4738      * @param transport Transport type
4739      * @param h Handler to notify
4740      */
unregisterForDataConnectionAttached(@ransportType int transport, Handler h)4741     public void unregisterForDataConnectionAttached(@TransportType int transport, Handler h) {
4742         if (mAttachedRegistrants.get(transport) != null) {
4743             mAttachedRegistrants.get(transport).remove(h);
4744         }
4745     }
4746 
4747     /**
4748      * Registration point for transition into DataConnection detached.
4749      * @param transport Transport type
4750      * @param h handler to notify
4751      * @param what what code of message when delivered
4752      * @param obj placed in Message.obj
4753      */
registerForDataConnectionDetached(@ransportType int transport, Handler h, int what, Object obj)4754     public void registerForDataConnectionDetached(@TransportType int transport, Handler h, int what,
4755                                                   Object obj) {
4756         Registrant r = new Registrant(h, what, obj);
4757         if (mDetachedRegistrants.get(transport) == null) {
4758             mDetachedRegistrants.put(transport, new RegistrantList());
4759         }
4760         mDetachedRegistrants.get(transport).add(r);
4761 
4762         if (mSS != null) {
4763             NetworkRegistrationInfo netRegState = mSS.getNetworkRegistrationInfo(
4764                     NetworkRegistrationInfo.DOMAIN_PS, transport);
4765             if (netRegState != null && !netRegState.isInService()) {
4766                 r.notifyRegistrant();
4767             }
4768         }
4769     }
4770 
4771     /**
4772      * Unregister for data detatched event
4773      *
4774      * @param transport Transport type
4775      * @param h Handler to notify
4776      */
unregisterForDataConnectionDetached(@ransportType int transport, Handler h)4777     public void unregisterForDataConnectionDetached(@TransportType int transport, Handler h) {
4778         if (mDetachedRegistrants.get(transport) != null) {
4779             mDetachedRegistrants.get(transport).remove(h);
4780         }
4781     }
4782 
4783     /**
4784      * Registration for RIL Voice Radio Technology changing. The
4785      * new radio technology will be returned AsyncResult#result as an Integer Object.
4786      * The AsyncResult will be in the notification Message#obj.
4787      *
4788      * @param h handler to notify
4789      * @param what what code of message when delivered
4790      * @param obj placed in Message.obj
4791      */
registerForVoiceRegStateOrRatChanged(Handler h, int what, Object obj)4792     public void registerForVoiceRegStateOrRatChanged(Handler h, int what, Object obj) {
4793         Registrant r = new Registrant(h, what, obj);
4794         mVoiceRegStateOrRatChangedRegistrants.add(r);
4795         notifyVoiceRegStateRilRadioTechnologyChanged();
4796     }
4797 
unregisterForVoiceRegStateOrRatChanged(Handler h)4798     public void unregisterForVoiceRegStateOrRatChanged(Handler h) {
4799         mVoiceRegStateOrRatChangedRegistrants.remove(h);
4800     }
4801 
4802     /**
4803      * Registration for DataConnection RIL Data Radio Technology changing. The
4804      * new radio technology will be returned AsyncResult#result as an Integer Object.
4805      * The AsyncResult will be in the notification Message#obj.
4806      *
4807      * @param transport Transport
4808      * @param h handler to notify
4809      * @param what what code of message when delivered
4810      * @param obj placed in Message.obj
4811      */
registerForDataRegStateOrRatChanged(@ransportType int transport, Handler h, int what, Object obj)4812     public void registerForDataRegStateOrRatChanged(@TransportType int transport, Handler h,
4813                                                     int what, Object obj) {
4814         Registrant r = new Registrant(h, what, obj);
4815         if (mDataRegStateOrRatChangedRegistrants.get(transport) == null) {
4816             mDataRegStateOrRatChangedRegistrants.put(transport, new RegistrantList());
4817         }
4818         mDataRegStateOrRatChangedRegistrants.get(transport).add(r);
4819         Pair<Integer, Integer> registrationInfo = getRegistrationInfo(transport);
4820         if (registrationInfo != null) {
4821             r.notifyResult(registrationInfo);
4822         }
4823     }
4824 
4825     /**
4826      * Unregister for data registration state changed or RAT changed event
4827      *
4828      * @param transport Transport
4829      * @param h The handler
4830      */
unregisterForDataRegStateOrRatChanged(@ransportType int transport, Handler h)4831     public void unregisterForDataRegStateOrRatChanged(@TransportType int transport, Handler h) {
4832         if (mDataRegStateOrRatChangedRegistrants.get(transport) != null) {
4833             mDataRegStateOrRatChangedRegistrants.get(transport).remove(h);
4834         }
4835     }
4836 
4837     /**
4838      * Registration for Airplane Mode changing.  The state of Airplane Mode will be returned
4839      * {@link AsyncResult#result} as a {@link Boolean} Object.
4840      * The {@link AsyncResult} will be in the notification {@link Message#obj}.
4841      * @param h handler to notify
4842      * @param what what code of message when delivered
4843      * @param obj placed in {@link AsyncResult#userObj}
4844      */
registerForAirplaneModeChanged(Handler h, int what, Object obj)4845     public void registerForAirplaneModeChanged(Handler h, int what, Object obj) {
4846         mAirplaneModeChangedRegistrants.add(h, what, obj);
4847     }
4848 
4849     /**
4850      * Unregister for Airplane Mode changed event.
4851      *
4852      * @param h The handler
4853      */
unregisterForAirplaneModeChanged(Handler h)4854     public void unregisterForAirplaneModeChanged(Handler h) {
4855         mAirplaneModeChangedRegistrants.remove(h);
4856     }
4857 
4858     /**
4859      * Registration point for transition into network attached.
4860      * @param h handler to notify
4861      * @param what what code of message when delivered
4862      * @param obj in Message.obj
4863      */
registerForNetworkAttached(Handler h, int what, Object obj)4864     public void registerForNetworkAttached(Handler h, int what, Object obj) {
4865         Registrant r = new Registrant(h, what, obj);
4866 
4867         mNetworkAttachedRegistrants.add(r);
4868         if (mSS.getState() == ServiceState.STATE_IN_SERVICE) {
4869             r.notifyRegistrant();
4870         }
4871     }
4872 
unregisterForNetworkAttached(Handler h)4873     public void unregisterForNetworkAttached(Handler h) {
4874         mNetworkAttachedRegistrants.remove(h);
4875     }
4876 
4877     /**
4878      * Registration point for transition into network detached.
4879      * @param h handler to notify
4880      * @param what what code of message when delivered
4881      * @param obj in Message.obj
4882      */
registerForNetworkDetached(Handler h, int what, Object obj)4883     public void registerForNetworkDetached(Handler h, int what, Object obj) {
4884         Registrant r = new Registrant(h, what, obj);
4885 
4886         mNetworkDetachedRegistrants.add(r);
4887         if (mSS.getState() != ServiceState.STATE_IN_SERVICE) {
4888             r.notifyRegistrant();
4889         }
4890     }
4891 
unregisterForNetworkDetached(Handler h)4892     public void unregisterForNetworkDetached(Handler h) {
4893         mNetworkDetachedRegistrants.remove(h);
4894     }
4895 
4896     /**
4897      * Registration point for transition into packet service restricted zone.
4898      * @param h handler to notify
4899      * @param what what code of message when delivered
4900      * @param obj placed in Message.obj
4901      */
registerForPsRestrictedEnabled(Handler h, int what, Object obj)4902     public void registerForPsRestrictedEnabled(Handler h, int what, Object obj) {
4903         Registrant r = new Registrant(h, what, obj);
4904         mPsRestrictEnabledRegistrants.add(r);
4905 
4906         if (mRestrictedState.isPsRestricted()) {
4907             r.notifyRegistrant();
4908         }
4909     }
4910 
unregisterForPsRestrictedEnabled(Handler h)4911     public void unregisterForPsRestrictedEnabled(Handler h) {
4912         mPsRestrictEnabledRegistrants.remove(h);
4913     }
4914 
4915     /**
4916      * Registration point for transition out of packet service restricted zone.
4917      * @param h handler to notify
4918      * @param what what code of message when delivered
4919      * @param obj placed in Message.obj
4920      */
registerForPsRestrictedDisabled(Handler h, int what, Object obj)4921     public void registerForPsRestrictedDisabled(Handler h, int what, Object obj) {
4922         Registrant r = new Registrant(h, what, obj);
4923         mPsRestrictDisabledRegistrants.add(r);
4924 
4925         if (mRestrictedState.isPsRestricted()) {
4926             r.notifyRegistrant();
4927         }
4928     }
4929 
unregisterForPsRestrictedDisabled(Handler h)4930     public void unregisterForPsRestrictedDisabled(Handler h) {
4931         mPsRestrictDisabledRegistrants.remove(h);
4932     }
4933 
4934     /**
4935      * Registers for IMS capability changed.
4936      * @param h handler to notify
4937      * @param what what code of message when delivered
4938      * @param obj placed in Message.obj
4939      */
registerForImsCapabilityChanged(Handler h, int what, Object obj)4940     public void registerForImsCapabilityChanged(Handler h, int what, Object obj) {
4941         Registrant r = new Registrant(h, what, obj);
4942         mImsCapabilityChangedRegistrants.add(r);
4943     }
4944 
4945     /**
4946      * Unregisters for IMS capability changed.
4947      * @param h handler to notify
4948      */
unregisterForImsCapabilityChanged(Handler h)4949     public void unregisterForImsCapabilityChanged(Handler h) {
4950         mImsCapabilityChangedRegistrants.remove(h);
4951     }
4952 
4953     /**
4954      * Register for service state changed event.
4955      *
4956      * @param h handler to notify
4957      * @param what what code of message when delivered
4958      * @param userobj the user obj that will be passed back when notify
4959      */
registerForServiceStateChanged(Handler h, int what, Object userobj)4960     public void registerForServiceStateChanged(Handler h, int what, Object userobj) {
4961         mServiceStateChangedRegistrants.addUnique(h, what, userobj);
4962     }
4963 
4964     /**
4965      * Unregister for service state changed event.
4966      *
4967      * @param h The handler.
4968      */
unregisterForServiceStateChanged(Handler h)4969     public void unregisterForServiceStateChanged(Handler h) {
4970         mServiceStateChangedRegistrants.remove(h);
4971     }
4972 
4973     /**
4974      * Clean up existing voice and data connection then turn off radio power.
4975      *
4976      * Hang up the existing voice calls to decrease call drop rate.
4977      */
powerOffRadioSafely()4978     public void powerOffRadioSafely() {
4979         synchronized (this) {
4980             SatelliteController.getInstance().onCellularRadioPowerOffRequested();
4981             if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
4982                 EmergencyStateTracker.getInstance().onCellularRadioPowerOffRequested();
4983             }
4984             if (!mPendingRadioPowerOffAfterDataOff) {
4985                 // hang up all active voice calls first
4986                 if (mPhone.isPhoneTypeGsm() && mPhone.isInCall()) {
4987                     mPhone.mCT.mRingingCall.hangupIfAlive();
4988                     mPhone.mCT.mBackgroundCall.hangupIfAlive();
4989                     mPhone.mCT.mForegroundCall.hangupIfAlive();
4990                 }
4991 
4992                 for (Phone phone : PhoneFactory.getPhones()) {
4993                     if (!phone.getDataNetworkController().areAllDataDisconnected()) {
4994                         log("powerOffRadioSafely: Data is active on phone " + phone.getSubId()
4995                                 + ". Wait for all data disconnect.");
4996                         mPendingRadioPowerOffAfterDataOff = true;
4997                         phone.getDataNetworkController().registerDataNetworkControllerCallback(
4998                                 mDataDisconnectedCallback);
4999                     }
5000                 }
5001 
5002                 // Tear down outside of the disconnected check to prevent race conditions.
5003                 mPhone.getDataNetworkController().tearDownAllDataNetworks(
5004                         DataNetwork.TEAR_DOWN_REASON_AIRPLANE_MODE_ON);
5005 
5006                 if (mPendingRadioPowerOffAfterDataOff) {
5007                     sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF,
5008                             POWER_OFF_ALL_DATA_NETWORKS_DISCONNECTED_TIMEOUT);
5009                 } else {
5010                     log("powerOffRadioSafely: No data is connected, turn off radio now.");
5011                     hangupAndPowerOff();
5012                 }
5013             }
5014         }
5015     }
5016 
5017     /**
5018      * return true if there is pending disconnect data request to process; false otherwise.
5019      */
isPendingRadioPowerOffAfterDataOff()5020     public boolean isPendingRadioPowerOffAfterDataOff() {
5021         return mPendingRadioPowerOffAfterDataOff;
5022     }
5023 
onCarrierConfigurationChanged(int slotIndex)5024     private void onCarrierConfigurationChanged(int slotIndex) {
5025         if (slotIndex != mPhone.getPhoneId()) return;
5026 
5027         mCarrierConfig = getCarrierConfig();
5028         log("CarrierConfigChange " + mCarrierConfig);
5029 
5030         // Load the ERI based on carrier config. Carrier might have their specific ERI.
5031         if (mEriManager != null) {
5032             mEriManager.loadEriFile();
5033             mCdnr.updateEfForEri(getOperatorNameFromEri());
5034         }
5035 
5036         updateOperatorNamePattern(mCarrierConfig);
5037         mCdnr.updateEfFromCarrierConfig(mCarrierConfig);
5038         mPhone.notifyCallForwardingIndicator();
5039 
5040         // Sometimes the network registration information comes before carrier config is ready.
5041         // For some cases like roaming/non-roaming overriding, we need carrier config. So it's
5042         // important to poll state again when carrier config is ready.
5043         pollStateInternal(false);
5044     }
5045 
5046     /**
5047      * Hang up all voice call and turn off radio. Implemented by derived class.
5048      */
hangupAndPowerOff()5049     protected void hangupAndPowerOff() {
5050         if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) return;
5051         // hang up all active voice calls
5052         if (!mPhone.isPhoneTypeGsm() || mPhone.isInCall()) {
5053             mPhone.mCT.mRingingCall.hangupIfAlive();
5054             mPhone.mCT.mBackgroundCall.hangupIfAlive();
5055             mPhone.mCT.mForegroundCall.hangupIfAlive();
5056         }
5057 
5058         mCi.setRadioPower(false, obtainMessage(EVENT_RADIO_POWER_OFF_DONE));
5059     }
5060 
5061     /** Cancel a pending (if any) pollState() operation */
cancelPollState()5062     protected void cancelPollState() {
5063         // This will effectively cancel the rest of the poll requests.
5064         mPollingContext = new int[1];
5065     }
5066 
5067     /**
5068      * Return true if the network operator's country code changed.
5069      */
networkCountryIsoChanged(String newCountryIsoCode, String prevCountryIsoCode)5070     private boolean networkCountryIsoChanged(String newCountryIsoCode, String prevCountryIsoCode) {
5071         // Return false if the new ISO code isn't valid as we don't know where we are.
5072         // Return true if the previous ISO code wasn't valid, or if it was and the new one differs.
5073 
5074         // If newCountryIsoCode is invalid then we'll return false
5075         if (TextUtils.isEmpty(newCountryIsoCode)) {
5076             if (DBG) {
5077                 log("countryIsoChanged: no new country ISO code");
5078             }
5079             return false;
5080         }
5081 
5082         if (TextUtils.isEmpty(prevCountryIsoCode)) {
5083             if (DBG) {
5084                 log("countryIsoChanged: no previous country ISO code");
5085             }
5086             return true;
5087         }
5088         return !newCountryIsoCode.equals(prevCountryIsoCode);
5089     }
5090 
5091     // Determine if the Icc card exists
iccCardExists()5092     private boolean iccCardExists() {
5093         boolean iccCardExist = false;
5094         if (mUiccApplication != null) {
5095             iccCardExist = mUiccApplication.getState() != AppState.APPSTATE_UNKNOWN;
5096         }
5097         return iccCardExist;
5098     }
5099 
5100     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getSystemProperty(String property, String defValue)5101     public String getSystemProperty(String property, String defValue) {
5102         return TelephonyManager.getTelephonyProperty(mPhone.getPhoneId(), property, defValue);
5103     }
5104 
getAllCellInfo()5105     public List<CellInfo> getAllCellInfo() {
5106         return mLastCellInfoList;
5107     }
5108 
5109     /** Set the minimum time between CellInfo requests to the modem, in milliseconds */
setCellInfoMinInterval(int interval)5110     public void setCellInfoMinInterval(int interval) {
5111         mCellInfoMinIntervalMs = interval;
5112     }
5113 
5114     /**
5115      * Request the latest CellInfo from the modem.
5116      *
5117      * If sufficient time has elapsed, then this request will be sent to the modem. Otherwise
5118      * the latest cached List<CellInfo> will be returned.
5119      *
5120      * @param workSource of the caller for power accounting
5121      * @param rspMsg an optional response message to get the response to the CellInfo request. If
5122      *     the rspMsg is not provided, then CellInfo will still be requested from the modem and
5123      *     cached locally for future lookup.
5124      */
requestAllCellInfo(WorkSource workSource, Message rspMsg)5125     public void requestAllCellInfo(WorkSource workSource, Message rspMsg) {
5126         if (VDBG) log("SST.requestAllCellInfo(): E");
5127         if (mCi.getRilVersion() < 8) {
5128             AsyncResult.forMessage(rspMsg);
5129             rspMsg.sendToTarget();
5130             if (DBG) log("SST.requestAllCellInfo(): not implemented");
5131             return;
5132         }
5133         synchronized (mPendingCellInfoRequests) {
5134             // If there are pending requests, then we already have a request active, so add this
5135             // request to the response queue without initiating a new request.
5136             if (mIsPendingCellInfoRequest) {
5137                 if (rspMsg != null) mPendingCellInfoRequests.add(rspMsg);
5138                 return;
5139             }
5140             // Check to see whether the elapsed time is sufficient for a new request; if not, then
5141             // return the result of the last request (if expected).
5142             final long curTime = SystemClock.elapsedRealtime();
5143             if ((curTime - mLastCellInfoReqTime) < mCellInfoMinIntervalMs) {
5144                 if (rspMsg != null) {
5145                     if (DBG) log("SST.requestAllCellInfo(): return last, back to back calls");
5146                     AsyncResult.forMessage(rspMsg, mLastCellInfoList, null);
5147                     rspMsg.sendToTarget();
5148                 }
5149                 return;
5150             }
5151             // If this request needs an explicit response (it's a synchronous request), then queue
5152             // the response message.
5153             if (rspMsg != null) mPendingCellInfoRequests.add(rspMsg);
5154             // Update the timeout window so that we don't delay based on slow responses
5155             mLastCellInfoReqTime = curTime;
5156             // Set a flag to remember that we have a pending cell info request
5157             mIsPendingCellInfoRequest = true;
5158             // Send a cell info request and also chase it with a timeout message
5159             Message msg = obtainMessage(EVENT_GET_CELL_INFO_LIST);
5160             mCi.getCellInfoList(msg, workSource);
5161             // This message will arrive TIMEOUT ms later and ensure that we don't wait forever for
5162             // a CELL_INFO response.
5163             sendMessageDelayed(
5164                     obtainMessage(EVENT_GET_CELL_INFO_LIST), CELL_INFO_LIST_QUERY_TIMEOUT);
5165         }
5166     }
5167 
5168     /**
5169      * Registration point for subscription info ready
5170      * @param h handler to notify
5171      * @param what what code of message when delivered
5172      * @param obj placed in Message.obj
5173      */
registerForSubscriptionInfoReady(Handler h, int what, Object obj)5174     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
5175         Registrant r = new Registrant(h, what, obj);
5176         mCdmaForSubscriptionInfoReadyRegistrants.add(r);
5177 
5178         if (isMinInfoReady()) {
5179             r.notifyRegistrant();
5180         }
5181     }
5182 
unregisterForSubscriptionInfoReady(Handler h)5183     public void unregisterForSubscriptionInfoReady(Handler h) {
5184         mCdmaForSubscriptionInfoReadyRegistrants.remove(h);
5185     }
5186 
5187     /**
5188      * Save current source of cdma subscription
5189      * @param source - 1 for NV, 0 for RUIM
5190      */
saveCdmaSubscriptionSource(int source)5191     private void saveCdmaSubscriptionSource(int source) {
5192         log("Storing cdma subscription source: " + source);
5193         Settings.Global.putInt(mPhone.getContext().getContentResolver(),
5194                 Settings.Global.CDMA_SUBSCRIPTION_MODE,
5195                 source);
5196         log("Read from settings: " + Settings.Global.getInt(mPhone.getContext().getContentResolver(),
5197                 Settings.Global.CDMA_SUBSCRIPTION_MODE, -1));
5198     }
5199 
getSubscriptionInfoAndStartPollingThreads()5200     private void getSubscriptionInfoAndStartPollingThreads() {
5201         mCi.getCDMASubscription(obtainMessage(EVENT_POLL_STATE_CDMA_SUBSCRIPTION));
5202 
5203         // Get Registration Information
5204         pollStateInternal(false);
5205     }
5206 
handleCdmaSubscriptionSource(int newSubscriptionSource)5207     private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
5208         log("Subscription Source : " + newSubscriptionSource);
5209         mIsSubscriptionFromRuim =
5210                 (newSubscriptionSource == CdmaSubscriptionSourceManager.SUBSCRIPTION_FROM_RUIM);
5211         log("isFromRuim: " + mIsSubscriptionFromRuim);
5212         saveCdmaSubscriptionSource(newSubscriptionSource);
5213         if (!mIsSubscriptionFromRuim) {
5214             // NV is ready when subscription source is NV
5215             sendMessage(obtainMessage(EVENT_NV_READY));
5216         }
5217     }
5218 
5219     /** Called when telecom has reported a voice service state change. */
onTelecomVoiceServiceStateOverrideChanged()5220     public void onTelecomVoiceServiceStateOverrideChanged() {
5221         sendMessage(obtainMessage(EVENT_TELECOM_VOICE_SERVICE_STATE_OVERRIDE_CHANGED));
5222     }
5223 
dumpCellInfoList(PrintWriter pw)5224     private void dumpCellInfoList(PrintWriter pw) {
5225         pw.print(" mLastCellInfoList={");
5226         if(mLastCellInfoList != null) {
5227             boolean first = true;
5228             for(CellInfo info : mLastCellInfoList) {
5229                if(first == false) {
5230                    pw.print(",");
5231                }
5232                first = false;
5233                pw.print(info.toString());
5234             }
5235         }
5236         pw.println("}");
5237     }
5238 
dump(FileDescriptor fd, PrintWriter pw, String[] args)5239     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
5240         pw.println("ServiceStateTracker:");
5241         pw.println(" mSubId=" + mSubId);
5242         pw.println(" mSS=" + mSS);
5243         pw.println(" mNewSS=" + mNewSS);
5244         pw.println(" mVoiceCapable=" + mVoiceCapable);
5245         pw.println(" mRestrictedState=" + mRestrictedState);
5246         pw.println(" mPollingContext=" + Arrays.toString(mPollingContext));
5247         pw.println(" mDesiredPowerState=" + mDesiredPowerState);
5248         pw.println(" mRestrictedState=" + mRestrictedState);
5249         pw.println(" mPendingRadioPowerOffAfterDataOff=" + mPendingRadioPowerOffAfterDataOff);
5250         pw.println(" mCellIdentity=" + Rlog.pii(VDBG, mCellIdentity));
5251         pw.println(" mLastCellInfoReqTime=" + mLastCellInfoReqTime);
5252         dumpCellInfoList(pw);
5253         pw.flush();
5254         pw.println(" mAllowedNetworkTypes=" + mAllowedNetworkTypes);
5255         pw.println(" mMaxDataCalls=" + mMaxDataCalls);
5256         pw.println(" mNewMaxDataCalls=" + mNewMaxDataCalls);
5257         pw.println(" mReasonDataDenied=" + mReasonDataDenied);
5258         pw.println(" mNewReasonDataDenied=" + mNewReasonDataDenied);
5259         pw.println(" mGsmVoiceRoaming=" + mGsmVoiceRoaming);
5260         pw.println(" mGsmDataRoaming=" + mGsmDataRoaming);
5261         pw.println(" mEmergencyOnly=" + mEmergencyOnly);
5262         pw.println(" mCSEmergencyOnly=" + mCSEmergencyOnly);
5263         pw.println(" mPSEmergencyOnly=" + mPSEmergencyOnly);
5264         pw.flush();
5265         mNitzState.dumpState(pw);
5266         pw.println(" mLastNitzData=" + mLastNitzData);
5267         pw.flush();
5268         pw.println(" mStartedGprsRegCheck=" + mStartedGprsRegCheck);
5269         pw.println(" mReportedGprsNoReg=" + mReportedGprsNoReg);
5270         pw.println(" mNotification=" + mNotification);
5271         pw.println(" mCurSpn=" + mCurSpn);
5272         pw.println(" mCurDataSpn=" + mCurDataSpn);
5273         pw.println(" mCurShowSpn=" + mCurShowSpn);
5274         pw.println(" mCurPlmn=" + mCurPlmn);
5275         pw.println(" mCurShowPlmn=" + mCurShowPlmn);
5276         pw.flush();
5277         pw.println(" mCurrentOtaspMode=" + mCurrentOtaspMode);
5278         pw.println(" mRoamingIndicator=" + mRoamingIndicator);
5279         pw.println(" mIsInPrl=" + mIsInPrl);
5280         pw.println(" mDefaultRoamingIndicator=" + mDefaultRoamingIndicator);
5281         pw.println(" mRegistrationState=" + mRegistrationState);
5282         pw.println(" mMdn=" + mMdn);
5283         pw.println(" mHomeSystemId=" + Arrays.toString(mHomeSystemId));
5284         pw.println(" mHomeNetworkId=" + Arrays.toString(mHomeNetworkId));
5285         pw.println(" mMin=" + mMin);
5286         pw.println(" mPrlVersion=" + mPrlVersion);
5287         pw.println(" mIsMinInfoReady=" + mIsMinInfoReady);
5288         pw.println(" mIsEriTextLoaded=" + mIsEriTextLoaded);
5289         pw.println(" mIsSubscriptionFromRuim=" + mIsSubscriptionFromRuim);
5290         pw.println(" mCdmaSSM=" + mCdmaSSM);
5291         pw.println(" mRegistrationDeniedReason=" + mRegistrationDeniedReason);
5292         pw.println(" mCurrentCarrier=" + mCurrentCarrier);
5293         pw.flush();
5294         pw.println(" mImsRegistered=" + mImsRegistered);
5295         pw.println(" mImsRegistrationOnOff=" + mImsRegistrationOnOff);
5296         pw.println(" pending radio off event="
5297                 + hasMessages(EVENT_POWER_OFF_RADIO_IMS_DEREG_TIMEOUT));
5298         pw.println(" mRadioPowerOffReasons=" + mRadioPowerOffReasons);
5299         pw.println(" mDeviceShuttingDown=" + mDeviceShuttingDown);
5300         pw.println(" mCellInfoMinIntervalMs=" + mCellInfoMinIntervalMs);
5301         pw.println(" mEriManager=" + mEriManager);
5302 
5303         mLocaleTracker.dump(fd, pw, args);
5304         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "    ");
5305 
5306         mCdnr.dump(ipw);
5307 
5308         ipw.println(" Carrier Display Name update records:");
5309         ipw.increaseIndent();
5310         mCdnrLogs.dump(fd, ipw, args);
5311         ipw.decreaseIndent();
5312 
5313         ipw.println(" Roaming Log:");
5314         ipw.increaseIndent();
5315         mRoamingLog.dump(fd, ipw, args);
5316         ipw.decreaseIndent();
5317 
5318         ipw.println(" Attach Log:");
5319         ipw.increaseIndent();
5320         mAttachLog.dump(fd, ipw, args);
5321         ipw.decreaseIndent();
5322 
5323         ipw.println(" Phone Change Log:");
5324         ipw.increaseIndent();
5325         mPhoneTypeLog.dump(fd, ipw, args);
5326         ipw.decreaseIndent();
5327 
5328         ipw.println(" Rat Change Log:");
5329         ipw.increaseIndent();
5330         mRatLog.dump(fd, ipw, args);
5331         ipw.decreaseIndent();
5332 
5333         ipw.println(" Radio power Log:");
5334         ipw.increaseIndent();
5335         mRadioPowerLog.dump(fd, ipw, args);
5336         ipw.decreaseIndent();
5337 
5338         mNitzState.dumpLogs(fd, ipw, args);
5339 
5340         ipw.flush();
5341     }
5342 
5343     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isImsRegistered()5344     public boolean isImsRegistered() {
5345         return mImsRegistered;
5346     }
5347     /**
5348      * Verifies the current thread is the same as the thread originally
5349      * used in the initialization of this instance. Throws RuntimeException
5350      * if not.
5351      *
5352      * @exception RuntimeException if the current thread is not
5353      * the thread that originally obtained this Phone instance.
5354      */
checkCorrectThread()5355     protected void checkCorrectThread() {
5356         if (Thread.currentThread() != getLooper().getThread()) {
5357             throw new RuntimeException(
5358                     "ServiceStateTracker must be used from within one thread");
5359         }
5360     }
5361 
isCallerOnDifferentThread()5362     protected boolean isCallerOnDifferentThread() {
5363         boolean value = Thread.currentThread() != getLooper().getThread();
5364         if (VDBG) log("isCallerOnDifferentThread: " + value);
5365         return value;
5366     }
5367 
5368     /**
5369      * Check ISO country by MCC to see if phone is roaming in same registered country
5370      */
inSameCountry(String operatorNumeric)5371     protected boolean inSameCountry(String operatorNumeric) {
5372         if (TextUtils.isEmpty(operatorNumeric) || (operatorNumeric.length() < 5)) {
5373             // Not a valid network
5374             return false;
5375         }
5376         final String homeNumeric = getHomeOperatorNumeric();
5377         if (TextUtils.isEmpty(homeNumeric) || (homeNumeric.length() < 5)) {
5378             // Not a valid SIM MCC
5379             return false;
5380         }
5381         boolean inSameCountry = true;
5382         final String networkMCC = operatorNumeric.substring(0, 3);
5383         final String homeMCC = homeNumeric.substring(0, 3);
5384         final String networkCountry = MccTable.countryCodeForMcc(networkMCC);
5385         final String homeCountry = MccTable.countryCodeForMcc(homeMCC);
5386 
5387         if (mLocaleTracker != null && !TextUtils.isEmpty(mLocaleTracker.getCountryOverride())) {
5388             log("inSameCountry:  countryOverride var set.  This should only be set for testing "
5389                     + "purposes to override the device location.");
5390             return mLocaleTracker.getCountryOverride().equals(homeCountry);
5391         }
5392 
5393         if (networkCountry.isEmpty() || homeCountry.isEmpty()) {
5394             // Not a valid country
5395             return false;
5396         }
5397         inSameCountry = homeCountry.equals(networkCountry);
5398         if (inSameCountry) {
5399             return inSameCountry;
5400         }
5401         // special same country cases
5402         if ("us".equals(homeCountry) && "vi".equals(networkCountry)) {
5403             inSameCountry = true;
5404         } else if ("vi".equals(homeCountry) && "us".equals(networkCountry)) {
5405             inSameCountry = true;
5406         }
5407         return inSameCountry;
5408     }
5409 
5410     /**
5411      * Set both voice and data roaming type,
5412      * judging from the ISO country of SIM VS network.
5413      */
5414     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setRoamingType(ServiceState currentServiceState)5415     protected void setRoamingType(ServiceState currentServiceState) {
5416         final boolean isVoiceInService =
5417                 (currentServiceState.getState() == ServiceState.STATE_IN_SERVICE);
5418         if (isVoiceInService) {
5419             if (currentServiceState.getVoiceRoaming()) {
5420                 if (mPhone.isPhoneTypeGsm()) {
5421                     // check roaming type by MCC
5422                     if (inSameCountry(currentServiceState.getOperatorNumeric())) {
5423                         currentServiceState.setVoiceRoamingType(
5424                                 ServiceState.ROAMING_TYPE_DOMESTIC);
5425                     } else {
5426                         currentServiceState.setVoiceRoamingType(
5427                                 ServiceState.ROAMING_TYPE_INTERNATIONAL);
5428                     }
5429                 } else {
5430                     // some carrier defines international roaming by indicator
5431                     int[] intRoamingIndicators = mPhone.getContext().getResources().getIntArray(
5432                             com.android.internal.R.array
5433                                     .config_cdma_international_roaming_indicators);
5434                     if ((intRoamingIndicators != null) && (intRoamingIndicators.length > 0)) {
5435                         // It's domestic roaming at least now
5436                         currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC);
5437                         int curRoamingIndicator = currentServiceState.getCdmaRoamingIndicator();
5438                         for (int i = 0; i < intRoamingIndicators.length; i++) {
5439                             if (curRoamingIndicator == intRoamingIndicators[i]) {
5440                                 currentServiceState.setVoiceRoamingType(
5441                                         ServiceState.ROAMING_TYPE_INTERNATIONAL);
5442                                 break;
5443                             }
5444                         }
5445                     } else {
5446                         // check roaming type by MCC
5447                         if (inSameCountry(currentServiceState.getOperatorNumeric())) {
5448                             currentServiceState.setVoiceRoamingType(
5449                                     ServiceState.ROAMING_TYPE_DOMESTIC);
5450                         } else {
5451                             currentServiceState.setVoiceRoamingType(
5452                                     ServiceState.ROAMING_TYPE_INTERNATIONAL);
5453                         }
5454                     }
5455                 }
5456             } else {
5457                 currentServiceState.setVoiceRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING);
5458             }
5459         }
5460         final boolean isDataInService =
5461                 (currentServiceState.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE);
5462         final int dataRegType = getRilDataRadioTechnologyForWwan(currentServiceState);
5463         if (isDataInService) {
5464             if (!currentServiceState.getDataRoaming()) {
5465                 currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_NOT_ROAMING);
5466             } else {
5467                 if (mPhone.isPhoneTypeGsm()) {
5468                     if (ServiceState.isGsm(dataRegType)) {
5469                         if (isVoiceInService) {
5470                             // GSM data should have the same state as voice
5471                             currentServiceState.setDataRoamingType(currentServiceState
5472                                     .getVoiceRoamingType());
5473                         } else {
5474                             // we can not decide GSM data roaming type without voice
5475                             currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN);
5476                         }
5477                     } else {
5478                         // we can not decide 3gpp2 roaming state here
5479                         currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN);
5480                     }
5481                 } else {
5482                     if (ServiceState.isCdma(dataRegType)) {
5483                         if (isVoiceInService) {
5484                             // CDMA data should have the same state as voice
5485                             currentServiceState.setDataRoamingType(currentServiceState
5486                                     .getVoiceRoamingType());
5487                         } else {
5488                             // we can not decide CDMA data roaming type without voice
5489                             // set it as same as last time
5490                             currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_UNKNOWN);
5491                         }
5492                     } else {
5493                         // take it as 3GPP roaming
5494                         if (inSameCountry(currentServiceState.getOperatorNumeric())) {
5495                             currentServiceState.setDataRoamingType(ServiceState.ROAMING_TYPE_DOMESTIC);
5496                         } else {
5497                             currentServiceState.setDataRoamingType(
5498                                     ServiceState.ROAMING_TYPE_INTERNATIONAL);
5499                         }
5500                     }
5501                 }
5502             }
5503         }
5504     }
5505 
getHomeOperatorNumeric()5506     protected String getHomeOperatorNumeric() {
5507         String numeric = ((TelephonyManager) mPhone.getContext().
5508                 getSystemService(Context.TELEPHONY_SERVICE)).
5509                 getSimOperatorNumericForPhone(mPhone.getPhoneId());
5510         if (!mPhone.isPhoneTypeGsm() && TextUtils.isEmpty(numeric)) {
5511             numeric = SystemProperties.get(GsmCdmaPhone.PROPERTY_CDMA_HOME_OPERATOR_NUMERIC, "");
5512         }
5513         return numeric;
5514     }
5515 
5516     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getPhoneId()5517     protected int getPhoneId() {
5518         return mPhone.getPhoneId();
5519     }
5520 
5521     /**
5522      * This method makes some adjustments when the device camps on IWLAN in airplane mode.
5523      */
processIwlanRegistrationInfo()5524     private void processIwlanRegistrationInfo() {
5525         if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
5526             boolean resetIwlanRatVal = false;
5527             log("set service state as POWER_OFF");
5528             if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
5529                     == mNewSS.getRilDataRadioTechnology()) {
5530                 log("pollStateDone: mNewSS = " + mNewSS);
5531                 log("pollStateDone: reset iwlan RAT value");
5532                 resetIwlanRatVal = true;
5533             }
5534             // operator info should be kept in SS
5535             String operator = mNewSS.getOperatorAlphaLong();
5536             mNewSS.setOutOfService(true);
5537             if (resetIwlanRatVal) {
5538                 mNewSS.setDataRegState(ServiceState.STATE_IN_SERVICE);
5539                 NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
5540                         .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
5541                         .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
5542                         .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
5543                         .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
5544                         .build();
5545                 mNewSS.addNetworkRegistrationInfo(nri);
5546                 mNewSS.setOperatorAlphaLong(operator);
5547                 // Since it's in airplane mode, cellular must be out of service. The only possible
5548                 // transport for data to go through is the IWLAN transport. Setting this to true
5549                 // so that ServiceState.getDataNetworkType can report the right RAT.
5550                 mNewSS.setIwlanPreferred(true);
5551                 log("pollStateDone: mNewSS = " + mNewSS);
5552             }
5553             return;
5554         }
5555     }
5556 
updateNtnCapability()5557     private void updateNtnCapability() {
5558         for (NetworkRegistrationInfo nri : mNewSS.getNetworkRegistrationInfoListForTransportType(
5559                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
5560             NtnCapabilityResolver.resolveNtnCapability(nri, mSubId);
5561             if (nri.isNonTerrestrialNetwork()) {
5562                 // Replace the existing NRI with the updated NRI.
5563                 mNewSS.addNetworkRegistrationInfo(nri);
5564             }
5565         }
5566     }
5567 
5568     /**
5569      * Check if device is non-roaming and always on home network.
5570      *
5571      * @param b carrier config bundle obtained from CarrierConfigManager
5572      * @return true if network is always on home network, false otherwise
5573      * @see CarrierConfigManager
5574      */
alwaysOnHomeNetwork(BaseBundle b)5575     protected final boolean alwaysOnHomeNetwork(BaseBundle b) {
5576         return b.getBoolean(CarrierConfigManager.KEY_FORCE_HOME_NETWORK_BOOL);
5577     }
5578 
5579     /**
5580      * Check if the network identifier has membership in the set of
5581      * network identifiers stored in the carrier config bundle.
5582      *
5583      * @param b carrier config bundle obtained from CarrierConfigManager
5584      * @param network The network identifier to check network existence in bundle
5585      * @param key The key to index into the bundle presenting a string array of
5586      *            networks to check membership
5587      * @return true if network has membership in bundle networks, false otherwise
5588      * @see CarrierConfigManager
5589      */
isInNetwork(BaseBundle b, String network, String key)5590     private boolean isInNetwork(BaseBundle b, String network, String key) {
5591         String[] networks = b.getStringArray(key);
5592 
5593         if (networks != null && Arrays.asList(networks).contains(network)) {
5594             return true;
5595         }
5596         return false;
5597     }
5598 
isRoamingInGsmNetwork(BaseBundle b, String network)5599     protected final boolean isRoamingInGsmNetwork(BaseBundle b, String network) {
5600         return isInNetwork(b, network, CarrierConfigManager.KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY);
5601     }
5602 
isNonRoamingInGsmNetwork(BaseBundle b, String network)5603     protected final boolean isNonRoamingInGsmNetwork(BaseBundle b, String network) {
5604         return isInNetwork(b, network, CarrierConfigManager.KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY);
5605     }
5606 
isRoamingInCdmaNetwork(BaseBundle b, String network)5607     protected final boolean isRoamingInCdmaNetwork(BaseBundle b, String network) {
5608         return isInNetwork(b, network, CarrierConfigManager.KEY_CDMA_ROAMING_NETWORKS_STRING_ARRAY);
5609     }
5610 
isNonRoamingInCdmaNetwork(BaseBundle b, String network)5611     protected final boolean isNonRoamingInCdmaNetwork(BaseBundle b, String network) {
5612         return isInNetwork(b, network, CarrierConfigManager.KEY_CDMA_NONROAMING_NETWORKS_STRING_ARRAY);
5613     }
5614 
5615     /** Check if the device is shutting down. */
isDeviceShuttingDown()5616     public boolean isDeviceShuttingDown() {
5617         return mDeviceShuttingDown;
5618     }
5619 
5620     /**
5621      * Consider dataRegState if voiceRegState is OOS to determine SPN to be displayed.
5622      * If dataRegState is in service on IWLAN, also check for wifi calling enabled.
5623      * @param ss service state.
5624      */
getCombinedRegState(ServiceState ss)5625     public int getCombinedRegState(ServiceState ss) {
5626         int regState = ss.getState();
5627         int dataRegState = ss.getDataRegistrationState();
5628         if ((regState == ServiceState.STATE_OUT_OF_SERVICE
5629                 || regState == ServiceState.STATE_POWER_OFF)
5630                 && (dataRegState == ServiceState.STATE_IN_SERVICE)) {
5631             if (ss.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_IWLAN) {
5632                 if (mPhone.getImsPhone() != null && mPhone.getImsPhone().isWifiCallingEnabled()) {
5633                     log("getCombinedRegState: return STATE_IN_SERVICE for IWLAN as "
5634                             + "Data is in service and WFC is enabled");
5635                     regState = dataRegState;
5636                 }
5637             } else {
5638                 log("getCombinedRegState: return STATE_IN_SERVICE as Data is in service");
5639                 regState = dataRegState;
5640             }
5641         }
5642         return regState;
5643     }
5644 
5645     /**
5646      * Gets the carrier configuration values for a particular subscription.
5647      *
5648      * @return A {@link PersistableBundle} containing the config for the given subId,
5649      *         or default values for an invalid subId.
5650      */
5651     @NonNull
getCarrierConfig()5652     private PersistableBundle getCarrierConfig() {
5653         CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
5654                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
5655         if (configManager != null) {
5656             // If an invalid subId is used, this bundle will contain default values.
5657             PersistableBundle config = configManager.getConfigForSubId(mPhone.getSubId());
5658             if (config != null) {
5659                 return config;
5660             }
5661         }
5662         // Return static default defined in CarrierConfigManager.
5663         return CarrierConfigManager.getDefaultConfig();
5664     }
5665 
getLocaleTracker()5666     public LocaleTracker getLocaleTracker() {
5667         return mLocaleTracker;
5668     }
5669 
getCdmaEriText(int roamInd, int defRoamInd)5670     String getCdmaEriText(int roamInd, int defRoamInd) {
5671         return mEriManager != null ? mEriManager.getCdmaEriText(roamInd, defRoamInd) : "no ERI";
5672     }
5673 
updateOperatorNamePattern(PersistableBundle config)5674     private void updateOperatorNamePattern(PersistableBundle config) {
5675         String operatorNamePattern = config.getString(
5676                 CarrierConfigManager.KEY_OPERATOR_NAME_FILTER_PATTERN_STRING);
5677         if (!TextUtils.isEmpty(operatorNamePattern)) {
5678             mOperatorNameStringPattern = Pattern.compile(operatorNamePattern);
5679             if (DBG) {
5680                 log("mOperatorNameStringPattern: " + mOperatorNameStringPattern.toString());
5681             }
5682         }
5683     }
5684 
updateOperatorNameForServiceState(ServiceState servicestate)5685     private void updateOperatorNameForServiceState(ServiceState servicestate) {
5686         if (servicestate == null) {
5687             return;
5688         }
5689 
5690         servicestate.setOperatorName(
5691                 filterOperatorNameByPattern(servicestate.getOperatorAlphaLong()),
5692                 filterOperatorNameByPattern(servicestate.getOperatorAlphaShort()),
5693                 servicestate.getOperatorNumeric());
5694 
5695         List<NetworkRegistrationInfo> networkRegistrationInfos =
5696                 servicestate.getNetworkRegistrationInfoList();
5697 
5698         for (int i = 0; i < networkRegistrationInfos.size(); i++) {
5699             if (networkRegistrationInfos.get(i) != null) {
5700                 updateOperatorNameForCellIdentity(
5701                         networkRegistrationInfos.get(i).getCellIdentity());
5702                 servicestate.addNetworkRegistrationInfo(networkRegistrationInfos.get(i));
5703             }
5704         }
5705     }
5706 
updateOperatorNameForCellIdentity(CellIdentity cellIdentity)5707     private void updateOperatorNameForCellIdentity(CellIdentity cellIdentity) {
5708         if (cellIdentity == null) {
5709             return;
5710         }
5711         cellIdentity.setOperatorAlphaLong(
5712                 filterOperatorNameByPattern((String) cellIdentity.getOperatorAlphaLong()));
5713         cellIdentity.setOperatorAlphaShort(
5714                 filterOperatorNameByPattern((String) cellIdentity.getOperatorAlphaShort()));
5715     }
5716 
5717     /**
5718      * To modify the operator name of CellInfo by pattern.
5719      *
5720      * @param cellInfos List of CellInfo{@link CellInfo}.
5721      */
updateOperatorNameForCellInfo(List<CellInfo> cellInfos)5722     public void updateOperatorNameForCellInfo(List<CellInfo> cellInfos) {
5723         if (cellInfos == null || cellInfos.isEmpty()) {
5724             return;
5725         }
5726         for (CellInfo cellInfo : cellInfos) {
5727             if (cellInfo.isRegistered()) {
5728                 updateOperatorNameForCellIdentity(cellInfo.getCellIdentity());
5729             }
5730         }
5731     }
5732 
5733     /**
5734      * To modify the operator name by pattern.
5735      *
5736      * @param operatorName Registered operator name
5737      * @return An operator name.
5738      */
filterOperatorNameByPattern(String operatorName)5739     public String filterOperatorNameByPattern(String operatorName) {
5740         if (mOperatorNameStringPattern == null || TextUtils.isEmpty(operatorName)) {
5741             return operatorName;
5742         }
5743         Matcher matcher = mOperatorNameStringPattern.matcher(operatorName);
5744         if (matcher.find()) {
5745             if (matcher.groupCount() > 0) {
5746                 operatorName = matcher.group(1);
5747             } else {
5748                 log("filterOperatorNameByPattern: pattern no group");
5749             }
5750         }
5751         return operatorName;
5752     }
5753 
5754     @RilRadioTechnology
getRilDataRadioTechnologyForWwan(ServiceState ss)5755     private static int getRilDataRadioTechnologyForWwan(ServiceState ss) {
5756         NetworkRegistrationInfo regInfo = ss.getNetworkRegistrationInfo(
5757                 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
5758         int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
5759         if (regInfo != null) {
5760             networkType = regInfo.getAccessNetworkTechnology();
5761         }
5762         return ServiceState.networkTypeToRilRadioTechnology(networkType);
5763     }
5764 
5765     /**
5766      * Registers for 5G NR state changed.
5767      * @param h handler to notify
5768      * @param what what code of message when delivered
5769      * @param obj placed in Message.obj
5770      */
registerForNrStateChanged(Handler h, int what, Object obj)5771     public void registerForNrStateChanged(Handler h, int what, Object obj) {
5772         Registrant r = new Registrant(h, what, obj);
5773         mNrStateChangedRegistrants.add(r);
5774     }
5775 
5776     /**
5777      * Unregisters for 5G NR state changed.
5778      * @param h handler to notify
5779      */
unregisterForNrStateChanged(Handler h)5780     public void unregisterForNrStateChanged(Handler h) {
5781         mNrStateChangedRegistrants.remove(h);
5782     }
5783 
5784     /**
5785      * Registers for 5G NR frequency changed.
5786      * @param h handler to notify
5787      * @param what what code of message when delivered
5788      * @param obj placed in Message.obj
5789      */
registerForNrFrequencyChanged(Handler h, int what, Object obj)5790     public void registerForNrFrequencyChanged(Handler h, int what, Object obj) {
5791         Registrant r = new Registrant(h, what, obj);
5792         mNrFrequencyChangedRegistrants.add(r);
5793     }
5794 
5795     /**
5796      * Unregisters for 5G NR frequency changed.
5797      * @param h handler to notify
5798      */
unregisterForNrFrequencyChanged(Handler h)5799     public void unregisterForNrFrequencyChanged(Handler h) {
5800         mNrFrequencyChangedRegistrants.remove(h);
5801     }
5802 
5803     /**
5804      * Registers for CSS indicator changed.
5805      * @param h handler to notify
5806      * @param what what code of message when delivered
5807      * @param obj placed in Message.obj
5808      */
registerForCssIndicatorChanged(Handler h, int what, Object obj)5809     public void registerForCssIndicatorChanged(Handler h, int what, Object obj) {
5810         Registrant r = new Registrant(h, what, obj);
5811         mCssIndicatorChangedRegistrants.add(r);
5812     }
5813 
5814     /**
5815      * Unregisters for CSS indicator changed.
5816      * @param h handler to notify
5817      */
unregisterForCssIndicatorChanged(Handler h)5818     public void unregisterForCssIndicatorChanged(Handler h) {
5819         mCssIndicatorChangedRegistrants.remove(h);
5820     }
5821 
5822     /**
5823      * Get the NR data connection context ids.
5824      *
5825      * @return data connection context ids.
5826      */
5827     @NonNull
getNrContextIds()5828     public Set<Integer> getNrContextIds() {
5829         Set<Integer> idSet = new HashSet<>();
5830 
5831         if (!ArrayUtils.isEmpty(mLastPhysicalChannelConfigList)) {
5832             for (PhysicalChannelConfig config : mLastPhysicalChannelConfigList) {
5833                 if (isNrPhysicalChannelConfig(config)) {
5834                     for (int id : config.getContextIds()) {
5835                         idSet.add(id);
5836                     }
5837                 }
5838             }
5839         }
5840 
5841         return idSet;
5842     }
5843 
setDataNetworkTypeForPhone(int type)5844     private void setDataNetworkTypeForPhone(int type) {
5845         if (mPhone.getUnitTestMode()) {
5846             return;
5847         }
5848         TelephonyManager tm = (TelephonyManager) mPhone.getContext().getSystemService(
5849                 Context.TELEPHONY_SERVICE);
5850         tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), type);
5851     }
5852 
5853     /** Returns the {@link ServiceStateStats} for the phone tracked. */
getServiceStateStats()5854     public ServiceStateStats getServiceStateStats() {
5855         return mServiceStateStats;
5856     }
5857 
5858     /** Replaces the {@link ServiceStateStats} for testing purposes. */
5859     @VisibleForTesting
setServiceStateStats(ServiceStateStats serviceStateStats)5860     public void setServiceStateStats(ServiceStateStats serviceStateStats) {
5861         mServiceStateStats = serviceStateStats;
5862     }
5863 
5864     /**
5865      * Used to insert a ServiceState into the ServiceStateProvider as a ContentValues instance.
5866      *
5867      * Copied from packages/services/Telephony/src/com/android/phone/ServiceStateProvider.java
5868      *
5869      * @param state the ServiceState to convert into ContentValues
5870      * @return the convertedContentValues instance
5871      */
getContentValuesForServiceState(ServiceState state)5872     private ContentValues getContentValuesForServiceState(ServiceState state) {
5873         ContentValues values = new ContentValues();
5874         final Parcel p = Parcel.obtain();
5875         state.writeToParcel(p, 0);
5876         // Turn the parcel to byte array. Safe to do this because the content values were never
5877         // written into a persistent storage. ServiceStateProvider keeps values in the memory.
5878         values.put(SERVICE_STATE, p.marshall());
5879         return values;
5880     }
5881 
5882     /**
5883      * Registers for TAC/LAC changed event.
5884      * @param h handler to notify
5885      * @param what what code of message when delivered
5886      * @param obj placed in Message.obj
5887      */
registerForAreaCodeChanged(Handler h, int what, Object obj)5888     public void registerForAreaCodeChanged(Handler h, int what, Object obj) {
5889         mAreaCodeChangedRegistrants.addUnique(h, what, obj);
5890     }
5891 
5892     /**
5893      * Unregisters for TAC/LAC changed event.
5894      * @param h handler to notify
5895      */
unregisterForAreaCodeChanged(Handler h)5896     public void unregisterForAreaCodeChanged(Handler h) {
5897         mAreaCodeChangedRegistrants.remove(h);
5898     }
5899 
5900     /**
5901      * get last known cell identity
5902      * If there is current registered network this value will be same as the registered cell
5903      * identity. If the device goes out of service the previous cell identity is cached and
5904      * will be returned. If the cache age of the cell identity is more than 24 hours
5905      * it will be cleared and null will be returned.
5906      * @return last known cell identity.
5907      */
getLastKnownCellIdentity()5908     public @Nullable CellIdentity getLastKnownCellIdentity() {
5909         return mLastKnownCellIdentity;
5910     }
5911 
5912     /**
5913      * Get the tech where ims is currently registered.
5914      * @return Returns the tech of ims registered. if not registered or no phome for ims, returns
5915      *   {@link ImsRegistrationImplBase#REGISTRATION_TECH_NONE}.
5916      */
getImsRegistrationTech()5917     private @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegistrationTech() {
5918         ImsPhone imsPhone = (ImsPhone) mPhone.getImsPhone();
5919         if (imsPhone != null) {
5920             return imsPhone.getImsRegistrationTech();
5921         }
5922         return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
5923     }
5924 }
5925