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