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