1/*
2 * Copyright (C) 2006 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
17package com.android.settings;
18
19import android.app.Activity;
20import android.app.AlertDialog;
21import android.app.Dialog;
22import android.app.QueuedWork;
23import android.content.ComponentName;
24import android.content.Context;
25import android.content.Intent;
26import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
28import android.content.res.Resources;
29import android.graphics.Typeface;
30import android.net.TrafficStats;
31import android.net.Uri;
32import android.os.AsyncResult;
33import android.os.Bundle;
34import android.os.Handler;
35import android.os.Message;
36import android.telephony.CarrierConfigManager;
37import android.telephony.CellInfo;
38import android.telephony.CellInfoCdma;
39import android.telephony.CellInfoGsm;
40import android.telephony.CellInfoLte;
41import android.telephony.CellInfoWcdma;
42import android.telephony.CellIdentityCdma;
43import android.telephony.CellIdentityGsm;
44import android.telephony.CellIdentityLte;
45import android.telephony.CellIdentityWcdma;
46import android.telephony.CellLocation;
47import android.telephony.CellSignalStrengthCdma;
48import android.telephony.CellSignalStrengthGsm;
49import android.telephony.CellSignalStrengthLte;
50import android.telephony.CellSignalStrengthWcdma;
51import android.telephony.DataConnectionRealTimeInfo;
52import android.telephony.NeighboringCellInfo;
53import android.telephony.PreciseCallState;
54import android.telephony.PhoneStateListener;
55import android.telephony.ServiceState;
56import android.telephony.SignalStrength;
57import android.telephony.SubscriptionManager;
58import android.telephony.TelephonyManager;
59import android.telephony.cdma.CdmaCellLocation;
60import android.telephony.gsm.GsmCellLocation;
61import android.util.Log;
62import android.view.Menu;
63import android.view.MenuItem;
64import android.view.View;
65import android.view.View.OnClickListener;
66import android.widget.AdapterView;
67import android.widget.ArrayAdapter;
68import android.widget.Button;
69import android.widget.CompoundButton;
70import android.widget.CompoundButton.OnCheckedChangeListener;
71import android.widget.EditText;
72import android.widget.Spinner;
73import android.widget.Switch;
74import android.widget.TextView;
75
76import com.android.ims.ImsConfig;
77import com.android.ims.ImsException;
78import com.android.ims.ImsManager;
79import com.android.internal.telephony.Phone;
80import com.android.internal.telephony.PhoneConstants;
81import com.android.internal.telephony.PhoneFactory;
82import com.android.internal.telephony.RILConstants;
83import com.android.internal.telephony.TelephonyProperties;
84
85import java.io.IOException;
86import java.net.HttpURLConnection;
87import java.net.URL;
88import java.net.UnknownHostException;
89import java.util.ArrayList;
90import java.util.List;
91
92public class RadioInfo extends Activity {
93    private static final String TAG = "RadioInfo";
94
95    private static final String[] mPreferredNetworkLabels = {
96            "WCDMA preferred",
97            "GSM only",
98            "WCDMA only",
99            "GSM auto (PRL)",
100            "CDMA auto (PRL)",
101            "CDMA only",
102            "EvDo only",
103            "Global auto (PRL)",
104            "LTE/CDMA auto (PRL)",
105            "LTE/UMTS auto (PRL)",
106            "LTE/CDMA/UMTS auto (PRL)",
107            "LTE only",
108            "LTE/WCDMA",
109            "TD-SCDMA only",
110            "TD-SCDMA/WCDMA",
111            "LTE/TD-SCDMA",
112            "TD-SCDMA/GSM",
113            "TD-SCDMA/UMTS",
114            "LTE/TD-SCDMA/WCDMA",
115            "LTE/TD-SCDMA/UMTS",
116            "TD-SCDMA/CDMA/UMTS",
117            "Global/TD-SCDMA",
118            "Unknown"
119    };
120
121
122    private static final int CELL_INFO_LIST_RATE_DISABLED = Integer.MAX_VALUE;
123    private static final int CELL_INFO_LIST_RATE_MAX = 0;
124
125
126    private static final int IMS_VOLTE_PROVISIONED_CONFIG_ID =
127        ImsConfig.ConfigConstants.VLT_SETTING_ENABLED;
128
129    private static final int IMS_VT_PROVISIONED_CONFIG_ID =
130        ImsConfig.ConfigConstants.LVC_SETTING_ENABLED;
131
132    private static final int IMS_WFC_PROVISIONED_CONFIG_ID =
133        ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED;
134
135    private static final int EAB_PROVISIONED_CONFIG_ID =
136        ImsConfig.ConfigConstants.EAB_SETTING_ENABLED;
137
138    //Values in must match mCellInfoRefreshRates
139    private static final String[] mCellInfoRefreshRateLabels = {
140            "Disabled",
141            "Immediate",
142            "Min 5s",
143            "Min 10s",
144            "Min 60s"
145    };
146
147    //Values in seconds, must match mCellInfoRefreshRateLabels
148    private static final int mCellInfoRefreshRates[] = {
149        CELL_INFO_LIST_RATE_DISABLED,
150        CELL_INFO_LIST_RATE_MAX,
151        5000,
152        10000,
153        60000
154    };
155
156    private void log(String s) {
157        Log.d(TAG, s);
158    }
159
160    private static final int EVENT_CFI_CHANGED = 302;
161
162    private static final int EVENT_QUERY_PREFERRED_TYPE_DONE = 1000;
163    private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001;
164    private static final int EVENT_QUERY_SMSC_DONE = 1005;
165    private static final int EVENT_UPDATE_SMSC_DONE = 1006;
166
167    private static final int MENU_ITEM_SELECT_BAND  = 0;
168    private static final int MENU_ITEM_VIEW_ADN     = 1;
169    private static final int MENU_ITEM_VIEW_FDN     = 2;
170    private static final int MENU_ITEM_VIEW_SDN     = 3;
171    private static final int MENU_ITEM_GET_IMS_STATUS = 4;
172    private static final int MENU_ITEM_TOGGLE_DATA  = 5;
173
174    private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
175    private TextView number;
176    private TextView mSubscriberId;
177    private TextView callState;
178    private TextView operatorName;
179    private TextView roamingState;
180    private TextView gsmState;
181    private TextView gprsState;
182    private TextView voiceNetwork;
183    private TextView dataNetwork;
184    private TextView dBm;
185    private TextView mMwi;
186    private TextView mCfi;
187    private TextView mLocation;
188    private TextView mNeighboringCids;
189    private TextView mCellInfo;
190    private TextView mDcRtInfoTv;
191    private TextView sent;
192    private TextView received;
193    private TextView mPingHostnameV4;
194    private TextView mPingHostnameV6;
195    private TextView mHttpClientTest;
196    private TextView dnsCheckState;
197    private EditText smsc;
198    private Switch radioPowerOnSwitch;
199    private Button cellInfoRefreshRateButton;
200    private Button dnsCheckToggleButton;
201    private Button pingTestButton;
202    private Button updateSmscButton;
203    private Button refreshSmscButton;
204    private Button oemInfoButton;
205    private Button carrierProvisioningButton;
206    private Button triggercarrierProvisioningButton;
207    private Switch imsVolteProvisionedSwitch;
208    private Switch imsVtProvisionedSwitch;
209    private Switch imsWfcProvisionedSwitch;
210    private Switch eabProvisionedSwitch;
211    private Spinner preferredNetworkType;
212    private Spinner cellInfoRefreshRateSpinner;
213
214    private TelephonyManager mTelephonyManager;
215    private ImsManager mImsManager = null;
216    private Phone phone = null;
217
218    private String mPingHostnameResultV4;
219    private String mPingHostnameResultV6;
220    private String mHttpClientTestResult;
221    private boolean mMwiValue = false;
222    private boolean mCfiValue = false;
223
224    private List<CellInfo> mCellInfoResult = null;
225    private CellLocation mCellLocationResult = null;
226    private List<NeighboringCellInfo> mNeighboringCellResult = null;
227
228    private int mPreferredNetworkTypeResult;
229    private int mCellInfoRefreshRateIndex;
230
231    private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
232        @Override
233        public void onDataConnectionStateChanged(int state) {
234            updateDataState();
235            updateNetworkType();
236        }
237
238        @Override
239        public void onDataActivity(int direction) {
240            updateDataStats2();
241        }
242
243        @Override
244        public void onCallStateChanged(int state, String incomingNumber) {
245            updateNetworkType();
246            updatePhoneState(state);
247        }
248
249        @Override
250        public void onPreciseCallStateChanged(PreciseCallState preciseState) {
251            updateNetworkType();
252        }
253
254        @Override
255        public void onCellLocationChanged(CellLocation location) {
256            updateLocation(location);
257        }
258
259        @Override
260        public void onMessageWaitingIndicatorChanged(boolean mwi) {
261            mMwiValue = mwi;
262            updateMessageWaiting();
263        }
264
265        @Override
266        public void onCallForwardingIndicatorChanged(boolean cfi) {
267            mCfiValue = cfi;
268            updateCallRedirect();
269        }
270
271        @Override
272        public void onCellInfoChanged(List<CellInfo> arrayCi) {
273            log("onCellInfoChanged: arrayCi=" + arrayCi);
274            mCellInfoResult = arrayCi;
275            updateCellInfo(mCellInfoResult);
276        }
277
278        @Override
279        public void onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo dcRtInfo) {
280            log("onDataConnectionRealTimeInfoChanged: dcRtInfo=" + dcRtInfo);
281            updateDcRtInfoTv(dcRtInfo);
282        }
283
284        @Override
285        public void onSignalStrengthsChanged(SignalStrength signalStrength) {
286            log("onSignalStrengthChanged: SignalStrength=" +signalStrength);
287            updateSignalStrength(signalStrength);
288        }
289
290        @Override
291        public void onServiceStateChanged(ServiceState serviceState) {
292            log("onServiceStateChanged: ServiceState=" + serviceState);
293            updateServiceState(serviceState);
294            updateRadioPowerState();
295            updateNetworkType();
296            updateImsProvisionedState();
297        }
298    };
299
300    private void updatePreferredNetworkType(int type) {
301        if (type >= mPreferredNetworkLabels.length || type < 0) {
302            log("EVENT_QUERY_PREFERRED_TYPE_DONE: unknown " +
303                    "type=" + type);
304            type = mPreferredNetworkLabels.length - 1; //set to Unknown
305        }
306        mPreferredNetworkTypeResult = type;
307
308        preferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
309    }
310
311    private Handler mHandler = new Handler() {
312        @Override
313        public void handleMessage(Message msg) {
314            AsyncResult ar;
315            switch (msg.what) {
316                case EVENT_QUERY_PREFERRED_TYPE_DONE:
317                    ar= (AsyncResult) msg.obj;
318                    if (ar.exception == null && ar.result != null) {
319                        updatePreferredNetworkType(((int[])ar.result)[0]);
320                    } else {
321                        //In case of an exception, we will set this to unknown
322                        updatePreferredNetworkType(mPreferredNetworkLabels.length-1);
323                    }
324                    break;
325                case EVENT_SET_PREFERRED_TYPE_DONE:
326                    ar= (AsyncResult) msg.obj;
327                    if (ar.exception != null) {
328                        log("Set preferred network type failed.");
329                    }
330                    break;
331                case EVENT_QUERY_SMSC_DONE:
332                    ar= (AsyncResult) msg.obj;
333                    if (ar.exception != null) {
334                        smsc.setText("refresh error");
335                    } else {
336                        smsc.setText((String)ar.result);
337                    }
338                    break;
339                case EVENT_UPDATE_SMSC_DONE:
340                    updateSmscButton.setEnabled(true);
341                    ar= (AsyncResult) msg.obj;
342                    if (ar.exception != null) {
343                        smsc.setText("update error");
344                    }
345                    break;
346                default:
347                    super.handleMessage(msg);
348                    break;
349
350            }
351        }
352    };
353
354    @Override
355    public void onCreate(Bundle icicle) {
356        super.onCreate(icicle);
357        if (!android.os.Process.myUserHandle().isSystem()) {
358            Log.e(TAG, "Not run from system user, don't do anything.");
359            finish();
360            return;
361        }
362
363        setContentView(R.layout.radio_info);
364
365        log("Started onCreate");
366
367        mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
368        phone = PhoneFactory.getDefaultPhone();
369
370        //TODO: Need to update this if the default phoneId changes?
371        //      Better to have an instance per phone?
372        mImsManager = ImsManager.getInstance(getApplicationContext(),
373                SubscriptionManager.getDefaultVoicePhoneId());
374
375        mDeviceId = (TextView) findViewById(R.id.imei);
376        number = (TextView) findViewById(R.id.number);
377        mSubscriberId = (TextView) findViewById(R.id.imsi);
378        callState = (TextView) findViewById(R.id.call);
379        operatorName = (TextView) findViewById(R.id.operator);
380        roamingState = (TextView) findViewById(R.id.roaming);
381        gsmState = (TextView) findViewById(R.id.gsm);
382        gprsState = (TextView) findViewById(R.id.gprs);
383        voiceNetwork = (TextView) findViewById(R.id.voice_network);
384        dataNetwork = (TextView) findViewById(R.id.data_network);
385        dBm = (TextView) findViewById(R.id.dbm);
386        mMwi = (TextView) findViewById(R.id.mwi);
387        mCfi = (TextView) findViewById(R.id.cfi);
388        mLocation = (TextView) findViewById(R.id.location);
389        mNeighboringCids = (TextView) findViewById(R.id.neighboring);
390        mCellInfo = (TextView) findViewById(R.id.cellinfo);
391        mCellInfo.setTypeface(Typeface.MONOSPACE);
392        mDcRtInfoTv = (TextView) findViewById(R.id.dcrtinfo);
393
394        sent = (TextView) findViewById(R.id.sent);
395        received = (TextView) findViewById(R.id.received);
396        smsc = (EditText) findViewById(R.id.smsc);
397        dnsCheckState = (TextView) findViewById(R.id.dnsCheckState);
398        mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4);
399        mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6);
400        mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
401
402        preferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
403        ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,
404                android.R.layout.simple_spinner_item, mPreferredNetworkLabels);
405        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
406        preferredNetworkType.setAdapter(adapter);
407
408        cellInfoRefreshRateSpinner = (Spinner) findViewById(R.id.cell_info_rate_select);
409        ArrayAdapter<String> cellInfoAdapter = new ArrayAdapter<String>(this,
410                android.R.layout.simple_spinner_item, mCellInfoRefreshRateLabels);
411        cellInfoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
412        cellInfoRefreshRateSpinner.setAdapter(cellInfoAdapter);
413
414        imsVolteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch);
415        imsVtProvisionedSwitch = (Switch) findViewById(R.id.vt_provisioned_switch);
416        imsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch);
417        eabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch);
418
419        radioPowerOnSwitch = (Switch) findViewById(R.id.radio_power);
420
421        pingTestButton = (Button) findViewById(R.id.ping_test);
422        pingTestButton.setOnClickListener(mPingButtonHandler);
423        updateSmscButton = (Button) findViewById(R.id.update_smsc);
424        updateSmscButton.setOnClickListener(mUpdateSmscButtonHandler);
425        refreshSmscButton = (Button) findViewById(R.id.refresh_smsc);
426        refreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
427        dnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle);
428        dnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler);
429        carrierProvisioningButton = (Button) findViewById(R.id.carrier_provisioning);
430        carrierProvisioningButton.setOnClickListener(mCarrierProvisioningButtonHandler);
431        triggercarrierProvisioningButton = (Button) findViewById(R.id.trigger_carrier_provisioning);
432        triggercarrierProvisioningButton.setOnClickListener(
433                mTriggerCarrierProvisioningButtonHandler);
434
435        oemInfoButton = (Button) findViewById(R.id.oem_info);
436        oemInfoButton.setOnClickListener(mOemInfoButtonHandler);
437        PackageManager pm = getPackageManager();
438        Intent oemInfoIntent = new Intent("com.android.settings.OEM_RADIO_INFO");
439        List<ResolveInfo> oemInfoIntentList = pm.queryIntentActivities(oemInfoIntent, 0);
440        if (oemInfoIntentList.size() == 0) {
441            oemInfoButton.setEnabled(false);
442        }
443
444        mCellInfoRefreshRateIndex = 0; //disabled
445        mPreferredNetworkTypeResult = mPreferredNetworkLabels.length - 1; //Unknown
446
447        //FIXME: Replace with TelephonyManager call
448        phone.getPreferredNetworkType(
449                mHandler.obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
450
451        restoreFromBundle(icicle);
452    }
453
454    @Override
455    protected void onResume() {
456        super.onResume();
457
458        log("Started onResume");
459
460        updateMessageWaiting();
461        updateCallRedirect();
462        updateDataState();
463        updateDataStats2();
464        updateRadioPowerState();
465        updateImsProvisionedState();
466        updateProperties();
467        updateDnsCheckState();
468        updateNetworkType();
469
470        updateNeighboringCids(mNeighboringCellResult);
471        updateLocation(mCellLocationResult);
472        updateCellInfo(mCellInfoResult);
473
474        mPingHostnameV4.setText(mPingHostnameResultV4);
475        mPingHostnameV6.setText(mPingHostnameResultV6);
476        mHttpClientTest.setText(mHttpClientTestResult);
477
478        cellInfoRefreshRateSpinner.setOnItemSelectedListener(mCellInfoRefreshRateHandler);
479        //set selection after registering listener to force update
480        cellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex);
481
482        //set selection before registering to prevent update
483        preferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
484        preferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
485
486        radioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
487        imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
488        imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
489        imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
490        eabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
491
492        mTelephonyManager.listen(mPhoneStateListener,
493                  PhoneStateListener.LISTEN_CALL_STATE
494        //b/27803938 - RadioInfo currently cannot read PRECISE_CALL_STATE
495        //      | PhoneStateListener.LISTEN_PRECISE_CALL_STATE
496                | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
497                | PhoneStateListener.LISTEN_DATA_ACTIVITY
498                | PhoneStateListener.LISTEN_CELL_LOCATION
499                | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
500                | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
501                | PhoneStateListener.LISTEN_CELL_INFO
502                | PhoneStateListener.LISTEN_SERVICE_STATE
503                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
504                | PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO);
505
506        smsc.clearFocus();
507    }
508
509    @Override
510    protected void onPause() {
511        super.onPause();
512
513        log("onPause: unregister phone & data intents");
514
515        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
516        mTelephonyManager.setCellInfoListRate(CELL_INFO_LIST_RATE_DISABLED);
517    }
518
519    private void restoreFromBundle(Bundle b) {
520        if(b == null) {
521            return;
522        }
523
524        mPingHostnameResultV4 = b.getString("mPingHostnameResultV4","");
525        mPingHostnameResultV6 = b.getString("mPingHostnameResultV6","");
526        mHttpClientTestResult = b.getString("mHttpClientTestResult","");
527
528        mPingHostnameV4.setText(mPingHostnameResultV4);
529        mPingHostnameV6.setText(mPingHostnameResultV6);
530        mHttpClientTest.setText(mHttpClientTestResult);
531
532        mPreferredNetworkTypeResult = b.getInt("mPreferredNetworkTypeResult",
533                                               mPreferredNetworkLabels.length - 1);
534
535        mCellInfoRefreshRateIndex = b.getInt("mCellInfoRefreshRateIndex", 0);
536    }
537
538    @Override
539    protected void onSaveInstanceState(Bundle outState) {
540        outState.putString("mPingHostnameResultV4", mPingHostnameResultV4);
541        outState.putString("mPingHostnameResultV6", mPingHostnameResultV6);
542        outState.putString("mHttpClientTestResult", mHttpClientTestResult);
543
544        outState.putInt("mPreferredNetworkTypeResult", mPreferredNetworkTypeResult);
545        outState.putInt("mCellInfoRefreshRateIndex", mCellInfoRefreshRateIndex);
546
547    }
548
549    @Override
550    public boolean onCreateOptionsMenu(Menu menu) {
551        menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label)
552                .setOnMenuItemClickListener(mSelectBandCallback)
553                .setAlphabeticShortcut('b');
554        menu.add(1, MENU_ITEM_VIEW_ADN, 0,
555                R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback);
556        menu.add(1, MENU_ITEM_VIEW_FDN, 0,
557                R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
558        menu.add(1, MENU_ITEM_VIEW_SDN, 0,
559                R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
560        menu.add(1, MENU_ITEM_GET_IMS_STATUS,
561                0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus);
562        menu.add(1, MENU_ITEM_TOGGLE_DATA,
563                0, R.string.radio_info_data_connection_disable).setOnMenuItemClickListener(mToggleData);
564        return true;
565    }
566
567    @Override
568    public boolean onPrepareOptionsMenu(Menu menu) {
569        // Get the TOGGLE DATA menu item in the right state.
570        MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA);
571        int state = mTelephonyManager.getDataState();
572        boolean visible = true;
573
574        switch (state) {
575            case TelephonyManager.DATA_CONNECTED:
576            case TelephonyManager.DATA_SUSPENDED:
577                item.setTitle(R.string.radio_info_data_connection_disable);
578                break;
579            case TelephonyManager.DATA_DISCONNECTED:
580                item.setTitle(R.string.radio_info_data_connection_enable);
581                break;
582            default:
583                visible = false;
584                break;
585        }
586        item.setVisible(visible);
587        return true;
588    }
589
590    private void updateDnsCheckState() {
591        //FIXME: Replace with a TelephonyManager call
592        dnsCheckState.setText(phone.isDnsCheckDisabled() ?
593                "0.0.0.0 allowed" :"0.0.0.0 not allowed");
594    }
595
596    private final void
597    updateSignalStrength(SignalStrength signalStrength) {
598        Resources r = getResources();
599
600        int signalDbm = signalStrength.getDbm();
601
602        int signalAsu = signalStrength.getAsuLevel();
603
604        if (-1 == signalAsu) signalAsu = 0;
605
606        dBm.setText(String.valueOf(signalDbm) + " "
607            + r.getString(R.string.radioInfo_display_dbm) + "   "
608            + String.valueOf(signalAsu) + " "
609            + r.getString(R.string.radioInfo_display_asu));
610    }
611
612    private final void updateLocation(CellLocation location) {
613        Resources r = getResources();
614        if (location instanceof GsmCellLocation) {
615            GsmCellLocation loc = (GsmCellLocation)location;
616            int lac = loc.getLac();
617            int cid = loc.getCid();
618            mLocation.setText(r.getString(R.string.radioInfo_lac) + " = "
619                    + ((lac == -1) ? "unknown" : Integer.toHexString(lac))
620                    + "   "
621                    + r.getString(R.string.radioInfo_cid) + " = "
622                    + ((cid == -1) ? "unknown" : Integer.toHexString(cid)));
623        } else if (location instanceof CdmaCellLocation) {
624            CdmaCellLocation loc = (CdmaCellLocation)location;
625            int bid = loc.getBaseStationId();
626            int sid = loc.getSystemId();
627            int nid = loc.getNetworkId();
628            int lat = loc.getBaseStationLatitude();
629            int lon = loc.getBaseStationLongitude();
630            mLocation.setText("BID = "
631                    + ((bid == -1) ? "unknown" : Integer.toHexString(bid))
632                    + "   "
633                    + "SID = "
634                    + ((sid == -1) ? "unknown" : Integer.toHexString(sid))
635                    + "   "
636                    + "NID = "
637                    + ((nid == -1) ? "unknown" : Integer.toHexString(nid))
638                    + "\n"
639                    + "LAT = "
640                    + ((lat == -1) ? "unknown" : Integer.toHexString(lat))
641                    + "   "
642                    + "LONG = "
643                    + ((lon == -1) ? "unknown" : Integer.toHexString(lon)));
644        } else {
645            mLocation.setText("unknown");
646        }
647
648
649    }
650
651    private final void updateNeighboringCids(List<NeighboringCellInfo> cids) {
652        StringBuilder sb = new StringBuilder();
653
654        if (cids != null) {
655            if (cids.isEmpty()) {
656                sb.append("no neighboring cells");
657            } else {
658                for (NeighboringCellInfo cell : cids) {
659                    sb.append(cell.toString()).append(" ");
660                }
661            }
662        } else {
663            sb.append("unknown");
664        }
665        mNeighboringCids.setText(sb.toString());
666    }
667
668    private final String getCellInfoDisplayString(int i) {
669        return (i != Integer.MAX_VALUE) ? Integer.toString(i) : "";
670    }
671
672    private final String getCellInfoDisplayString(long i) {
673        return (i != Long.MAX_VALUE) ? Long.toString(i) : "";
674    }
675
676    private final String buildCdmaInfoString(CellInfoCdma ci) {
677        CellIdentityCdma cidCdma = ci.getCellIdentity();
678        CellSignalStrengthCdma ssCdma = ci.getCellSignalStrength();
679
680        return String.format("%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s",
681                ci.isRegistered() ? "S  " : "   ",
682                getCellInfoDisplayString(cidCdma.getSystemId()),
683                getCellInfoDisplayString(cidCdma.getNetworkId()),
684                getCellInfoDisplayString(cidCdma.getBasestationId()),
685                getCellInfoDisplayString(ssCdma.getCdmaDbm()),
686                getCellInfoDisplayString(ssCdma.getCdmaEcio()),
687                getCellInfoDisplayString(ssCdma.getEvdoDbm()),
688                getCellInfoDisplayString(ssCdma.getEvdoEcio()),
689                getCellInfoDisplayString(ssCdma.getEvdoSnr()));
690    }
691
692    private final String buildGsmInfoString(CellInfoGsm ci) {
693        CellIdentityGsm cidGsm = ci.getCellIdentity();
694        CellSignalStrengthGsm ssGsm = ci.getCellSignalStrength();
695
696        return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
697                ci.isRegistered() ? "S  " : "   ",
698                getCellInfoDisplayString(cidGsm.getMcc()),
699                getCellInfoDisplayString(cidGsm.getMnc()),
700                getCellInfoDisplayString(cidGsm.getLac()),
701                getCellInfoDisplayString(cidGsm.getCid()),
702                getCellInfoDisplayString(cidGsm.getArfcn()),
703                getCellInfoDisplayString(cidGsm.getBsic()),
704                getCellInfoDisplayString(ssGsm.getDbm()));
705    }
706
707    private final String buildLteInfoString(CellInfoLte ci) {
708        CellIdentityLte cidLte = ci.getCellIdentity();
709        CellSignalStrengthLte ssLte = ci.getCellSignalStrength();
710
711        return String.format(
712                "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-4.4s %-4.4s %-2.2s\n",
713                ci.isRegistered() ? "S  " : "   ",
714                getCellInfoDisplayString(cidLte.getMcc()),
715                getCellInfoDisplayString(cidLte.getMnc()),
716                getCellInfoDisplayString(cidLte.getTac()),
717                getCellInfoDisplayString(cidLte.getCi()),
718                getCellInfoDisplayString(cidLte.getPci()),
719                getCellInfoDisplayString(cidLte.getEarfcn()),
720                getCellInfoDisplayString(ssLte.getDbm()),
721                getCellInfoDisplayString(ssLte.getRsrq()),
722                getCellInfoDisplayString(ssLte.getTimingAdvance()));
723    }
724
725    private final String buildWcdmaInfoString(CellInfoWcdma ci) {
726        CellIdentityWcdma cidWcdma = ci.getCellIdentity();
727        CellSignalStrengthWcdma ssWcdma = ci.getCellSignalStrength();
728
729        return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
730                ci.isRegistered() ? "S  " : "   ",
731                getCellInfoDisplayString(cidWcdma.getMcc()),
732                getCellInfoDisplayString(cidWcdma.getMnc()),
733                getCellInfoDisplayString(cidWcdma.getLac()),
734                getCellInfoDisplayString(cidWcdma.getCid()),
735                getCellInfoDisplayString(cidWcdma.getUarfcn()),
736                getCellInfoDisplayString(cidWcdma.getPsc()),
737                getCellInfoDisplayString(ssWcdma.getDbm()));
738    }
739
740    private final String buildCellInfoString(List<CellInfo> arrayCi) {
741        String value = new String();
742        StringBuilder cdmaCells = new StringBuilder(),
743                gsmCells = new StringBuilder(),
744                lteCells = new StringBuilder(),
745                wcdmaCells = new StringBuilder();
746
747        if (arrayCi != null) {
748            for (CellInfo ci : arrayCi) {
749
750                if (ci instanceof CellInfoLte) {
751                    lteCells.append(buildLteInfoString((CellInfoLte) ci));
752                } else if (ci instanceof CellInfoWcdma) {
753                    wcdmaCells.append(buildWcdmaInfoString((CellInfoWcdma) ci));
754                } else if (ci instanceof CellInfoGsm) {
755                    gsmCells.append(buildGsmInfoString((CellInfoGsm) ci));
756                } else if (ci instanceof CellInfoCdma) {
757                    cdmaCells.append(buildCdmaInfoString((CellInfoCdma) ci));
758                }
759            }
760            if (lteCells.length() != 0) {
761                value += String.format(
762                        "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-4.4s %-4.4s %-2.2s\n",
763                        "SRV", "MCC", "MNC", "TAC", "CID", "PCI", "EARFCN", "RSRP", "RSRQ", "TA");
764                value += lteCells.toString();
765            }
766            if (wcdmaCells.length() != 0) {
767                value += String.format("WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n",
768                        "SRV", "MCC", "MNC", "LAC", "CID", "UARFCN", "PSC", "RSCP");
769                value += wcdmaCells.toString();
770            }
771            if (gsmCells.length() != 0) {
772                value += String.format("GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n",
773                        "SRV", "MCC", "MNC", "LAC", "CID", "ARFCN", "BSIC", "RSSI");
774                value += gsmCells.toString();
775            }
776            if (cdmaCells.length() != 0) {
777                value += String.format(
778                        "CDMA/EVDO\n%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s\n",
779                        "SRV", "SID", "NID", "BSID", "C-RSSI", "C-ECIO", "E-RSSI", "E-ECIO", "E-SNR");
780                value += cdmaCells.toString();
781            }
782        } else {
783            value ="unknown";
784        }
785
786        return value.toString();
787    }
788
789    private final void updateCellInfo(List<CellInfo> arrayCi) {
790        mCellInfo.setText(buildCellInfoString(arrayCi));
791    }
792
793    private final void updateDcRtInfoTv(DataConnectionRealTimeInfo dcRtInfo) {
794        mDcRtInfoTv.setText(dcRtInfo.toString());
795    }
796
797    private final void
798    updateMessageWaiting() {
799        mMwi.setText(String.valueOf(mMwiValue));
800    }
801
802    private final void
803    updateCallRedirect() {
804        mCfi.setText(String.valueOf(mCfiValue));
805    }
806
807
808    private final void
809    updateServiceState(ServiceState serviceState) {
810        int state = serviceState.getState();
811        Resources r = getResources();
812        String display = r.getString(R.string.radioInfo_unknown);
813
814        switch (state) {
815            case ServiceState.STATE_IN_SERVICE:
816                display = r.getString(R.string.radioInfo_service_in);
817                break;
818            case ServiceState.STATE_OUT_OF_SERVICE:
819            case ServiceState.STATE_EMERGENCY_ONLY:
820                display = r.getString(R.string.radioInfo_service_emergency);
821                break;
822            case ServiceState.STATE_POWER_OFF:
823                display = r.getString(R.string.radioInfo_service_off);
824                break;
825        }
826
827        gsmState.setText(display);
828
829        if (serviceState.getRoaming()) {
830            roamingState.setText(R.string.radioInfo_roaming_in);
831        } else {
832            roamingState.setText(R.string.radioInfo_roaming_not);
833        }
834
835        operatorName.setText(serviceState.getOperatorAlphaLong());
836    }
837
838    private final void
839    updatePhoneState(int state) {
840        Resources r = getResources();
841        String display = r.getString(R.string.radioInfo_unknown);
842
843        switch (state) {
844            case TelephonyManager.CALL_STATE_IDLE:
845                display = r.getString(R.string.radioInfo_phone_idle);
846                break;
847            case TelephonyManager.CALL_STATE_RINGING:
848                display = r.getString(R.string.radioInfo_phone_ringing);
849                break;
850            case TelephonyManager.CALL_STATE_OFFHOOK:
851                display = r.getString(R.string.radioInfo_phone_offhook);
852                break;
853        }
854
855        callState.setText(display);
856    }
857
858    private final void
859    updateDataState() {
860        int state = mTelephonyManager.getDataState();
861        Resources r = getResources();
862        String display = r.getString(R.string.radioInfo_unknown);
863
864        switch (state) {
865            case TelephonyManager.DATA_CONNECTED:
866                display = r.getString(R.string.radioInfo_data_connected);
867                break;
868            case TelephonyManager.DATA_CONNECTING:
869                display = r.getString(R.string.radioInfo_data_connecting);
870                break;
871            case TelephonyManager.DATA_DISCONNECTED:
872                display = r.getString(R.string.radioInfo_data_disconnected);
873                break;
874            case TelephonyManager.DATA_SUSPENDED:
875                display = r.getString(R.string.radioInfo_data_suspended);
876                break;
877        }
878
879        gprsState.setText(display);
880    }
881
882    private final void updateNetworkType() {
883        if(phone != null) {
884            ServiceState ss = phone.getServiceState();
885            dataNetwork.setText(ServiceState.rilRadioTechnologyToString(
886                    phone.getServiceState().getRilDataRadioTechnology()));
887            voiceNetwork.setText(ServiceState.rilRadioTechnologyToString(
888                    phone.getServiceState().getRilVoiceRadioTechnology()));
889        }
890    }
891
892    private final void
893    updateProperties() {
894        String s;
895        Resources r = getResources();
896
897        s = phone.getDeviceId();
898        if (s == null) s = r.getString(R.string.radioInfo_unknown);
899        mDeviceId.setText(s);
900
901        s = phone.getSubscriberId();
902        if (s == null) s = r.getString(R.string.radioInfo_unknown);
903        mSubscriberId.setText(s);
904
905        //FIXME: Replace with a TelephonyManager call
906        s = phone.getLine1Number();
907        if (s == null) s = r.getString(R.string.radioInfo_unknown);
908        number.setText(s);
909    }
910
911    private final void updateDataStats2() {
912        Resources r = getResources();
913
914        long txPackets = TrafficStats.getMobileTxPackets();
915        long rxPackets = TrafficStats.getMobileRxPackets();
916        long txBytes   = TrafficStats.getMobileTxBytes();
917        long rxBytes   = TrafficStats.getMobileRxBytes();
918
919        String packets = r.getString(R.string.radioInfo_display_packets);
920        String bytes   = r.getString(R.string.radioInfo_display_bytes);
921
922        sent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes);
923        received.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes);
924    }
925
926    /**
927     *  Ping a host name
928     */
929    private final void pingHostname() {
930        try {
931            try {
932                Process p4 = Runtime.getRuntime().exec("ping -c 1 www.google.com");
933                int status4 = p4.waitFor();
934                if (status4 == 0) {
935                    mPingHostnameResultV4 = "Pass";
936                } else {
937                    mPingHostnameResultV4 = String.format("Fail(%d)", status4);
938                }
939            } catch (IOException e) {
940                mPingHostnameResultV4 = "Fail: IOException";
941            }
942            try {
943                Process p6 = Runtime.getRuntime().exec("ping6 -c 1 www.google.com");
944                int status6 = p6.waitFor();
945                if (status6 == 0) {
946                    mPingHostnameResultV6 = "Pass";
947                } else {
948                    mPingHostnameResultV6 = String.format("Fail(%d)", status6);
949                }
950            } catch (IOException e) {
951                mPingHostnameResultV6 = "Fail: IOException";
952            }
953        } catch (InterruptedException e) {
954            mPingHostnameResultV4 = mPingHostnameResultV6 = "Fail: InterruptedException";
955        }
956    }
957
958    /**
959     * This function checks for basic functionality of HTTP Client.
960     */
961    private void httpClientTest() {
962        HttpURLConnection urlConnection = null;
963        try {
964            // TODO: Hardcoded for now, make it UI configurable
965            URL url = new URL("https://www.google.com");
966            urlConnection = (HttpURLConnection) url.openConnection();
967            if (urlConnection.getResponseCode() == 200) {
968                mHttpClientTestResult = "Pass";
969            } else {
970                mHttpClientTestResult = "Fail: Code: " + urlConnection.getResponseMessage();
971            }
972        } catch (IOException e) {
973            mHttpClientTestResult = "Fail: IOException";
974        } finally {
975            if (urlConnection != null) {
976                urlConnection.disconnect();
977            }
978        }
979    }
980
981    private void refreshSmsc() {
982        //FIXME: Replace with a TelephonyManager call
983        phone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
984    }
985
986    private final void updateAllCellInfo() {
987
988        mCellInfo.setText("");
989        mNeighboringCids.setText("");
990        mLocation.setText("");
991
992        final Runnable updateAllCellInfoResults = new Runnable() {
993            public void run() {
994                updateNeighboringCids(mNeighboringCellResult);
995                updateLocation(mCellLocationResult);
996                updateCellInfo(mCellInfoResult);
997            }
998        };
999
1000        Thread locThread = new Thread() {
1001            @Override
1002            public void run() {
1003                mCellInfoResult = mTelephonyManager.getAllCellInfo();
1004                mCellLocationResult = mTelephonyManager.getCellLocation();
1005                mNeighboringCellResult = mTelephonyManager.getNeighboringCellInfo();
1006
1007                mHandler.post(updateAllCellInfoResults);
1008            }
1009        };
1010        locThread.start();
1011    }
1012
1013    private final void updatePingState() {
1014        // Set all to unknown since the threads will take a few secs to update.
1015        mPingHostnameResultV4 = getResources().getString(R.string.radioInfo_unknown);
1016        mPingHostnameResultV6 = getResources().getString(R.string.radioInfo_unknown);
1017        mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown);
1018
1019        mPingHostnameV4.setText(mPingHostnameResultV4);
1020        mPingHostnameV6.setText(mPingHostnameResultV6);
1021        mHttpClientTest.setText(mHttpClientTestResult);
1022
1023        final Runnable updatePingResults = new Runnable() {
1024            public void run() {
1025                mPingHostnameV4.setText(mPingHostnameResultV4);
1026                mPingHostnameV6.setText(mPingHostnameResultV6);
1027                mHttpClientTest.setText(mHttpClientTestResult);
1028            }
1029        };
1030
1031        Thread hostname = new Thread() {
1032            @Override
1033            public void run() {
1034                pingHostname();
1035                mHandler.post(updatePingResults);
1036            }
1037        };
1038        hostname.start();
1039
1040        Thread httpClient = new Thread() {
1041            @Override
1042            public void run() {
1043                httpClientTest();
1044                mHandler.post(updatePingResults);
1045            }
1046        };
1047        httpClient.start();
1048    }
1049
1050    private MenuItem.OnMenuItemClickListener mViewADNCallback = new MenuItem.OnMenuItemClickListener() {
1051        public boolean onMenuItemClick(MenuItem item) {
1052            Intent intent = new Intent(Intent.ACTION_VIEW);
1053            // XXX We need to specify the component here because if we don't
1054            // the activity manager will try to resolve the type by calling
1055            // the content provider, which causes it to be loaded in a process
1056            // other than the Dialer process, which causes a lot of stuff to
1057            // break.
1058            intent.setClassName("com.android.phone",
1059                    "com.android.phone.SimContacts");
1060            startActivity(intent);
1061            return true;
1062        }
1063    };
1064
1065    private MenuItem.OnMenuItemClickListener mViewFDNCallback = new MenuItem.OnMenuItemClickListener() {
1066        public boolean onMenuItemClick(MenuItem item) {
1067            Intent intent = new Intent(Intent.ACTION_VIEW);
1068            // XXX We need to specify the component here because if we don't
1069            // the activity manager will try to resolve the type by calling
1070            // the content provider, which causes it to be loaded in a process
1071            // other than the Dialer process, which causes a lot of stuff to
1072            // break.
1073            intent.setClassName("com.android.phone",
1074                    "com.android.phone.settings.fdn.FdnList");
1075            startActivity(intent);
1076            return true;
1077        }
1078    };
1079
1080    private MenuItem.OnMenuItemClickListener mViewSDNCallback = new MenuItem.OnMenuItemClickListener() {
1081        public boolean onMenuItemClick(MenuItem item) {
1082            Intent intent = new Intent(
1083                    Intent.ACTION_VIEW, Uri.parse("content://icc/sdn"));
1084            // XXX We need to specify the component here because if we don't
1085            // the activity manager will try to resolve the type by calling
1086            // the content provider, which causes it to be loaded in a process
1087            // other than the Dialer process, which causes a lot of stuff to
1088            // break.
1089            intent.setClassName("com.android.phone",
1090                    "com.android.phone.ADNList");
1091            startActivity(intent);
1092            return true;
1093        }
1094    };
1095
1096    private MenuItem.OnMenuItemClickListener mGetImsStatus = new MenuItem.OnMenuItemClickListener() {
1097        public boolean onMenuItemClick(MenuItem item) {
1098            boolean isImsRegistered = phone.isImsRegistered();
1099            boolean availableVolte = phone.isVolteEnabled();
1100            boolean availableWfc = phone.isWifiCallingEnabled();
1101            boolean availableVt = phone.isVideoEnabled();
1102            boolean availableUt = phone.isUtEnabled();
1103
1104            final String imsRegString = isImsRegistered ?
1105                getString(R.string.radio_info_ims_reg_status_registered) :
1106                getString(R.string.radio_info_ims_reg_status_not_registered);
1107
1108            final String available = getString(R.string.radio_info_ims_feature_status_available);
1109            final String unavailable = getString(
1110                    R.string.radio_info_ims_feature_status_unavailable);
1111
1112            String imsStatus = getString(R.string.radio_info_ims_reg_status,
1113                    imsRegString,
1114                    availableVolte ? available : unavailable,
1115                    availableWfc ? available : unavailable,
1116                    availableVt ? available : unavailable,
1117                    availableUt ? available : unavailable);
1118
1119            AlertDialog imsDialog = new AlertDialog.Builder(RadioInfo.this)
1120                .setMessage(imsStatus)
1121                .setTitle(getString(R.string.radio_info_ims_reg_status_title))
1122                .create();
1123
1124            imsDialog.show();
1125
1126            return true;
1127        }
1128    };
1129
1130    private MenuItem.OnMenuItemClickListener mSelectBandCallback = new MenuItem.OnMenuItemClickListener() {
1131        public boolean onMenuItemClick(MenuItem item) {
1132            Intent intent = new Intent();
1133            intent.setClass(RadioInfo.this, BandMode.class);
1134            startActivity(intent);
1135            return true;
1136        }
1137    };
1138
1139    private MenuItem.OnMenuItemClickListener mToggleData = new MenuItem.OnMenuItemClickListener() {
1140        public boolean onMenuItemClick(MenuItem item) {
1141            int state = mTelephonyManager.getDataState();
1142            switch (state) {
1143                case TelephonyManager.DATA_CONNECTED:
1144                    //FIXME: Replace with a TelephonyManager call
1145                    phone.setDataEnabled(false);
1146                    break;
1147                case TelephonyManager.DATA_DISCONNECTED:
1148                    //FIXME: Replace with a TelephonyManager call
1149                    phone.setDataEnabled(true);
1150                    break;
1151                default:
1152                    // do nothing
1153                    break;
1154            }
1155            return true;
1156        }
1157    };
1158
1159    private boolean isRadioOn() {
1160        //FIXME: Replace with a TelephonyManager call
1161        return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
1162    }
1163
1164    private void updateRadioPowerState() {
1165        //delightful hack to prevent on-checked-changed calls from
1166        //actually forcing the radio preference to its transient/current value.
1167        radioPowerOnSwitch.setOnCheckedChangeListener(null);
1168        radioPowerOnSwitch.setChecked(isRadioOn());
1169        radioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
1170    }
1171
1172    void setImsVolteProvisionedState(boolean state) {
1173        Log.d(TAG, "setImsVolteProvisioned state: " + ((state)? "on":"off"));
1174        setImsConfigProvisionedState(IMS_VOLTE_PROVISIONED_CONFIG_ID, state);
1175    }
1176
1177    void setImsVtProvisionedState(boolean state) {
1178        Log.d(TAG, "setImsVtProvisioned() state: " + ((state)? "on":"off"));
1179        setImsConfigProvisionedState(IMS_VT_PROVISIONED_CONFIG_ID, state);
1180    }
1181
1182    void setImsWfcProvisionedState(boolean state) {
1183        Log.d(TAG, "setImsWfcProvisioned() state: " + ((state)? "on":"off"));
1184        setImsConfigProvisionedState(IMS_WFC_PROVISIONED_CONFIG_ID, state);
1185    }
1186
1187    void setEabProvisionedState(boolean state) {
1188        Log.d(TAG, "setEabProvisioned() state: " + ((state)? "on":"off"));
1189        setImsConfigProvisionedState(EAB_PROVISIONED_CONFIG_ID, state);
1190    }
1191
1192    void setImsConfigProvisionedState(int configItem, boolean state) {
1193        if (phone != null && mImsManager != null) {
1194            QueuedWork.queue(new Runnable() {
1195                public void run() {
1196                    try {
1197                        mImsManager.getConfigInterface().setProvisionedValue(
1198                                configItem,
1199                                state? 1 : 0);
1200                    } catch (ImsException e) {
1201                        Log.e(TAG, "setImsConfigProvisioned() exception:", e);
1202                    }
1203                }
1204            }, false);
1205        }
1206    }
1207
1208    OnCheckedChangeListener mRadioPowerOnChangeListener = new OnCheckedChangeListener() {
1209        @Override
1210        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1211            log("toggle radio power: currently " + (isRadioOn()?"on":"off"));
1212            phone.setRadioPower(isChecked);
1213       }
1214    };
1215
1216    private boolean isImsVolteProvisioned() {
1217        if (phone != null && mImsManager != null) {
1218            return mImsManager.isVolteEnabledByPlatform(phone.getContext())
1219                && mImsManager.isVolteProvisionedOnDevice(phone.getContext());
1220        }
1221        return false;
1222    }
1223
1224    OnCheckedChangeListener mImsVolteCheckedChangeListener = new OnCheckedChangeListener() {
1225        @Override
1226        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1227            setImsVolteProvisionedState(isChecked);
1228        }
1229    };
1230
1231    private boolean isImsVtProvisioned() {
1232        if (phone != null && mImsManager != null) {
1233            return mImsManager.isVtEnabledByPlatform(phone.getContext())
1234                && mImsManager.isVtProvisionedOnDevice(phone.getContext());
1235        }
1236        return false;
1237    }
1238
1239    OnCheckedChangeListener mImsVtCheckedChangeListener = new OnCheckedChangeListener() {
1240        @Override
1241        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1242            setImsVtProvisionedState(isChecked);
1243        }
1244    };
1245
1246    private boolean isImsWfcProvisioned() {
1247        if (phone != null && mImsManager != null) {
1248            return mImsManager.isWfcEnabledByPlatform(phone.getContext())
1249                && mImsManager.isWfcProvisionedOnDevice(phone.getContext());
1250        }
1251        return false;
1252    }
1253
1254    OnCheckedChangeListener mImsWfcCheckedChangeListener = new OnCheckedChangeListener() {
1255        @Override
1256        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1257            setImsWfcProvisionedState(isChecked);
1258        }
1259    };
1260
1261    private boolean isEabProvisioned() {
1262        return isFeatureProvisioned(EAB_PROVISIONED_CONFIG_ID, false);
1263    }
1264
1265    OnCheckedChangeListener mEabCheckedChangeListener = new OnCheckedChangeListener() {
1266        @Override
1267        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
1268            setEabProvisionedState(isChecked);
1269        }
1270    };
1271
1272    private boolean isFeatureProvisioned(int featureId, boolean defaultValue) {
1273        boolean provisioned = defaultValue;
1274        if (mImsManager != null) {
1275            try {
1276                ImsConfig imsConfig = mImsManager.getConfigInterface();
1277                if (imsConfig != null) {
1278                    provisioned =
1279                            (imsConfig.getProvisionedValue(featureId)
1280                                    == ImsConfig.FeatureValueConstants.ON);
1281                }
1282            } catch (ImsException ex) {
1283                Log.e(TAG, "isFeatureProvisioned() exception:", ex);
1284            }
1285        }
1286
1287        log("isFeatureProvisioned() featureId=" + featureId + " provisioned=" + provisioned);
1288        return provisioned;
1289    }
1290
1291    private static boolean isEabEnabledByPlatform(Context context) {
1292        if (context != null) {
1293            CarrierConfigManager configManager = (CarrierConfigManager)
1294                    context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1295            if (configManager != null && configManager.getConfig().getBoolean(
1296                        CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL)) {
1297                return true;
1298            }
1299        }
1300        return false;
1301    }
1302
1303    private void updateImsProvisionedState() {
1304        log("updateImsProvisionedState isImsVolteProvisioned()=" + isImsVolteProvisioned());
1305        //delightful hack to prevent on-checked-changed calls from
1306        //actually forcing the ims provisioning to its transient/current value.
1307        imsVolteProvisionedSwitch.setOnCheckedChangeListener(null);
1308        imsVolteProvisionedSwitch.setChecked(isImsVolteProvisioned());
1309        imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
1310        imsVolteProvisionedSwitch.setEnabled(
1311                mImsManager.isVolteEnabledByPlatform(phone.getContext()));
1312
1313        imsVtProvisionedSwitch.setOnCheckedChangeListener(null);
1314        imsVtProvisionedSwitch.setChecked(isImsVtProvisioned());
1315        imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
1316        imsVtProvisionedSwitch.setEnabled(
1317            mImsManager.isVtEnabledByPlatform(phone.getContext()));
1318
1319        imsWfcProvisionedSwitch.setOnCheckedChangeListener(null);
1320        imsWfcProvisionedSwitch.setChecked(isImsWfcProvisioned());
1321        imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
1322        imsWfcProvisionedSwitch.setEnabled(
1323            mImsManager.isWfcEnabledByPlatform(phone.getContext()));
1324
1325        eabProvisionedSwitch.setOnCheckedChangeListener(null);
1326        eabProvisionedSwitch.setChecked(isEabProvisioned());
1327        eabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener);
1328        eabProvisionedSwitch.setEnabled(isEabEnabledByPlatform(phone.getContext()));
1329    }
1330
1331    OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
1332        public void onClick(View v) {
1333            //FIXME: Replace with a TelephonyManager call
1334            phone.disableDnsCheck(!phone.isDnsCheckDisabled());
1335            updateDnsCheckState();
1336        }
1337    };
1338
1339    OnClickListener mOemInfoButtonHandler = new OnClickListener() {
1340        public void onClick(View v) {
1341            Intent intent = new Intent("com.android.settings.OEM_RADIO_INFO");
1342            try {
1343                startActivity(intent);
1344            } catch (android.content.ActivityNotFoundException ex) {
1345                log("OEM-specific Info/Settings Activity Not Found : " + ex);
1346                // If the activity does not exist, there are no OEM
1347                // settings, and so we can just do nothing...
1348            }
1349        }
1350    };
1351
1352    OnClickListener mPingButtonHandler = new OnClickListener() {
1353        public void onClick(View v) {
1354            updatePingState();
1355        }
1356    };
1357
1358    OnClickListener mUpdateSmscButtonHandler = new OnClickListener() {
1359        public void onClick(View v) {
1360            updateSmscButton.setEnabled(false);
1361            phone.setSmscAddress(smsc.getText().toString(),
1362                    mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE));
1363        }
1364    };
1365
1366    OnClickListener mRefreshSmscButtonHandler = new OnClickListener() {
1367        public void onClick(View v) {
1368            refreshSmsc();
1369        }
1370    };
1371
1372    OnClickListener mCarrierProvisioningButtonHandler = new OnClickListener() {
1373        public void onClick(View v) {
1374            final Intent intent = new Intent("com.android.settings.CARRIER_PROVISIONING");
1375            final ComponentName serviceComponent = ComponentName.unflattenFromString(
1376                    "com.android.omadm.service/.DMIntentReceiver");
1377            intent.setComponent(serviceComponent);
1378            sendBroadcast(intent);
1379        }
1380    };
1381
1382    OnClickListener mTriggerCarrierProvisioningButtonHandler = new OnClickListener() {
1383        public void onClick(View v) {
1384            final Intent intent = new Intent("com.android.settings.TRIGGER_CARRIER_PROVISIONING");
1385            final ComponentName serviceComponent = ComponentName.unflattenFromString(
1386                    "com.android.omadm.service/.DMIntentReceiver");
1387            intent.setComponent(serviceComponent);
1388            sendBroadcast(intent);
1389        }
1390    };
1391
1392    AdapterView.OnItemSelectedListener mPreferredNetworkHandler =
1393            new AdapterView.OnItemSelectedListener() {
1394
1395        public void onItemSelected(AdapterView parent, View v, int pos, long id) {
1396            if (mPreferredNetworkTypeResult != pos && pos >= 0
1397                    && pos <= mPreferredNetworkLabels.length - 2) {
1398                mPreferredNetworkTypeResult = pos;
1399                Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
1400                phone.setPreferredNetworkType(mPreferredNetworkTypeResult, msg);
1401            }
1402        }
1403
1404        public void onNothingSelected(AdapterView parent) {
1405        }
1406    };
1407
1408    AdapterView.OnItemSelectedListener mCellInfoRefreshRateHandler  =
1409            new AdapterView.OnItemSelectedListener() {
1410
1411        public void onItemSelected(AdapterView parent, View v, int pos, long id) {
1412            mCellInfoRefreshRateIndex = pos;
1413            mTelephonyManager.setCellInfoListRate(mCellInfoRefreshRates[pos]);
1414            updateAllCellInfo();
1415        }
1416
1417        public void onNothingSelected(AdapterView parent) {
1418        }
1419    };
1420
1421}
1422