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