• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.settings.deviceinfo.simstatus;
18 
19 import static androidx.lifecycle.Lifecycle.Event;
20 
21 import android.annotation.Nullable;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.ServiceConnection;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ResolveInfo;
30 import android.content.res.Resources;
31 import android.os.IBinder;
32 import android.os.PersistableBundle;
33 import android.os.RemoteException;
34 import android.telephony.AccessNetworkConstants;
35 import android.telephony.Annotation;
36 import android.telephony.CarrierConfigManager;
37 import android.telephony.CellBroadcastIntents;
38 import android.telephony.CellBroadcastService;
39 import android.telephony.CellSignalStrength;
40 import android.telephony.ICellBroadcastService;
41 import android.telephony.ServiceState;
42 import android.telephony.SignalStrength;
43 import android.telephony.SubscriptionInfo;
44 import android.telephony.SubscriptionManager;
45 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
46 import android.telephony.TelephonyCallback;
47 import android.telephony.TelephonyDisplayInfo;
48 import android.telephony.TelephonyManager;
49 import android.telephony.UiccCardInfo;
50 import android.telephony.euicc.EuiccManager;
51 import android.telephony.ims.ImsException;
52 import android.telephony.ims.ImsMmTelManager;
53 import android.telephony.ims.ImsReasonInfo;
54 import android.text.TextUtils;
55 import android.util.Log;
56 
57 import androidx.annotation.NonNull;
58 import androidx.annotation.VisibleForTesting;
59 import androidx.lifecycle.LifecycleObserver;
60 import androidx.lifecycle.OnLifecycleEvent;
61 
62 import com.android.settings.R;
63 import com.android.settingslib.DeviceInfoUtils;
64 import com.android.settingslib.Utils;
65 import com.android.settingslib.core.lifecycle.Lifecycle;
66 import com.android.settingslib.utils.ThreadUtils;
67 
68 import java.util.List;
69 import java.util.Map;
70 import java.util.concurrent.atomic.AtomicReference;
71 
72 /**
73  * Controller for Sim Status information within the About Phone Settings page.
74  */
75 public class SimStatusDialogController implements LifecycleObserver {
76 
77     private final static String TAG = "SimStatusDialogCtrl";
78 
79     @VisibleForTesting
80     final static int NETWORK_PROVIDER_VALUE_ID = R.id.operator_name_value;
81     @VisibleForTesting
82     final static int PHONE_NUMBER_VALUE_ID = R.id.number_value;
83     @VisibleForTesting
84     final static int CELLULAR_NETWORK_STATE = R.id.data_state_value;
85     @VisibleForTesting
86     final static int OPERATOR_INFO_LABEL_ID = R.id.latest_area_info_label;
87     @VisibleForTesting
88     final static int OPERATOR_INFO_VALUE_ID = R.id.latest_area_info_value;
89     @VisibleForTesting
90     final static int SERVICE_STATE_VALUE_ID = R.id.service_state_value;
91     @VisibleForTesting
92     final static int SIGNAL_STRENGTH_LABEL_ID = R.id.signal_strength_label;
93     @VisibleForTesting
94     final static int SIGNAL_STRENGTH_VALUE_ID = R.id.signal_strength_value;
95     @VisibleForTesting
96     final static int CELL_VOICE_NETWORK_TYPE_VALUE_ID = R.id.voice_network_type_value;
97     @VisibleForTesting
98     final static int CELL_DATA_NETWORK_TYPE_VALUE_ID = R.id.data_network_type_value;
99     @VisibleForTesting
100     final static int ROAMING_INFO_VALUE_ID = R.id.roaming_state_value;
101     @VisibleForTesting
102     final static int ICCID_INFO_LABEL_ID = R.id.icc_id_label;
103     @VisibleForTesting
104     final static int ICCID_INFO_VALUE_ID = R.id.icc_id_value;
105     @VisibleForTesting
106     final static int EID_INFO_LABEL_ID = R.id.esim_id_label;
107     @VisibleForTesting
108     final static int EID_INFO_VALUE_ID = R.id.esim_id_value;
109     @VisibleForTesting
110     final static int IMS_REGISTRATION_STATE_LABEL_ID = R.id.ims_reg_state_label;
111     @VisibleForTesting
112     final static int IMS_REGISTRATION_STATE_VALUE_ID = R.id.ims_reg_state_value;
113 
114     @VisibleForTesting
115     static final int MAX_PHONE_COUNT_SINGLE_SIM = 1;
116 
117     private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
118             new OnSubscriptionsChangedListener() {
119                 @Override
120                 public void onSubscriptionsChanged() {
121                     final int prevSubId = (mSubscriptionInfo != null)
122                             ? mSubscriptionInfo.getSubscriptionId()
123                             : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
124 
125                     mSubscriptionInfo = getPhoneSubscriptionInfo(mSlotIndex);
126 
127                     final int nextSubId = (mSubscriptionInfo != null)
128                             ? mSubscriptionInfo.getSubscriptionId()
129                             : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
130 
131                     if (prevSubId != nextSubId) {
132                         if (SubscriptionManager.isValidSubscriptionId(prevSubId)) {
133                             unregisterImsRegistrationCallback(prevSubId);
134                         }
135                         if (SubscriptionManager.isValidSubscriptionId(nextSubId)) {
136                             mTelephonyManager =
137                                     mTelephonyManager.createForSubscriptionId(nextSubId);
138                             registerImsRegistrationCallback(nextSubId);
139                         }
140                     }
141                     updateSubscriptionStatus();
142                 }
143             };
144 
145     private SubscriptionInfo mSubscriptionInfo;
146     private TelephonyDisplayInfo mTelephonyDisplayInfo;
147     private ServiceState mPreviousServiceState;
148 
149     private final int mSlotIndex;
150     private TelephonyManager mTelephonyManager;
151 
152     private final SimStatusDialogFragment mDialog;
153     private final SubscriptionManager mSubscriptionManager;
154     private final CarrierConfigManager mCarrierConfigManager;
155     private final EuiccManager mEuiccManager;
156     private final Resources mRes;
157     private final Context mContext;
158 
159     private boolean mShowLatestAreaInfo;
160     private boolean mIsRegisteredListener = false;
161 
162     private final BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
163         @Override
164         public void onReceive(Context context, Intent intent) {
165             if (CellBroadcastIntents.ACTION_AREA_INFO_UPDATED.equals(intent.getAction())
166                     && intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0)
167                     == mSlotIndex) {
168                 updateAreaInfoText();
169             }
170         }
171     };
172 
173     @VisibleForTesting
174     protected SimStatusDialogTelephonyCallback mTelephonyCallback;
175 
176     private CellBroadcastServiceConnection mCellBroadcastServiceConnection;
177 
178     private class CellBroadcastServiceConnection implements ServiceConnection {
179         private IBinder mService;
180 
181         @Nullable
getService()182         public IBinder getService() {
183             return mService;
184         }
185 
186         @Override
onServiceConnected(ComponentName className, IBinder service)187         public void onServiceConnected(ComponentName className, IBinder service) {
188             Log.d(TAG, "connected to CellBroadcastService");
189             this.mService = service;
190             updateAreaInfoText();
191         }
192 
193         @Override
onServiceDisconnected(ComponentName className)194         public void onServiceDisconnected(ComponentName className) {
195             this.mService = null;
196             Log.d(TAG, "mICellBroadcastService has disconnected unexpectedly");
197         }
198 
199         @Override
onBindingDied(ComponentName name)200         public void onBindingDied(ComponentName name) {
201             this.mService = null;
202             Log.d(TAG, "Binding died");
203         }
204 
205         @Override
onNullBinding(ComponentName name)206         public void onNullBinding(ComponentName name) {
207             this.mService = null;
208             Log.d(TAG, "Null binding");
209         }
210     }
211 
SimStatusDialogController(@onNull SimStatusDialogFragment dialog, Lifecycle lifecycle, int slotId)212     public SimStatusDialogController(@NonNull SimStatusDialogFragment dialog, Lifecycle lifecycle,
213             int slotId) {
214         mDialog = dialog;
215         mContext = dialog.getContext();
216         mSlotIndex = slotId;
217         mSubscriptionInfo = getPhoneSubscriptionInfo(slotId);
218 
219         mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
220         mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
221         mEuiccManager = mContext.getSystemService(EuiccManager.class);
222         mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
223 
224         mRes = mContext.getResources();
225 
226         if (lifecycle != null) {
227             lifecycle.addObserver(this);
228         }
229     }
230 
initialize()231     public void initialize() {
232         requestForUpdateEid();
233 
234         if (mSubscriptionInfo == null) {
235             return;
236         }
237         mTelephonyManager =
238             mTelephonyManager.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId());
239         mTelephonyCallback = new SimStatusDialogTelephonyCallback();
240         updateLatestAreaInfo();
241         updateSubscriptionStatus();
242     }
243 
updateSubscriptionStatus()244     private void updateSubscriptionStatus() {
245         updateNetworkProvider();
246 
247         // getServiceState() may return null when the subscription is inactive
248         // or when there was an error communicating with the phone process.
249         final ServiceState serviceState = mTelephonyManager.getServiceState();
250         final SignalStrength signalStrength = mTelephonyManager.getSignalStrength();
251 
252         updatePhoneNumber();
253         updateServiceState(serviceState);
254         updateSignalStrength(signalStrength);
255         updateNetworkType();
256         updateRoamingStatus(serviceState);
257         updateIccidNumber();
258         updateImsRegistrationState();
259     }
260 
261     /**
262      * Deinitialization works
263      */
deinitialize()264     public void deinitialize() {
265         if (mShowLatestAreaInfo) {
266             if (mCellBroadcastServiceConnection != null
267                     && mCellBroadcastServiceConnection.getService() != null) {
268                 mContext.unbindService(mCellBroadcastServiceConnection);
269             }
270             mCellBroadcastServiceConnection = null;
271         }
272     }
273 
274     /**
275      * OnResume lifecycle event, resume listening for phone state or subscription changes.
276      */
277     @OnLifecycleEvent(Event.ON_RESUME)
onResume()278     public void onResume() {
279         if (mSubscriptionInfo == null) {
280             return;
281         }
282         mTelephonyManager = mTelephonyManager.createForSubscriptionId(
283                 mSubscriptionInfo.getSubscriptionId());
284         mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), mTelephonyCallback);
285         mSubscriptionManager.addOnSubscriptionsChangedListener(
286                 mContext.getMainExecutor(), mOnSubscriptionsChangedListener);
287         registerImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId());
288 
289         if (mShowLatestAreaInfo) {
290             updateAreaInfoText();
291             mContext.registerReceiver(mAreaInfoReceiver,
292                     new IntentFilter(CellBroadcastIntents.ACTION_AREA_INFO_UPDATED));
293         }
294 
295         mIsRegisteredListener = true;
296     }
297 
298     /**
299      * onPause lifecycle event, no longer listen for phone state or subscription changes.
300      */
301     @OnLifecycleEvent(Event.ON_PAUSE)
onPause()302     public void onPause() {
303         if (mSubscriptionInfo == null) {
304             if (mIsRegisteredListener) {
305                 mSubscriptionManager.removeOnSubscriptionsChangedListener(
306                         mOnSubscriptionsChangedListener);
307                 mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
308                 if (mShowLatestAreaInfo) {
309                     mContext.unregisterReceiver(mAreaInfoReceiver);
310                 }
311                 mIsRegisteredListener = false;
312             }
313             return;
314         }
315 
316         unregisterImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId());
317         mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
318         mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
319 
320         if (mShowLatestAreaInfo) {
321             mContext.unregisterReceiver(mAreaInfoReceiver);
322         }
323     }
324 
updateNetworkProvider()325     private void updateNetworkProvider() {
326         final CharSequence carrierName =
327                 mSubscriptionInfo != null ? mSubscriptionInfo.getCarrierName() : null;
328         mDialog.setText(NETWORK_PROVIDER_VALUE_ID, carrierName);
329     }
330 
331     @VisibleForTesting
updatePhoneNumber()332     protected void updatePhoneNumber() {
333         // If formattedNumber is null or empty, it'll display as "Unknown".
334         mDialog.setText(PHONE_NUMBER_VALUE_ID,
335                 DeviceInfoUtils.getBidiFormattedPhoneNumber(mContext, mSubscriptionInfo));
336     }
337 
updateDataState(int state)338     private void updateDataState(int state) {
339         String networkStateValue;
340 
341         switch (state) {
342             case TelephonyManager.DATA_CONNECTED:
343                 networkStateValue = mRes.getString(R.string.radioInfo_data_connected);
344                 break;
345             case TelephonyManager.DATA_SUSPENDED:
346                 networkStateValue = mRes.getString(R.string.radioInfo_data_suspended);
347                 break;
348             case TelephonyManager.DATA_CONNECTING:
349                 networkStateValue = mRes.getString(R.string.radioInfo_data_connecting);
350                 break;
351             case TelephonyManager.DATA_DISCONNECTED:
352                 networkStateValue = mRes.getString(R.string.radioInfo_data_disconnected);
353                 break;
354             default:
355                 networkStateValue = mRes.getString(R.string.radioInfo_unknown);
356                 break;
357         }
358 
359         mDialog.setText(CELLULAR_NETWORK_STATE, networkStateValue);
360     }
361 
362     /**
363      * Update area info text retrieved from
364      * {@link CellBroadcastService#getCellBroadcastAreaInfo(int)}
365      */
updateAreaInfoText()366     private void updateAreaInfoText() {
367         if (!mShowLatestAreaInfo || mCellBroadcastServiceConnection == null) return;
368         ICellBroadcastService cellBroadcastService =
369                 ICellBroadcastService.Stub.asInterface(
370                         mCellBroadcastServiceConnection.getService());
371         if (cellBroadcastService == null) return;
372         try {
373             mDialog.setText(OPERATOR_INFO_VALUE_ID,
374                     cellBroadcastService.getCellBroadcastAreaInfo(mSlotIndex));
375 
376         } catch (RemoteException e) {
377             Log.d(TAG, "Can't get area info. e=" + e);
378         }
379     }
380 
381     /**
382      * Bind cell broadcast service.
383      */
bindCellBroadcastService()384     private void bindCellBroadcastService() {
385         mCellBroadcastServiceConnection = new CellBroadcastServiceConnection();
386         Intent intent = new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE);
387         String cbsPackage = getCellBroadcastServicePackage();
388         if (TextUtils.isEmpty(cbsPackage)) return;
389         intent.setPackage(cbsPackage);
390         if (mCellBroadcastServiceConnection != null
391                 && mCellBroadcastServiceConnection.getService() == null) {
392             if (!mContext.bindService(intent, mCellBroadcastServiceConnection,
393                     Context.BIND_AUTO_CREATE)) {
394                 Log.e(TAG, "Unable to bind to service");
395             }
396         } else {
397             Log.d(TAG, "skipping bindService because connection already exists");
398         }
399     }
400 
401     /** Returns the package name of the cell broadcast service, or null if there is none. */
getCellBroadcastServicePackage()402     private String getCellBroadcastServicePackage() {
403         PackageManager packageManager = mContext.getPackageManager();
404         List<ResolveInfo> cbsPackages = packageManager.queryIntentServices(
405                 new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE),
406                 PackageManager.MATCH_SYSTEM_ONLY);
407         if (cbsPackages.size() != 1) {
408             Log.e(TAG, "getCellBroadcastServicePackageName: found " + cbsPackages.size()
409                     + " CBS packages");
410         }
411         for (ResolveInfo info : cbsPackages) {
412             if (info.serviceInfo == null) continue;
413             String packageName = info.serviceInfo.packageName;
414             if (!TextUtils.isEmpty(packageName)) {
415                 if (packageManager.checkPermission(
416                         android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
417                         packageName) == PackageManager.PERMISSION_GRANTED) {
418                     Log.d(TAG, "getCellBroadcastServicePackageName: " + packageName);
419                     return packageName;
420                 } else {
421                     Log.e(TAG, "getCellBroadcastServicePackageName: " + packageName
422                             + " does not have READ_PRIVILEGED_PHONE_STATE permission");
423                 }
424             } else {
425                 Log.e(TAG, "getCellBroadcastServicePackageName: found a CBS package but "
426                         + "packageName is null/empty");
427             }
428         }
429         Log.e(TAG, "getCellBroadcastServicePackageName: package name not found");
430         return null;
431     }
432 
updateLatestAreaInfo()433     private void updateLatestAreaInfo() {
434         mShowLatestAreaInfo = Resources.getSystem().getBoolean(
435                 com.android.internal.R.bool.config_showAreaUpdateInfoSettings)
436                 && mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA;
437 
438         if (mShowLatestAreaInfo) {
439             // Bind cell broadcast service to get the area info. The info will be updated once
440             // the service is connected.
441             bindCellBroadcastService();
442         } else {
443             mDialog.removeSettingFromScreen(OPERATOR_INFO_LABEL_ID);
444             mDialog.removeSettingFromScreen(OPERATOR_INFO_VALUE_ID);
445         }
446     }
447 
updateServiceState(ServiceState serviceState)448     private void updateServiceState(ServiceState serviceState) {
449         final int state = Utils.getCombinedServiceState(serviceState);
450         if (!Utils.isInService(serviceState)) {
451             resetSignalStrength();
452         } else if (!Utils.isInService(mPreviousServiceState)) {
453             // If ServiceState changed from out of service -> in service, update signal strength.
454             updateSignalStrength(mTelephonyManager.getSignalStrength());
455         }
456 
457         String serviceStateValue;
458 
459         switch (state) {
460             case ServiceState.STATE_IN_SERVICE:
461                 serviceStateValue = mRes.getString(R.string.radioInfo_service_in);
462                 break;
463             case ServiceState.STATE_OUT_OF_SERVICE:
464             case ServiceState.STATE_EMERGENCY_ONLY:
465                 // Set summary string of service state to radioInfo_service_out when
466                 // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY
467                 serviceStateValue = mRes.getString(R.string.radioInfo_service_out);
468                 break;
469             case ServiceState.STATE_POWER_OFF:
470                 serviceStateValue = mRes.getString(R.string.radioInfo_service_off);
471                 break;
472             default:
473                 serviceStateValue = mRes.getString(R.string.radioInfo_unknown);
474                 break;
475         }
476 
477         mDialog.setText(SERVICE_STATE_VALUE_ID, serviceStateValue);
478     }
479 
updateSignalStrength(SignalStrength signalStrength)480     private void updateSignalStrength(SignalStrength signalStrength) {
481         if (signalStrength == null) {
482             return;
483         }
484         // by default we show the signal strength
485         boolean showSignalStrength = true;
486         if (mSubscriptionInfo != null) {
487             final int subscriptionId = mSubscriptionInfo.getSubscriptionId();
488             final PersistableBundle carrierConfig =
489                     mCarrierConfigManager.getConfigForSubId(subscriptionId);
490             if (carrierConfig != null) {
491                 showSignalStrength = carrierConfig.getBoolean(
492                         CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL);
493             }
494         }
495         if (!showSignalStrength) {
496             mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_LABEL_ID);
497             mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_VALUE_ID);
498             return;
499         }
500 
501         ServiceState serviceState = mTelephonyManager.getServiceState();
502         if (!Utils.isInService(serviceState)) {
503             return;
504         }
505 
506         int signalDbm = getDbm(signalStrength);
507         int signalAsu = getAsuLevel(signalStrength);
508 
509         if (signalDbm == -1) {
510             signalDbm = 0;
511         }
512 
513         if (signalAsu == -1) {
514             signalAsu = 0;
515         }
516 
517         mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, mRes.getString(R.string.sim_signal_strength,
518                 signalDbm, signalAsu));
519     }
520 
resetSignalStrength()521     private void resetSignalStrength() {
522         mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, "0");
523     }
524 
updateNetworkType()525     private void updateNetworkType() {
526         // TODO: all of this should be based on TelephonyDisplayInfo instead of just the 5G logic
527         if (mSubscriptionInfo == null) {
528             final String unknownNetworkType =
529                     getNetworkTypeName(TelephonyManager.NETWORK_TYPE_UNKNOWN);
530             mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, unknownNetworkType);
531             mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, unknownNetworkType);
532             return;
533         }
534 
535         // Whether EDGE, UMTS, etc...
536         String dataNetworkTypeName = null;
537         String voiceNetworkTypeName = null;
538         final int subId = mSubscriptionInfo.getSubscriptionId();
539         final int actualDataNetworkType = mTelephonyManager.getDataNetworkType();
540         final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType();
541         final int overrideNetworkType = mTelephonyDisplayInfo == null
542                 ? TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
543                 : mTelephonyDisplayInfo.getOverrideNetworkType();
544 
545         if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) {
546             dataNetworkTypeName = getNetworkTypeName(actualDataNetworkType);
547         }
548         if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) {
549             voiceNetworkTypeName = getNetworkTypeName(actualVoiceNetworkType);
550         }
551 
552         final boolean isOverrideNwTypeNrAdvancedOrNsa =
553                 overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED
554                         || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA;
555         if (actualDataNetworkType == TelephonyManager.NETWORK_TYPE_LTE
556                 && isOverrideNwTypeNrAdvancedOrNsa) {
557             dataNetworkTypeName = "NR NSA";
558         }
559 
560         boolean show4GForLTE = false;
561         final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
562         if (carrierConfig != null) {
563             show4GForLTE = carrierConfig.getBoolean(
564                     CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
565         }
566 
567         if (show4GForLTE) {
568             if ("LTE".equals(dataNetworkTypeName)) {
569                 dataNetworkTypeName = "4G";
570             }
571             if ("LTE".equals(voiceNetworkTypeName)) {
572                 voiceNetworkTypeName = "4G";
573             }
574         }
575 
576         mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, voiceNetworkTypeName);
577         mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, dataNetworkTypeName);
578     }
579 
updateRoamingStatus(ServiceState serviceState)580     private void updateRoamingStatus(ServiceState serviceState) {
581         // If the serviceState is null, we assume that roaming is disabled.
582         if (serviceState == null) {
583             mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_unknown));
584         } else if (serviceState.getRoaming()) {
585             mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_in));
586         } else {
587             mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_not));
588         }
589     }
590 
updateIccidNumber()591     private void updateIccidNumber() {
592         // do not show iccid by default
593         boolean showIccId = false;
594         if (mSubscriptionInfo != null) {
595             final int subscriptionId = mSubscriptionInfo.getSubscriptionId();
596             final PersistableBundle carrierConfig =
597                     mCarrierConfigManager.getConfigForSubId(subscriptionId);
598             if (carrierConfig != null) {
599                 showIccId = carrierConfig.getBoolean(
600                         CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL);
601             }
602         }
603         if (!showIccId) {
604             mDialog.removeSettingFromScreen(ICCID_INFO_LABEL_ID);
605             mDialog.removeSettingFromScreen(ICCID_INFO_VALUE_ID);
606         } else {
607             mDialog.setText(ICCID_INFO_VALUE_ID, mTelephonyManager.getSimSerialNumber());
608         }
609     }
610 
611     @VisibleForTesting
requestForUpdateEid()612     protected void requestForUpdateEid() {
613         ThreadUtils.postOnBackgroundThread(() -> {
614             final AtomicReference<String> eid = getEid(mSlotIndex);
615             ThreadUtils.postOnMainThread(() -> updateEid(eid));
616         });
617     }
618 
619     @VisibleForTesting
getEid(int slotIndex)620     protected AtomicReference<String> getEid(int slotIndex) {
621         boolean shouldHaveEid = false;
622         String eid = null;
623         if (mTelephonyManager.getActiveModemCount() > MAX_PHONE_COUNT_SINGLE_SIM) {
624             // Get EID per-SIM in multi-SIM mode
625             final Map<Integer, Integer> mapping = mTelephonyManager
626                     .getLogicalToPhysicalSlotMapping();
627             final int pSlotId = mapping.getOrDefault(slotIndex,
628                     SubscriptionManager.INVALID_SIM_SLOT_INDEX);
629 
630             if (pSlotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
631                 final List<UiccCardInfo> infos = mTelephonyManager.getUiccCardsInfo();
632 
633                 for (UiccCardInfo info : infos) {
634                     if (info.getSlotIndex() == pSlotId) {
635                         if (info.isEuicc()) {
636                             shouldHaveEid = true;
637                             eid = info.getEid();
638                             if (TextUtils.isEmpty(eid)) {
639                                 eid = mEuiccManager.createForCardId(info.getCardId()).getEid();
640                             }
641                         }
642                         break;
643                     }
644                 }
645             }
646         } else if (mEuiccManager.isEnabled()) {
647             // Get EID of default eSIM in single-SIM mode
648             shouldHaveEid = true;
649             eid = mEuiccManager.getEid();
650         }
651         if ((!shouldHaveEid) && (eid == null)) {
652             return null;
653         }
654         return new AtomicReference<String>(eid);
655     }
656 
657     @VisibleForTesting
updateEid(AtomicReference<String> eid)658     protected void updateEid(AtomicReference<String> eid) {
659         if (eid == null) {
660             mDialog.removeSettingFromScreen(EID_INFO_LABEL_ID);
661             mDialog.removeSettingFromScreen(EID_INFO_VALUE_ID);
662         } else if (eid.get() != null) {
663             mDialog.setText(EID_INFO_VALUE_ID, eid.get());
664         }
665     }
666 
isImsRegistrationStateShowUp()667     private boolean isImsRegistrationStateShowUp() {
668         if (mSubscriptionInfo == null) {
669             return false;
670         }
671         final int subscriptionId = mSubscriptionInfo.getSubscriptionId();
672         final PersistableBundle carrierConfig =
673                 mCarrierConfigManager.getConfigForSubId(subscriptionId);
674         return carrierConfig == null ? false :
675                 carrierConfig.getBoolean(
676                         CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL);
677     }
678 
updateImsRegistrationState()679     private void updateImsRegistrationState() {
680         if (isImsRegistrationStateShowUp()) {
681             return;
682         }
683         mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_LABEL_ID);
684         mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID);
685     }
686 
687     private ImsMmTelManager.RegistrationCallback mImsRegStateCallback =
688             new ImsMmTelManager.RegistrationCallback() {
689         @Override
690         public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) {
691             mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(
692                     R.string.ims_reg_status_registered));
693         }
694         @Override
695         public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) {
696             mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(
697                     R.string.ims_reg_status_not_registered));
698         }
699         @Override
700         public void onUnregistered(@Nullable ImsReasonInfo info) {
701             mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(
702                     R.string.ims_reg_status_not_registered));
703         }
704         @Override
705         public void onTechnologyChangeFailed(
706                 @AccessNetworkConstants.TransportType int imsTransportType,
707                 @Nullable ImsReasonInfo info) {
708             mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(
709                     R.string.ims_reg_status_not_registered));
710         }
711     };
712 
registerImsRegistrationCallback(int subId)713     private void registerImsRegistrationCallback(int subId) {
714         if (!isImsRegistrationStateShowUp()) {
715             return;
716         }
717         try {
718             final ImsMmTelManager imsMmTelMgr = ImsMmTelManager.createForSubscriptionId(subId);
719             imsMmTelMgr.registerImsRegistrationCallback(mDialog.getContext().getMainExecutor(),
720                     mImsRegStateCallback);
721         } catch (ImsException exception) {
722             Log.w(TAG, "fail to register IMS status for subId=" + subId, exception);
723         }
724     }
725 
unregisterImsRegistrationCallback(int subId)726     private void unregisterImsRegistrationCallback(int subId) {
727         if (!isImsRegistrationStateShowUp()) {
728             return;
729         }
730         final ImsMmTelManager imsMmTelMgr = ImsMmTelManager.createForSubscriptionId(subId);
731         imsMmTelMgr.unregisterImsRegistrationCallback(mImsRegStateCallback);
732     }
733 
getPhoneSubscriptionInfo(int slotId)734     private SubscriptionInfo getPhoneSubscriptionInfo(int slotId) {
735         return SubscriptionManager.from(mContext).getActiveSubscriptionInfoForSimSlotIndex(slotId);
736     }
737 
getDbm(SignalStrength signalStrength)738     private int getDbm(SignalStrength signalStrength) {
739         List<CellSignalStrength> cellSignalStrengthList = signalStrength.getCellSignalStrengths();
740         int dbm = -1;
741         if (cellSignalStrengthList == null) {
742             return dbm;
743         }
744 
745         for (CellSignalStrength cell : cellSignalStrengthList) {
746             if (cell.getDbm() != -1) {
747                 dbm = cell.getDbm();
748                 break;
749             }
750         }
751 
752         return dbm;
753     }
754 
getAsuLevel(SignalStrength signalStrength)755     private int getAsuLevel(SignalStrength signalStrength) {
756         List<CellSignalStrength> cellSignalStrengthList = signalStrength.getCellSignalStrengths();
757         int asu = -1;
758         if (cellSignalStrengthList == null) {
759             return asu;
760         }
761 
762         for (CellSignalStrength cell : cellSignalStrengthList) {
763             if (cell.getAsuLevel() != -1) {
764                 asu = cell.getAsuLevel();
765                 break;
766             }
767         }
768 
769         return asu;
770     }
771 
772     @VisibleForTesting
773     class SimStatusDialogTelephonyCallback extends TelephonyCallback implements
774             TelephonyCallback.DataConnectionStateListener,
775             TelephonyCallback.SignalStrengthsListener,
776             TelephonyCallback.ServiceStateListener,
777             TelephonyCallback.DisplayInfoListener {
778         @Override
onDataConnectionStateChanged(int state, int networkType)779         public void onDataConnectionStateChanged(int state, int networkType) {
780             updateDataState(state);
781             updateNetworkType();
782         }
783 
784         @Override
onSignalStrengthsChanged(SignalStrength signalStrength)785         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
786             updateSignalStrength(signalStrength);
787         }
788 
789         @Override
onServiceStateChanged(ServiceState serviceState)790         public void onServiceStateChanged(ServiceState serviceState) {
791             updateNetworkProvider();
792             updateServiceState(serviceState);
793             updateRoamingStatus(serviceState);
794             mPreviousServiceState = serviceState;
795         }
796 
797         @Override
onDisplayInfoChanged(@onNull TelephonyDisplayInfo displayInfo)798         public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo displayInfo) {
799             mTelephonyDisplayInfo = displayInfo;
800             updateNetworkType();
801         }
802     }
803 
804     @VisibleForTesting
getNetworkTypeName(@nnotation.NetworkType int type)805     static String getNetworkTypeName(@Annotation.NetworkType int type) {
806         switch (type) {
807             case TelephonyManager.NETWORK_TYPE_GPRS:
808                 return "GPRS";
809             case TelephonyManager.NETWORK_TYPE_EDGE:
810                 return "EDGE";
811             case TelephonyManager.NETWORK_TYPE_UMTS:
812                 return "UMTS";
813             case TelephonyManager.NETWORK_TYPE_HSDPA:
814                 return "HSDPA";
815             case TelephonyManager.NETWORK_TYPE_HSUPA:
816                 return "HSUPA";
817             case TelephonyManager.NETWORK_TYPE_HSPA:
818                 return "HSPA";
819             case TelephonyManager.NETWORK_TYPE_CDMA:
820                 return "CDMA";
821             case TelephonyManager.NETWORK_TYPE_EVDO_0:
822                 return "CDMA - EvDo rev. 0";
823             case TelephonyManager.NETWORK_TYPE_EVDO_A:
824                 return "CDMA - EvDo rev. A";
825             case TelephonyManager.NETWORK_TYPE_EVDO_B:
826                 return "CDMA - EvDo rev. B";
827             case TelephonyManager.NETWORK_TYPE_1xRTT:
828                 return "CDMA - 1xRTT";
829             case TelephonyManager.NETWORK_TYPE_LTE:
830                 return "LTE";
831             case TelephonyManager.NETWORK_TYPE_EHRPD:
832                 return "CDMA - eHRPD";
833             case TelephonyManager.NETWORK_TYPE_IDEN:
834                 return "iDEN";
835             case TelephonyManager.NETWORK_TYPE_HSPAP:
836                 return "HSPA+";
837             case TelephonyManager.NETWORK_TYPE_GSM:
838                 return "GSM";
839             case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
840                 return "TD_SCDMA";
841             case TelephonyManager.NETWORK_TYPE_IWLAN:
842                 return "IWLAN";
843 //          case TelephonyManager.NETWORK_TYPE_LTE_CA:
844 //              return "LTE_CA";
845             case TelephonyManager.NETWORK_TYPE_NR:
846                 return "NR SA";
847             default:
848                 return "UNKNOWN";
849         }
850     }
851 }
852