• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.phone.settings;
18 
19 import static android.net.ConnectivityManager.NetworkCallback;
20 
21 import static java.util.concurrent.TimeUnit.MILLISECONDS;
22 
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.DialogInterface;
26 import android.content.Intent;
27 import android.content.pm.ComponentInfo;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ResolveInfo;
30 import android.content.res.Resources;
31 import android.graphics.Typeface;
32 import android.hardware.radio.modem.ImeiInfo;
33 import android.net.ConnectivityManager;
34 import android.net.Network;
35 import android.net.NetworkCapabilities;
36 import android.net.NetworkRequest;
37 import android.net.TrafficStats;
38 import android.net.Uri;
39 import android.os.AsyncResult;
40 import android.os.Build;
41 import android.os.Bundle;
42 import android.os.Handler;
43 import android.os.HandlerExecutor;
44 import android.os.Message;
45 import android.os.PersistableBundle;
46 import android.os.SystemProperties;
47 import android.telephony.AccessNetworkConstants;
48 import android.telephony.CarrierConfigManager;
49 import android.telephony.CellIdentityCdma;
50 import android.telephony.CellIdentityGsm;
51 import android.telephony.CellIdentityLte;
52 import android.telephony.CellIdentityNr;
53 import android.telephony.CellIdentityWcdma;
54 import android.telephony.CellInfo;
55 import android.telephony.CellInfoCdma;
56 import android.telephony.CellInfoGsm;
57 import android.telephony.CellInfoLte;
58 import android.telephony.CellInfoNr;
59 import android.telephony.CellInfoWcdma;
60 import android.telephony.CellSignalStrengthCdma;
61 import android.telephony.CellSignalStrengthGsm;
62 import android.telephony.CellSignalStrengthLte;
63 import android.telephony.CellSignalStrengthNr;
64 import android.telephony.CellSignalStrengthWcdma;
65 import android.telephony.DataSpecificRegistrationInfo;
66 import android.telephony.NetworkRegistrationInfo;
67 import android.telephony.PhysicalChannelConfig;
68 import android.telephony.RadioAccessFamily;
69 import android.telephony.ServiceState;
70 import android.telephony.SignalStrength;
71 import android.telephony.SubscriptionManager;
72 import android.telephony.TelephonyCallback;
73 import android.telephony.TelephonyDisplayInfo;
74 import android.telephony.TelephonyManager;
75 import android.telephony.data.NetworkSlicingConfig;
76 import android.telephony.ims.ImsException;
77 import android.telephony.ims.ImsManager;
78 import android.telephony.ims.ImsMmTelManager;
79 import android.telephony.ims.ImsRcsManager;
80 import android.telephony.ims.ProvisioningManager;
81 import android.telephony.ims.feature.MmTelFeature;
82 import android.telephony.ims.stub.ImsRegistrationImplBase;
83 import android.text.TextUtils;
84 import android.util.Log;
85 import android.view.Menu;
86 import android.view.MenuItem;
87 import android.view.View;
88 import android.view.View.OnClickListener;
89 import android.widget.AdapterView;
90 import android.widget.ArrayAdapter;
91 import android.widget.Button;
92 import android.widget.CompoundButton;
93 import android.widget.CompoundButton.OnCheckedChangeListener;
94 import android.widget.EditText;
95 import android.widget.Spinner;
96 import android.widget.Switch;
97 import android.widget.TextView;
98 
99 import androidx.appcompat.app.AlertDialog;
100 import androidx.appcompat.app.AlertDialog.Builder;
101 import androidx.appcompat.app.AppCompatActivity;
102 
103 import com.android.internal.telephony.Phone;
104 import com.android.internal.telephony.PhoneFactory;
105 import com.android.internal.telephony.euicc.EuiccConnector;
106 import com.android.internal.telephony.util.TelephonyUtils;
107 import com.android.phone.R;
108 
109 import java.io.IOException;
110 import java.net.HttpURLConnection;
111 import java.net.URL;
112 import java.util.List;
113 import java.util.concurrent.CompletableFuture;
114 import java.util.concurrent.ExecutionException;
115 import java.util.concurrent.LinkedBlockingDeque;
116 import java.util.concurrent.ThreadPoolExecutor;
117 import java.util.concurrent.TimeUnit;
118 import java.util.concurrent.TimeoutException;
119 
120 /**
121  * Radio Information Class
122  *
123  * Allows user to read and alter some of the radio related information.
124  *
125  */
126 public class RadioInfo extends AppCompatActivity {
127     private static final String TAG = "RadioInfo";
128 
129     private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
130 
131     private static final String[] PREFERRED_NETWORK_LABELS = {
132             "GSM/WCDMA preferred",
133             "GSM only",
134             "WCDMA only",
135             "GSM/WCDMA auto (PRL)",
136             "CDMA/EvDo auto (PRL)",
137             "CDMA only",
138             "EvDo only",
139             "CDMA/EvDo/GSM/WCDMA (PRL)",
140             "CDMA + LTE/EvDo (PRL)",
141             "GSM/WCDMA/LTE (PRL)",
142             "LTE/CDMA/EvDo/GSM/WCDMA (PRL)",
143             "LTE only",
144             "LTE/WCDMA",
145             "TDSCDMA only",
146             "TDSCDMA/WCDMA",
147             "LTE/TDSCDMA",
148             "TDSCDMA/GSM",
149             "LTE/TDSCDMA/GSM",
150             "TDSCDMA/GSM/WCDMA",
151             "LTE/TDSCDMA/WCDMA",
152             "LTE/TDSCDMA/GSM/WCDMA",
153             "TDSCDMA/CDMA/EvDo/GSM/WCDMA ",
154             "LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA",
155             "NR only",
156             "NR/LTE",
157             "NR/LTE/CDMA/EvDo",
158             "NR/LTE/GSM/WCDMA",
159             "NR/LTE/CDMA/EvDo/GSM/WCDMA",
160             "NR/LTE/WCDMA",
161             "NR/LTE/TDSCDMA",
162             "NR/LTE/TDSCDMA/GSM",
163             "NR/LTE/TDSCDMA/WCDMA",
164             "NR/LTE/TDSCDMA/GSM/WCDMA",
165             "NR/LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA",
166             "Unknown"
167     };
168 
169     private static String[] sPhoneIndexLabels;
170 
171     private static final int sCellInfoListRateDisabled = Integer.MAX_VALUE;
172     private static final int sCellInfoListRateMax = 0;
173 
174     private static final String OEM_RADIO_INFO_INTENT =
175             "com.android.phone.settings.OEM_RADIO_INFO";
176 
177     private static final String DSDS_MODE_PROPERTY = "ro.boot.hardware.dsds";
178 
179     /**
180      * A value indicates the device is always on dsds mode.
181      * @see {@link #DSDS_MODE_PROPERTY}
182      */
183     private static final int ALWAYS_ON_DSDS_MODE = 1;
184 
185     //Values in must match CELL_INFO_REFRESH_RATES
186     private static final String[] CELL_INFO_REFRESH_RATE_LABELS = {
187             "Disabled",
188             "Immediate",
189             "Min 5s",
190             "Min 10s",
191             "Min 60s"
192     };
193 
194     //Values in seconds, must match CELL_INFO_REFRESH_RATE_LABELS
195     private static final int [] CELL_INFO_REFRESH_RATES = {
196         sCellInfoListRateDisabled,
197         sCellInfoListRateMax,
198         5000,
199         10000,
200         60000
201     };
202 
log(String s)203     private static void log(String s) {
204         Log.d(TAG, s);
205     }
206 
207     private static final int EVENT_QUERY_SMSC_DONE = 1005;
208     private static final int EVENT_UPDATE_SMSC_DONE = 1006;
209     private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 1007;
210     private static final int EVENT_UPDATE_NR_STATS = 1008;
211 
212     private static final int MENU_ITEM_VIEW_ADN            = 1;
213     private static final int MENU_ITEM_VIEW_FDN            = 2;
214     private static final int MENU_ITEM_VIEW_SDN            = 3;
215     private static final int MENU_ITEM_GET_IMS_STATUS      = 4;
216     private static final int MENU_ITEM_TOGGLE_DATA         = 5;
217 
218     private static final String CARRIER_PROVISIONING_ACTION =
219             "com.android.phone.settings.CARRIER_PROVISIONING";
220     private static final String TRIGGER_CARRIER_PROVISIONING_ACTION =
221             "com.android.phone.settings.TRIGGER_CARRIER_PROVISIONING";
222 
223     private static final String ACTION_REMOVABLE_ESIM_AS_DEFAULT =
224             "android.telephony.euicc.action.REMOVABLE_ESIM_AS_DEFAULT";
225 
226     private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
227     private TextView mLine1Number;
228     private TextView mSubscriptionId;
229     private TextView mDds;
230     private TextView mSubscriberId;
231     private TextView mCallState;
232     private TextView mOperatorName;
233     private TextView mRoamingState;
234     private TextView mGsmState;
235     private TextView mGprsState;
236     private TextView mVoiceNetwork;
237     private TextView mDataNetwork;
238     private TextView mVoiceRawReg;
239     private TextView mDataRawReg;
240     private TextView mWlanDataRawReg;
241     private TextView mOverrideNetwork;
242     private TextView mDBm;
243     private TextView mMwi;
244     private TextView mCfi;
245     private TextView mCellInfo;
246     private TextView mSent;
247     private TextView mReceived;
248     private TextView mPingHostnameV4;
249     private TextView mPingHostnameV6;
250     private TextView mHttpClientTest;
251     private TextView mPhyChanConfig;
252     private TextView mDnsCheckState;
253     private TextView mDownlinkKbps;
254     private TextView mUplinkKbps;
255     private TextView mEndcAvailable;
256     private TextView mDcnrRestricted;
257     private TextView mNrAvailable;
258     private TextView mNrState;
259     private TextView mNrFrequency;
260     private TextView mNetworkSlicingConfig;
261     private EditText mSmsc;
262     private Switch mRadioPowerOnSwitch;
263     private Switch mSimulateOutOfServiceSwitch;
264     private Button mDnsCheckToggleButton;
265     private Button mPingTestButton;
266     private Button mUpdateSmscButton;
267     private Button mRefreshSmscButton;
268     private Button mOemInfoButton;
269     private Button mCarrierProvisioningButton;
270     private Button mTriggerCarrierProvisioningButton;
271     private Switch mImsVolteProvisionedSwitch;
272     private Switch mImsVtProvisionedSwitch;
273     private Switch mImsWfcProvisionedSwitch;
274     private Switch mEabProvisionedSwitch;
275     private Switch mCbrsDataSwitch;
276     private Switch mDsdsSwitch;
277     private Switch mRemovableEsimSwitch;
278     private Spinner mPreferredNetworkType;
279     private Spinner mSelectPhoneIndex;
280     private Spinner mCellInfoRefreshRateSpinner;
281 
282     private static final long RUNNABLE_TIMEOUT_MS = 5 * 60 * 1000L;
283 
284     private ThreadPoolExecutor mQueuedWork;
285 
286     private ConnectivityManager mConnectivityManager;
287     private TelephonyManager mTelephonyManager;
288     private ImsManager mImsManager = null;
289     private Phone mPhone = null;
290     private ProvisioningManager mProvisioningManager = null;
291 
292     private String mPingHostnameResultV4;
293     private String mPingHostnameResultV6;
294     private String mHttpClientTestResult;
295     private boolean mMwiValue = false;
296     private boolean mCfiValue = false;
297 
298     private List<CellInfo> mCellInfoResult = null;
299     private final boolean[] mSimulateOos = new boolean[2];
300 
301     private int mPreferredNetworkTypeResult;
302     private int mCellInfoRefreshRateIndex;
303     private int mSelectedPhoneIndex;
304 
305     private final NetworkRequest mDefaultNetworkRequest = new NetworkRequest.Builder()
306             .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
307             .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
308             .build();
309 
310     private final NetworkCallback mNetworkCallback = new NetworkCallback() {
311         public void onCapabilitiesChanged(Network n, NetworkCapabilities nc) {
312             int dlbw = nc.getLinkDownstreamBandwidthKbps();
313             int ulbw = nc.getLinkUpstreamBandwidthKbps();
314             updateBandwidths(dlbw, ulbw);
315         }
316     };
317 
318     private static final int DEFAULT_TIMEOUT_MS = 1000;
319 
320     // not final because we need to recreate this object to register on a new subId (b/117555407)
321     private TelephonyCallback mTelephonyCallback = new RadioInfoTelephonyCallback();
322     private class RadioInfoTelephonyCallback extends TelephonyCallback implements
323             TelephonyCallback.DataConnectionStateListener,
324             TelephonyCallback.DataActivityListener,
325             TelephonyCallback.CallStateListener,
326             TelephonyCallback.MessageWaitingIndicatorListener,
327             TelephonyCallback.CallForwardingIndicatorListener,
328             TelephonyCallback.CellInfoListener,
329             TelephonyCallback.SignalStrengthsListener,
330             TelephonyCallback.ServiceStateListener,
331             TelephonyCallback.DisplayInfoListener {
332 
333         @Override
onDataConnectionStateChanged(int state, int networkType)334         public void onDataConnectionStateChanged(int state, int networkType) {
335             updateDataState();
336             updateNetworkType();
337         }
338 
339         @Override
onDataActivity(int direction)340         public void onDataActivity(int direction) {
341             updateDataStats2();
342         }
343 
344         @Override
onCallStateChanged(int state)345         public void onCallStateChanged(int state) {
346             updateNetworkType();
347             updatePhoneState(state);
348         }
349 
350         @Override
onMessageWaitingIndicatorChanged(boolean mwi)351         public void onMessageWaitingIndicatorChanged(boolean mwi) {
352             mMwiValue = mwi;
353             updateMessageWaiting();
354         }
355 
356         @Override
onCallForwardingIndicatorChanged(boolean cfi)357         public void onCallForwardingIndicatorChanged(boolean cfi) {
358             mCfiValue = cfi;
359             updateCallRedirect();
360         }
361 
362         @Override
onCellInfoChanged(List<CellInfo> arrayCi)363         public void onCellInfoChanged(List<CellInfo> arrayCi) {
364             log("onCellInfoChanged: arrayCi=" + arrayCi);
365             mCellInfoResult = arrayCi;
366             updateCellInfo(mCellInfoResult);
367         }
368 
369         @Override
onSignalStrengthsChanged(SignalStrength signalStrength)370         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
371             log("onSignalStrengthChanged: SignalStrength=" + signalStrength);
372             updateSignalStrength(signalStrength);
373         }
374 
375         @Override
onServiceStateChanged(ServiceState serviceState)376         public void onServiceStateChanged(ServiceState serviceState) {
377             log("onServiceStateChanged: ServiceState=" + serviceState);
378             updateServiceState(serviceState);
379             updateRadioPowerState();
380             updateNetworkType();
381             updateRawRegistrationState(serviceState);
382             updateImsProvisionedState();
383 
384             // Since update NR stats includes a ril message to get slicing information, it runs
385             // as blocking during the timeout period of 1 second. if ServiceStateChanged event
386             // fires consecutively, RadioInfo can run for more than 10 seconds. This can cause ANR.
387             // Therefore, send event only when there is no same event being processed.
388             if (!mHandler.hasMessages(EVENT_UPDATE_NR_STATS)) {
389                 mHandler.obtainMessage(EVENT_UPDATE_NR_STATS).sendToTarget();
390             }
391         }
392 
393         @Override
onDisplayInfoChanged(TelephonyDisplayInfo displayInfo)394         public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) {
395             updateNetworkType();
396         }
397     }
398 
updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs)399     private void updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) {
400         StringBuilder sb = new StringBuilder();
401         String div = "";
402         sb.append("{");
403         if (configs != null) {
404             for (PhysicalChannelConfig c : configs) {
405                 sb.append(div).append(c);
406                 div = ",";
407             }
408         }
409         sb.append("}");
410         mPhyChanConfig.setText(sb.toString());
411     }
412 
updatePreferredNetworkType(int type)413     private void updatePreferredNetworkType(int type) {
414         if (type >= PREFERRED_NETWORK_LABELS.length || type < 0) {
415             log("Network type: unknown type value=" + type);
416             type = PREFERRED_NETWORK_LABELS.length - 1; //set to Unknown
417         }
418         mPreferredNetworkTypeResult = type;
419 
420         mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
421     }
422 
updatePhoneIndex(int phoneIndex, int subId)423     private void updatePhoneIndex(int phoneIndex, int subId) {
424         // unregister listeners on the old subId
425         unregisterPhoneStateListener();
426         mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mPhone.getSubId());
427 
428         if (phoneIndex == SubscriptionManager.INVALID_PHONE_INDEX) {
429             log("Invalid phone index " + phoneIndex + ", subscription ID " + subId);
430             return;
431         }
432 
433         // update the subId
434         mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
435 
436         // update the phoneId
437         mPhone = PhoneFactory.getPhone(phoneIndex);
438         mImsManager = new ImsManager(mPhone.getContext());
439         try {
440             mProvisioningManager = ProvisioningManager.createForSubscriptionId(subId);
441         } catch (IllegalArgumentException e) {
442             log("updatePhoneIndex : IllegalArgumentException " + e.getMessage());
443             mProvisioningManager = null;
444         }
445 
446         updateAllFields();
447     }
448 
449     private Handler mHandler = new Handler() {
450         @Override
451         public void handleMessage(Message msg) {
452             AsyncResult ar;
453             switch (msg.what) {
454                 case EVENT_QUERY_SMSC_DONE:
455                     ar = (AsyncResult) msg.obj;
456                     if (ar.exception != null) {
457                         mSmsc.setText("refresh error");
458                     } else {
459                         mSmsc.setText((String) ar.result);
460                     }
461                     break;
462                 case EVENT_UPDATE_SMSC_DONE:
463                     mUpdateSmscButton.setEnabled(true);
464                     ar = (AsyncResult) msg.obj;
465                     if (ar.exception != null) {
466                         mSmsc.setText("update error");
467                     }
468                     break;
469                 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
470                     ar = (AsyncResult) msg.obj;
471                     if (ar.exception != null) {
472                         mPhyChanConfig.setText(("update error"));
473                     }
474                     updatePhysicalChannelConfiguration((List<PhysicalChannelConfig>) ar.result);
475                     break;
476                 case EVENT_UPDATE_NR_STATS:
477                     log("got EVENT_UPDATE_NR_STATS");
478                     updateNrStats();
479                     break;
480                 default:
481                     super.handleMessage(msg);
482                     break;
483 
484             }
485         }
486     };
487 
488     @Override
onCreate(Bundle icicle)489     public void onCreate(Bundle icicle) {
490         super.onCreate(icicle);
491         if (!android.os.Process.myUserHandle().isSystem()) {
492             Log.e(TAG, "Not run from system user, don't do anything.");
493             finish();
494             return;
495         }
496 
497         setContentView(R.layout.radio_info);
498 
499         log("Started onCreate");
500 
501         mQueuedWork = new ThreadPoolExecutor(1, 1, RUNNABLE_TIMEOUT_MS, TimeUnit.MICROSECONDS,
502                 new LinkedBlockingDeque<Runnable>());
503         mConnectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
504         mPhone = getPhone(SubscriptionManager.getDefaultSubscriptionId());
505         mTelephonyManager = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
506                 .createForSubscriptionId(mPhone.getSubId());
507 
508         mImsManager = new ImsManager(mPhone.getContext());
509         try {
510             mProvisioningManager = ProvisioningManager.createForSubscriptionId(mPhone.getSubId());
511         } catch (IllegalArgumentException e) {
512             log("onCreate : IllegalArgumentException " + e.getMessage());
513             mProvisioningManager = null;
514         }
515 
516         sPhoneIndexLabels = getPhoneIndexLabels(mTelephonyManager);
517 
518         mDeviceId = (TextView) findViewById(R.id.imei);
519         mLine1Number = (TextView) findViewById(R.id.number);
520         mSubscriptionId = (TextView) findViewById(R.id.subid);
521         mDds = (TextView) findViewById(R.id.dds);
522         mSubscriberId = (TextView) findViewById(R.id.imsi);
523         mCallState = (TextView) findViewById(R.id.call);
524         mOperatorName = (TextView) findViewById(R.id.operator);
525         mRoamingState = (TextView) findViewById(R.id.roaming);
526         mGsmState = (TextView) findViewById(R.id.gsm);
527         mGprsState = (TextView) findViewById(R.id.gprs);
528         mVoiceNetwork = (TextView) findViewById(R.id.voice_network);
529         mDataNetwork = (TextView) findViewById(R.id.data_network);
530         mVoiceRawReg = (TextView) findViewById(R.id.voice_raw_registration_state);
531         mDataRawReg = (TextView) findViewById(R.id.data_raw_registration_state);
532         mWlanDataRawReg = (TextView) findViewById(R.id.wlan_data_raw_registration_state);
533         mOverrideNetwork = (TextView) findViewById(R.id.override_network);
534         mDBm = (TextView) findViewById(R.id.dbm);
535         mMwi = (TextView) findViewById(R.id.mwi);
536         mCfi = (TextView) findViewById(R.id.cfi);
537         mCellInfo = (TextView) findViewById(R.id.cellinfo);
538         mCellInfo.setTypeface(Typeface.MONOSPACE);
539 
540         mSent = (TextView) findViewById(R.id.sent);
541         mReceived = (TextView) findViewById(R.id.received);
542         mSmsc = (EditText) findViewById(R.id.smsc);
543         mDnsCheckState = (TextView) findViewById(R.id.dnsCheckState);
544         mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4);
545         mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6);
546         mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
547         mEndcAvailable = (TextView) findViewById(R.id.endc_available);
548         mDcnrRestricted = (TextView) findViewById(R.id.dcnr_restricted);
549         mNrAvailable = (TextView) findViewById(R.id.nr_available);
550         mNrState = (TextView) findViewById(R.id.nr_state);
551         mNrFrequency = (TextView) findViewById(R.id.nr_frequency);
552         mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config);
553         mNetworkSlicingConfig = (TextView) findViewById(R.id.network_slicing_config);
554 
555         // hide 5G stats on devices that don't support 5G
556         if ((mTelephonyManager.getSupportedRadioAccessFamily()
557                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
558             setNrStatsVisibility(View.GONE);
559         }
560 
561         mPreferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
562         ArrayAdapter<String> mPreferredNetworkTypeAdapter = new ArrayAdapter<String>(this,
563                 android.R.layout.simple_spinner_item, PREFERRED_NETWORK_LABELS);
564         mPreferredNetworkTypeAdapter
565                 .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
566         mPreferredNetworkType.setAdapter(mPreferredNetworkTypeAdapter);
567 
568         mSelectPhoneIndex = (Spinner) findViewById(R.id.phoneIndex);
569         ArrayAdapter<String> phoneIndexAdapter = new ArrayAdapter<String>(this,
570                 android.R.layout.simple_spinner_item, sPhoneIndexLabels);
571         phoneIndexAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
572         mSelectPhoneIndex.setAdapter(phoneIndexAdapter);
573 
574         mCellInfoRefreshRateSpinner = (Spinner) findViewById(R.id.cell_info_rate_select);
575         ArrayAdapter<String> cellInfoAdapter = new ArrayAdapter<String>(this,
576                 android.R.layout.simple_spinner_item, CELL_INFO_REFRESH_RATE_LABELS);
577         cellInfoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
578         mCellInfoRefreshRateSpinner.setAdapter(cellInfoAdapter);
579 
580         mImsVolteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch);
581         mImsVtProvisionedSwitch = (Switch) findViewById(R.id.vt_provisioned_switch);
582         mImsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
583         mEabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch);
584 
585         if (!isImsSupportedOnDevice(mPhone.getContext())) {
586             mImsVolteProvisionedSwitch.setVisibility(View.GONE);
587             mImsVtProvisionedSwitch.setVisibility(View.GONE);
588             mImsWfcProvisionedSwitch.setVisibility(View.GONE);
589             mEabProvisionedSwitch.setVisibility(View.GONE);
590         }
591 
592         mCbrsDataSwitch = (Switch) findViewById(R.id.cbrs_data_switch);
593         mCbrsDataSwitch.setVisibility(isCbrsSupported() ? View.VISIBLE : View.GONE);
594 
595         mDsdsSwitch = findViewById(R.id.dsds_switch);
596         if (isDsdsSupported() && !dsdsModeOnly()) {
597             mDsdsSwitch.setVisibility(View.VISIBLE);
598             mDsdsSwitch.setOnClickListener(v -> {
599                 if (mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot()) {
600                     // Undo the click action until user clicks the confirm dialog.
601                     mDsdsSwitch.toggle();
602                     showDsdsChangeDialog();
603                 } else {
604                     performDsdsSwitch();
605                 }
606             });
607             mDsdsSwitch.setChecked(isDsdsEnabled());
608         } else {
609             mDsdsSwitch.setVisibility(View.GONE);
610         }
611 
612         mRemovableEsimSwitch = (Switch) findViewById(R.id.removable_esim_switch);
613         if (!IS_USER_BUILD) {
614             mRemovableEsimSwitch.setEnabled(true);
615             mRemovableEsimSwitch.setChecked(mTelephonyManager.isRemovableEsimDefaultEuicc());
616             mRemovableEsimSwitch.setOnCheckedChangeListener(mRemovableEsimChangeListener);
617         }
618 
619         mRadioPowerOnSwitch = (Switch) findViewById(R.id.radio_power);
620 
621         mSimulateOutOfServiceSwitch = (Switch) findViewById(R.id.simulate_out_of_service);
622         if (!TelephonyUtils.IS_DEBUGGABLE) {
623             mSimulateOutOfServiceSwitch.setVisibility(View.GONE);
624         }
625 
626         mDownlinkKbps = (TextView) findViewById(R.id.dl_kbps);
627         mUplinkKbps = (TextView) findViewById(R.id.ul_kbps);
628         updateBandwidths(0, 0);
629 
630         mPingTestButton = (Button) findViewById(R.id.ping_test);
631         mPingTestButton.setOnClickListener(mPingButtonHandler);
632         mUpdateSmscButton = (Button) findViewById(R.id.update_smsc);
633         mUpdateSmscButton.setOnClickListener(mUpdateSmscButtonHandler);
634         mRefreshSmscButton = (Button) findViewById(R.id.refresh_smsc);
635         mRefreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
636         mDnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle);
637         mDnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler);
638         mCarrierProvisioningButton = (Button) findViewById(R.id.carrier_provisioning);
639         if (!TextUtils.isEmpty(getCarrierProvisioningAppString())) {
640             mCarrierProvisioningButton.setOnClickListener(mCarrierProvisioningButtonHandler);
641         } else {
642             mCarrierProvisioningButton.setEnabled(false);
643         }
644 
645         mTriggerCarrierProvisioningButton = (Button) findViewById(
646                 R.id.trigger_carrier_provisioning);
647         if (!TextUtils.isEmpty(getCarrierProvisioningAppString())) {
648             mTriggerCarrierProvisioningButton.setOnClickListener(
649                     mTriggerCarrierProvisioningButtonHandler);
650         } else {
651             mTriggerCarrierProvisioningButton.setEnabled(false);
652         }
653 
654         mOemInfoButton = (Button) findViewById(R.id.oem_info);
655         mOemInfoButton.setOnClickListener(mOemInfoButtonHandler);
656         PackageManager pm = getPackageManager();
657         Intent oemInfoIntent = new Intent(OEM_RADIO_INFO_INTENT);
658         List<ResolveInfo> oemInfoIntentList = pm.queryIntentActivities(oemInfoIntent, 0);
659         if (oemInfoIntentList.size() == 0) {
660             mOemInfoButton.setEnabled(false);
661         }
662 
663         mCellInfoRefreshRateIndex = 0; //disabled
664         mPreferredNetworkTypeResult = PREFERRED_NETWORK_LABELS.length - 1; //Unknown
665         mSelectedPhoneIndex = mPhone.getPhoneId();
666 
667         new Thread(() -> {
668             int networkType = (int) mTelephonyManager.getPreferredNetworkTypeBitmask();
669             runOnUiThread(() -> updatePreferredNetworkType(
670                     RadioAccessFamily.getNetworkTypeFromRaf(networkType)));
671         }).start();
672 
673         restoreFromBundle(icicle);
674     }
675 
676     @Override
getParentActivityIntent()677     public Intent getParentActivityIntent() {
678         Intent parentActivity = super.getParentActivityIntent();
679         if (parentActivity == null) {
680             parentActivity = (new Intent()).setClassName("com.android.settings",
681                     "com.android.settings.Settings$TestingSettingsActivity");
682         }
683         return parentActivity;
684     }
685 
686     @Override
onResume()687     protected void onResume() {
688         super.onResume();
689 
690         log("Started onResume");
691 
692         updateAllFields();
693     }
694 
updateAllFields()695     private void updateAllFields() {
696         updateMessageWaiting();
697         updateCallRedirect();
698         updateDataState();
699         updateDataStats2();
700         updateRadioPowerState();
701         updateImsProvisionedState();
702         updateProperties();
703         updateDnsCheckState();
704         updateNetworkType();
705         updateNrStats();
706 
707         updateCellInfo(mCellInfoResult);
708         updateSubscriptionIds();
709 
710         mPingHostnameV4.setText(mPingHostnameResultV4);
711         mPingHostnameV6.setText(mPingHostnameResultV6);
712         mHttpClientTest.setText(mHttpClientTestResult);
713 
714         mCellInfoRefreshRateSpinner.setOnItemSelectedListener(mCellInfoRefreshRateHandler);
715         //set selection after registering listener to force update
716         mCellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex);
717         // Request cell information update from RIL.
718         mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[mCellInfoRefreshRateIndex],
719                 mPhone.getSubId());
720 
721         //set selection before registering to prevent update
722         mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
723         mPreferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
724 
725         new Thread(() -> {
726             int networkType = (int) mTelephonyManager.getPreferredNetworkTypeBitmask();
727             runOnUiThread(() -> updatePreferredNetworkType(
728                     RadioAccessFamily.getNetworkTypeFromRaf(networkType)));
729         }).start();
730 
731         // set phone index
732         mSelectPhoneIndex.setSelection(mSelectedPhoneIndex, true);
733         mSelectPhoneIndex.setOnItemSelectedListener(mSelectPhoneIndexHandler);
734 
735         mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
736         mSimulateOutOfServiceSwitch.setOnCheckedChangeListener(mSimulateOosOnChangeListener);
737         mSimulateOutOfServiceSwitch.setChecked(mSimulateOos[mPhone.getPhoneId()]);
738         mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
739         mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
740         mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
741         mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
742 
743         if (isCbrsSupported()) {
744             mCbrsDataSwitch.setChecked(getCbrsDataState());
745             mCbrsDataSwitch.setOnCheckedChangeListener(mCbrsDataSwitchChangeListener);
746         }
747 
748         unregisterPhoneStateListener();
749         registerPhoneStateListener();
750         mPhone.registerForPhysicalChannelConfig(mHandler,
751             EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, null);
752 
753         mConnectivityManager.registerNetworkCallback(
754                 mDefaultNetworkRequest, mNetworkCallback, mHandler);
755 
756         mSmsc.clearFocus();
757     }
758 
759     @Override
onPause()760     protected void onPause() {
761         super.onPause();
762 
763         log("onPause: unregister phone & data intents");
764 
765         mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
766         mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mPhone.getSubId());
767         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
768 
769     }
770 
restoreFromBundle(Bundle b)771     private void restoreFromBundle(Bundle b) {
772         if (b == null) {
773             return;
774         }
775 
776         mPingHostnameResultV4 = b.getString("mPingHostnameResultV4", "");
777         mPingHostnameResultV6 = b.getString("mPingHostnameResultV6", "");
778         mHttpClientTestResult = b.getString("mHttpClientTestResult", "");
779 
780         mPingHostnameV4.setText(mPingHostnameResultV4);
781         mPingHostnameV6.setText(mPingHostnameResultV6);
782         mHttpClientTest.setText(mHttpClientTestResult);
783 
784         mPreferredNetworkTypeResult = b.getInt("mPreferredNetworkTypeResult",
785                 PREFERRED_NETWORK_LABELS.length - 1);
786 
787         mSelectedPhoneIndex = b.getInt("mSelectedPhoneIndex", 0);
788 
789         mCellInfoRefreshRateIndex = b.getInt("mCellInfoRefreshRateIndex", 0);
790     }
791 
792     @SuppressWarnings("MissingSuperCall") // TODO: Fix me
793     @Override
onSaveInstanceState(Bundle outState)794     protected void onSaveInstanceState(Bundle outState) {
795         outState.putString("mPingHostnameResultV4", mPingHostnameResultV4);
796         outState.putString("mPingHostnameResultV6", mPingHostnameResultV6);
797         outState.putString("mHttpClientTestResult", mHttpClientTestResult);
798 
799         outState.putInt("mPreferredNetworkTypeResult", mPreferredNetworkTypeResult);
800         outState.putInt("mSelectedPhoneIndex", mSelectedPhoneIndex);
801         outState.putInt("mCellInfoRefreshRateIndex", mCellInfoRefreshRateIndex);
802 
803     }
804 
805     @Override
onCreateOptionsMenu(Menu menu)806     public boolean onCreateOptionsMenu(Menu menu) {
807         // Removed "select Radio band". If need it back, use setSystemSelectionChannels()
808         menu.add(1, MENU_ITEM_VIEW_ADN, 0,
809                 R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback);
810         menu.add(1, MENU_ITEM_VIEW_FDN, 0,
811                 R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
812         menu.add(1, MENU_ITEM_VIEW_SDN, 0,
813                 R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
814         if (isImsSupportedOnDevice(mPhone.getContext())) {
815             menu.add(1, MENU_ITEM_GET_IMS_STATUS,
816                     0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
817         }
818         menu.add(1, MENU_ITEM_TOGGLE_DATA,
819                 0, R.string.radio_info_data_connection_disable)
820                 .setOnMenuItemClickListener(mToggleData);
821         return true;
822     }
823 
824     @Override
onPrepareOptionsMenu(Menu menu)825     public boolean onPrepareOptionsMenu(Menu menu) {
826         // Get the TOGGLE DATA menu item in the right state.
827         MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA);
828         int state = mTelephonyManager.getDataState();
829         boolean visible = true;
830 
831         switch (state) {
832             case TelephonyManager.DATA_CONNECTED:
833             case TelephonyManager.DATA_SUSPENDED:
834                 item.setTitle(R.string.radio_info_data_connection_disable);
835                 break;
836             case TelephonyManager.DATA_DISCONNECTED:
837                 item.setTitle(R.string.radio_info_data_connection_enable);
838                 break;
839             default:
840                 visible = false;
841                 break;
842         }
843         item.setVisible(visible);
844         return true;
845     }
846 
847     @Override
onDestroy()848     protected void onDestroy() {
849         super.onDestroy();
850         mQueuedWork.shutdown();
851     }
852 
853     // returns array of string labels for each phone index. The array index is equal to the phone
854     // index.
getPhoneIndexLabels(TelephonyManager tm)855     private static String[] getPhoneIndexLabels(TelephonyManager tm) {
856         int phones = tm.getPhoneCount();
857         String[] labels = new String[phones];
858         for (int i = 0; i < phones; i++) {
859             labels[i] = "Phone " + i;
860         }
861         return labels;
862     }
863 
unregisterPhoneStateListener()864     private void unregisterPhoneStateListener() {
865         mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
866         mPhone.unregisterForPhysicalChannelConfig(mHandler);
867 
868         // clear all fields so they are blank until the next listener event occurs
869         mOperatorName.setText("");
870         mGprsState.setText("");
871         mDataNetwork.setText("");
872         mDataRawReg.setText("");
873         mOverrideNetwork.setText("");
874         mVoiceNetwork.setText("");
875         mVoiceRawReg.setText("");
876         mWlanDataRawReg.setText("");
877         mSent.setText("");
878         mReceived.setText("");
879         mCallState.setText("");
880         mMwiValue = false;
881         mMwi.setText("");
882         mCfiValue = false;
883         mCfi.setText("");
884         mCellInfo.setText("");
885         mDBm.setText("");
886         mGsmState.setText("");
887         mRoamingState.setText("");
888         mPhyChanConfig.setText("");
889     }
890 
891     // register mTelephonyCallback for relevant fields using the current TelephonyManager
registerPhoneStateListener()892     private void registerPhoneStateListener() {
893         mTelephonyCallback = new RadioInfoTelephonyCallback();
894         mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(mHandler),
895                 mTelephonyCallback);
896     }
897 
setNrStatsVisibility(int visibility)898     private void setNrStatsVisibility(int visibility) {
899         ((TextView) findViewById(R.id.endc_available_label)).setVisibility(visibility);
900         mEndcAvailable.setVisibility(visibility);
901         ((TextView) findViewById(R.id.dcnr_restricted_label)).setVisibility(visibility);
902         mDcnrRestricted.setVisibility(visibility);
903         ((TextView) findViewById(R.id.nr_available_label)).setVisibility(visibility);
904         mNrAvailable.setVisibility(visibility);
905         ((TextView) findViewById(R.id.nr_state_label)).setVisibility(visibility);
906         mNrState.setVisibility(visibility);
907         ((TextView) findViewById(R.id.nr_frequency_label)).setVisibility(visibility);
908         mNrFrequency.setVisibility(visibility);
909         ((TextView) findViewById(R.id.network_slicing_config_label)).setVisibility(visibility);
910         mNetworkSlicingConfig.setVisibility(visibility);
911     }
912 
updateDnsCheckState()913     private void updateDnsCheckState() {
914         //FIXME: Replace with a TelephonyManager call
915         mDnsCheckState.setText(mPhone.isDnsCheckDisabled()
916                 ? "0.0.0.0 allowed" : "0.0.0.0 not allowed");
917     }
918 
updateBandwidths(int dlbw, int ulbw)919     private void updateBandwidths(int dlbw, int ulbw) {
920         dlbw = (dlbw < 0 || dlbw == Integer.MAX_VALUE) ? -1 : dlbw;
921         ulbw = (ulbw < 0 || ulbw == Integer.MAX_VALUE) ? -1 : ulbw;
922         mDownlinkKbps.setText(String.format("%-5d", dlbw));
923         mUplinkKbps.setText(String.format("%-5d", ulbw));
924     }
925 
updateSignalStrength(SignalStrength signalStrength)926     private void updateSignalStrength(SignalStrength signalStrength) {
927         Resources r = getResources();
928 
929         int signalDbm = signalStrength.getDbm();
930 
931         int signalAsu = signalStrength.getAsuLevel();
932 
933         if (-1 == signalAsu) signalAsu = 0;
934 
935         mDBm.setText(String.valueOf(signalDbm) + " "
936                 + r.getString(R.string.radioInfo_display_dbm) + "   "
937                 + String.valueOf(signalAsu) + " "
938                 + r.getString(R.string.radioInfo_display_asu));
939     }
940 
getCellInfoDisplayString(int i)941     private String getCellInfoDisplayString(int i) {
942         return (i != Integer.MAX_VALUE) ? Integer.toString(i) : "";
943     }
944 
getCellInfoDisplayString(long i)945     private String getCellInfoDisplayString(long i) {
946         return (i != Long.MAX_VALUE) ? Long.toString(i) : "";
947     }
948 
getConnectionStatusString(CellInfo ci)949     private String getConnectionStatusString(CellInfo ci) {
950         String regStr = "";
951         String connStatStr = "";
952         String connector = "";
953 
954         if (ci.isRegistered()) {
955             regStr = "R";
956         }
957         switch (ci.getCellConnectionStatus()) {
958             case CellInfo.CONNECTION_PRIMARY_SERVING: connStatStr = "P"; break;
959             case CellInfo.CONNECTION_SECONDARY_SERVING: connStatStr = "S"; break;
960             case CellInfo.CONNECTION_NONE: connStatStr = "N"; break;
961             case CellInfo.CONNECTION_UNKNOWN: /* Field is unsupported */ break;
962             default: break;
963         }
964         if (!TextUtils.isEmpty(regStr) && !TextUtils.isEmpty(connStatStr)) {
965             connector = "+";
966         }
967 
968         return regStr + connector + connStatStr;
969     }
970 
buildCdmaInfoString(CellInfoCdma ci)971     private String buildCdmaInfoString(CellInfoCdma ci) {
972         CellIdentityCdma cidCdma = ci.getCellIdentity();
973         CellSignalStrengthCdma ssCdma = ci.getCellSignalStrength();
974 
975         return String.format("%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s",
976                 getConnectionStatusString(ci),
977                 getCellInfoDisplayString(cidCdma.getSystemId()),
978                 getCellInfoDisplayString(cidCdma.getNetworkId()),
979                 getCellInfoDisplayString(cidCdma.getBasestationId()),
980                 getCellInfoDisplayString(ssCdma.getCdmaDbm()),
981                 getCellInfoDisplayString(ssCdma.getCdmaEcio()),
982                 getCellInfoDisplayString(ssCdma.getEvdoDbm()),
983                 getCellInfoDisplayString(ssCdma.getEvdoEcio()),
984                 getCellInfoDisplayString(ssCdma.getEvdoSnr()));
985     }
986 
buildGsmInfoString(CellInfoGsm ci)987     private String buildGsmInfoString(CellInfoGsm ci) {
988         CellIdentityGsm cidGsm = ci.getCellIdentity();
989         CellSignalStrengthGsm ssGsm = ci.getCellSignalStrength();
990 
991         return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
992                 getConnectionStatusString(ci),
993                 getCellInfoDisplayString(cidGsm.getMcc()),
994                 getCellInfoDisplayString(cidGsm.getMnc()),
995                 getCellInfoDisplayString(cidGsm.getLac()),
996                 getCellInfoDisplayString(cidGsm.getCid()),
997                 getCellInfoDisplayString(cidGsm.getArfcn()),
998                 getCellInfoDisplayString(cidGsm.getBsic()),
999                 getCellInfoDisplayString(ssGsm.getDbm()));
1000     }
1001 
buildLteInfoString(CellInfoLte ci)1002     private String buildLteInfoString(CellInfoLte ci) {
1003         CellIdentityLte cidLte = ci.getCellIdentity();
1004         CellSignalStrengthLte ssLte = ci.getCellSignalStrength();
1005 
1006         return String.format(
1007                 "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n",
1008                 getConnectionStatusString(ci),
1009                 getCellInfoDisplayString(cidLte.getMcc()),
1010                 getCellInfoDisplayString(cidLte.getMnc()),
1011                 getCellInfoDisplayString(cidLte.getTac()),
1012                 getCellInfoDisplayString(cidLte.getCi()),
1013                 getCellInfoDisplayString(cidLte.getPci()),
1014                 getCellInfoDisplayString(cidLte.getEarfcn()),
1015                 getCellInfoDisplayString(cidLte.getBandwidth()),
1016                 getCellInfoDisplayString(ssLte.getDbm()),
1017                 getCellInfoDisplayString(ssLte.getRsrq()),
1018                 getCellInfoDisplayString(ssLte.getTimingAdvance()));
1019     }
1020 
buildNrInfoString(CellInfoNr ci)1021     private String buildNrInfoString(CellInfoNr ci) {
1022         CellIdentityNr cidNr = (CellIdentityNr) ci.getCellIdentity();
1023         CellSignalStrengthNr ssNr = (CellSignalStrengthNr) ci.getCellSignalStrength();
1024 
1025         return String.format(
1026                 "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-4.4s %-4.4s\n",
1027                 getConnectionStatusString(ci),
1028                 cidNr.getMccString(),
1029                 cidNr.getMncString(),
1030                 getCellInfoDisplayString(cidNr.getTac()),
1031                 getCellInfoDisplayString(cidNr.getNci()),
1032                 getCellInfoDisplayString(cidNr.getPci()),
1033                 getCellInfoDisplayString(cidNr.getNrarfcn()),
1034                 getCellInfoDisplayString(ssNr.getSsRsrp()),
1035                 getCellInfoDisplayString(ssNr.getSsRsrq()));
1036     }
1037 
buildWcdmaInfoString(CellInfoWcdma ci)1038     private String buildWcdmaInfoString(CellInfoWcdma ci) {
1039         CellIdentityWcdma cidWcdma = ci.getCellIdentity();
1040         CellSignalStrengthWcdma ssWcdma = ci.getCellSignalStrength();
1041 
1042         return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
1043                 getConnectionStatusString(ci),
1044                 getCellInfoDisplayString(cidWcdma.getMcc()),
1045                 getCellInfoDisplayString(cidWcdma.getMnc()),
1046                 getCellInfoDisplayString(cidWcdma.getLac()),
1047                 getCellInfoDisplayString(cidWcdma.getCid()),
1048                 getCellInfoDisplayString(cidWcdma.getUarfcn()),
1049                 getCellInfoDisplayString(cidWcdma.getPsc()),
1050                 getCellInfoDisplayString(ssWcdma.getDbm()));
1051     }
1052 
buildCellInfoString(List<CellInfo> arrayCi)1053     private String buildCellInfoString(List<CellInfo> arrayCi) {
1054         String value = new String();
1055         StringBuilder cdmaCells = new StringBuilder(),
1056                 gsmCells = new StringBuilder(),
1057                 lteCells = new StringBuilder(),
1058                 wcdmaCells = new StringBuilder(),
1059                 nrCells = new StringBuilder();
1060 
1061         if (arrayCi != null) {
1062             for (CellInfo ci : arrayCi) {
1063 
1064                 if (ci instanceof CellInfoLte) {
1065                     lteCells.append(buildLteInfoString((CellInfoLte) ci));
1066                 } else if (ci instanceof CellInfoWcdma) {
1067                     wcdmaCells.append(buildWcdmaInfoString((CellInfoWcdma) ci));
1068                 } else if (ci instanceof CellInfoGsm) {
1069                     gsmCells.append(buildGsmInfoString((CellInfoGsm) ci));
1070                 } else if (ci instanceof CellInfoCdma) {
1071                     cdmaCells.append(buildCdmaInfoString((CellInfoCdma) ci));
1072                 } else if (ci instanceof CellInfoNr) {
1073                     nrCells.append(buildNrInfoString((CellInfoNr) ci));
1074                 }
1075             }
1076             if (nrCells.length() != 0) {
1077                 value += String.format(
1078                         "NR\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s"
1079                                 + " %-6.6s %-4.4s %-4.4s\n",
1080                         "SRV", "MCC", "MNC", "TAC", "NCI", "PCI",
1081                         "NRARFCN", "SS-RSRP", "SS-RSRQ");
1082                 value += nrCells.toString();
1083             }
1084 
1085             if (lteCells.length() != 0) {
1086                 value += String.format(
1087                         "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s"
1088                                 + " %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n",
1089                         "SRV", "MCC", "MNC", "TAC", "CID", "PCI",
1090                         "EARFCN", "BW", "RSRP", "RSRQ", "TA");
1091                 value += lteCells.toString();
1092             }
1093             if (wcdmaCells.length() != 0) {
1094                 value += String.format(
1095                         "WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
1096                         "SRV", "MCC", "MNC", "LAC", "CID", "UARFCN", "PSC", "RSCP");
1097                 value += wcdmaCells.toString();
1098             }
1099             if (gsmCells.length() != 0) {
1100                 value += String.format(
1101                         "GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
1102                         "SRV", "MCC", "MNC", "LAC", "CID", "ARFCN", "BSIC", "RSSI");
1103                 value += gsmCells.toString();
1104             }
1105             if (cdmaCells.length() != 0) {
1106                 value += String.format(
1107                         "CDMA/EVDO\n%-3.3s %-5.5s %-5.5s %-5.5s"
1108                                 + " %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s\n",
1109                         "SRV", "SID", "NID", "BSID",
1110                         "C-RSSI", "C-ECIO", "E-RSSI", "E-ECIO", "E-SNR");
1111                 value += cdmaCells.toString();
1112             }
1113         } else {
1114             value = "unknown";
1115         }
1116 
1117         return value.toString();
1118     }
1119 
updateCellInfo(List<CellInfo> arrayCi)1120     private void updateCellInfo(List<CellInfo> arrayCi) {
1121         mCellInfo.setText(buildCellInfoString(arrayCi));
1122     }
1123 
updateSubscriptionIds()1124     private void updateSubscriptionIds() {
1125         mSubscriptionId.setText(Integer.toString(mPhone.getSubId()));
1126         mDds.setText(Integer.toString(SubscriptionManager.getDefaultDataSubscriptionId()));
1127     }
1128 
updateMessageWaiting()1129     private void updateMessageWaiting() {
1130         mMwi.setText(String.valueOf(mMwiValue));
1131     }
1132 
updateCallRedirect()1133     private void updateCallRedirect() {
1134         mCfi.setText(String.valueOf(mCfiValue));
1135     }
1136 
1137 
updateServiceState(ServiceState serviceState)1138     private void updateServiceState(ServiceState serviceState) {
1139         int state = serviceState.getState();
1140         Resources r = getResources();
1141         String display = r.getString(R.string.radioInfo_unknown);
1142 
1143         switch (state) {
1144             case ServiceState.STATE_IN_SERVICE:
1145                 display = r.getString(R.string.radioInfo_service_in);
1146                 break;
1147             case ServiceState.STATE_OUT_OF_SERVICE:
1148                 display = r.getString(R.string.radioInfo_service_out);
1149                 break;
1150             case ServiceState.STATE_EMERGENCY_ONLY:
1151                 display = r.getString(R.string.radioInfo_service_emergency);
1152                 break;
1153             case ServiceState.STATE_POWER_OFF:
1154                 display = r.getString(R.string.radioInfo_service_off);
1155                 break;
1156         }
1157 
1158         mGsmState.setText(display);
1159 
1160         if (serviceState.getRoaming()) {
1161             mRoamingState.setText(R.string.radioInfo_roaming_in);
1162         } else {
1163             mRoamingState.setText(R.string.radioInfo_roaming_not);
1164         }
1165 
1166         mOperatorName.setText(serviceState.getOperatorAlphaLong());
1167     }
1168 
updatePhoneState(int state)1169     private void updatePhoneState(int state) {
1170         Resources r = getResources();
1171         String display = r.getString(R.string.radioInfo_unknown);
1172 
1173         switch (state) {
1174             case TelephonyManager.CALL_STATE_IDLE:
1175                 display = r.getString(R.string.radioInfo_phone_idle);
1176                 break;
1177             case TelephonyManager.CALL_STATE_RINGING:
1178                 display = r.getString(R.string.radioInfo_phone_ringing);
1179                 break;
1180             case TelephonyManager.CALL_STATE_OFFHOOK:
1181                 display = r.getString(R.string.radioInfo_phone_offhook);
1182                 break;
1183         }
1184 
1185         mCallState.setText(display);
1186     }
1187 
updateDataState()1188     private void updateDataState() {
1189         int state = mTelephonyManager.getDataState();
1190         Resources r = getResources();
1191         String display = r.getString(R.string.radioInfo_unknown);
1192 
1193         switch (state) {
1194             case TelephonyManager.DATA_CONNECTED:
1195                 display = r.getString(R.string.radioInfo_data_connected);
1196                 break;
1197             case TelephonyManager.DATA_CONNECTING:
1198                 display = r.getString(R.string.radioInfo_data_connecting);
1199                 break;
1200             case TelephonyManager.DATA_DISCONNECTED:
1201                 display = r.getString(R.string.radioInfo_data_disconnected);
1202                 break;
1203             case TelephonyManager.DATA_SUSPENDED:
1204                 display = r.getString(R.string.radioInfo_data_suspended);
1205                 break;
1206         }
1207 
1208         mGprsState.setText(display);
1209     }
1210 
updateNetworkType()1211     private void updateNetworkType() {
1212         if (mPhone != null) {
1213             mDataNetwork.setText(ServiceState.rilRadioTechnologyToString(
1214                     mPhone.getServiceState().getRilDataRadioTechnology()));
1215             mVoiceNetwork.setText(ServiceState.rilRadioTechnologyToString(
1216                     mPhone.getServiceState().getRilVoiceRadioTechnology()));
1217             int overrideNetwork = mPhone.getDisplayInfoController().getTelephonyDisplayInfo()
1218                     .getOverrideNetworkType();
1219             mOverrideNetwork.setText(
1220                     TelephonyDisplayInfo.overrideNetworkTypeToString(overrideNetwork));
1221         }
1222     }
1223 
getRawRegistrationStateText(ServiceState ss, int domain, int transportType)1224     private String getRawRegistrationStateText(ServiceState ss, int domain, int transportType) {
1225         if (ss != null) {
1226             NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(domain, transportType);
1227             if (nri != null) {
1228                 return NetworkRegistrationInfo.registrationStateToString(
1229                         nri.getNetworkRegistrationState())
1230                         + (nri.isEmergencyEnabled() ? "_EM" : "");
1231             }
1232         }
1233         return "";
1234     }
1235 
updateRawRegistrationState(ServiceState serviceState)1236     private void updateRawRegistrationState(ServiceState serviceState) {
1237         ServiceState ss = serviceState;
1238         if (ss == null && mPhone != null) {
1239             ss = mPhone.getServiceState();
1240         }
1241 
1242         mVoiceRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_CS,
1243                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
1244         mDataRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_PS,
1245                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
1246         mWlanDataRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_PS,
1247                     AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
1248     }
1249 
updateNrStats()1250     private void updateNrStats() {
1251         if ((mTelephonyManager.getSupportedRadioAccessFamily()
1252                 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
1253             return;
1254         }
1255         ServiceState ss = (mPhone == null) ? null : mPhone.getServiceState();
1256         if (ss != null) {
1257             NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
1258                     NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1259             if (nri != null) {
1260                 DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
1261                 if (dsri != null) {
1262                     mEndcAvailable.setText(String.valueOf(dsri.isEnDcAvailable));
1263                     mDcnrRestricted.setText(String.valueOf(dsri.isDcNrRestricted));
1264                     mNrAvailable.setText(String.valueOf(dsri.isNrAvailable));
1265                 }
1266             }
1267             mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
1268             mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
1269         } else {
1270             Log.e(TAG, "Clear Nr stats by null service state");
1271             mEndcAvailable.setText("");
1272             mDcnrRestricted.setText("");
1273             mNrAvailable.setText("");
1274             mNrState.setText("");
1275             mNrFrequency.setText("");
1276         }
1277 
1278         CompletableFuture<NetworkSlicingConfig> resultFuture = new CompletableFuture<>();
1279         mTelephonyManager.getNetworkSlicingConfiguration(Runnable::run, resultFuture::complete);
1280         try {
1281             NetworkSlicingConfig networkSlicingConfig =
1282                     resultFuture.get(DEFAULT_TIMEOUT_MS, MILLISECONDS);
1283             mNetworkSlicingConfig.setText(networkSlicingConfig.toString());
1284         } catch (ExecutionException | InterruptedException | TimeoutException e) {
1285             Log.e(TAG, "Unable to get slicing config: " + e.toString());
1286             mNetworkSlicingConfig.setText("Unable to get slicing config.");
1287         }
1288 
1289     }
1290 
updateProperties()1291     private void updateProperties() {
1292         String s;
1293         Resources r = getResources();
1294 
1295         s = mPhone.getDeviceId();
1296         if (s == null) {
1297             s = r.getString(R.string.radioInfo_unknown);
1298         }  else if (mPhone.getImeiType() == ImeiInfo.ImeiType.PRIMARY) {
1299             s = s + " (" + r.getString(R.string.radioInfo_imei_primary) + ")";
1300         }
1301         mDeviceId.setText(s);
1302 
1303         s = mPhone.getSubscriberId();
1304         if (s == null) s = r.getString(R.string.radioInfo_unknown);
1305 
1306         mSubscriberId.setText(s);
1307 
1308         SubscriptionManager subMgr = getSystemService(SubscriptionManager.class);
1309         int subId = mPhone.getSubId();
1310         s = subMgr.getPhoneNumber(subId)
1311                 + " { CARRIER:"
1312                 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER)
1313                 + ", UICC:"
1314                 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_UICC)
1315                 + ", IMS:"
1316                 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_IMS)
1317                 + " }";
1318         mLine1Number.setText(s);
1319     }
1320 
updateDataStats2()1321     private void updateDataStats2() {
1322         Resources r = getResources();
1323 
1324         long txPackets = TrafficStats.getMobileTxPackets();
1325         long rxPackets = TrafficStats.getMobileRxPackets();
1326         long txBytes   = TrafficStats.getMobileTxBytes();
1327         long rxBytes   = TrafficStats.getMobileRxBytes();
1328 
1329         String packets = r.getString(R.string.radioInfo_display_packets);
1330         String bytes   = r.getString(R.string.radioInfo_display_bytes);
1331 
1332         mSent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes);
1333         mReceived.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes);
1334     }
1335 
1336     /**
1337      *  Ping a host name
1338      */
pingHostname()1339     private void pingHostname() {
1340         try {
1341             try {
1342                 Process p4 = Runtime.getRuntime().exec("ping -c 1 www.google.com");
1343                 int status4 = p4.waitFor();
1344                 if (status4 == 0) {
1345                     mPingHostnameResultV4 = "Pass";
1346                 } else {
1347                     mPingHostnameResultV4 = String.format("Fail(%d)", status4);
1348                 }
1349             } catch (IOException e) {
1350                 mPingHostnameResultV4 = "Fail: IOException";
1351             }
1352             try {
1353                 Process p6 = Runtime.getRuntime().exec("ping6 -c 1 www.google.com");
1354                 int status6 = p6.waitFor();
1355                 if (status6 == 0) {
1356                     mPingHostnameResultV6 = "Pass";
1357                 } else {
1358                     mPingHostnameResultV6 = String.format("Fail(%d)", status6);
1359                 }
1360             } catch (IOException e) {
1361                 mPingHostnameResultV6 = "Fail: IOException";
1362             }
1363         } catch (InterruptedException e) {
1364             mPingHostnameResultV4 = mPingHostnameResultV6 = "Fail: InterruptedException";
1365         }
1366     }
1367 
1368     /**
1369      * This function checks for basic functionality of HTTP Client.
1370      */
httpClientTest()1371     private void httpClientTest() {
1372         HttpURLConnection urlConnection = null;
1373         try {
1374             // TODO: Hardcoded for now, make it UI configurable
1375             URL url = new URL("https://www.google.com");
1376             urlConnection = (HttpURLConnection) url.openConnection();
1377             if (urlConnection.getResponseCode() == 200) {
1378                 mHttpClientTestResult = "Pass";
1379             } else {
1380                 mHttpClientTestResult = "Fail: Code: " + urlConnection.getResponseMessage();
1381             }
1382         } catch (IOException e) {
1383             mHttpClientTestResult = "Fail: IOException";
1384         } finally {
1385             if (urlConnection != null) {
1386                 urlConnection.disconnect();
1387             }
1388         }
1389     }
1390 
refreshSmsc()1391     private void refreshSmsc() {
1392         mQueuedWork.execute(new Runnable() {
1393             public void run() {
1394                 //FIXME: Replace with a TelephonyManager call
1395                 mPhone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
1396             }
1397         });
1398     }
1399 
updateAllCellInfo()1400     private void updateAllCellInfo() {
1401 
1402         mCellInfo.setText("");
1403 
1404         final Runnable updateAllCellInfoResults = new Runnable() {
1405             public void run() {
1406                 updateCellInfo(mCellInfoResult);
1407             }
1408         };
1409 
1410         mQueuedWork.execute(new Runnable() {
1411             @Override
1412             public void run() {
1413                 mCellInfoResult = mTelephonyManager.getAllCellInfo();
1414 
1415                 mHandler.post(updateAllCellInfoResults);
1416             }
1417         });
1418     }
1419 
updatePingState()1420     private void updatePingState() {
1421         // Set all to unknown since the threads will take a few secs to update.
1422         mPingHostnameResultV4 = getResources().getString(R.string.radioInfo_unknown);
1423         mPingHostnameResultV6 = getResources().getString(R.string.radioInfo_unknown);
1424         mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown);
1425 
1426         mPingHostnameV4.setText(mPingHostnameResultV4);
1427         mPingHostnameV6.setText(mPingHostnameResultV6);
1428         mHttpClientTest.setText(mHttpClientTestResult);
1429 
1430         final Runnable updatePingResults = new Runnable() {
1431             public void run() {
1432                 mPingHostnameV4.setText(mPingHostnameResultV4);
1433                 mPingHostnameV6.setText(mPingHostnameResultV6);
1434                 mHttpClientTest.setText(mHttpClientTestResult);
1435             }
1436         };
1437 
1438         Thread hostname = new Thread() {
1439             @Override
1440             public void run() {
1441                 pingHostname();
1442                 mHandler.post(updatePingResults);
1443             }
1444         };
1445         hostname.start();
1446 
1447         Thread httpClient = new Thread() {
1448             @Override
1449             public void run() {
1450                 httpClientTest();
1451                 mHandler.post(updatePingResults);
1452             }
1453         };
1454         httpClient.start();
1455     }
1456 
1457     private MenuItem.OnMenuItemClickListener mViewADNCallback =
1458             new MenuItem.OnMenuItemClickListener() {
1459         public boolean onMenuItemClick(MenuItem item) {
1460             Intent intent = new Intent(Intent.ACTION_VIEW);
1461             // XXX We need to specify the component here because if we don't
1462             // the activity manager will try to resolve the type by calling
1463             // the content provider, which causes it to be loaded in a process
1464             // other than the Dialer process, which causes a lot of stuff to
1465             // break.
1466             intent.setClassName("com.android.phone", "com.android.phone.SimContacts");
1467             startActivity(intent);
1468             return true;
1469         }
1470     };
1471 
1472     private MenuItem.OnMenuItemClickListener mViewFDNCallback =
1473             new MenuItem.OnMenuItemClickListener() {
1474         public boolean onMenuItemClick(MenuItem item) {
1475             Intent intent = new Intent(Intent.ACTION_VIEW);
1476             // XXX We need to specify the component here because if we don't
1477             // the activity manager will try to resolve the type by calling
1478             // the content provider, which causes it to be loaded in a process
1479             // other than the Dialer process, which causes a lot of stuff to
1480             // break.
1481             intent.setClassName("com.android.phone", "com.android.phone.settings.fdn.FdnList");
1482             startActivity(intent);
1483             return true;
1484         }
1485     };
1486 
1487     private MenuItem.OnMenuItemClickListener mViewSDNCallback =
1488             new MenuItem.OnMenuItemClickListener() {
1489         public boolean onMenuItemClick(MenuItem item) {
1490             Intent intent = new Intent(
1491                     Intent.ACTION_VIEW, Uri.parse("content://icc/sdn"));
1492             // XXX We need to specify the component here because if we don't
1493             // the activity manager will try to resolve the type by calling
1494             // the content provider, which causes it to be loaded in a process
1495             // other than the Dialer process, which causes a lot of stuff to
1496             // break.
1497             intent.setClassName("com.android.phone", "com.android.phone.ADNList");
1498             startActivity(intent);
1499             return true;
1500         }
1501     };
1502 
1503     private MenuItem.OnMenuItemClickListener mGetImsStatus =
1504             new MenuItem.OnMenuItemClickListener() {
1505         public boolean onMenuItemClick(MenuItem item) {
1506             boolean isImsRegistered = mPhone.isImsRegistered();
1507             boolean availableVolte = mPhone.isVoiceOverCellularImsEnabled();
1508             boolean availableWfc = mPhone.isWifiCallingEnabled();
1509             boolean availableVt = mPhone.isVideoEnabled();
1510             boolean availableUt = mPhone.isUtEnabled();
1511 
1512             final String imsRegString = isImsRegistered
1513                     ? getString(R.string.radio_info_ims_reg_status_registered)
1514                     : getString(R.string.radio_info_ims_reg_status_not_registered);
1515 
1516             final String available = getString(R.string.radio_info_ims_feature_status_available);
1517             final String unavailable = getString(
1518                     R.string.radio_info_ims_feature_status_unavailable);
1519 
1520             String imsStatus = getString(R.string.radio_info_ims_reg_status,
1521                     imsRegString,
1522                     availableVolte ? available : unavailable,
1523                     availableWfc ? available : unavailable,
1524                     availableVt ? available : unavailable,
1525                     availableUt ? available : unavailable);
1526 
1527             AlertDialog imsDialog = new AlertDialog.Builder(RadioInfo.this)
1528                     .setMessage(imsStatus)
1529                     .setTitle(getString(R.string.radio_info_ims_reg_status_title))
1530                     .create();
1531 
1532             imsDialog.show();
1533 
1534             return true;
1535         }
1536     };
1537 
1538     private MenuItem.OnMenuItemClickListener mToggleData =
1539             new MenuItem.OnMenuItemClickListener() {
1540         public boolean onMenuItemClick(MenuItem item) {
1541             int state = mTelephonyManager.getDataState();
1542             switch (state) {
1543                 case TelephonyManager.DATA_CONNECTED:
1544                     mTelephonyManager.setDataEnabled(false);
1545                     break;
1546                 case TelephonyManager.DATA_DISCONNECTED:
1547                     mTelephonyManager.setDataEnabled(true);
1548                     break;
1549                 default:
1550                     // do nothing
1551                     break;
1552             }
1553             return true;
1554         }
1555     };
1556 
isRadioOn()1557     private boolean isRadioOn() {
1558         //FIXME: Replace with a TelephonyManager call
1559         return mPhone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
1560     }
1561 
updateRadioPowerState()1562     private void updateRadioPowerState() {
1563         //delightful hack to prevent on-checked-changed calls from
1564         //actually forcing the radio preference to its transient/current value.
1565         mRadioPowerOnSwitch.setOnCheckedChangeListener(null);
1566         mRadioPowerOnSwitch.setChecked(isRadioOn());
1567         mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
1568     }
1569 
setImsVolteProvisionedState(boolean state)1570     private void setImsVolteProvisionedState(boolean state) {
1571         Log.d(TAG, "setImsVolteProvisioned state: " + ((state) ? "on" : "off"));
1572         setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1573                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state);
1574     }
1575 
setImsVtProvisionedState(boolean state)1576     private void setImsVtProvisionedState(boolean state) {
1577         Log.d(TAG, "setImsVtProvisioned() state: " + ((state) ? "on" : "off"));
1578         setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
1579                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state);
1580     }
1581 
setImsWfcProvisionedState(boolean state)1582     private void setImsWfcProvisionedState(boolean state) {
1583         Log.d(TAG, "setImsWfcProvisioned() state: " + ((state) ? "on" : "off"));
1584         setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1585                 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, state);
1586     }
1587 
setEabProvisionedState(boolean state)1588     private void setEabProvisionedState(boolean state) {
1589         Log.d(TAG, "setEabProvisioned() state: " + ((state) ? "on" : "off"));
1590         setRcsConfigProvisionedState(ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
1591                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state);
1592     }
1593 
setImsConfigProvisionedState(int capability, int tech, boolean state)1594     private void setImsConfigProvisionedState(int capability, int tech, boolean state) {
1595         if (mProvisioningManager != null) {
1596             mQueuedWork.execute(new Runnable() {
1597                 public void run() {
1598                     try {
1599                         mProvisioningManager.setProvisioningStatusForCapability(
1600                                 capability, tech, state);
1601                     } catch (RuntimeException e) {
1602                         Log.e(TAG, "setImsConfigProvisioned() exception:", e);
1603                     }
1604                 }
1605             });
1606         }
1607     }
1608 
setRcsConfigProvisionedState(int capability, int tech, boolean state)1609     private void setRcsConfigProvisionedState(int capability, int tech, boolean state) {
1610         if (mProvisioningManager != null) {
1611             mQueuedWork.execute(new Runnable() {
1612                 public void run() {
1613                     try {
1614                         mProvisioningManager.setRcsProvisioningStatusForCapability(
1615                                 capability, tech, state);
1616                     } catch (RuntimeException e) {
1617                         Log.e(TAG, "setRcsConfigProvisioned() exception:", e);
1618                     }
1619                 }
1620             });
1621         }
1622     }
1623 
isImsVolteProvisioningRequired()1624     private boolean isImsVolteProvisioningRequired() {
1625         return isImsConfigProvisioningRequired(
1626                 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1627                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1628     }
1629 
isImsVtProvisioningRequired()1630     private boolean isImsVtProvisioningRequired() {
1631         return isImsConfigProvisioningRequired(
1632                 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
1633                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1634     }
1635 
isImsWfcProvisioningRequired()1636     private boolean isImsWfcProvisioningRequired() {
1637         return isImsConfigProvisioningRequired(
1638                 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1639                 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
1640     }
1641 
isEabProvisioningRequired()1642     private boolean isEabProvisioningRequired() {
1643         return isRcsConfigProvisioningRequired(
1644                 ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
1645                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1646     }
1647 
isImsConfigProvisioningRequired(int capability, int tech)1648     private boolean isImsConfigProvisioningRequired(int capability, int tech) {
1649         if (mProvisioningManager != null) {
1650             try {
1651                 return mProvisioningManager.isProvisioningRequiredForCapability(
1652                         capability, tech);
1653             } catch (RuntimeException e) {
1654                 Log.e(TAG, "isImsConfigProvisioningRequired() exception:", e);
1655             }
1656         }
1657 
1658         return false;
1659     }
1660 
isRcsConfigProvisioningRequired(int capability, int tech)1661     private boolean isRcsConfigProvisioningRequired(int capability, int tech) {
1662         if (mProvisioningManager != null) {
1663             try {
1664                 return mProvisioningManager.isRcsProvisioningRequiredForCapability(
1665                         capability, tech);
1666             } catch (RuntimeException e) {
1667                 Log.e(TAG, "isRcsConfigProvisioningRequired() exception:", e);
1668             }
1669         }
1670 
1671         return false;
1672     }
1673 
1674     OnCheckedChangeListener mRadioPowerOnChangeListener = new OnCheckedChangeListener() {
1675         @Override
1676         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1677             // TODO: b/145681511. Within current design, radio power on all of the phones need
1678             // to be controlled at the same time.
1679             Phone[] phones = PhoneFactory.getPhones();
1680             if (phones == null) {
1681                 return;
1682             }
1683             log("toggle radio power: phone*" + phones.length + " " + (isRadioOn() ? "on" : "off"));
1684             for (int phoneIndex = 0; phoneIndex < phones.length; phoneIndex++) {
1685                 if (phones[phoneIndex] != null) {
1686                     phones[phoneIndex].setRadioPower(isChecked);
1687                 }
1688             }
1689         }
1690     };
1691 
1692     private final OnCheckedChangeListener mSimulateOosOnChangeListener =
1693             (buttonView, isChecked) -> {
1694         Intent intent = new Intent("com.android.internal.telephony.TestServiceState");
1695         if (isChecked) {
1696             log("Send OOS override broadcast intent.");
1697             intent.putExtra("data_reg_state", 1);
1698             mSimulateOos[mPhone.getPhoneId()] = true;
1699         } else {
1700             log("Remove OOS override.");
1701             intent.putExtra("action", "reset");
1702             mSimulateOos[mPhone.getPhoneId()] = false;
1703         }
1704 
1705         mPhone.getTelephonyTester().setServiceStateTestIntent(intent);
1706     };
1707 
isImsVolteProvisioned()1708     private boolean isImsVolteProvisioned() {
1709         return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1710                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1711     }
1712 
1713     OnCheckedChangeListener mImsVolteCheckedChangeListener = new OnCheckedChangeListener() {
1714         @Override
1715         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1716             setImsVolteProvisionedState(isChecked);
1717         }
1718     };
1719 
isImsVtProvisioned()1720     private boolean isImsVtProvisioned() {
1721         return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
1722                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1723     }
1724 
1725     OnCheckedChangeListener mImsVtCheckedChangeListener = new OnCheckedChangeListener() {
1726         @Override
1727         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1728             setImsVtProvisionedState(isChecked);
1729         }
1730     };
1731 
isImsWfcProvisioned()1732     private boolean isImsWfcProvisioned() {
1733         return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
1734                 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
1735     }
1736 
1737     OnCheckedChangeListener mImsWfcCheckedChangeListener = new OnCheckedChangeListener() {
1738         @Override
1739         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1740             setImsWfcProvisionedState(isChecked);
1741         }
1742     };
1743 
isEabProvisioned()1744     private boolean isEabProvisioned() {
1745         return getRcsConfigProvisionedState(ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE,
1746                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
1747     }
1748 
1749     OnCheckedChangeListener mEabCheckedChangeListener = new OnCheckedChangeListener() {
1750         @Override
1751         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1752             setEabProvisionedState(isChecked);
1753         }
1754     };
1755 
getImsConfigProvisionedState(int capability, int tech)1756     private boolean getImsConfigProvisionedState(int capability, int tech) {
1757         if (mProvisioningManager != null) {
1758             try {
1759                 return mProvisioningManager.getProvisioningStatusForCapability(
1760                         capability, tech);
1761             } catch (RuntimeException e) {
1762                 Log.e(TAG, "getImsConfigProvisionedState() exception:", e);
1763             }
1764         }
1765 
1766         return false;
1767     }
1768 
getRcsConfigProvisionedState(int capability, int tech)1769     private boolean getRcsConfigProvisionedState(int capability, int tech) {
1770         if (mProvisioningManager != null) {
1771             try {
1772                 return mProvisioningManager.getRcsProvisioningStatusForCapability(
1773                         capability, tech);
1774             } catch (RuntimeException e) {
1775                 Log.e(TAG, "getRcsConfigProvisionedState() exception:", e);
1776             }
1777         }
1778 
1779         return false;
1780     }
1781 
isEabEnabledByPlatform()1782     private boolean isEabEnabledByPlatform() {
1783         if (mPhone != null) {
1784             CarrierConfigManager configManager = (CarrierConfigManager)
1785                     mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
1786             PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
1787             if (b != null) {
1788                 return b.getBoolean(
1789                         CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false) || b.getBoolean(
1790                         CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL,
1791                         false);
1792             }
1793         }
1794         return false;
1795     }
1796 
updateImsProvisionedState()1797     private void updateImsProvisionedState() {
1798         if (!isImsSupportedOnDevice(mPhone.getContext())) {
1799             return;
1800         }
1801 
1802         updateServiceEnabledByPlatform();
1803 
1804         updateEabProvisionedSwitch(isEabEnabledByPlatform());
1805     }
1806 
updateVolteProvisionedSwitch(boolean isEnabledByPlatform)1807     private void updateVolteProvisionedSwitch(boolean isEnabledByPlatform) {
1808         boolean isProvisioned = isEnabledByPlatform && isImsVolteProvisioned();
1809         log("updateVolteProvisionedSwitch isProvisioned" + isProvisioned);
1810 
1811         mImsVolteProvisionedSwitch.setOnCheckedChangeListener(null);
1812         mImsVolteProvisionedSwitch.setChecked(isProvisioned);
1813         mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
1814         mImsVolteProvisionedSwitch.setEnabled(!IS_USER_BUILD
1815                 && isEnabledByPlatform && isImsVolteProvisioningRequired());
1816     }
1817 
updateVtProvisionedSwitch(boolean isEnabledByPlatform)1818     private void updateVtProvisionedSwitch(boolean isEnabledByPlatform) {
1819         boolean isProvisioned = isEnabledByPlatform && isImsVtProvisioned();
1820         log("updateVtProvisionedSwitch isProvisioned" + isProvisioned);
1821 
1822         mImsVtProvisionedSwitch.setOnCheckedChangeListener(null);
1823         mImsVtProvisionedSwitch.setChecked(isProvisioned);
1824         mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
1825         mImsVtProvisionedSwitch.setEnabled(!IS_USER_BUILD
1826                 && isEnabledByPlatform && isImsVtProvisioningRequired());
1827     }
1828 
updateWfcProvisionedSwitch(boolean isEnabledByPlatform)1829     private void updateWfcProvisionedSwitch(boolean isEnabledByPlatform) {
1830         boolean isProvisioned = isEnabledByPlatform && isImsWfcProvisioned();
1831         log("updateWfcProvisionedSwitch isProvisioned" + isProvisioned);
1832 
1833         mImsWfcProvisionedSwitch.setOnCheckedChangeListener(null);
1834         mImsWfcProvisionedSwitch.setChecked(isProvisioned);
1835         mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
1836         mImsWfcProvisionedSwitch.setEnabled(!IS_USER_BUILD
1837                 && isEnabledByPlatform && isImsWfcProvisioningRequired());
1838     }
1839 
updateEabProvisionedSwitch(boolean isEnabledByPlatform)1840     private void updateEabProvisionedSwitch(boolean isEnabledByPlatform) {
1841         log("updateEabProvisionedSwitch isEabWfcProvisioned()=" + isEabProvisioned());
1842 
1843         mEabProvisionedSwitch.setOnCheckedChangeListener(null);
1844         mEabProvisionedSwitch.setChecked(isEabProvisioned());
1845         mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
1846         mEabProvisionedSwitch.setEnabled(!IS_USER_BUILD
1847                 && isEnabledByPlatform && isEabProvisioningRequired());
1848     }
1849 
1850     OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
1851         public void onClick(View v) {
1852             //FIXME: Replace with a TelephonyManager call
1853             mPhone.disableDnsCheck(!mPhone.isDnsCheckDisabled());
1854             updateDnsCheckState();
1855         }
1856     };
1857 
1858     OnClickListener mOemInfoButtonHandler = new OnClickListener() {
1859         public void onClick(View v) {
1860             Intent intent = new Intent(OEM_RADIO_INFO_INTENT);
1861             try {
1862                 startActivity(intent);
1863             } catch (android.content.ActivityNotFoundException ex) {
1864                 log("OEM-specific Info/Settings Activity Not Found : " + ex);
1865                 // If the activity does not exist, there are no OEM
1866                 // settings, and so we can just do nothing...
1867             }
1868         }
1869     };
1870 
1871     OnClickListener mPingButtonHandler = new OnClickListener() {
1872         public void onClick(View v) {
1873             updatePingState();
1874         }
1875     };
1876 
1877     OnClickListener mUpdateSmscButtonHandler = new OnClickListener() {
1878         public void onClick(View v) {
1879             mUpdateSmscButton.setEnabled(false);
1880             mQueuedWork.execute(new Runnable() {
1881                 public void run() {
1882                     mPhone.setSmscAddress(mSmsc.getText().toString(),
1883                             mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE));
1884                 }
1885             });
1886         }
1887     };
1888 
1889     OnClickListener mRefreshSmscButtonHandler = new OnClickListener() {
1890         public void onClick(View v) {
1891             refreshSmsc();
1892         }
1893     };
1894 
1895     OnClickListener mCarrierProvisioningButtonHandler = v -> {
1896         String carrierProvisioningApp = getCarrierProvisioningAppString();
1897         if (!TextUtils.isEmpty(carrierProvisioningApp)) {
1898             final Intent intent = new Intent(CARRIER_PROVISIONING_ACTION);
1899             final ComponentName serviceComponent =
1900                     ComponentName.unflattenFromString(carrierProvisioningApp);
1901             intent.setComponent(serviceComponent);
1902             sendBroadcast(intent);
1903         }
1904     };
1905 
1906     OnClickListener mTriggerCarrierProvisioningButtonHandler = v -> {
1907         String carrierProvisioningApp = getCarrierProvisioningAppString();
1908         if (!TextUtils.isEmpty(carrierProvisioningApp)) {
1909             final Intent intent = new Intent(TRIGGER_CARRIER_PROVISIONING_ACTION);
1910             final ComponentName serviceComponent =
1911                     ComponentName.unflattenFromString(carrierProvisioningApp);
1912             intent.setComponent(serviceComponent);
1913             sendBroadcast(intent);
1914         }
1915     };
1916 
1917     AdapterView.OnItemSelectedListener mPreferredNetworkHandler =
1918             new AdapterView.OnItemSelectedListener() {
1919 
1920         public void onItemSelected(AdapterView parent, View v, int pos, long id) {
1921             if (mPreferredNetworkTypeResult != pos && pos >= 0
1922                     && pos <= PREFERRED_NETWORK_LABELS.length - 2) {
1923                 mPreferredNetworkTypeResult = pos;
1924                 new Thread(() -> {
1925                     mTelephonyManager.setAllowedNetworkTypesForReason(
1926                             TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
1927                             RadioAccessFamily.getRafFromNetworkType(mPreferredNetworkTypeResult));
1928                 }).start();
1929             }
1930         }
1931 
1932         public void onNothingSelected(AdapterView parent) {
1933         }
1934     };
1935 
1936     AdapterView.OnItemSelectedListener mSelectPhoneIndexHandler =
1937             new AdapterView.OnItemSelectedListener() {
1938 
1939         public void onItemSelected(AdapterView parent, View v, int pos, long id) {
1940             if (pos >= 0 && pos <= sPhoneIndexLabels.length - 1) {
1941                 // the array position is equal to the phone index
1942                 int phoneIndex = pos;
1943                 Phone[] phones = PhoneFactory.getPhones();
1944                 if (phones == null || phones.length <= phoneIndex) {
1945                     return;
1946                 }
1947                 // getSubId says it takes a slotIndex, but it actually takes a phone index
1948                 mSelectedPhoneIndex = phoneIndex;
1949                 updatePhoneIndex(phoneIndex, SubscriptionManager.getSubscriptionId(phoneIndex));
1950             }
1951         }
1952 
1953         public void onNothingSelected(AdapterView parent) {
1954         }
1955     };
1956 
1957     AdapterView.OnItemSelectedListener mCellInfoRefreshRateHandler  =
1958             new AdapterView.OnItemSelectedListener() {
1959 
1960         public void onItemSelected(AdapterView parent, View v, int pos, long id) {
1961             mCellInfoRefreshRateIndex = pos;
1962             mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[pos], mPhone.getSubId());
1963             updateAllCellInfo();
1964         }
1965 
1966         public void onNothingSelected(AdapterView parent) {
1967         }
1968     };
1969 
getCarrierProvisioningAppString()1970     private String getCarrierProvisioningAppString() {
1971         if (mPhone != null) {
1972             CarrierConfigManager configManager =
1973                     mPhone.getContext().getSystemService(CarrierConfigManager.class);
1974             PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
1975             if (b != null) {
1976                 return b.getString(
1977                         CarrierConfigManager.KEY_CARRIER_PROVISIONING_APP_STRING, "");
1978             }
1979         }
1980         return "";
1981     }
1982 
isCbrsSupported()1983     boolean isCbrsSupported() {
1984         return getResources().getBoolean(
1985               com.android.internal.R.bool.config_cbrs_supported);
1986     }
1987 
updateCbrsDataState(boolean state)1988     void updateCbrsDataState(boolean state) {
1989         Log.d(TAG, "setCbrsDataSwitchState() state:" + ((state) ? "on" : "off"));
1990         if (mTelephonyManager != null) {
1991             mQueuedWork.execute(new Runnable() {
1992                 public void run() {
1993                     mTelephonyManager.setOpportunisticNetworkState(state);
1994                     mHandler.post(() -> mCbrsDataSwitch.setChecked(getCbrsDataState()));
1995                 }
1996             });
1997         }
1998     }
1999 
getCbrsDataState()2000     boolean getCbrsDataState() {
2001         boolean state = false;
2002         if (mTelephonyManager != null) {
2003             state = mTelephonyManager.isOpportunisticNetworkEnabled();
2004         }
2005         Log.d(TAG, "getCbrsDataState() state:" + ((state) ? "on" : "off"));
2006         return state;
2007     }
2008 
2009     OnCheckedChangeListener mCbrsDataSwitchChangeListener = new OnCheckedChangeListener() {
2010         @Override
2011         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2012             updateCbrsDataState(isChecked);
2013         }
2014     };
2015 
showDsdsChangeDialog()2016     private void showDsdsChangeDialog() {
2017         final AlertDialog confirmDialog = new Builder(RadioInfo.this)
2018                 .setTitle(R.string.dsds_dialog_title)
2019                 .setMessage(R.string.dsds_dialog_message)
2020                 .setPositiveButton(R.string.dsds_dialog_confirm, mOnDsdsDialogConfirmedListener)
2021                 .setNegativeButton(R.string.dsds_dialog_cancel, mOnDsdsDialogConfirmedListener)
2022                 .create();
2023         confirmDialog.show();
2024     }
2025 
isDsdsSupported()2026     private static boolean isDsdsSupported() {
2027         return (TelephonyManager.getDefault().isMultiSimSupported()
2028             == TelephonyManager.MULTISIM_ALLOWED);
2029     }
2030 
isDsdsEnabled()2031     private static boolean isDsdsEnabled() {
2032         return TelephonyManager.getDefault().getPhoneCount() > 1;
2033     }
2034 
performDsdsSwitch()2035     private void performDsdsSwitch() {
2036         mTelephonyManager.switchMultiSimConfig(mDsdsSwitch.isChecked() ? 2 : 1);
2037     }
2038 
2039     /**
2040      * @return {@code True} if the device is only supported dsds mode.
2041      */
dsdsModeOnly()2042     private boolean dsdsModeOnly() {
2043         String dsdsMode = SystemProperties.get(DSDS_MODE_PROPERTY);
2044         return !TextUtils.isEmpty(dsdsMode) && Integer.parseInt(dsdsMode) == ALWAYS_ON_DSDS_MODE;
2045     }
2046 
2047     DialogInterface.OnClickListener mOnDsdsDialogConfirmedListener =
2048             new DialogInterface.OnClickListener() {
2049         @Override
2050         public void onClick(DialogInterface dialog, int which) {
2051             if (which == DialogInterface.BUTTON_POSITIVE) {
2052                 mDsdsSwitch.toggle();
2053                 performDsdsSwitch();
2054             }
2055         }
2056     };
2057 
2058     OnCheckedChangeListener mRemovableEsimChangeListener = new OnCheckedChangeListener() {
2059         @Override
2060         public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
2061             setRemovableEsimAsDefaultEuicc(isChecked);
2062         }
2063     };
2064 
setRemovableEsimAsDefaultEuicc(boolean isChecked)2065     private void setRemovableEsimAsDefaultEuicc(boolean isChecked) {
2066         Log.d(TAG, "setRemovableEsimAsDefaultEuicc isChecked: " + isChecked);
2067         mTelephonyManager.setRemovableEsimAsDefaultEuicc(isChecked);
2068         // TODO(b/232528117): Instead of sending intent, add new APIs in platform,
2069         //  LPA can directly use the API.
2070         ComponentInfo componentInfo = EuiccConnector.findBestComponent(getPackageManager());
2071         if (componentInfo == null) {
2072             Log.d(TAG, "setRemovableEsimAsDefaultEuicc: unable to find suitable component info");
2073             return;
2074         }
2075         final Intent intent = new Intent(ACTION_REMOVABLE_ESIM_AS_DEFAULT);
2076         intent.setPackage(componentInfo.packageName);
2077         intent.putExtra("isDefault", isChecked);
2078         sendBroadcast(intent);
2079     }
2080 
isImsSupportedOnDevice(Context context)2081     private boolean isImsSupportedOnDevice(Context context) {
2082         return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS);
2083     }
2084 
updateServiceEnabledByPlatform()2085     private void updateServiceEnabledByPlatform() {
2086         int subId = mPhone.getSubId();
2087         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2088             log("updateServiceEnabledByPlatform subscription ID is invalid");
2089             return;
2090         }
2091 
2092         ImsMmTelManager imsMmTelManager = mImsManager.getImsMmTelManager(subId);
2093         try {
2094             imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
2095                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getMainExecutor(), (result) -> {
2096                         updateVolteProvisionedSwitch(result);
2097                     });
2098             imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
2099                     AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getMainExecutor(), (result) -> {
2100                         updateVtProvisionedSwitch(result);
2101                     });
2102             imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
2103                     AccessNetworkConstants.TRANSPORT_TYPE_WLAN, getMainExecutor(), (result) -> {
2104                         updateWfcProvisionedSwitch(result);
2105                     });
2106         } catch (ImsException e) {
2107             e.printStackTrace();
2108         }
2109     }
2110 
getPhone(int subId)2111     private Phone getPhone(int subId) {
2112         log("getPhone subId = " + subId);
2113         Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
2114         if (phone == null) {
2115             log("return the default phone");
2116             return PhoneFactory.getDefaultPhone();
2117         }
2118 
2119         return phone;
2120     }
2121 }
2122