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