RadioInfo.java revision 86997beac8ccd3d9e1deedb4a7afe6ddeb3a0bd7
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.content.DialogInterface;
22import android.content.Intent;
23import android.content.SharedPreferences;
24import android.content.res.Resources;
25import android.net.Uri;
26import android.os.AsyncResult;
27import android.os.Bundle;
28import android.os.Handler;
29import android.os.INetStatService;
30import android.os.Message;
31import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.os.SystemProperties;
34import android.preference.PreferenceManager;
35import android.telephony.CellLocation;
36import android.telephony.PhoneStateListener;
37import android.telephony.ServiceState;
38import android.telephony.TelephonyManager;
39import android.telephony.NeighboringCellInfo;
40import android.telephony.gsm.GsmCellLocation;
41import android.text.format.DateUtils;
42import android.util.Log;
43import android.view.Menu;
44import android.view.MenuItem;
45import android.view.View;
46import android.view.View.OnClickListener;
47import android.widget.AdapterView;
48import android.widget.ArrayAdapter;
49import android.widget.Button;
50import android.widget.Spinner;
51import android.widget.TextView;
52import android.widget.EditText;
53
54import com.android.internal.telephony.Phone;
55import com.android.internal.telephony.PhoneFactory;
56import com.android.internal.telephony.PhoneStateIntentReceiver;
57import com.android.internal.telephony.TelephonyProperties;
58import com.android.internal.telephony.gsm.GSMPhone;
59import com.android.internal.telephony.gsm.PdpConnection;
60
61import org.apache.http.HttpResponse;
62import org.apache.http.client.HttpClient;
63import org.apache.http.client.methods.HttpGet;
64import org.apache.http.impl.client.DefaultHttpClient;
65
66import java.io.ByteArrayOutputStream;
67import java.io.DataOutputStream;
68import java.io.IOException;
69import java.net.UnknownHostException;
70import java.util.ArrayList;
71import java.util.List;
72
73public class RadioInfo extends Activity {
74    private final String TAG = "phone";
75
76    private static final int EVENT_PHONE_STATE_CHANGED = 100;
77    private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 200;
78    private static final int EVENT_SERVICE_STATE_CHANGED = 300;
79    private static final int EVENT_CFI_CHANGED = 302;
80
81    private static final int EVENT_QUERY_PREFERRED_TYPE_DONE = 1000;
82    private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001;
83    private static final int EVENT_QUERY_NEIGHBORING_CIDS_DONE = 1002;
84    private static final int EVENT_SET_QXDMLOG_DONE = 1003;
85    private static final int EVENT_SET_CIPHER_DONE = 1004;
86    private static final int EVENT_QUERY_SMSC_DONE = 1005;
87    private static final int EVENT_UPDATE_SMSC_DONE = 1006;
88
89    private static final int MENU_ITEM_SELECT_BAND  = 0;
90    private static final int MENU_ITEM_VIEW_ADN     = 1;
91    private static final int MENU_ITEM_VIEW_FDN     = 2;
92    private static final int MENU_ITEM_VIEW_SDN     = 3;
93    private static final int MENU_ITEM_GET_PDP_LIST = 4;
94    private static final int MENU_ITEM_TOGGLE_DATA  = 5;
95    private static final int MENU_ITEM_TOGGLE_DATA_ON_BOOT = 6;
96
97    private TextView mImei;
98    private TextView number;
99    private TextView callState;
100    private TextView operatorName;
101    private TextView roamingState;
102    private TextView gsmState;
103    private TextView gprsState;
104    private TextView network;
105    private TextView dBm;
106    private TextView mMwi;
107    private TextView mCfi;
108    private TextView mLocation;
109    private TextView mNeighboringCids;
110    private TextView resets;
111    private TextView attempts;
112    private TextView successes;
113    private TextView disconnects;
114    private TextView sentSinceReceived;
115    private TextView sent;
116    private TextView received;
117    private TextView mPingIpAddr;
118    private TextView mPingHostname;
119    private TextView mHttpClientTest;
120    private TextView cipherState;
121    private TextView dnsCheckState;
122    private EditText smsc;
123    private Button radioPowerButton;
124    private Button qxdmLogButton;
125    private Button cipherToggleButton;
126    private Button dnsCheckToggleButton;
127    private Button pingTestButton;
128    private Button updateSmscButton;
129    private Button refreshSmscButton;
130    private Spinner preferredNetworkType;
131
132    private TelephonyManager mTelephonyManager;
133    private Phone phone = null;
134    private PhoneStateIntentReceiver mPhoneStateReceiver;
135    private INetStatService netstat;
136
137    private OemCommands mOem = null;
138    private boolean mQxdmLogEnabled;
139    // The requested cipher state
140    private boolean mCipherOn;
141
142    private String mPingIpAddrResult;
143    private String mPingHostnameResult;
144    private String mHttpClientTestResult;
145    private boolean mMwiValue = false;
146    private boolean mCfiValue = false;
147
148    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
149        @Override
150        public void onDataConnectionStateChanged(int state) {
151            updateDataState();
152            updateDataStats();
153            updatePdpList();
154            updateNetworkType();
155        }
156
157        @Override
158        public void onDataActivity(int direction) {
159            updateDataStats2();
160        }
161
162        @Override
163        public void onCellLocationChanged(CellLocation location) {
164            updateLocation(location);
165        }
166
167        @Override
168        public void onMessageWaitingIndicatorChanged(boolean mwi) {
169            mMwiValue = mwi;
170            updateMessageWaiting();
171        }
172
173        @Override
174        public void onCallForwardingIndicatorChanged(boolean cfi) {
175            mCfiValue = cfi;
176            updateCallRedirect();
177        }
178    };
179
180    private Handler mHandler = new Handler() {
181        public void handleMessage(Message msg) {
182            AsyncResult ar;
183            switch (msg.what) {
184                case EVENT_PHONE_STATE_CHANGED:
185                    updatePhoneState();
186                    break;
187
188                case EVENT_SIGNAL_STRENGTH_CHANGED:
189                    updateSignalStrength();
190                    break;
191
192                case EVENT_SERVICE_STATE_CHANGED:
193                    updateServiceState();
194                    updatePowerState();
195                    break;
196
197                case EVENT_QUERY_PREFERRED_TYPE_DONE:
198                    ar= (AsyncResult) msg.obj;
199                    if (ar.exception == null) {
200                        int type = ((int[])ar.result)[0];
201                        preferredNetworkType.setSelection(type, true);
202                    } else {
203                        preferredNetworkType.setSelection(3, true);
204                    }
205                    break;
206                case EVENT_SET_PREFERRED_TYPE_DONE:
207                    ar= (AsyncResult) msg.obj;
208                    if (ar.exception != null) {
209                        phone.getPreferredNetworkType(
210                                obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
211                    }
212                    break;
213                case EVENT_QUERY_NEIGHBORING_CIDS_DONE:
214                    ar= (AsyncResult) msg.obj;
215                    if (ar.exception == null) {
216                        updateNeighboringCids((ArrayList<NeighboringCellInfo>)ar.result);
217                    } else {
218                        mNeighboringCids.setText("unknown");
219                    }
220                    break;
221                case EVENT_SET_QXDMLOG_DONE:
222                    ar= (AsyncResult) msg.obj;
223                    if (ar.exception == null) {
224                        mQxdmLogEnabled = !mQxdmLogEnabled;
225
226                        updateQxdmState(mQxdmLogEnabled);
227                        displayQxdmEnableResult();
228                    }
229                    break;
230                case EVENT_SET_CIPHER_DONE:
231                    ar= (AsyncResult) msg.obj;
232                    if (ar.exception == null) {
233                        setCiphPref(mCipherOn);
234                    }
235                    updateCiphState();
236                    break;
237                case EVENT_QUERY_SMSC_DONE:
238                    ar= (AsyncResult) msg.obj;
239                    if (ar.exception != null) {
240                        smsc.setText("refresh error");
241                    } else {
242                        byte[] buf = (byte[]) ar.result;
243                        smsc.setText(new String(buf));
244                    }
245                    break;
246                case EVENT_UPDATE_SMSC_DONE:
247                    updateSmscButton.setEnabled(true);
248                    ar= (AsyncResult) msg.obj;
249                    if (ar.exception != null) {
250                        smsc.setText("update error");
251                    }
252                    break;
253                default:
254                    break;
255
256            }
257        }
258    };
259
260    private class OemCommands {
261
262        public  final int OEM_QXDM_SDLOG_DEFAULT_FILE_SIZE = 32;
263        public  final int OEM_QXDM_SDLOG_DEFAULT_MASK = 0;
264        public  final int OEM_QXDM_SDLOG_DEFAULT_MAX_INDEX = 8;
265
266        final int SIZE_OF_INT = 4;
267        final int OEM_FEATURE_ENABLE = 1;
268        final int OEM_FEATURE_DISABLE = 0;
269        final int OEM_SIMPE_FEAUTURE_LEN = 1;
270
271        final int OEM_QXDM_SDLOG_FUNCTAG = 0x00010000;
272        final int OEM_QXDM_SDLOG_LEN = 4;
273        final int OEM_PS_AUTO_ATTACH_FUNCTAG = 0x00020000;
274        final int OEM_CIPHERING_FUNCTAG = 0x00020001;
275        final int OEM_SMSC_UPDATE_FUNCTAG = 0x00020002;
276        final int OEM_SMSC_QUERY_FUNCTAG = 0x00020003;
277        final int OEM_SMSC_QUERY_LEN = 0;
278
279        /**
280         * The OEM interface to store QXDM to SD.
281         *
282         * To start/stop logging QXDM logs to SD card, use tag
283         * OEM_RIL_HOOK_QXDM_SD_LOG_SETUP 0x00010000
284         *
285         * "data" is a const oem_ril_hook_qxdm_sdlog_setup_data_st *
286         * ((const oem_ril_hook_qxdm_sdlog_setup_data_st *)data)->head.func_tag
287         * should be OEM_RIL_HOOK_QXDM_SD_LOG_SETUP
288         * ((const oem_ril_hook_qxdm_sdlog_setup_data_st *)data)->head.len
289         * should be "sizeof(unsigned int) * 4"
290         * ((const oem_ril_hook_qxdm_sdlog_setup_data_st *)data)->mode
291         * could be 0 for 'stop logging', or 1 for 'start logging'
292         * ((const oem_ril_hook_qxdm_sdlog_setup_data_st *)data)->log_file_size
293         * will assign the size of each log file, and it could be a value between
294         * 1 and 512 (in megabytes, default value is recommended to set as 32).
295         * This value will be ignored when mode == 0.
296         * ((const oem_ril_hook_qxdm_sdlog_setup_data_st *)data)->log_mask will
297         * assign the rule to filter logs, and it is a bitmask (bit0 is for MsgAll,
298         * bit1 is for LogAll, and bit2 is for EventAll) recommended to be set as 0
299         * by default. This value will be ignored when mode == 0.
300         * ((const oem_ril_hook_qxdm_sdlog_setup_data_st *)data)->log_max_fileindex
301         * set the how many logfiles will storted before roll over. This value will
302         * be ignored when mode == 0.
303         *
304         * "response" is NULL
305         *
306         * typedef struct _oem_ril_hook_raw_head_st {
307         *      unsigned int func_tag;
308         *      unsigned int len;
309         * } oem_ril_hook_raw_head_st;
310         *
311         * typedef struct _oem_ril_hook_qxdm_sdlog_setup_data_st {
312         *      oem_ril_hook_raw_head_st head;
313         *      unsigned int mode;
314         *      unsigned int log_file_size;
315         *      unsigned int log_mask;
316         *      unsigned int log_max_fileindex;
317         * } oem_ril_hook_qxdm_sdlog_setup_data_st;
318         *
319         * @param enable set true to start logging QXDM in SD card
320         * @param fileSize is the log file size in MB
321         * @param mask is the log mask to filter
322         * @param maxIndex is the maximum roll-over file number
323         * @return byteArray to use in RIL RAW command
324         */
325        byte[] getQxdmSdlogData(boolean enable, int fileSize, int mask, int maxIndex) {
326            ByteArrayOutputStream bos = new ByteArrayOutputStream();
327            DataOutputStream dos = new DataOutputStream(bos);
328            try {
329                writeIntLittleEndian(dos, OEM_QXDM_SDLOG_FUNCTAG);
330                writeIntLittleEndian(dos, OEM_QXDM_SDLOG_LEN * SIZE_OF_INT);
331                writeIntLittleEndian(dos, enable ?
332                        OEM_FEATURE_ENABLE : OEM_FEATURE_DISABLE);
333                writeIntLittleEndian(dos, fileSize);
334                writeIntLittleEndian(dos, mask);
335                writeIntLittleEndian(dos, maxIndex);
336            } catch (IOException e) {
337                return null;
338            }
339            return bos.toByteArray();
340        }
341
342        byte[] getSmscQueryData() {
343            ByteArrayOutputStream bos = new ByteArrayOutputStream();
344            DataOutputStream dos = new DataOutputStream(bos);
345            try {
346                writeIntLittleEndian(dos, OEM_SMSC_QUERY_FUNCTAG);
347                writeIntLittleEndian(dos, OEM_SMSC_QUERY_LEN * SIZE_OF_INT);
348            } catch (IOException e) {
349                return null;
350            }
351            return bos.toByteArray();
352        }
353
354        byte[] getSmscUpdateData(String smsc) {
355            ByteArrayOutputStream bos = new ByteArrayOutputStream();
356            DataOutputStream dos = new DataOutputStream(bos);
357            try {
358                byte[] smsc_bytes = smsc.getBytes();
359                writeIntLittleEndian(dos, OEM_SMSC_UPDATE_FUNCTAG);
360                writeIntLittleEndian(dos, smsc_bytes.length);
361                dos.write(smsc_bytes);
362            } catch (IOException e) {
363                return null;
364            }
365            return bos.toByteArray();
366        }
367
368        byte[] getPsAutoAttachData(boolean enable) {
369            return getSimpleFeatureData(OEM_PS_AUTO_ATTACH_FUNCTAG, enable);
370        }
371
372        byte[] getCipheringData(boolean enable) {
373            return getSimpleFeatureData(OEM_CIPHERING_FUNCTAG, enable);
374        }
375
376        private byte[] getSimpleFeatureData(int tag, boolean enable) {
377            ByteArrayOutputStream bos = new ByteArrayOutputStream();
378            DataOutputStream dos = new DataOutputStream(bos);
379            try {
380                writeIntLittleEndian(dos, tag);
381                writeIntLittleEndian(dos, OEM_SIMPE_FEAUTURE_LEN * SIZE_OF_INT);
382                writeIntLittleEndian(dos, enable ?
383                        OEM_FEATURE_ENABLE : OEM_FEATURE_DISABLE);
384            } catch (IOException e) {
385                return null;
386            }
387            return bos.toByteArray();
388        }
389
390        private void writeIntLittleEndian(DataOutputStream dos, int val)
391                throws IOException {
392            dos.writeByte(val);
393            dos.writeByte(val >> 8);
394            dos.writeByte(val >> 16);
395            dos.writeByte(val >> 24);
396        }
397    }
398
399    @Override
400    public void onCreate(Bundle icicle) {
401        super.onCreate(icicle);
402
403        setContentView(R.layout.radio_info);
404
405        mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
406        phone = PhoneFactory.getDefaultPhone();
407
408        mImei = (TextView) findViewById(R.id.imei);
409        number = (TextView) findViewById(R.id.number);
410        callState = (TextView) findViewById(R.id.call);
411        operatorName = (TextView) findViewById(R.id.operator);
412        roamingState = (TextView) findViewById(R.id.roaming);
413        gsmState = (TextView) findViewById(R.id.gsm);
414        gprsState = (TextView) findViewById(R.id.gprs);
415        network = (TextView) findViewById(R.id.network);
416        dBm = (TextView) findViewById(R.id.dbm);
417        mMwi = (TextView) findViewById(R.id.mwi);
418        mCfi = (TextView) findViewById(R.id.cfi);
419        mLocation = (TextView) findViewById(R.id.location);
420        mNeighboringCids = (TextView) findViewById(R.id.neighboring);
421
422        resets = (TextView) findViewById(R.id.resets);
423        attempts = (TextView) findViewById(R.id.attempts);
424        successes = (TextView) findViewById(R.id.successes);
425        disconnects = (TextView) findViewById(R.id.disconnects);
426        sentSinceReceived = (TextView) findViewById(R.id.sentSinceReceived);
427        sent = (TextView) findViewById(R.id.sent);
428        received = (TextView) findViewById(R.id.received);
429        cipherState = (TextView) findViewById(R.id.ciphState);
430        smsc = (EditText) findViewById(R.id.smsc);
431        dnsCheckState = (TextView) findViewById(R.id.dnsCheckState);
432
433        mPingIpAddr = (TextView) findViewById(R.id.pingIpAddr);
434        mPingHostname = (TextView) findViewById(R.id.pingHostname);
435        mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
436
437        preferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
438        ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,
439                android.R.layout.simple_spinner_item, mPreferredNetworkLabels);
440        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
441        preferredNetworkType.setAdapter(adapter);
442        preferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
443
444        radioPowerButton = (Button) findViewById(R.id.radio_power);
445        radioPowerButton.setOnClickListener(mPowerButtonHandler);
446
447        qxdmLogButton = (Button) findViewById(R.id.qxdm_log);
448        qxdmLogButton.setOnClickListener(mQxdmButtonHandler);
449
450        cipherToggleButton = (Button) findViewById(R.id.ciph_toggle);
451        cipherToggleButton.setOnClickListener(mCipherButtonHandler);
452        pingTestButton = (Button) findViewById(R.id.ping_test);
453        pingTestButton.setOnClickListener(mPingButtonHandler);
454        updateSmscButton = (Button) findViewById(R.id.update_smsc);
455        updateSmscButton.setOnClickListener(mUpdateSmscButtonHandler);
456        refreshSmscButton = (Button) findViewById(R.id.refresh_smsc);
457        refreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
458        dnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle);
459        dnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler);
460
461        mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);
462        mPhoneStateReceiver.notifySignalStrength(EVENT_SIGNAL_STRENGTH_CHANGED);
463        mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
464        mPhoneStateReceiver.notifyPhoneCallState(EVENT_PHONE_STATE_CHANGED);
465
466        updateQxdmState(null);
467        mOem = new OemCommands();
468
469        phone.getPreferredNetworkType(
470                mHandler.obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
471        phone.getNeighboringCids(
472                mHandler.obtainMessage(EVENT_QUERY_NEIGHBORING_CIDS_DONE));
473
474        netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));
475
476        CellLocation.requestLocationUpdate();
477    }
478
479    @Override
480    protected void onResume() {
481        super.onResume();
482
483        updatePhoneState();
484        updateSignalStrength();
485        updateMessageWaiting();
486        updateCallRedirect();
487        updateServiceState();
488        updateLocation(mTelephonyManager.getCellLocation());
489        updateDataState();
490        updateDataStats();
491        updateDataStats2();
492        updatePowerState();
493        updateQxdmState(null);
494        updateProperties();
495        updateCiphState();
496        updateDnsCheckState();
497
498        Log.i(TAG, "[RadioInfo] onResume: register phone & data intents");
499
500        mPhoneStateReceiver.registerIntent();
501        mTelephonyManager.listen(mPhoneStateListener,
502                  PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
503                | PhoneStateListener.LISTEN_DATA_ACTIVITY
504                | PhoneStateListener.LISTEN_CELL_LOCATION
505                | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
506                | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR);
507    }
508
509    @Override
510    public void onPause() {
511        super.onPause();
512
513        Log.i(TAG, "[RadioInfo] onPause: unregister phone & data intents");
514
515        mPhoneStateReceiver.unregisterIntent();
516        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
517    }
518
519    @Override
520    public boolean onCreateOptionsMenu(Menu menu) {
521        menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label).setOnMenuItemClickListener(mSelectBandCallback)
522                .setAlphabeticShortcut('b');
523        menu.add(1, MENU_ITEM_VIEW_ADN, 0,
524                R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback);
525        menu.add(1, MENU_ITEM_VIEW_FDN, 0,
526                R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
527        menu.add(1, MENU_ITEM_VIEW_SDN, 0,
528                R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
529        menu.add(1, MENU_ITEM_GET_PDP_LIST,
530                0, R.string.radioInfo_menu_getPDP).setOnMenuItemClickListener(mGetPdpList);
531        menu.add(1, MENU_ITEM_TOGGLE_DATA,
532                0, R.string.radioInfo_menu_disableData).setOnMenuItemClickListener(mToggleData);
533        menu.add(1, MENU_ITEM_TOGGLE_DATA_ON_BOOT,
534                0, R.string.radioInfo_menu_disableDataOnBoot).setOnMenuItemClickListener(mToggleDataOnBoot);
535        return true;
536    }
537
538
539    @Override
540    public boolean onPrepareOptionsMenu(Menu menu)
541    {
542        // Get the TOGGLE DATA menu item in the right state.
543        MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA);
544        int state = mTelephonyManager.getDataState();
545        boolean visible = true;
546
547        switch (state) {
548            case TelephonyManager.DATA_CONNECTED:
549            case TelephonyManager.DATA_SUSPENDED:
550                item.setTitle(R.string.radioInfo_menu_disableData);
551                break;
552            case TelephonyManager.DATA_DISCONNECTED:
553                item.setTitle(R.string.radioInfo_menu_enableData);
554                break;
555            default:
556                visible = false;
557                break;
558        }
559        item.setVisible(visible);
560
561        // Get the toggle-data-on-boot menu item in the right state.
562        item = menu.findItem(MENU_ITEM_TOGGLE_DATA_ON_BOOT);
563        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
564        boolean value = sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
565        if (value) {
566            item.setTitle(R.string.radioInfo_menu_enableDataOnBoot);
567        } else {
568            item.setTitle(R.string.radioInfo_menu_disableDataOnBoot);
569        }
570        return true;
571    }
572
573    private boolean isRadioOn() {
574        return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
575    }
576
577    private void updatePowerState() {
578    	//log("updatePowerState");
579        String buttonText = isRadioOn() ?
580                            getString(R.string.turn_off_radio) :
581                            getString(R.string.turn_on_radio);
582        radioPowerButton.setText(buttonText);
583    }
584
585    private void updateQxdmState(Boolean newQxdmStatus) {
586        SharedPreferences sp =
587          PreferenceManager.getDefaultSharedPreferences(phone.getContext());
588        mQxdmLogEnabled = sp.getBoolean("qxdmstatus", false);
589        // This is called from onCreate, onResume, and the handler when the status
590        // is updated.
591        if (newQxdmStatus != null) {
592            SharedPreferences.Editor editor = sp.edit();
593            editor.putBoolean("qxdmstatus", newQxdmStatus);
594            editor.commit();
595            mQxdmLogEnabled = newQxdmStatus;
596        }
597
598        String buttonText = mQxdmLogEnabled ?
599                            getString(R.string.turn_off_qxdm) :
600                            getString(R.string.turn_on_qxdm);
601        qxdmLogButton.setText(buttonText);
602    }
603
604    private void setCiphPref(boolean value) {
605        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
606        SharedPreferences.Editor editor = sp.edit();
607        editor.putBoolean(GSMPhone.CIPHERING_KEY, value);
608        editor.commit();
609    }
610
611    private boolean getCiphPref() {
612        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
613        boolean ret = sp.getBoolean(GSMPhone.CIPHERING_KEY, true);
614        return ret;
615    }
616
617    private void updateCiphState() {
618        cipherState.setText(getCiphPref() ? "Ciphering ON" : "Ciphering OFF");
619    }
620
621    private void updateDnsCheckState() {
622        GSMPhone gsmPhone = (GSMPhone) phone;
623        dnsCheckState.setText(gsmPhone.isDnsCheckDisabled() ?
624                "0.0.0.0 allowed" :"0.0.0.0 not allowed");
625    }
626
627    private final void
628    updateSignalStrength() {
629        int state =
630                mPhoneStateReceiver.getServiceState().getState();
631        Resources r = getResources();
632
633        if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
634                (ServiceState.STATE_POWER_OFF == state)) {
635            dBm.setText("0");
636        }
637
638        int signalDbm = mPhoneStateReceiver.getSignalStrengthDbm();
639
640        if (-1 == signalDbm) signalDbm = 0;
641
642        int signalAsu = mPhoneStateReceiver.getSignalStrength();
643
644        if (-1 == signalAsu) signalAsu = 0;
645
646        dBm.setText(String.valueOf(signalDbm) + " "
647            + r.getString(R.string.radioInfo_display_dbm) + "   "
648            + String.valueOf(signalAsu) + " "
649            + r.getString(R.string.radioInfo_display_asu));
650    }
651
652    private final void updateLocation(CellLocation location) {
653        GsmCellLocation loc = (GsmCellLocation)location;
654        Resources r = getResources();
655
656        int lac = loc.getLac();
657        int cid = loc.getCid();
658
659        mLocation.setText(r.getString(R.string.radioInfo_lac) + " = "
660                          + ((lac == -1) ? "unknown" : Integer.toHexString(lac))
661                          + "   "
662                          + r.getString(R.string.radioInfo_cid) + " = "
663                + ((cid == -1) ? "unknown" : Integer.toHexString(cid)));
664    }
665
666    private final void updateNeighboringCids(ArrayList<NeighboringCellInfo> cids) {
667        String neighborings = "";
668        if (cids != null) {
669            if ( cids.isEmpty() ) {
670                neighborings = "no neighboring cells";
671            } else {
672                for (NeighboringCellInfo cell : cids) {
673                    neighborings += "{" + Integer.toHexString(cell.getCid())
674                    + "@" + cell.getRssi() + "} ";
675                }
676            }
677        } else {
678            neighborings = "unknown";
679        }
680        mNeighboringCids.setText(neighborings);
681    }
682
683    private final void
684    updateMessageWaiting() {
685        mMwi.setText(String.valueOf(mMwiValue));
686    }
687
688    private final void
689    updateCallRedirect() {
690        mCfi.setText(String.valueOf(mCfiValue));
691    }
692
693
694    private final void
695    updateServiceState() {
696        ServiceState serviceState = mPhoneStateReceiver.getServiceState();
697        int state = serviceState.getState();
698        Resources r = getResources();
699        String display = r.getString(R.string.radioInfo_unknown);
700
701        switch (state) {
702            case ServiceState.STATE_IN_SERVICE:
703                display = r.getString(R.string.radioInfo_service_in);
704                break;
705            case ServiceState.STATE_OUT_OF_SERVICE:
706            case ServiceState.STATE_EMERGENCY_ONLY:
707                display = r.getString(R.string.radioInfo_service_emergency);
708                break;
709            case ServiceState.STATE_POWER_OFF:
710                display = r.getString(R.string.radioInfo_service_off);
711                break;
712        }
713
714        gsmState.setText(display);
715
716        if (serviceState.getRoaming()) {
717            roamingState.setText(R.string.radioInfo_roaming_in);
718        } else {
719            roamingState.setText(R.string.radioInfo_roaming_not);
720        }
721
722        operatorName.setText(serviceState.getOperatorAlphaLong());
723    }
724
725    private final void
726    updatePhoneState() {
727        Phone.State state = mPhoneStateReceiver.getPhoneState();
728        Resources r = getResources();
729        String display = r.getString(R.string.radioInfo_unknown);
730
731        switch (state) {
732            case IDLE:
733                display = r.getString(R.string.radioInfo_phone_idle);
734                break;
735            case RINGING:
736                display = r.getString(R.string.radioInfo_phone_ringing);
737                break;
738            case OFFHOOK:
739                display = r.getString(R.string.radioInfo_phone_offhook);
740                break;
741        }
742
743        callState.setText(display);
744    }
745
746    private final void
747    updateDataState() {
748        int state = mTelephonyManager.getDataState();
749        Resources r = getResources();
750        String display = r.getString(R.string.radioInfo_unknown);
751
752        switch (state) {
753            case TelephonyManager.DATA_CONNECTED:
754                display = r.getString(R.string.radioInfo_data_connected);
755                break;
756            case TelephonyManager.DATA_CONNECTING:
757                display = r.getString(R.string.radioInfo_data_connecting);
758                break;
759            case TelephonyManager.DATA_DISCONNECTED:
760                display = r.getString(R.string.radioInfo_data_disconnected);
761                break;
762            case TelephonyManager.DATA_SUSPENDED:
763                display = r.getString(R.string.radioInfo_data_suspended);
764                break;
765        }
766
767        gprsState.setText(display);
768    }
769
770    private final void updateNetworkType() {
771        Resources r = getResources();
772        String display = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
773                r.getString(R.string.radioInfo_unknown));
774
775        network.setText(display);
776    }
777
778    private final void
779    updateProperties() {
780        String s;
781        Resources r = getResources();
782
783        s = phone.getDeviceId();
784        if (s == null) s = r.getString(R.string.radioInfo_unknown);
785        mImei.setText(s);
786
787        s = phone.getLine1Number();
788        if (s == null) s = r.getString(R.string.radioInfo_unknown);
789        number.setText(s);
790    }
791
792    private final void updateDataStats() {
793        String s;
794
795        s = SystemProperties.get("net.gsm.radio-reset", "0");
796        resets.setText(s);
797
798        s = SystemProperties.get("net.gsm.attempt-gprs", "0");
799        attempts.setText(s);
800
801        s = SystemProperties.get("net.gsm.succeed-gprs", "0");
802        successes.setText(s);
803
804        //s = SystemProperties.get("net.gsm.disconnect", "0");
805        //disconnects.setText(s);
806
807        s = SystemProperties.get("net.ppp.reset-by-timeout", "0");
808        sentSinceReceived.setText(s);
809    }
810
811    private final void updateDataStats2() {
812        Resources r = getResources();
813
814        try {
815            long txPackets = netstat.getMobileTxPackets();
816            long rxPackets = netstat.getMobileRxPackets();
817            long txBytes   = netstat.getMobileTxBytes();
818            long rxBytes   = netstat.getMobileRxBytes();
819
820            String packets = r.getString(R.string.radioInfo_display_packets);
821            String bytes   = r.getString(R.string.radioInfo_display_bytes);
822
823            sent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes);
824            received.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes);
825        } catch (RemoteException e) {
826        }
827    }
828
829    /**
830     * Ping a IP address.
831     */
832    private final void pingIpAddr() {
833        try {
834            // This is hardcoded IP addr. This is for testing purposes.
835            // We would need to get rid of this before release.
836            String ipAddress = "74.125.47.104";
837            Process p = Runtime.getRuntime().exec("ping -c 1 " + ipAddress);
838            int status = p.waitFor();
839            if (status == 0) {
840                mPingIpAddrResult = "Pass";
841            } else {
842                mPingIpAddrResult = "Fail: IP addr not reachable";
843            }
844        } catch (IOException e) {
845            mPingIpAddrResult = "Fail: IOException";
846        } catch (InterruptedException e) {
847            mPingIpAddrResult = "Fail: InterruptedException";
848        }
849    }
850
851    /**
852     *  Ping a host name
853     */
854    private final void pingHostname() {
855        try {
856            Process p = Runtime.getRuntime().exec("ping -c 1 www.google.com");
857            int status = p.waitFor();
858            if (status == 0) {
859                mPingHostnameResult = "Pass";
860            } else {
861                mPingHostnameResult = "Fail: Host unreachable";
862            }
863        } catch (UnknownHostException e) {
864            mPingHostnameResult = "Fail: Unknown Host";
865        } catch (IOException e) {
866            mPingHostnameResult= "Fail: IOException";
867        } catch (InterruptedException e) {
868            mPingHostnameResult = "Fail: InterruptedException";
869        }
870    }
871
872    /**
873     * This function checks for basic functionality of HTTP Client.
874     */
875    private void httpClientTest() {
876        HttpClient client = new DefaultHttpClient();
877        try {
878            HttpGet request = new HttpGet("http://www.google.com");
879            HttpResponse response = client.execute(request);
880            if (response.getStatusLine().getStatusCode() == 200) {
881                mHttpClientTestResult = "Pass";
882            } else {
883                mHttpClientTestResult = "Fail: Code: " + String.valueOf(response);
884            }
885            request.abort();
886        } catch (IOException e) {
887            mHttpClientTestResult = "Fail: IOException";
888        }
889    }
890
891    private void refreshSmsc() {
892        byte[] data = mOem.getSmscQueryData();
893        if (data == null) return;
894        phone.invokeOemRilRequestRaw(data,
895                mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
896    }
897
898    private final void updatePingState() {
899        final Handler handler = new Handler();
900        // Set all to unknown since the threads will take a few secs to update.
901        mPingIpAddrResult = getResources().getString(R.string.radioInfo_unknown);
902        mPingHostnameResult = getResources().getString(R.string.radioInfo_unknown);
903        mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown);
904
905        mPingIpAddr.setText(mPingIpAddrResult);
906        mPingHostname.setText(mPingHostnameResult);
907        mHttpClientTest.setText(mHttpClientTestResult);
908
909        final Runnable updatePingResults = new Runnable() {
910            public void run() {
911                mPingIpAddr.setText(mPingIpAddrResult);
912                mPingHostname.setText(mPingHostnameResult);
913                mHttpClientTest.setText(mHttpClientTestResult);
914            }
915        };
916        Thread ipAddr = new Thread() {
917            @Override
918            public void run() {
919                pingIpAddr();
920                handler.post(updatePingResults);
921            }
922        };
923        ipAddr.start();
924
925        Thread hostname = new Thread() {
926            @Override
927            public void run() {
928                pingHostname();
929                handler.post(updatePingResults);
930            }
931        };
932        hostname.start();
933
934        Thread httpClient = new Thread() {
935            @Override
936            public void run() {
937                httpClientTest();
938                handler.post(updatePingResults);
939            }
940        };
941        httpClient.start();
942    }
943
944    private final void updatePdpList() {
945        StringBuilder sb = new StringBuilder("========DATA=======\n");
946
947        List<PdpConnection> pdps = phone.getCurrentPdpList();
948
949        for (PdpConnection pdp : pdps) {
950            sb.append("    State: ").append(pdp.getState().toString()).append("\n");
951            if (pdp.getState().isActive()) {
952                long timeElapsed =
953                    (System.currentTimeMillis() - pdp.getConnectionTime())/1000;
954                sb.append("    connected at ")
955                  .append(DateUtils.timeString(pdp.getConnectionTime()))
956                  .append(" and elapsed ")
957                  .append(DateUtils.formatElapsedTime(timeElapsed))
958                  .append("\n    to ")
959                  .append(pdp.getApn().toString())
960                  .append("\ninterface: ")
961                  .append(phone.getInterfaceName(phone.getActiveApnTypes()[0]))
962                  .append("\naddress: ")
963                  .append(phone.getIpAddress(phone.getActiveApnTypes()[0]))
964                  .append("\ngateway: ")
965                  .append(phone.getGateway(phone.getActiveApnTypes()[0]));
966                String[] dns = phone.getDnsServers(phone.getActiveApnTypes()[0]);
967                if (dns != null) {
968                    sb.append("\ndns: ").append(dns[0]).append(", ").append(dns[1]);
969                }
970            } else if (pdp.getState().isInactive()) {
971                sb.append("    disconnected with last try at ")
972                  .append(DateUtils.timeString(pdp.getLastFailTime()))
973                  .append("\n    fail because ")
974                  .append(pdp.getLastFailCause().toString());
975            } else {
976                sb.append("    is connecting to ")
977                  .append(pdp.getApn().toString());
978            }
979            sb.append("\n===================");
980        }
981
982
983        disconnects.setText(sb.toString());
984    }
985
986    private void displayQxdmEnableResult() {
987        String status = mQxdmLogEnabled ? "Start QXDM Log" : "Stop QXDM Log";
988
989        DialogInterface mProgressPanel = new AlertDialog.
990                Builder(this).setMessage(status).show();
991
992        mHandler.postDelayed(
993                new Runnable() {
994                    public void run() {
995                        finish();
996                    }
997                }, 2000);
998    }
999
1000    private MenuItem.OnMenuItemClickListener mViewADNCallback = new MenuItem.OnMenuItemClickListener() {
1001        public boolean onMenuItemClick(MenuItem item) {
1002            Intent intent = new Intent(Intent.ACTION_VIEW);
1003            // XXX We need to specify the component here because if we don't
1004            // the activity manager will try to resolve the type by calling
1005            // the content provider, which causes it to be loaded in a process
1006            // other than the Dialer process, which causes a lot of stuff to
1007            // break.
1008            intent.setClassName("com.android.phone",
1009                    "com.android.phone.SimContacts");
1010            startActivity(intent);
1011            return true;
1012        }
1013    };
1014
1015    private MenuItem.OnMenuItemClickListener mViewFDNCallback = new MenuItem.OnMenuItemClickListener() {
1016        public boolean onMenuItemClick(MenuItem item) {
1017            Intent intent = new Intent(Intent.ACTION_VIEW);
1018            // XXX We need to specify the component here because if we don't
1019            // the activity manager will try to resolve the type by calling
1020            // the content provider, which causes it to be loaded in a process
1021            // other than the Dialer process, which causes a lot of stuff to
1022            // break.
1023            intent.setClassName("com.android.phone",
1024                    "com.android.phone.FdnList");
1025            startActivity(intent);
1026            return true;
1027        }
1028    };
1029
1030    private MenuItem.OnMenuItemClickListener mViewSDNCallback = new MenuItem.OnMenuItemClickListener() {
1031        public boolean onMenuItemClick(MenuItem item) {
1032            Intent intent = new Intent(
1033                Intent.ACTION_VIEW, Uri.parse("content://sim/sdn"));
1034            // XXX We need to specify the component here because if we don't
1035            // the activity manager will try to resolve the type by calling
1036            // the content provider, which causes it to be loaded in a process
1037            // other than the Dialer process, which causes a lot of stuff to
1038            // break.
1039            intent.setClassName("com.android.phone",
1040                    "com.android.phone.ADNList");
1041            startActivity(intent);
1042            return true;
1043        }
1044    };
1045
1046    private void toggleDataDisabledOnBoot() {
1047        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
1048        SharedPreferences.Editor editor = sp.edit();
1049        boolean value = sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
1050        editor.putBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, !value);
1051        byte[] data = mOem.getPsAutoAttachData(value);
1052        if (data == null) {
1053            // don't commit
1054            return;
1055        }
1056
1057        editor.commit();
1058        phone.invokeOemRilRequestRaw(data, null);
1059    }
1060
1061    private MenuItem.OnMenuItemClickListener mToggleDataOnBoot = new MenuItem.OnMenuItemClickListener() {
1062        public boolean onMenuItemClick(MenuItem item) {
1063            toggleDataDisabledOnBoot();
1064            return true;
1065        }
1066    };
1067
1068    private MenuItem.OnMenuItemClickListener mToggleData = new MenuItem.OnMenuItemClickListener() {
1069        public boolean onMenuItemClick(MenuItem item) {
1070            int state = mTelephonyManager.getDataState();
1071            switch (state) {
1072                case TelephonyManager.DATA_CONNECTED:
1073                    phone.disableDataConnectivity();
1074                    break;
1075                case TelephonyManager.DATA_DISCONNECTED:
1076                    phone.enableDataConnectivity();
1077                    break;
1078                default:
1079                    // do nothing
1080                    break;
1081            }
1082            return true;
1083        }
1084    };
1085
1086    private MenuItem.OnMenuItemClickListener mGetPdpList = new MenuItem.OnMenuItemClickListener() {
1087        public boolean onMenuItemClick(MenuItem item) {
1088            phone.getPdpContextList(null);
1089            return true;
1090        }
1091    };
1092
1093    private MenuItem.OnMenuItemClickListener mSelectBandCallback = new MenuItem.OnMenuItemClickListener() {
1094        public boolean onMenuItemClick(MenuItem item) {
1095            Intent intent = new Intent();
1096            intent.setClass(RadioInfo.this, BandMode.class);
1097            startActivity(intent);
1098            return true;
1099        }
1100    };
1101
1102    OnClickListener mPowerButtonHandler = new OnClickListener() {
1103        public void onClick(View v) {
1104            //log("toggle radio power: currently " + (isRadioOn()?"on":"off"));
1105            phone.setRadioPower(!isRadioOn());
1106        }
1107    };
1108
1109    OnClickListener mCipherButtonHandler = new OnClickListener() {
1110        public void onClick(View v) {
1111            mCipherOn = !getCiphPref();
1112            byte[] data = mOem.getCipheringData(mCipherOn);
1113
1114            if (data == null)
1115                return;
1116
1117            cipherState.setText("Setting...");
1118            phone.invokeOemRilRequestRaw(data,
1119                    mHandler.obtainMessage(EVENT_SET_CIPHER_DONE));
1120        }
1121    };
1122
1123    OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
1124        public void onClick(View v) {
1125            GSMPhone gsmPhone = (GSMPhone) phone;
1126            gsmPhone.disableDnsCheck(!gsmPhone.isDnsCheckDisabled());
1127            updateDnsCheckState();
1128        }
1129    };
1130
1131    OnClickListener mPingButtonHandler = new OnClickListener() {
1132        public void onClick(View v) {
1133            updatePingState();
1134        }
1135    };
1136
1137    OnClickListener mUpdateSmscButtonHandler = new OnClickListener() {
1138        public void onClick(View v) {
1139            updateSmscButton.setEnabled(false);
1140            byte[] data = mOem.getSmscUpdateData(smsc.getText().toString());
1141            if (data == null) return;
1142            phone.invokeOemRilRequestRaw(data,
1143                    mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE));
1144        }
1145    };
1146
1147    OnClickListener mRefreshSmscButtonHandler = new OnClickListener() {
1148        public void onClick(View v) {
1149            refreshSmsc();
1150        }
1151    };
1152
1153    OnClickListener mQxdmButtonHandler = new OnClickListener() {
1154        public void onClick(View v) {
1155            byte[] data = mOem.getQxdmSdlogData(
1156                    !mQxdmLogEnabled,
1157                    mOem.OEM_QXDM_SDLOG_DEFAULT_FILE_SIZE,
1158                    mOem.OEM_QXDM_SDLOG_DEFAULT_MASK,
1159                    mOem.OEM_QXDM_SDLOG_DEFAULT_MAX_INDEX);
1160
1161            if (data == null)
1162                return;
1163
1164            phone.invokeOemRilRequestRaw(data,
1165                    mHandler.obtainMessage(EVENT_SET_QXDMLOG_DONE));
1166        }
1167    };
1168
1169    AdapterView.OnItemSelectedListener
1170            mPreferredNetworkHandler = new AdapterView.OnItemSelectedListener() {
1171        public void onItemSelected(AdapterView parent, View v, int pos, long id) {
1172            Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
1173            if (pos>=0 && pos<=2) {
1174                phone.setPreferredNetworkType(pos, msg);
1175            }
1176        }
1177
1178        public void onNothingSelected(AdapterView parent) {
1179        }
1180    };
1181
1182    private String[] mPreferredNetworkLabels = {
1183            "WCDMA preferred", "GSM only", "WCDMA only", "Unknown"};
1184}
1185