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