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