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