blob: 1ba480481a87729169cfa78bed3141eb71a3bf75 [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;
Robert Greenwalt99be5002010-11-24 17:20:59 -080020import android.content.Context;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080021import android.content.Intent;
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +080022import android.content.pm.PackageManager;
23import android.content.pm.ResolveInfo;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080024import android.content.res.Resources;
Robert Greenwalt99be5002010-11-24 17:20:59 -080025import android.net.ConnectivityManager;
Robert Greenwaltae04c1a2010-08-30 15:33:28 -070026import android.net.LinkProperties;
Jeff Sharkey93029862011-05-27 18:26:15 -070027import android.net.TrafficStats;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080028import android.net.Uri;
29import android.os.AsyncResult;
30import android.os.Bundle;
31import android.os.Handler;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080032import android.os.Message;
33import android.os.RemoteException;
34import android.os.ServiceManager;
35import android.os.SystemProperties;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080036import android.telephony.CellLocation;
37import android.telephony.PhoneStateListener;
38import android.telephony.ServiceState;
39import android.telephony.TelephonyManager;
40import android.telephony.NeighboringCellInfo;
jsh534f5ae2009-09-24 09:19:22 -070041import android.telephony.cdma.CdmaCellLocation;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080042import android.telephony.gsm.GsmCellLocation;
43import android.text.format.DateUtils;
44import android.util.Log;
45import android.view.Menu;
46import android.view.MenuItem;
47import android.view.View;
48import android.view.View.OnClickListener;
49import android.widget.AdapterView;
50import android.widget.ArrayAdapter;
51import android.widget.Button;
52import android.widget.Spinner;
53import android.widget.TextView;
54import android.widget.EditText;
55
jsh87fa11b2009-08-18 18:00:15 -070056import com.android.internal.telephony.DataConnection;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080057import com.android.internal.telephony.Phone;
58import com.android.internal.telephony.PhoneFactory;
59import com.android.internal.telephony.PhoneStateIntentReceiver;
60import com.android.internal.telephony.TelephonyProperties;
Wink Saville0d936972009-12-22 14:36:47 -080061import com.android.internal.telephony.gsm.GsmDataConnection;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080062
63import org.apache.http.HttpResponse;
64import org.apache.http.client.HttpClient;
65import org.apache.http.client.methods.HttpGet;
66import org.apache.http.impl.client.DefaultHttpClient;
67
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080068import java.io.IOException;
Wink Savillea9f16372010-08-27 13:53:26 -070069import java.net.InetAddress;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080070import java.net.UnknownHostException;
71import java.util.ArrayList;
72import java.util.List;
73
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +080074import android.util.Log;
75
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080076public class RadioInfo extends Activity {
77 private final String TAG = "phone";
johnwang342101a2009-09-23 16:22:34 -070078
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080079 private static final int EVENT_PHONE_STATE_CHANGED = 100;
80 private static final int EVENT_SIGNAL_STRENGTH_CHANGED = 200;
81 private static final int EVENT_SERVICE_STATE_CHANGED = 300;
82 private static final int EVENT_CFI_CHANGED = 302;
83
84 private static final int EVENT_QUERY_PREFERRED_TYPE_DONE = 1000;
85 private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001;
86 private static final int EVENT_QUERY_NEIGHBORING_CIDS_DONE = 1002;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080087 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;
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +080096
97 static final String ENABLE_DATA_STR = "Enable data connection";
98 static final String DISABLE_DATA_STR = "Disable data connection";
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080099
Wink Savillec3886682009-04-02 11:00:56 -0700100 private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800101 private TextView number;
102 private TextView callState;
103 private TextView operatorName;
104 private TextView roamingState;
105 private TextView gsmState;
106 private TextView gprsState;
107 private TextView network;
108 private TextView dBm;
109 private TextView mMwi;
110 private TextView mCfi;
111 private TextView mLocation;
112 private TextView mNeighboringCids;
113 private TextView resets;
114 private TextView attempts;
115 private TextView successes;
116 private TextView disconnects;
117 private TextView sentSinceReceived;
118 private TextView sent;
119 private TextView received;
120 private TextView mPingIpAddr;
121 private TextView mPingHostname;
122 private TextView mHttpClientTest;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800123 private TextView dnsCheckState;
124 private EditText smsc;
125 private Button radioPowerButton;
Wink Saville1e596f32011-09-19 14:24:39 -0700126 private Button imsRegRequiredButton;
Wink Saville382a75b2011-09-22 15:17:00 -0700127 private Button smsOverImsButton;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800128 private Button dnsCheckToggleButton;
129 private Button pingTestButton;
130 private Button updateSmscButton;
131 private Button refreshSmscButton;
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +0800132 private Button oemInfoButton;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800133 private Spinner preferredNetworkType;
134
135 private TelephonyManager mTelephonyManager;
136 private Phone phone = null;
137 private PhoneStateIntentReceiver mPhoneStateReceiver;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800138
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800139 private String mPingIpAddrResult;
140 private String mPingHostnameResult;
141 private String mHttpClientTestResult;
142 private boolean mMwiValue = false;
143 private boolean mCfiValue = false;
144
145 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
146 @Override
147 public void onDataConnectionStateChanged(int state) {
148 updateDataState();
149 updateDataStats();
150 updatePdpList();
151 updateNetworkType();
152 }
153
154 @Override
155 public void onDataActivity(int direction) {
156 updateDataStats2();
157 }
158
159 @Override
160 public void onCellLocationChanged(CellLocation location) {
161 updateLocation(location);
162 }
163
164 @Override
165 public void onMessageWaitingIndicatorChanged(boolean mwi) {
166 mMwiValue = mwi;
167 updateMessageWaiting();
168 }
169
170 @Override
171 public void onCallForwardingIndicatorChanged(boolean cfi) {
172 mCfiValue = cfi;
173 updateCallRedirect();
174 }
175 };
176
177 private Handler mHandler = new Handler() {
178 public void handleMessage(Message msg) {
179 AsyncResult ar;
180 switch (msg.what) {
181 case EVENT_PHONE_STATE_CHANGED:
182 updatePhoneState();
183 break;
184
185 case EVENT_SIGNAL_STRENGTH_CHANGED:
186 updateSignalStrength();
187 break;
188
189 case EVENT_SERVICE_STATE_CHANGED:
190 updateServiceState();
191 updatePowerState();
192 break;
193
194 case EVENT_QUERY_PREFERRED_TYPE_DONE:
195 ar= (AsyncResult) msg.obj;
196 if (ar.exception == null) {
197 int type = ((int[])ar.result)[0];
198 preferredNetworkType.setSelection(type, true);
199 } else {
jsh87fa11b2009-08-18 18:00:15 -0700200 preferredNetworkType.setSelection(8, true);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800201 }
202 break;
203 case EVENT_SET_PREFERRED_TYPE_DONE:
204 ar= (AsyncResult) msg.obj;
205 if (ar.exception != null) {
206 phone.getPreferredNetworkType(
207 obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
208 }
209 break;
210 case EVENT_QUERY_NEIGHBORING_CIDS_DONE:
211 ar= (AsyncResult) msg.obj;
212 if (ar.exception == null) {
213 updateNeighboringCids((ArrayList<NeighboringCellInfo>)ar.result);
214 } else {
215 mNeighboringCids.setText("unknown");
216 }
217 break;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800218 case EVENT_QUERY_SMSC_DONE:
219 ar= (AsyncResult) msg.obj;
220 if (ar.exception != null) {
221 smsc.setText("refresh error");
222 } else {
jsh21dd4072009-05-12 11:26:55 -0700223 smsc.setText((String)ar.result);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800224 }
225 break;
226 case EVENT_UPDATE_SMSC_DONE:
227 updateSmscButton.setEnabled(true);
228 ar= (AsyncResult) msg.obj;
229 if (ar.exception != null) {
230 smsc.setText("update error");
231 }
232 break;
233 default:
234 break;
235
236 }
237 }
238 };
239
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800240 @Override
241 public void onCreate(Bundle icicle) {
242 super.onCreate(icicle);
243
244 setContentView(R.layout.radio_info);
245
246 mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
247 phone = PhoneFactory.getDefaultPhone();
248
Wink Savillec3886682009-04-02 11:00:56 -0700249 mDeviceId= (TextView) findViewById(R.id.imei);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800250 number = (TextView) findViewById(R.id.number);
251 callState = (TextView) findViewById(R.id.call);
252 operatorName = (TextView) findViewById(R.id.operator);
253 roamingState = (TextView) findViewById(R.id.roaming);
254 gsmState = (TextView) findViewById(R.id.gsm);
255 gprsState = (TextView) findViewById(R.id.gprs);
256 network = (TextView) findViewById(R.id.network);
257 dBm = (TextView) findViewById(R.id.dbm);
258 mMwi = (TextView) findViewById(R.id.mwi);
259 mCfi = (TextView) findViewById(R.id.cfi);
260 mLocation = (TextView) findViewById(R.id.location);
261 mNeighboringCids = (TextView) findViewById(R.id.neighboring);
262
263 resets = (TextView) findViewById(R.id.resets);
264 attempts = (TextView) findViewById(R.id.attempts);
265 successes = (TextView) findViewById(R.id.successes);
266 disconnects = (TextView) findViewById(R.id.disconnects);
267 sentSinceReceived = (TextView) findViewById(R.id.sentSinceReceived);
268 sent = (TextView) findViewById(R.id.sent);
269 received = (TextView) findViewById(R.id.received);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800270 smsc = (EditText) findViewById(R.id.smsc);
271 dnsCheckState = (TextView) findViewById(R.id.dnsCheckState);
272
273 mPingIpAddr = (TextView) findViewById(R.id.pingIpAddr);
274 mPingHostname = (TextView) findViewById(R.id.pingHostname);
275 mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
276
277 preferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
278 ArrayAdapter<String> adapter = new ArrayAdapter<String> (this,
279 android.R.layout.simple_spinner_item, mPreferredNetworkLabels);
johnwang342101a2009-09-23 16:22:34 -0700280 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800281 preferredNetworkType.setAdapter(adapter);
282 preferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler);
283
284 radioPowerButton = (Button) findViewById(R.id.radio_power);
285 radioPowerButton.setOnClickListener(mPowerButtonHandler);
286
Wink Saville1e596f32011-09-19 14:24:39 -0700287 imsRegRequiredButton = (Button) findViewById(R.id.ims_reg_required);
288 imsRegRequiredButton.setOnClickListener(mImsRegRequiredHandler);
289
Wink Saville382a75b2011-09-22 15:17:00 -0700290 smsOverImsButton = (Button) findViewById(R.id.sms_over_ims);
291 smsOverImsButton.setOnClickListener(mSmsOverImsHandler);
292
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800293 pingTestButton = (Button) findViewById(R.id.ping_test);
294 pingTestButton.setOnClickListener(mPingButtonHandler);
295 updateSmscButton = (Button) findViewById(R.id.update_smsc);
296 updateSmscButton.setOnClickListener(mUpdateSmscButtonHandler);
297 refreshSmscButton = (Button) findViewById(R.id.refresh_smsc);
298 refreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler);
299 dnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle);
300 dnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler);
johnwang342101a2009-09-23 16:22:34 -0700301
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +0800302 oemInfoButton = (Button) findViewById(R.id.oem_info);
303 oemInfoButton.setOnClickListener(mOemInfoButtonHandler);
304 PackageManager pm = getPackageManager();
305 Intent oemInfoIntent = new Intent("com.android.settings.OEM_RADIO_INFO");
306 List<ResolveInfo> oemInfoIntentList = pm.queryIntentActivities(oemInfoIntent, 0);
307 if (oemInfoIntentList.size() == 0) {
308 oemInfoButton.setEnabled(false);
309 }
310
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800311 mPhoneStateReceiver = new PhoneStateIntentReceiver(this, mHandler);
312 mPhoneStateReceiver.notifySignalStrength(EVENT_SIGNAL_STRENGTH_CHANGED);
313 mPhoneStateReceiver.notifyServiceState(EVENT_SERVICE_STATE_CHANGED);
314 mPhoneStateReceiver.notifyPhoneCallState(EVENT_PHONE_STATE_CHANGED);
johnwang342101a2009-09-23 16:22:34 -0700315
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800316 phone.getPreferredNetworkType(
317 mHandler.obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE));
318 phone.getNeighboringCids(
319 mHandler.obtainMessage(EVENT_QUERY_NEIGHBORING_CIDS_DONE));
320
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800321 CellLocation.requestLocationUpdate();
322 }
323
324 @Override
325 protected void onResume() {
326 super.onResume();
327
328 updatePhoneState();
329 updateSignalStrength();
330 updateMessageWaiting();
331 updateCallRedirect();
332 updateServiceState();
333 updateLocation(mTelephonyManager.getCellLocation());
334 updateDataState();
335 updateDataStats();
336 updateDataStats2();
337 updatePowerState();
Wink Saville1e596f32011-09-19 14:24:39 -0700338 updateImsRegRequiredState();
Wink Saville382a75b2011-09-22 15:17:00 -0700339 updateSmsOverImsState();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800340 updateProperties();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800341 updateDnsCheckState();
342
343 Log.i(TAG, "[RadioInfo] onResume: register phone & data intents");
344
345 mPhoneStateReceiver.registerIntent();
346 mTelephonyManager.listen(mPhoneStateListener,
347 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
348 | PhoneStateListener.LISTEN_DATA_ACTIVITY
349 | PhoneStateListener.LISTEN_CELL_LOCATION
350 | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
351 | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR);
352 }
353
354 @Override
355 public void onPause() {
356 super.onPause();
357
358 Log.i(TAG, "[RadioInfo] onPause: unregister phone & data intents");
359
360 mPhoneStateReceiver.unregisterIntent();
361 mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
362 }
363
364 @Override
365 public boolean onCreateOptionsMenu(Menu menu) {
Wink Savillec3886682009-04-02 11:00:56 -0700366 menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label)
367 .setOnMenuItemClickListener(mSelectBandCallback)
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800368 .setAlphabeticShortcut('b');
369 menu.add(1, MENU_ITEM_VIEW_ADN, 0,
370 R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback);
371 menu.add(1, MENU_ITEM_VIEW_FDN, 0,
372 R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback);
373 menu.add(1, MENU_ITEM_VIEW_SDN, 0,
374 R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback);
375 menu.add(1, MENU_ITEM_GET_PDP_LIST,
376 0, R.string.radioInfo_menu_getPDP).setOnMenuItemClickListener(mGetPdpList);
377 menu.add(1, MENU_ITEM_TOGGLE_DATA,
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +0800378 0, DISABLE_DATA_STR).setOnMenuItemClickListener(mToggleData);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800379 return true;
380 }
381
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800382 @Override
Wink Savillec3886682009-04-02 11:00:56 -0700383 public boolean onPrepareOptionsMenu(Menu menu) {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800384 // Get the TOGGLE DATA menu item in the right state.
385 MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA);
386 int state = mTelephonyManager.getDataState();
387 boolean visible = true;
388
389 switch (state) {
390 case TelephonyManager.DATA_CONNECTED:
391 case TelephonyManager.DATA_SUSPENDED:
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +0800392 item.setTitle(DISABLE_DATA_STR);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800393 break;
394 case TelephonyManager.DATA_DISCONNECTED:
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +0800395 item.setTitle(ENABLE_DATA_STR);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800396 break;
397 default:
398 visible = false;
399 break;
400 }
401 item.setVisible(visible);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800402 return true;
403 }
404
405 private boolean isRadioOn() {
406 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
407 }
johnwang342101a2009-09-23 16:22:34 -0700408
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800409 private void updatePowerState() {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800410 String buttonText = isRadioOn() ?
411 getString(R.string.turn_off_radio) :
412 getString(R.string.turn_on_radio);
Wink Savillec3886682009-04-02 11:00:56 -0700413 radioPowerButton.setText(buttonText);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800414 }
415
Wink Saville1e596f32011-09-19 14:24:39 -0700416 private boolean isImsRegRequired() {
417 return SystemProperties.getBoolean(TelephonyProperties.PROPERTY_IMS_REG_REQUIRED, false);
418 }
419
420 private void updateImsRegRequiredState() {
421 Log.d(TAG, "updateImsRegRequiredState isImsRegRequired()=" + isImsRegRequired());
422 String buttonText = isImsRegRequired() ?
423 getString(R.string.ims_reg_required_off) :
424 getString(R.string.ims_reg_required_on);
425 imsRegRequiredButton.setText(buttonText);
426 }
427
Wink Saville382a75b2011-09-22 15:17:00 -0700428 private boolean isSmsOverImsEnabled() {
429 return SystemProperties.getBoolean(PROPERTY_SMS_OVER_IMS, false);
430 }
431
432 private void updateSmsOverImsState() {
433 Log.d(TAG, "updateSmsOverImsState isSmsOverImsEnabled()=" + isSmsOverImsEnabled());
434 String buttonText = isSmsOverImsEnabled() ?
435 getString(R.string.sms_over_ims_off) :
436 getString(R.string.sms_over_ims_on);
437 smsOverImsButton.setText(buttonText);
438 }
439
Wink Saville1e596f32011-09-19 14:24:39 -0700440
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800441 private void updateDnsCheckState() {
Mike Lockwood5304c7e2009-04-05 11:37:45 -0700442 dnsCheckState.setText(phone.isDnsCheckDisabled() ?
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800443 "0.0.0.0 allowed" :"0.0.0.0 not allowed");
444 }
Wink Savillee2a14e32009-05-29 14:06:30 -0700445
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800446 private final void
447 updateSignalStrength() {
Wink Savillee2a14e32009-05-29 14:06:30 -0700448 // TODO PhoneStateIntentReceiver is deprecated and PhoneStateListener
449 // should probably used instead.
450 int state = mPhoneStateReceiver.getServiceState().getState();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800451 Resources r = getResources();
452
453 if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
454 (ServiceState.STATE_POWER_OFF == state)) {
455 dBm.setText("0");
456 }
Wink Savillee2a14e32009-05-29 14:06:30 -0700457
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800458 int signalDbm = mPhoneStateReceiver.getSignalStrengthDbm();
Wink Savillee2a14e32009-05-29 14:06:30 -0700459
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800460 if (-1 == signalDbm) signalDbm = 0;
461
Wink Saville882c74a2011-02-17 12:00:03 -0800462 int signalAsu = mPhoneStateReceiver.getSignalStrengthLevelAsu();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800463
464 if (-1 == signalAsu) signalAsu = 0;
465
466 dBm.setText(String.valueOf(signalDbm) + " "
467 + r.getString(R.string.radioInfo_display_dbm) + " "
468 + String.valueOf(signalAsu) + " "
469 + r.getString(R.string.radioInfo_display_asu));
470 }
471
472 private final void updateLocation(CellLocation location) {
jsh534f5ae2009-09-24 09:19:22 -0700473 Resources r = getResources();
Wink Savillec3886682009-04-02 11:00:56 -0700474 if (location instanceof GsmCellLocation) {
475 GsmCellLocation loc = (GsmCellLocation)location;
jsh534f5ae2009-09-24 09:19:22 -0700476 int lac = loc.getLac();
477 int cid = loc.getCid();
478 mLocation.setText(r.getString(R.string.radioInfo_lac) + " = "
479 + ((lac == -1) ? "unknown" : Integer.toHexString(lac))
480 + " "
481 + r.getString(R.string.radioInfo_cid) + " = "
482 + ((cid == -1) ? "unknown" : Integer.toHexString(cid)));
483 } else if (location instanceof CdmaCellLocation) {
484 CdmaCellLocation loc = (CdmaCellLocation)location;
485 int bid = loc.getBaseStationId();
486 int sid = loc.getSystemId();
487 int nid = loc.getNetworkId();
488 int lat = loc.getBaseStationLatitude();
489 int lon = loc.getBaseStationLongitude();
490 mLocation.setText("BID = "
491 + ((bid == -1) ? "unknown" : Integer.toHexString(bid))
492 + " "
493 + "SID = "
494 + ((sid == -1) ? "unknown" : Integer.toHexString(sid))
495 + " "
496 + "NID = "
497 + ((nid == -1) ? "unknown" : Integer.toHexString(nid))
498 + "\n"
499 + "LAT = "
500 + ((lat == -1) ? "unknown" : Integer.toHexString(lat))
501 + " "
502 + "LONG = "
503 + ((lon == -1) ? "unknown" : Integer.toHexString(lon)));
504 } else {
505 mLocation.setText("unknown");
Wink Savillec3886682009-04-02 11:00:56 -0700506 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800507
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800508
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800509 }
510
511 private final void updateNeighboringCids(ArrayList<NeighboringCellInfo> cids) {
johnwangf02c65f2009-09-25 17:26:54 -0700512 StringBuilder sb = new StringBuilder();
513
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800514 if (cids != null) {
515 if ( cids.isEmpty() ) {
johnwangf02c65f2009-09-25 17:26:54 -0700516 sb.append("no neighboring cells");
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800517 } else {
518 for (NeighboringCellInfo cell : cids) {
johnwangf02c65f2009-09-25 17:26:54 -0700519 sb.append(cell.toString()).append(" ");
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800520 }
521 }
522 } else {
johnwangf02c65f2009-09-25 17:26:54 -0700523 sb.append("unknown");
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800524 }
johnwangf02c65f2009-09-25 17:26:54 -0700525 mNeighboringCids.setText(sb.toString());
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800526 }
527
528 private final void
529 updateMessageWaiting() {
530 mMwi.setText(String.valueOf(mMwiValue));
531 }
532
533 private final void
534 updateCallRedirect() {
535 mCfi.setText(String.valueOf(mCfiValue));
536 }
537
538
539 private final void
540 updateServiceState() {
541 ServiceState serviceState = mPhoneStateReceiver.getServiceState();
542 int state = serviceState.getState();
543 Resources r = getResources();
544 String display = r.getString(R.string.radioInfo_unknown);
johnwang342101a2009-09-23 16:22:34 -0700545
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800546 switch (state) {
547 case ServiceState.STATE_IN_SERVICE:
548 display = r.getString(R.string.radioInfo_service_in);
549 break;
550 case ServiceState.STATE_OUT_OF_SERVICE:
551 case ServiceState.STATE_EMERGENCY_ONLY:
552 display = r.getString(R.string.radioInfo_service_emergency);
553 break;
554 case ServiceState.STATE_POWER_OFF:
555 display = r.getString(R.string.radioInfo_service_off);
556 break;
557 }
johnwang342101a2009-09-23 16:22:34 -0700558
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800559 gsmState.setText(display);
johnwang342101a2009-09-23 16:22:34 -0700560
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800561 if (serviceState.getRoaming()) {
562 roamingState.setText(R.string.radioInfo_roaming_in);
563 } else {
564 roamingState.setText(R.string.radioInfo_roaming_not);
565 }
566
567 operatorName.setText(serviceState.getOperatorAlphaLong());
568 }
569
570 private final void
571 updatePhoneState() {
572 Phone.State state = mPhoneStateReceiver.getPhoneState();
573 Resources r = getResources();
574 String display = r.getString(R.string.radioInfo_unknown);
575
576 switch (state) {
577 case IDLE:
578 display = r.getString(R.string.radioInfo_phone_idle);
579 break;
580 case RINGING:
581 display = r.getString(R.string.radioInfo_phone_ringing);
582 break;
583 case OFFHOOK:
584 display = r.getString(R.string.radioInfo_phone_offhook);
585 break;
586 }
587
588 callState.setText(display);
589 }
590
591 private final void
592 updateDataState() {
593 int state = mTelephonyManager.getDataState();
594 Resources r = getResources();
595 String display = r.getString(R.string.radioInfo_unknown);
596
597 switch (state) {
598 case TelephonyManager.DATA_CONNECTED:
599 display = r.getString(R.string.radioInfo_data_connected);
600 break;
601 case TelephonyManager.DATA_CONNECTING:
602 display = r.getString(R.string.radioInfo_data_connecting);
603 break;
604 case TelephonyManager.DATA_DISCONNECTED:
605 display = r.getString(R.string.radioInfo_data_disconnected);
606 break;
607 case TelephonyManager.DATA_SUSPENDED:
608 display = r.getString(R.string.radioInfo_data_suspended);
609 break;
610 }
johnwang342101a2009-09-23 16:22:34 -0700611
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800612 gprsState.setText(display);
613 }
614
615 private final void updateNetworkType() {
616 Resources r = getResources();
617 String display = SystemProperties.get(TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE,
618 r.getString(R.string.radioInfo_unknown));
619
620 network.setText(display);
621 }
622
623 private final void
624 updateProperties() {
625 String s;
626 Resources r = getResources();
627
628 s = phone.getDeviceId();
johnwang342101a2009-09-23 16:22:34 -0700629 if (s == null) s = r.getString(R.string.radioInfo_unknown);
Wink Savillec3886682009-04-02 11:00:56 -0700630 mDeviceId.setText(s);
johnwang342101a2009-09-23 16:22:34 -0700631
Wink Savillec3886682009-04-02 11:00:56 -0700632
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800633 s = phone.getLine1Number();
johnwang342101a2009-09-23 16:22:34 -0700634 if (s == null) s = r.getString(R.string.radioInfo_unknown);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800635 number.setText(s);
636 }
637
638 private final void updateDataStats() {
639 String s;
640
641 s = SystemProperties.get("net.gsm.radio-reset", "0");
642 resets.setText(s);
643
644 s = SystemProperties.get("net.gsm.attempt-gprs", "0");
645 attempts.setText(s);
646
647 s = SystemProperties.get("net.gsm.succeed-gprs", "0");
648 successes.setText(s);
649
650 //s = SystemProperties.get("net.gsm.disconnect", "0");
651 //disconnects.setText(s);
652
653 s = SystemProperties.get("net.ppp.reset-by-timeout", "0");
654 sentSinceReceived.setText(s);
655 }
656
657 private final void updateDataStats2() {
658 Resources r = getResources();
659
Jeff Sharkey93029862011-05-27 18:26:15 -0700660 long txPackets = TrafficStats.getMobileTxPackets();
661 long rxPackets = TrafficStats.getMobileRxPackets();
662 long txBytes = TrafficStats.getMobileTxBytes();
663 long rxBytes = TrafficStats.getMobileRxBytes();
johnwang342101a2009-09-23 16:22:34 -0700664
Jeff Sharkey93029862011-05-27 18:26:15 -0700665 String packets = r.getString(R.string.radioInfo_display_packets);
666 String bytes = r.getString(R.string.radioInfo_display_bytes);
johnwang342101a2009-09-23 16:22:34 -0700667
Jeff Sharkey93029862011-05-27 18:26:15 -0700668 sent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes);
669 received.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800670 }
671
672 /**
673 * Ping a IP address.
674 */
675 private final void pingIpAddr() {
676 try {
677 // This is hardcoded IP addr. This is for testing purposes.
678 // We would need to get rid of this before release.
679 String ipAddress = "74.125.47.104";
680 Process p = Runtime.getRuntime().exec("ping -c 1 " + ipAddress);
681 int status = p.waitFor();
682 if (status == 0) {
683 mPingIpAddrResult = "Pass";
684 } else {
685 mPingIpAddrResult = "Fail: IP addr not reachable";
686 }
687 } catch (IOException e) {
688 mPingIpAddrResult = "Fail: IOException";
689 } catch (InterruptedException e) {
690 mPingIpAddrResult = "Fail: InterruptedException";
691 }
692 }
693
694 /**
695 * Ping a host name
696 */
697 private final void pingHostname() {
698 try {
johnwang342101a2009-09-23 16:22:34 -0700699 Process p = Runtime.getRuntime().exec("ping -c 1 www.google.com");
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800700 int status = p.waitFor();
701 if (status == 0) {
702 mPingHostnameResult = "Pass";
703 } else {
704 mPingHostnameResult = "Fail: Host unreachable";
705 }
706 } catch (UnknownHostException e) {
707 mPingHostnameResult = "Fail: Unknown Host";
708 } catch (IOException e) {
709 mPingHostnameResult= "Fail: IOException";
710 } catch (InterruptedException e) {
711 mPingHostnameResult = "Fail: InterruptedException";
712 }
713 }
714
715 /**
716 * This function checks for basic functionality of HTTP Client.
717 */
718 private void httpClientTest() {
719 HttpClient client = new DefaultHttpClient();
720 try {
721 HttpGet request = new HttpGet("http://www.google.com");
722 HttpResponse response = client.execute(request);
723 if (response.getStatusLine().getStatusCode() == 200) {
724 mHttpClientTestResult = "Pass";
725 } else {
726 mHttpClientTestResult = "Fail: Code: " + String.valueOf(response);
727 }
728 request.abort();
729 } catch (IOException e) {
730 mHttpClientTestResult = "Fail: IOException";
731 }
732 }
733
734 private void refreshSmsc() {
jsh21dd4072009-05-12 11:26:55 -0700735 phone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE));
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800736 }
737
738 private final void updatePingState() {
739 final Handler handler = new Handler();
740 // Set all to unknown since the threads will take a few secs to update.
741 mPingIpAddrResult = getResources().getString(R.string.radioInfo_unknown);
742 mPingHostnameResult = getResources().getString(R.string.radioInfo_unknown);
743 mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown);
744
745 mPingIpAddr.setText(mPingIpAddrResult);
746 mPingHostname.setText(mPingHostnameResult);
747 mHttpClientTest.setText(mHttpClientTestResult);
748
749 final Runnable updatePingResults = new Runnable() {
750 public void run() {
751 mPingIpAddr.setText(mPingIpAddrResult);
752 mPingHostname.setText(mPingHostnameResult);
753 mHttpClientTest.setText(mHttpClientTestResult);
754 }
755 };
756 Thread ipAddr = new Thread() {
757 @Override
758 public void run() {
759 pingIpAddr();
760 handler.post(updatePingResults);
761 }
762 };
763 ipAddr.start();
764
765 Thread hostname = new Thread() {
766 @Override
767 public void run() {
768 pingHostname();
769 handler.post(updatePingResults);
770 }
771 };
772 hostname.start();
773
774 Thread httpClient = new Thread() {
775 @Override
776 public void run() {
777 httpClientTest();
778 handler.post(updatePingResults);
779 }
780 };
781 httpClient.start();
782 }
783
784 private final void updatePdpList() {
785 StringBuilder sb = new StringBuilder("========DATA=======\n");
786
Wink Saville2c3ec092011-04-20 10:24:36 -0700787// List<DataConnection> dcs = phone.getCurrentDataConnectionList();
788//
789// for (DataConnection dc : dcs) {
790// sb.append(" State=").append(dc.getStateAsString()).append("\n");
791// if (dc.isActive()) {
792// long timeElapsed =
793// (System.currentTimeMillis() - dc.getConnectionTime())/1000;
794// sb.append(" connected at ")
795// .append(DateUtils.timeString(dc.getConnectionTime()))
796// .append(" and elapsed ")
797// .append(DateUtils.formatElapsedTime(timeElapsed));
798//
799// if (dc instanceof GsmDataConnection) {
800// GsmDataConnection pdp = (GsmDataConnection)dc;
801// sb.append("\n to ")
802// .append(pdp.getApn().toString());
803// }
804// sb.append("\nLinkProperties: ");
805// sb.append(phone.getLinkProperties(phone.getActiveApnTypes()[0]).toString());
806// } else if (dc.isInactive()) {
807// sb.append(" disconnected with last try at ")
808// .append(DateUtils.timeString(dc.getLastFailTime()))
809// .append("\n fail because ")
810// .append(dc.getLastFailCause().toString());
811// } else {
812// if (dc instanceof GsmDataConnection) {
813// GsmDataConnection pdp = (GsmDataConnection)dc;
814// sb.append(" is connecting to ")
815// .append(pdp.getApn().toString());
816// } else {
817// sb.append(" is connecting");
818// }
819// }
820// sb.append("\n===================");
821// }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800822
823 disconnects.setText(sb.toString());
824 }
825
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800826 private MenuItem.OnMenuItemClickListener mViewADNCallback = new MenuItem.OnMenuItemClickListener() {
827 public boolean onMenuItemClick(MenuItem item) {
828 Intent intent = new Intent(Intent.ACTION_VIEW);
829 // XXX We need to specify the component here because if we don't
830 // the activity manager will try to resolve the type by calling
831 // the content provider, which causes it to be loaded in a process
832 // other than the Dialer process, which causes a lot of stuff to
833 // break.
834 intent.setClassName("com.android.phone",
835 "com.android.phone.SimContacts");
836 startActivity(intent);
837 return true;
838 }
839 };
840
841 private MenuItem.OnMenuItemClickListener mViewFDNCallback = new MenuItem.OnMenuItemClickListener() {
842 public boolean onMenuItemClick(MenuItem item) {
843 Intent intent = new Intent(Intent.ACTION_VIEW);
844 // XXX We need to specify the component here because if we don't
845 // the activity manager will try to resolve the type by calling
846 // the content provider, which causes it to be loaded in a process
847 // other than the Dialer process, which causes a lot of stuff to
848 // break.
849 intent.setClassName("com.android.phone",
850 "com.android.phone.FdnList");
851 startActivity(intent);
852 return true;
853 }
854 };
855
856 private MenuItem.OnMenuItemClickListener mViewSDNCallback = new MenuItem.OnMenuItemClickListener() {
857 public boolean onMenuItemClick(MenuItem item) {
858 Intent intent = new Intent(
Wink Savillec3886682009-04-02 11:00:56 -0700859 Intent.ACTION_VIEW, Uri.parse("content://icc/sdn"));
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800860 // XXX We need to specify the component here because if we don't
861 // the activity manager will try to resolve the type by calling
862 // the content provider, which causes it to be loaded in a process
863 // other than the Dialer process, which causes a lot of stuff to
864 // break.
865 intent.setClassName("com.android.phone",
866 "com.android.phone.ADNList");
867 startActivity(intent);
868 return true;
869 }
870 };
871
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +0800872 private MenuItem.OnMenuItemClickListener mGetPdpList = new MenuItem.OnMenuItemClickListener() {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800873 public boolean onMenuItemClick(MenuItem item) {
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +0800874 phone.getDataCallList(null);
875 return true;
876 }
877 };
878
879 private MenuItem.OnMenuItemClickListener mSelectBandCallback = new MenuItem.OnMenuItemClickListener() {
880 public boolean onMenuItemClick(MenuItem item) {
881 Intent intent = new Intent();
882 intent.setClass(RadioInfo.this, BandMode.class);
883 startActivity(intent);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800884 return true;
885 }
886 };
johnwang342101a2009-09-23 16:22:34 -0700887
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800888 private MenuItem.OnMenuItemClickListener mToggleData = new MenuItem.OnMenuItemClickListener() {
889 public boolean onMenuItemClick(MenuItem item) {
Robert Greenwalt99be5002010-11-24 17:20:59 -0800890 ConnectivityManager cm =
891 (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800892 int state = mTelephonyManager.getDataState();
893 switch (state) {
894 case TelephonyManager.DATA_CONNECTED:
Robert Greenwalt99be5002010-11-24 17:20:59 -0800895 cm.setMobileDataEnabled(false);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800896 break;
897 case TelephonyManager.DATA_DISCONNECTED:
Robert Greenwalt99be5002010-11-24 17:20:59 -0800898 cm.setMobileDataEnabled(true);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800899 break;
900 default:
901 // do nothing
902 break;
903 }
904 return true;
905 }
906 };
907
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800908 OnClickListener mPowerButtonHandler = new OnClickListener() {
909 public void onClick(View v) {
910 //log("toggle radio power: currently " + (isRadioOn()?"on":"off"));
911 phone.setRadioPower(!isRadioOn());
912 }
913 };
914
Wink Saville1e596f32011-09-19 14:24:39 -0700915 OnClickListener mImsRegRequiredHandler = new OnClickListener() {
916 @Override
917 public void onClick(View v) {
918 Log.d(TAG, String.format("toggle %s: currently %s",
919 TelephonyProperties.PROPERTY_IMS_REG_REQUIRED, (isImsRegRequired() ? "on":"off")));
920 boolean newValue = !isImsRegRequired();
921 SystemProperties.set(TelephonyProperties.PROPERTY_IMS_REG_REQUIRED,
922 newValue ? "1":"0");
923 updateImsRegRequiredState();
924 }
925 };
926
Wink Saville382a75b2011-09-22 15:17:00 -0700927 static final String PROPERTY_SMS_OVER_IMS = "persist.radio.imsallowmtsms";
928 OnClickListener mSmsOverImsHandler = new OnClickListener() {
929 @Override
930 public void onClick(View v) {
931 Log.d(TAG, String.format("toggle %s: currently %s",
932 PROPERTY_SMS_OVER_IMS, (isSmsOverImsEnabled() ? "on":"off")));
933 boolean newValue = !isSmsOverImsEnabled();
934 SystemProperties.set(PROPERTY_SMS_OVER_IMS, newValue ? "1":"0");
935 updateSmsOverImsState();
936 }
937 };
938
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800939 OnClickListener mDnsCheckButtonHandler = new OnClickListener() {
940 public void onClick(View v) {
Wink Savillec3886682009-04-02 11:00:56 -0700941 phone.disableDnsCheck(!phone.isDnsCheckDisabled());
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800942 updateDnsCheckState();
943 }
944 };
johnwang342101a2009-09-23 16:22:34 -0700945
Tammo Spalinka5f4c8f2009-10-15 20:08:58 +0800946 OnClickListener mOemInfoButtonHandler = new OnClickListener() {
947 public void onClick(View v) {
948 Intent intent = new Intent("com.android.settings.OEM_RADIO_INFO");
949 try {
950 startActivity(intent);
951 } catch (android.content.ActivityNotFoundException ex) {
952 Log.d(TAG, "OEM-specific Info/Settings Activity Not Found : " + ex);
953 // If the activity does not exist, there are no OEM
954 // settings, and so we can just do nothing...
955 }
956 }
957 };
958
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800959 OnClickListener mPingButtonHandler = new OnClickListener() {
960 public void onClick(View v) {
961 updatePingState();
962 }
963 };
964
965 OnClickListener mUpdateSmscButtonHandler = new OnClickListener() {
966 public void onClick(View v) {
967 updateSmscButton.setEnabled(false);
jsh21dd4072009-05-12 11:26:55 -0700968 phone.setSmscAddress(smsc.getText().toString(),
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800969 mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE));
970 }
971 };
972
973 OnClickListener mRefreshSmscButtonHandler = new OnClickListener() {
974 public void onClick(View v) {
975 refreshSmsc();
976 }
977 };
978
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800979 AdapterView.OnItemSelectedListener
980 mPreferredNetworkHandler = new AdapterView.OnItemSelectedListener() {
981 public void onItemSelected(AdapterView parent, View v, int pos, long id) {
982 Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE);
Wink Savilleead69282009-05-13 11:51:03 -0700983 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 -0800984 phone.setPreferredNetworkType(pos, msg);
985 }
986 }
987
988 public void onNothingSelected(AdapterView parent) {
989 }
990 };
991
992 private String[] mPreferredNetworkLabels = {
jsh87fa11b2009-08-18 18:00:15 -0700993 "WCDMA preferred",
994 "GSM only",
995 "WCDMA only",
996 "GSM auto (PRL)",
997 "CDMA auto (PRL)",
998 "CDMA only",
999 "EvDo only",
1000 "GSM/CDMA auto (PRL)",
1001 "Unknown"};
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001002}