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