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