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