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