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.content.Context;
21import android.content.Intent;
22import android.content.pm.PackageManager;
23import android.content.pm.ResolveInfo;
24import android.content.res.Resources;
25import android.net.ConnectivityManager;
26import android.net.LinkProperties;
27import android.net.TrafficStats;
28import android.net.Uri;
29import android.os.AsyncResult;
30import android.os.Bundle;
31import android.os.Handler;
32import android.os.Message;
33import android.os.RemoteException;
34import android.os.ServiceManager;
35import android.os.SystemProperties;
36import android.telephony.CellLocation;
37import android.telephony.PhoneStateListener;
38import android.telephony.ServiceState;
39import android.telephony.TelephonyManager;
40import android.telephony.NeighboringCellInfo;
41import android.telephony.cdma.CdmaCellLocation;
42import android.telephony.gsm.GsmCellLocation;
43import android.text.format.DateUtils;
44import android.util.Log;
45import android.view.Menu;
46import android.view.MenuItem;
47import android.view.View;
48import android.view.View.OnClickListener;
49import android.widget.AdapterView;
50import android.widget.ArrayAdapter;
51import android.widget.Button;
52import android.widget.Spinner;
53import android.widget.TextView;
54import android.widget.EditText;
55
56import com.android.internal.telephony.DataConnection;
57import com.android.internal.telephony.Phone;
58import com.android.internal.telephony.PhoneFactory;
59import com.android.internal.telephony.PhoneStateIntentReceiver;
60import com.android.internal.telephony.TelephonyProperties;
61import com.android.internal.telephony.gsm.GsmDataConnection;
62
63import org.apache.http.HttpResponse;
64import org.apache.http.client.HttpClient;
65import org.apache.http.client.methods.HttpGet;
66import org.apache.http.impl.client.DefaultHttpClient;
67
68import java.io.IOException;
69import java.net.InetAddress;
70import java.net.UnknownHostException;
71import java.util.ArrayList;
72import java.util.List;
73
74import android.util.Log;
75
76public class RadioInfo extends Activity {
77    private final String TAG = "phone";
78
79    private static final int EVENT_PHONE_STATE_CHANGED = 100;
80    private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 200;
81    private static final int EVENT_SERVICE_STATE_CHANGED = 300;
82    private static final int EVENT_CFI_CHANGED = 302;
83
84    private static final int EVENT_QUERY_PREFERRED_TYPE_DONE = 1000;
85    private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001;
86    private static final int EVENT_QUERY_NEIGHBORING_CIDS_DONE = 1002;
87    private static final int EVENT_QUERY_SMSC_DONE = 1005;
88    private static final int EVENT_UPDATE_SMSC_DONE = 1006;
89
90    private static final int MENU_ITEM_SELECT_BAND  = 0;
91    private static final int MENU_ITEM_VIEW_ADN     = 1;
92    private static final int MENU_ITEM_VIEW_FDN     = 2;
93    private static final int MENU_ITEM_VIEW_SDN     = 3;
94    private static final int MENU_ITEM_GET_PDP_LIST = 4;
95    private static final int MENU_ITEM_TOGGLE_DATA  = 5;
96
97    static final String ENABLE_DATA_STR = "Enable data connection";
98    static final String DISABLE_DATA_STR = "Disable data connection";
99
100    private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
101    private TextView number;
102    private TextView callState;
103    private TextView operatorName;
104    private TextView roamingState;
105    private TextView gsmState;
106    private TextView gprsState;
107    private TextView network;
108    private TextView dBm;
109    private TextView mMwi;
110    private TextView mCfi;
111    private TextView mLocation;
112    private TextView mNeighboringCids;
113    private TextView resets;
114    private TextView attempts;
115    private TextView successes;
116    private TextView disconnects;
117    private TextView sentSinceReceived;
118    private TextView sent;
119    private TextView received;
120    private TextView mPingIpAddr;
121    private TextView mPingHostname;
122    private TextView mHttpClientTest;
123    private TextView dnsCheckState;
124    private EditText smsc;
125    private Button radioPowerButton;
126    private Button dnsCheckToggleButton;
127    private Button pingTestButton;
128    private Button updateSmscButton;
129    private Button refreshSmscButton;
130    private Button oemInfoButton;
131    private Spinner preferredNetworkType;
132
133    private TelephonyManager mTelephonyManager;
134    private Phone phone = null;
135    private PhoneStateIntentReceiver mPhoneStateReceiver;
136
137    private String mPingIpAddrResult;
138    private String mPingHostnameResult;
139    private String mHttpClientTestResult;
140    private boolean mMwiValue = false;
141    private boolean mCfiValue = false;
142
143    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
144        @Override
145        public void onDataConnectionStateChanged(int state) {
146            updateDataState();
147            updateDataStats();
148            updatePdpList();
149            updateNetworkType();
150        }
151
152        @Override
153        public void onDataActivity(int direction) {
154            updateDataStats2();
155        }
156
157        @Override
158        public void onCellLocationChanged(CellLocation location) {
159            updateLocation(location);
160        }
161
162        @Override
163        public void onMessageWaitingIndicatorChanged(boolean mwi) {
164            mMwiValue = mwi;
165            updateMessageWaiting();
166        }
167
168        @Override
169        public void onCallForwardingIndicatorChanged(boolean cfi) {
170            mCfiValue = cfi;
171            updateCallRedirect();
172        }
173    };
174
175    private Handler mHandler = new Handler() {
176        public void handleMessage(Message msg) {
177            AsyncResult ar;
178            switch (msg.what) {
179                case EVENT_PHONE_STATE_CHANGED:
180                    updatePhoneState();
181                    break;
182
183                case EVENT_SIGNAL_STRENGTH_CHANGED:
184                    updateSignalStrength();
185                    break;
186
187                case EVENT_SERVICE_STATE_CHANGED:
188                    updateServiceState();
189                    updatePowerState();
190                    break;
191
192                case EVENT_QUERY_PREFERRED_TYPE_DONE:
193                    ar= (AsyncResult) msg.obj;
194                    if (ar.exception == null) {
195                        int type = ((int[])ar.result)[0];
196                        preferredNetworkType.setSelection(type, true);
197                    } else {
198                        preferredNetworkType.setSelection(8, true);
199                    }
200                    break;
201                case EVENT_SET_PREFERRED_TYPE_DONE:
202                    ar= (AsyncResult) msg.obj;
203                    if (ar.exception != null) {
204                        phone.getPreferredNetworkType(
205                                obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
206                    }
207                    break;
208                case EVENT_QUERY_NEIGHBORING_CIDS_DONE:
209                    ar= (AsyncResult) msg.obj;
210                    if (ar.exception == null) {
211                        updateNeighboringCids((ArrayList<NeighboringCellInfo>)ar.result);
212                    } else {
213                        mNeighboringCids.setText("unknown");
214                    }
215                    break;
216                case EVENT_QUERY_SMSC_DONE:
217                    ar= (AsyncResult) msg.obj;
218                    if (ar.exception != null) {
219                        smsc.setText("refresh error");
220                    } else {
221                        smsc.setText((String)ar.result);
222                    }
223                    break;
224                case EVENT_UPDATE_SMSC_DONE:
225                    updateSmscButton.setEnabled(true);
226                    ar= (AsyncResult) msg.obj;
227                    if (ar.exception != null) {
228                        smsc.setText("update error");
229                    }
230                    break;
231                default:
232                    break;
233
234            }
235        }
236    };
237
238    @Override
239    public void onCreate(Bundle icicle) {
240        super.onCreate(icicle);
241
242        setContentView(R.layout.radio_info);
243
244        mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
245        phone = PhoneFactory.getDefaultPhone();
246
247        mDeviceId= (TextView) findViewById(R.id.imei);
248        number = (TextView) findViewById(R.id.number);
249        callState = (TextView) findViewById(R.id.call);
250        operatorName = (TextView) findViewById(R.id.operator);
251        roamingState = (TextView) findViewById(R.id.roaming);
252        gsmState = (TextView) findViewById(R.id.gsm);
253        gprsState = (TextView) findViewById(R.id.gprs);
254        network = (TextView) findViewById(R.id.network);
255        dBm = (TextView) findViewById(R.id.dbm);
256        mMwi = (TextView) findViewById(R.id.mwi);
257        mCfi = (TextView) findViewById(R.id.cfi);
258        mLocation = (TextView) findViewById(R.id.location);
259        mNeighboringCids = (TextView) findViewById(R.id.neighboring);
260
261        resets = (TextView) findViewById(R.id.resets);
262        attempts = (TextView) findViewById(R.id.attempts);
263        successes = (TextView) findViewById(R.id.successes);
264        disconnects = (TextView) findViewById(R.id.disconnects);
265        sentSinceReceived = (TextView) findViewById(R.id.sentSinceReceived);
266        sent = (TextView) findViewById(R.id.sent);
267        received = (TextView) findViewById(R.id.received);
268        smsc = (EditText) findViewById(R.id.smsc);
269        dnsCheckState = (TextView) findViewById(R.id.dnsCheckState);
270
271        mPingIpAddr = (TextView) findViewById(R.id.pingIpAddr);
272        mPingHostname = (TextView) findViewById(R.id.pingHostname);
273        mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
274
275        preferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
276        ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,
277                android.R.layout.simple_spinner_item, mPreferredNetworkLabels);
278        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
279        preferredNetworkType.setAdapter(adapter);
280        preferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
281
282        radioPowerButton = (Button) findViewById(R.id.radio_power);
283        radioPowerButton.setOnClickListener(mPowerButtonHandler);
284
285        imsRegRequiredButton = (Button) findViewById(R.id.ims_reg_required);
286        imsRegRequiredButton.setOnClickListener(mImsRegRequiredHandler);
287
288        smsOverImsButton = (Button) findViewById(R.id.sms_over_ims);
289        smsOverImsButton.setOnClickListener(mSmsOverImsHandler);
290
291        lteRamDumpButton = (Button) findViewById(R.id.lte_ram_dump);
292        lteRamDumpButton.setOnClickListener(mLteRamDumpHandler);
293
294        pingTestButton = (Button) findViewById(R.id.ping_test);
295        pingTestButton.setOnClickListener(mPingButtonHandler);
296        updateSmscButton = (Button) findViewById(R.id.update_smsc);
297        updateSmscButton.setOnClickListener(mUpdateSmscButtonHandler);
298        refreshSmscButton = (Button) findViewById(R.id.refresh_smsc);
299        refreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
300        dnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle);
301        dnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler);
302
303        oemInfoButton = (Button) findViewById(R.id.oem_info);
304        oemInfoButton.setOnClickListener(mOemInfoButtonHandler);
305        PackageManager pm = getPackageManager();
306        Intent oemInfoIntent = new Intent("com.android.settings.OEM_RADIO_INFO");
307        List<ResolveInfo> oemInfoIntentList = pm.queryIntentActivities(oemInfoIntent, 0);
308        if (oemInfoIntentList.size() == 0) {
309            oemInfoButton.setEnabled(false);
310        }
311
312        mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);
313        mPhoneStateReceiver.notifySignalStrength(EVENT_SIGNAL_STRENGTH_CHANGED);
314        mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
315        mPhoneStateReceiver.notifyPhoneCallState(EVENT_PHONE_STATE_CHANGED);
316
317        phone.getPreferredNetworkType(
318                mHandler.obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
319        phone.getNeighboringCids(
320                mHandler.obtainMessage(EVENT_QUERY_NEIGHBORING_CIDS_DONE));
321
322        CellLocation.requestLocationUpdate();
323    }
324
325    @Override
326    protected void onResume() {
327        super.onResume();
328
329        updatePhoneState();
330        updateSignalStrength();
331        updateMessageWaiting();
332        updateCallRedirect();
333        updateServiceState();
334        updateLocation(mTelephonyManager.getCellLocation());
335        updateDataState();
336        updateDataStats();
337        updateDataStats2();
338        updatePowerState();
339        updateImsRegRequiredState();
340        updateSmsOverImsState();
341        updateLteRamDumpState();
342        updateProperties();
343        updateDnsCheckState();
344
345        Log.i(TAG, "[RadioInfo] onResume: register phone & data intents");
346
347        mPhoneStateReceiver.registerIntent();
348        mTelephonyManager.listen(mPhoneStateListener,
349                  PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
350                | PhoneStateListener.LISTEN_DATA_ACTIVITY
351                | PhoneStateListener.LISTEN_CELL_LOCATION
352                | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
353                | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR);
354    }
355
356    @Override
357    public void onPause() {
358        super.onPause();
359
360        Log.i(TAG, "[RadioInfo] onPause: unregister phone & data intents");
361
362        mPhoneStateReceiver.unregisterIntent();
363        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
364    }
365
366    @Override
367    public boolean onCreateOptionsMenu(Menu menu) {
368        menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label)
369                .setOnMenuItemClickListener(mSelectBandCallback)
370                .setAlphabeticShortcut('b');
371        menu.add(1, MENU_ITEM_VIEW_ADN, 0,
372                R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback);
373        menu.add(1, MENU_ITEM_VIEW_FDN, 0,
374                R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
375        menu.add(1, MENU_ITEM_VIEW_SDN, 0,
376                R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
377        menu.add(1, MENU_ITEM_GET_PDP_LIST,
378                0, R.string.radioInfo_menu_getPDP).setOnMenuItemClickListener(mGetPdpList);
379        menu.add(1, MENU_ITEM_TOGGLE_DATA,
380                0, DISABLE_DATA_STR).setOnMenuItemClickListener(mToggleData);
381        return true;
382    }
383
384    @Override
385    public boolean onPrepareOptionsMenu(Menu menu) {
386        // Get the TOGGLE DATA menu item in the right state.
387        MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA);
388        int state = mTelephonyManager.getDataState();
389        boolean visible = true;
390
391        switch (state) {
392            case TelephonyManager.DATA_CONNECTED:
393            case TelephonyManager.DATA_SUSPENDED:
394                item.setTitle(DISABLE_DATA_STR);
395                break;
396            case TelephonyManager.DATA_DISCONNECTED:
397                item.setTitle(ENABLE_DATA_STR);
398                break;
399            default:
400                visible = false;
401                break;
402        }
403        item.setVisible(visible);
404        return true;
405    }
406
407    private boolean isRadioOn() {
408        return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
409    }
410
411    private void updatePowerState() {
412        String buttonText = isRadioOn() ?
413                            getString(R.string.turn_off_radio) :
414                            getString(R.string.turn_on_radio);
415        radioPowerButton.setText(buttonText);
416    }
417
418    private void updateDnsCheckState() {
419        dnsCheckState.setText(phone.isDnsCheckDisabled() ?
420                "0.0.0.0 allowed" :"0.0.0.0 not allowed");
421    }
422
423    private final void
424    updateSignalStrength() {
425        // TODO PhoneStateIntentReceiver is deprecated and PhoneStateListener
426        // should probably used instead.
427        int state = mPhoneStateReceiver.getServiceState().getState();
428        Resources r = getResources();
429
430        if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
431                (ServiceState.STATE_POWER_OFF == state)) {
432            dBm.setText("0");
433        }
434
435        int signalDbm = mPhoneStateReceiver.getSignalStrengthDbm();
436
437        if (-1 == signalDbm) signalDbm = 0;
438
439        int signalAsu = mPhoneStateReceiver.getSignalStrengthLevelAsu();
440
441        if (-1 == signalAsu) signalAsu = 0;
442
443        dBm.setText(String.valueOf(signalDbm) + " "
444            + r.getString(R.string.radioInfo_display_dbm) + "   "
445            + String.valueOf(signalAsu) + " "
446            + r.getString(R.string.radioInfo_display_asu));
447    }
448
449    private final void updateLocation(CellLocation location) {
450        Resources r = getResources();
451        if (location instanceof GsmCellLocation) {
452            GsmCellLocation loc = (GsmCellLocation)location;
453            int lac = loc.getLac();
454            int cid = loc.getCid();
455            mLocation.setText(r.getString(R.string.radioInfo_lac) + " = "
456                    + ((lac == -1) ? "unknown" : Integer.toHexString(lac))
457                    + "   "
458                    + r.getString(R.string.radioInfo_cid) + " = "
459                    + ((cid == -1) ? "unknown" : Integer.toHexString(cid)));
460        } else if (location instanceof CdmaCellLocation) {
461            CdmaCellLocation loc = (CdmaCellLocation)location;
462            int bid = loc.getBaseStationId();
463            int sid = loc.getSystemId();
464            int nid = loc.getNetworkId();
465            int lat = loc.getBaseStationLatitude();
466            int lon = loc.getBaseStationLongitude();
467            mLocation.setText("BID = "
468                    + ((bid == -1) ? "unknown" : Integer.toHexString(bid))
469                    + "   "
470                    + "SID = "
471                    + ((sid == -1) ? "unknown" : Integer.toHexString(sid))
472                    + "   "
473                    + "NID = "
474                    + ((nid == -1) ? "unknown" : Integer.toHexString(nid))
475                    + "\n"
476                    + "LAT = "
477                    + ((lat == -1) ? "unknown" : Integer.toHexString(lat))
478                    + "   "
479                    + "LONG = "
480                    + ((lon == -1) ? "unknown" : Integer.toHexString(lon)));
481        } else {
482            mLocation.setText("unknown");
483        }
484
485
486    }
487
488    private final void updateNeighboringCids(ArrayList<NeighboringCellInfo> cids) {
489        StringBuilder sb = new StringBuilder();
490
491        if (cids != null) {
492            if ( cids.isEmpty() ) {
493                sb.append("no neighboring cells");
494            } else {
495                for (NeighboringCellInfo cell : cids) {
496                    sb.append(cell.toString()).append(" ");
497                }
498            }
499        } else {
500            sb.append("unknown");
501        }
502        mNeighboringCids.setText(sb.toString());
503    }
504
505    private final void
506    updateMessageWaiting() {
507        mMwi.setText(String.valueOf(mMwiValue));
508    }
509
510    private final void
511    updateCallRedirect() {
512        mCfi.setText(String.valueOf(mCfiValue));
513    }
514
515
516    private final void
517    updateServiceState() {
518        ServiceState serviceState = mPhoneStateReceiver.getServiceState();
519        int state = serviceState.getState();
520        Resources r = getResources();
521        String display = r.getString(R.string.radioInfo_unknown);
522
523        switch (state) {
524            case ServiceState.STATE_IN_SERVICE:
525                display = r.getString(R.string.radioInfo_service_in);
526                break;
527            case ServiceState.STATE_OUT_OF_SERVICE:
528            case ServiceState.STATE_EMERGENCY_ONLY:
529                display = r.getString(R.string.radioInfo_service_emergency);
530                break;
531            case ServiceState.STATE_POWER_OFF:
532                display = r.getString(R.string.radioInfo_service_off);
533                break;
534        }
535
536        gsmState.setText(display);
537
538        if (serviceState.getRoaming()) {
539            roamingState.setText(R.string.radioInfo_roaming_in);
540        } else {
541            roamingState.setText(R.string.radioInfo_roaming_not);
542        }
543
544        operatorName.setText(serviceState.getOperatorAlphaLong());
545    }
546
547    private final void
548    updatePhoneState() {
549        Phone.State state = mPhoneStateReceiver.getPhoneState();
550        Resources r = getResources();
551        String display = r.getString(R.string.radioInfo_unknown);
552
553        switch (state) {
554            case IDLE:
555                display = r.getString(R.string.radioInfo_phone_idle);
556                break;
557            case RINGING:
558                display = r.getString(R.string.radioInfo_phone_ringing);
559                break;
560            case OFFHOOK:
561                display = r.getString(R.string.radioInfo_phone_offhook);
562                break;
563        }
564
565        callState.setText(display);
566    }
567
568    private final void
569    updateDataState() {
570        int state = mTelephonyManager.getDataState();
571        Resources r = getResources();
572        String display = r.getString(R.string.radioInfo_unknown);
573
574        switch (state) {
575            case TelephonyManager.DATA_CONNECTED:
576                display = r.getString(R.string.radioInfo_data_connected);
577                break;
578            case TelephonyManager.DATA_CONNECTING:
579                display = r.getString(R.string.radioInfo_data_connecting);
580                break;
581            case TelephonyManager.DATA_DISCONNECTED:
582                display = r.getString(R.string.radioInfo_data_disconnected);
583                break;
584            case TelephonyManager.DATA_SUSPENDED:
585                display = r.getString(R.string.radioInfo_data_suspended);
586                break;
587        }
588
589        gprsState.setText(display);
590    }
591
592    private final void updateNetworkType() {
593        Resources r = getResources();
594        String display = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
595                r.getString(R.string.radioInfo_unknown));
596
597        network.setText(display);
598    }
599
600    private final void
601    updateProperties() {
602        String s;
603        Resources r = getResources();
604
605        s = phone.getDeviceId();
606        if (s == null) s = r.getString(R.string.radioInfo_unknown);
607        mDeviceId.setText(s);
608
609
610        s = phone.getLine1Number();
611        if (s == null) s = r.getString(R.string.radioInfo_unknown);
612        number.setText(s);
613    }
614
615    private final void updateDataStats() {
616        String s;
617
618        s = SystemProperties.get("net.gsm.radio-reset", "0");
619        resets.setText(s);
620
621        s = SystemProperties.get("net.gsm.attempt-gprs", "0");
622        attempts.setText(s);
623
624        s = SystemProperties.get("net.gsm.succeed-gprs", "0");
625        successes.setText(s);
626
627        //s = SystemProperties.get("net.gsm.disconnect", "0");
628        //disconnects.setText(s);
629
630        s = SystemProperties.get("net.ppp.reset-by-timeout", "0");
631        sentSinceReceived.setText(s);
632    }
633
634    private final void updateDataStats2() {
635        Resources r = getResources();
636
637        long txPackets = TrafficStats.getMobileTxPackets();
638        long rxPackets = TrafficStats.getMobileRxPackets();
639        long txBytes   = TrafficStats.getMobileTxBytes();
640        long rxBytes   = TrafficStats.getMobileRxBytes();
641
642        String packets = r.getString(R.string.radioInfo_display_packets);
643        String bytes   = r.getString(R.string.radioInfo_display_bytes);
644
645        sent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes);
646        received.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes);
647    }
648
649    /**
650     * Ping a IP address.
651     */
652    private final void pingIpAddr() {
653        try {
654            // This is hardcoded IP addr. This is for testing purposes.
655            // We would need to get rid of this before release.
656            String ipAddress = "74.125.47.104";
657            Process p = Runtime.getRuntime().exec("ping -c 1 " + ipAddress);
658            int status = p.waitFor();
659            if (status == 0) {
660                mPingIpAddrResult = "Pass";
661            } else {
662                mPingIpAddrResult = "Fail: IP addr not reachable";
663            }
664        } catch (IOException e) {
665            mPingIpAddrResult = "Fail: IOException";
666        } catch (InterruptedException e) {
667            mPingIpAddrResult = "Fail: InterruptedException";
668        }
669    }
670
671    /**
672     *  Ping a host name
673     */
674    private final void pingHostname() {
675        try {
676            Process p = Runtime.getRuntime().exec("ping -c 1 www.google.com");
677            int status = p.waitFor();
678            if (status == 0) {
679                mPingHostnameResult = "Pass";
680            } else {
681                mPingHostnameResult = "Fail: Host unreachable";
682            }
683        } catch (UnknownHostException e) {
684            mPingHostnameResult = "Fail: Unknown Host";
685        } catch (IOException e) {
686            mPingHostnameResult= "Fail: IOException";
687        } catch (InterruptedException e) {
688            mPingHostnameResult = "Fail: InterruptedException";
689        }
690    }
691
692    /**
693     * This function checks for basic functionality of HTTP Client.
694     */
695    private void httpClientTest() {
696        HttpClient client = new DefaultHttpClient();
697        try {
698            HttpGet request = new HttpGet("http://www.google.com");
699            HttpResponse response = client.execute(request);
700            if (response.getStatusLine().getStatusCode() == 200) {
701                mHttpClientTestResult = "Pass";
702            } else {
703                mHttpClientTestResult = "Fail: Code: " + String.valueOf(response);
704            }
705            request.abort();
706        } catch (IOException e) {
707            mHttpClientTestResult = "Fail: IOException";
708        }
709    }
710
711    private void refreshSmsc() {
712        phone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
713    }
714
715    private final void updatePingState() {
716        final Handler handler = new Handler();
717        // Set all to unknown since the threads will take a few secs to update.
718        mPingIpAddrResult = getResources().getString(R.string.radioInfo_unknown);
719        mPingHostnameResult = getResources().getString(R.string.radioInfo_unknown);
720        mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown);
721
722        mPingIpAddr.setText(mPingIpAddrResult);
723        mPingHostname.setText(mPingHostnameResult);
724        mHttpClientTest.setText(mHttpClientTestResult);
725
726        final Runnable updatePingResults = new Runnable() {
727            public void run() {
728                mPingIpAddr.setText(mPingIpAddrResult);
729                mPingHostname.setText(mPingHostnameResult);
730                mHttpClientTest.setText(mHttpClientTestResult);
731            }
732        };
733        Thread ipAddr = new Thread() {
734            @Override
735            public void run() {
736                pingIpAddr();
737                handler.post(updatePingResults);
738            }
739        };
740        ipAddr.start();
741
742        Thread hostname = new Thread() {
743            @Override
744            public void run() {
745                pingHostname();
746                handler.post(updatePingResults);
747            }
748        };
749        hostname.start();
750
751        Thread httpClient = new Thread() {
752            @Override
753            public void run() {
754                httpClientTest();
755                handler.post(updatePingResults);
756            }
757        };
758        httpClient.start();
759    }
760
761    private final void updatePdpList() {
762        StringBuilder sb = new StringBuilder("========DATA=======\n");
763
764//        List<DataConnection> dcs = phone.getCurrentDataConnectionList();
765//
766//        for (DataConnection dc : dcs) {
767//            sb.append("    State=").append(dc.getStateAsString()).append("\n");
768//            if (dc.isActive()) {
769//                long timeElapsed =
770//                    (System.currentTimeMillis() - dc.getConnectionTime())/1000;
771//                sb.append("    connected at ")
772//                  .append(DateUtils.timeString(dc.getConnectionTime()))
773//                  .append(" and elapsed ")
774//                  .append(DateUtils.formatElapsedTime(timeElapsed));
775//
776//                if (dc instanceof GsmDataConnection) {
777//                    GsmDataConnection pdp = (GsmDataConnection)dc;
778//                    sb.append("\n    to ")
779//                      .append(pdp.getApn().toString());
780//                }
781//                sb.append("\nLinkProperties: ");
782//                sb.append(phone.getLinkProperties(phone.getActiveApnTypes()[0]).toString());
783//            } else if (dc.isInactive()) {
784//                sb.append("    disconnected with last try at ")
785//                  .append(DateUtils.timeString(dc.getLastFailTime()))
786//                  .append("\n    fail because ")
787//                  .append(dc.getLastFailCause().toString());
788//            } else {
789//                if (dc instanceof GsmDataConnection) {
790//                    GsmDataConnection pdp = (GsmDataConnection)dc;
791//                    sb.append("    is connecting to ")
792//                      .append(pdp.getApn().toString());
793//                } else {
794//                    sb.append("    is connecting");
795//                }
796//            }
797//            sb.append("\n===================");
798//        }
799
800        disconnects.setText(sb.toString());
801    }
802
803    private MenuItem.OnMenuItemClickListener mViewADNCallback = new MenuItem.OnMenuItemClickListener() {
804        public boolean onMenuItemClick(MenuItem item) {
805            Intent intent = new Intent(Intent.ACTION_VIEW);
806            // XXX We need to specify the component here because if we don't
807            // the activity manager will try to resolve the type by calling
808            // the content provider, which causes it to be loaded in a process
809            // other than the Dialer process, which causes a lot of stuff to
810            // break.
811            intent.setClassName("com.android.phone",
812                    "com.android.phone.SimContacts");
813            startActivity(intent);
814            return true;
815        }
816    };
817
818    private MenuItem.OnMenuItemClickListener mViewFDNCallback = new MenuItem.OnMenuItemClickListener() {
819        public boolean onMenuItemClick(MenuItem item) {
820            Intent intent = new Intent(Intent.ACTION_VIEW);
821            // XXX We need to specify the component here because if we don't
822            // the activity manager will try to resolve the type by calling
823            // the content provider, which causes it to be loaded in a process
824            // other than the Dialer process, which causes a lot of stuff to
825            // break.
826            intent.setClassName("com.android.phone",
827                    "com.android.phone.FdnList");
828            startActivity(intent);
829            return true;
830        }
831    };
832
833    private MenuItem.OnMenuItemClickListener mViewSDNCallback = new MenuItem.OnMenuItemClickListener() {
834        public boolean onMenuItemClick(MenuItem item) {
835            Intent intent = new Intent(
836                    Intent.ACTION_VIEW, Uri.parse("content://icc/sdn"));
837            // XXX We need to specify the component here because if we don't
838            // the activity manager will try to resolve the type by calling
839            // the content provider, which causes it to be loaded in a process
840            // other than the Dialer process, which causes a lot of stuff to
841            // break.
842            intent.setClassName("com.android.phone",
843                    "com.android.phone.ADNList");
844            startActivity(intent);
845            return true;
846        }
847    };
848
849    private MenuItem.OnMenuItemClickListener mGetPdpList = new MenuItem.OnMenuItemClickListener() {
850        public boolean onMenuItemClick(MenuItem item) {
851            phone.getDataCallList(null);
852            return true;
853        }
854    };
855
856    private MenuItem.OnMenuItemClickListener mSelectBandCallback = new MenuItem.OnMenuItemClickListener() {
857        public boolean onMenuItemClick(MenuItem item) {
858            Intent intent = new Intent();
859            intent.setClass(RadioInfo.this, BandMode.class);
860            startActivity(intent);
861            return true;
862        }
863    };
864
865    private MenuItem.OnMenuItemClickListener mToggleData = new MenuItem.OnMenuItemClickListener() {
866        public boolean onMenuItemClick(MenuItem item) {
867            ConnectivityManager cm =
868                    (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
869            int state = mTelephonyManager.getDataState();
870            switch (state) {
871                case TelephonyManager.DATA_CONNECTED:
872                    cm.setMobileDataEnabled(false);
873                    break;
874                case TelephonyManager.DATA_DISCONNECTED:
875                    cm.setMobileDataEnabled(true);
876                    break;
877                default:
878                    // do nothing
879                    break;
880            }
881            return true;
882        }
883    };
884
885    OnClickListener mPowerButtonHandler = new OnClickListener() {
886        public void onClick(View v) {
887            //log("toggle radio power: currently " + (isRadioOn()?"on":"off"));
888            phone.setRadioPower(!isRadioOn());
889        }
890    };
891
892    private Button imsRegRequiredButton;
893    static final String PROPERTY_IMS_REG_REQUIRED = "persist.radio.imsregrequired";
894    OnClickListener mImsRegRequiredHandler = new OnClickListener() {
895        @Override
896        public void onClick(View v) {
897            Log.d(TAG, String.format("toggle %s: currently %s",
898                PROPERTY_IMS_REG_REQUIRED, (isImsRegRequired() ? "on":"off")));
899            boolean newValue = !isImsRegRequired();
900            SystemProperties.set(PROPERTY_IMS_REG_REQUIRED,
901                    newValue ? "1":"0");
902            updateImsRegRequiredState();
903        }
904    };
905
906    private boolean isImsRegRequired() {
907        return SystemProperties.getBoolean(PROPERTY_IMS_REG_REQUIRED, false);
908    }
909
910    private void updateImsRegRequiredState() {
911        Log.d(TAG, "updateImsRegRequiredState isImsRegRequired()=" + isImsRegRequired());
912        String buttonText = isImsRegRequired() ?
913                            getString(R.string.ims_reg_required_off) :
914                            getString(R.string.ims_reg_required_on);
915        imsRegRequiredButton.setText(buttonText);
916    }
917
918    private Button smsOverImsButton;
919    static final String PROPERTY_SMS_OVER_IMS = "persist.radio.imsallowmtsms";
920    OnClickListener mSmsOverImsHandler = new OnClickListener() {
921        @Override
922        public void onClick(View v) {
923            Log.d(TAG, String.format("toggle %s: currently %s",
924                    PROPERTY_SMS_OVER_IMS, (isSmsOverImsEnabled() ? "on":"off")));
925            boolean newValue = !isSmsOverImsEnabled();
926            SystemProperties.set(PROPERTY_SMS_OVER_IMS, newValue ? "1":"0");
927            updateSmsOverImsState();
928        }
929    };
930
931    private boolean isSmsOverImsEnabled() {
932        return SystemProperties.getBoolean(PROPERTY_SMS_OVER_IMS, false);
933    }
934
935    private void updateSmsOverImsState() {
936        Log.d(TAG, "updateSmsOverImsState isSmsOverImsEnabled()=" + isSmsOverImsEnabled());
937        String buttonText = isSmsOverImsEnabled() ?
938                            getString(R.string.sms_over_ims_off) :
939                            getString(R.string.sms_over_ims_on);
940        smsOverImsButton.setText(buttonText);
941    }
942
943    private Button lteRamDumpButton;
944    static final String PROPERTY_LTE_RAM_DUMP = "persist.radio.ramdump";
945    OnClickListener mLteRamDumpHandler = new OnClickListener() {
946        @Override
947        public void onClick(View v) {
948            Log.d(TAG, String.format("toggle %s: currently %s",
949                    PROPERTY_LTE_RAM_DUMP, (isSmsOverImsEnabled() ? "on":"off")));
950            boolean newValue = !isLteRamDumpEnabled();
951            SystemProperties.set(PROPERTY_LTE_RAM_DUMP, newValue ? "1":"0");
952            updateLteRamDumpState();
953        }
954    };
955
956    private boolean isLteRamDumpEnabled() {
957        return SystemProperties.getBoolean(PROPERTY_LTE_RAM_DUMP, false);
958    }
959
960    private void updateLteRamDumpState() {
961        Log.d(TAG, "updateLteRamDumpState isLteRamDumpEnabled()=" + isLteRamDumpEnabled());
962        String buttonText = isLteRamDumpEnabled() ?
963                            getString(R.string.lte_ram_dump_off) :
964                            getString(R.string.lte_ram_dump_on);
965        lteRamDumpButton.setText(buttonText);
966    }
967
968    OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
969        public void onClick(View v) {
970            phone.disableDnsCheck(!phone.isDnsCheckDisabled());
971            updateDnsCheckState();
972        }
973    };
974
975    OnClickListener mOemInfoButtonHandler = new OnClickListener() {
976        public void onClick(View v) {
977            Intent intent = new Intent("com.android.settings.OEM_RADIO_INFO");
978            try {
979                startActivity(intent);
980            } catch (android.content.ActivityNotFoundException ex) {
981                Log.d(TAG, "OEM-specific Info/Settings Activity Not Found : " + ex);
982                // If the activity does not exist, there are no OEM
983                // settings, and so we can just do nothing...
984            }
985        }
986    };
987
988    OnClickListener mPingButtonHandler = new OnClickListener() {
989        public void onClick(View v) {
990            updatePingState();
991        }
992    };
993
994    OnClickListener mUpdateSmscButtonHandler = new OnClickListener() {
995        public void onClick(View v) {
996            updateSmscButton.setEnabled(false);
997            phone.setSmscAddress(smsc.getText().toString(),
998                    mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE));
999        }
1000    };
1001
1002    OnClickListener mRefreshSmscButtonHandler = new OnClickListener() {
1003        public void onClick(View v) {
1004            refreshSmsc();
1005        }
1006    };
1007
1008    AdapterView.OnItemSelectedListener
1009            mPreferredNetworkHandler = new AdapterView.OnItemSelectedListener() {
1010        public void onItemSelected(AdapterView parent, View v, int pos, long id) {
1011            Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
1012            if (pos>=0 && pos<=7) { //IS THIS NEEDED to extend to the entire range of values
1013                phone.setPreferredNetworkType(pos, msg);
1014            }
1015        }
1016
1017        public void onNothingSelected(AdapterView parent) {
1018        }
1019    };
1020
1021    private String[] mPreferredNetworkLabels = {
1022            "WCDMA preferred",
1023            "GSM only",
1024            "WCDMA only",
1025            "GSM auto (PRL)",
1026            "CDMA auto (PRL)",
1027            "CDMA only",
1028            "EvDo only",
1029            "GSM/CDMA auto (PRL)",
1030            "Unknown"};
1031}
1032