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