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