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