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