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