1 /* 2 * Copyright (C) 2019 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.car.developeroptions; 18 19 import static android.net.ConnectivityManager.NetworkCallback; 20 import static android.provider.Settings.Global.PREFERRED_NETWORK_MODE; 21 22 import android.app.Activity; 23 import android.app.QueuedWork; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.DialogInterface; 27 import android.content.Intent; 28 import android.content.pm.PackageManager; 29 import android.content.pm.ResolveInfo; 30 import android.content.res.Resources; 31 import android.graphics.Typeface; 32 import android.net.ConnectivityManager; 33 import android.net.Network; 34 import android.net.NetworkCapabilities; 35 import android.net.NetworkRequest; 36 import android.net.TrafficStats; 37 import android.net.Uri; 38 import android.os.AsyncResult; 39 import android.os.Build; 40 import android.os.Bundle; 41 import android.os.Handler; 42 import android.os.Message; 43 import android.provider.Settings; 44 import android.telephony.CarrierConfigManager; 45 import android.telephony.CellIdentityCdma; 46 import android.telephony.CellIdentityGsm; 47 import android.telephony.CellIdentityLte; 48 import android.telephony.CellIdentityWcdma; 49 import android.telephony.CellInfo; 50 import android.telephony.CellInfoCdma; 51 import android.telephony.CellInfoGsm; 52 import android.telephony.CellInfoLte; 53 import android.telephony.CellInfoWcdma; 54 import android.telephony.CellLocation; 55 import android.telephony.CellSignalStrengthCdma; 56 import android.telephony.CellSignalStrengthGsm; 57 import android.telephony.CellSignalStrengthLte; 58 import android.telephony.CellSignalStrengthWcdma; 59 import android.telephony.PhoneStateListener; 60 import android.telephony.PhysicalChannelConfig; 61 import android.telephony.PreciseCallState; 62 import android.telephony.ServiceState; 63 import android.telephony.SignalStrength; 64 import android.telephony.SubscriptionManager; 65 import android.telephony.TelephonyManager; 66 import android.telephony.cdma.CdmaCellLocation; 67 import android.telephony.gsm.GsmCellLocation; 68 import android.text.TextUtils; 69 import android.util.Log; 70 import android.view.Menu; 71 import android.view.MenuItem; 72 import android.view.View; 73 import android.view.View.OnClickListener; 74 import android.widget.AdapterView; 75 import android.widget.ArrayAdapter; 76 import android.widget.Button; 77 import android.widget.CompoundButton; 78 import android.widget.CompoundButton.OnCheckedChangeListener; 79 import android.widget.EditText; 80 import android.widget.Spinner; 81 import android.widget.Switch; 82 import android.widget.TextView; 83 84 import androidx.appcompat.app.AlertDialog; 85 import androidx.appcompat.app.AlertDialog.Builder; 86 87 import com.android.ims.ImsConfig; 88 import com.android.ims.ImsException; 89 import com.android.ims.ImsManager; 90 import com.android.internal.telephony.Phone; 91 import com.android.internal.telephony.PhoneFactory; 92 93 import java.io.IOException; 94 import java.net.HttpURLConnection; 95 import java.net.URL; 96 import java.util.List; 97 98 // TODO(b/123598192) consider to move this activity to telephony package. 99 public class RadioInfo extends Activity { 100 private static final String TAG = "RadioInfo"; 101 102 private static final String[] mPreferredNetworkLabels = { 103 "WCDMA preferred", 104 "GSM only", 105 "WCDMA only", 106 "GSM auto (PRL)", 107 "CDMA auto (PRL)", 108 "CDMA only", 109 "EvDo only", 110 "Global auto (PRL)", 111 "LTE/CDMA auto (PRL)", 112 "LTE/UMTS auto (PRL)", 113 "LTE/CDMA/UMTS auto (PRL)", 114 "LTE only", 115 "LTE/WCDMA", 116 "TD-SCDMA only", 117 "TD-SCDMA/WCDMA", 118 "LTE/TD-SCDMA", 119 "TD-SCDMA/GSM", 120 "TD-SCDMA/UMTS", 121 "LTE/TD-SCDMA/WCDMA", 122 "LTE/TD-SCDMA/UMTS", 123 "TD-SCDMA/CDMA/UMTS", 124 "Global/TD-SCDMA", 125 "Unknown" 126 }; 127 128 129 private static final int CELL_INFO_LIST_RATE_DISABLED = Integer.MAX_VALUE; 130 private static final int CELL_INFO_LIST_RATE_MAX = 0; 131 132 133 private static final int IMS_VOLTE_PROVISIONED_CONFIG_ID = 134 ImsConfig.ConfigConstants.VLT_SETTING_ENABLED; 135 136 private static final int IMS_VT_PROVISIONED_CONFIG_ID = 137 ImsConfig.ConfigConstants.LVC_SETTING_ENABLED; 138 139 private static final int IMS_WFC_PROVISIONED_CONFIG_ID = 140 ImsConfig.ConfigConstants.VOICE_OVER_WIFI_SETTING_ENABLED; 141 142 private static final int EAB_PROVISIONED_CONFIG_ID = 143 ImsConfig.ConfigConstants.EAB_SETTING_ENABLED; 144 145 //Values in must match mCellInfoRefreshRates 146 private static final String[] mCellInfoRefreshRateLabels = { 147 "Disabled", 148 "Immediate", 149 "Min 5s", 150 "Min 10s", 151 "Min 60s" 152 }; 153 154 //Values in seconds, must match mCellInfoRefreshRateLabels 155 private static final int mCellInfoRefreshRates[] = { 156 CELL_INFO_LIST_RATE_DISABLED, 157 CELL_INFO_LIST_RATE_MAX, 158 5000, 159 10000, 160 60000 161 }; 162 log(String s)163 private void log(String s) { 164 Log.d(TAG, s); 165 } 166 167 private static final int EVENT_CFI_CHANGED = 302; 168 169 private static final int EVENT_QUERY_PREFERRED_TYPE_DONE = 1000; 170 private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001; 171 private static final int EVENT_QUERY_SMSC_DONE = 1005; 172 private static final int EVENT_UPDATE_SMSC_DONE = 1006; 173 private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 1007; 174 175 private static final int MENU_ITEM_SELECT_BAND = 0; 176 private static final int MENU_ITEM_VIEW_ADN = 1; 177 private static final int MENU_ITEM_VIEW_FDN = 2; 178 private static final int MENU_ITEM_VIEW_SDN = 3; 179 private static final int MENU_ITEM_GET_IMS_STATUS = 4; 180 private static final int MENU_ITEM_TOGGLE_DATA = 5; 181 182 private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA 183 private TextView number; 184 private TextView mSubscriberId; 185 private TextView callState; 186 private TextView operatorName; 187 private TextView roamingState; 188 private TextView gsmState; 189 private TextView gprsState; 190 private TextView voiceNetwork; 191 private TextView dataNetwork; 192 private TextView dBm; 193 private TextView mMwi; 194 private TextView mCfi; 195 private TextView mLocation; 196 private TextView mCellInfo; 197 private TextView sent; 198 private TextView received; 199 private TextView mPingHostnameV4; 200 private TextView mPingHostnameV6; 201 private TextView mHttpClientTest; 202 private TextView mPhyChanConfig; 203 private TextView dnsCheckState; 204 private TextView mDownlinkKbps; 205 private TextView mUplinkKbps; 206 private EditText smsc; 207 private Switch radioPowerOnSwitch; 208 private Button cellInfoRefreshRateButton; 209 private Button dnsCheckToggleButton; 210 private Button pingTestButton; 211 private Button updateSmscButton; 212 private Button refreshSmscButton; 213 private Button oemInfoButton; 214 private Button carrierProvisioningButton; 215 private Button triggercarrierProvisioningButton; 216 private Switch imsVolteProvisionedSwitch; 217 private Switch imsVtProvisionedSwitch; 218 private Switch imsWfcProvisionedSwitch; 219 private Switch eabProvisionedSwitch; 220 private Switch cbrsDataSwitch; 221 private Switch dsdsSwitch; 222 private Spinner preferredNetworkType; 223 private Spinner cellInfoRefreshRateSpinner; 224 225 private ConnectivityManager mConnectivityManager; 226 private TelephonyManager mTelephonyManager; 227 private ImsManager mImsManager = null; 228 private Phone phone = null; 229 230 private String mPingHostnameResultV4; 231 private String mPingHostnameResultV6; 232 private String mHttpClientTestResult; 233 private boolean mMwiValue = false; 234 private boolean mCfiValue = false; 235 236 private List<CellInfo> mCellInfoResult = null; 237 private CellLocation mCellLocationResult = null; 238 239 private int mPreferredNetworkTypeResult; 240 private int mCellInfoRefreshRateIndex; 241 242 private final NetworkRequest mDefaultNetworkRequest = new NetworkRequest.Builder() 243 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 244 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 245 .build(); 246 247 private final NetworkCallback mNetworkCallback = new NetworkCallback() { 248 public void onCapabilitiesChanged(Network n, NetworkCapabilities nc) { 249 int dlbw = nc.getLinkDownstreamBandwidthKbps(); 250 int ulbw = nc.getLinkUpstreamBandwidthKbps(); 251 updateBandwidths(dlbw, ulbw); 252 } 253 }; 254 255 private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 256 @Override 257 public void onDataConnectionStateChanged(int state) { 258 updateDataState(); 259 updateNetworkType(); 260 } 261 262 @Override 263 public void onDataActivity(int direction) { 264 updateDataStats2(); 265 } 266 267 @Override 268 public void onCallStateChanged(int state, String incomingNumber) { 269 updateNetworkType(); 270 updatePhoneState(state); 271 } 272 273 @Override 274 public void onPreciseCallStateChanged(PreciseCallState preciseState) { 275 updateNetworkType(); 276 } 277 278 @Override 279 public void onCellLocationChanged(CellLocation location) { 280 updateLocation(location); 281 } 282 283 @Override 284 public void onMessageWaitingIndicatorChanged(boolean mwi) { 285 mMwiValue = mwi; 286 updateMessageWaiting(); 287 } 288 289 @Override 290 public void onCallForwardingIndicatorChanged(boolean cfi) { 291 mCfiValue = cfi; 292 updateCallRedirect(); 293 } 294 295 @Override 296 public void onCellInfoChanged(List<CellInfo> arrayCi) { 297 log("onCellInfoChanged: arrayCi=" + arrayCi); 298 mCellInfoResult = arrayCi; 299 updateCellInfo(mCellInfoResult); 300 } 301 302 @Override 303 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 304 log("onSignalStrengthChanged: SignalStrength=" +signalStrength); 305 updateSignalStrength(signalStrength); 306 } 307 308 @Override 309 public void onServiceStateChanged(ServiceState serviceState) { 310 log("onServiceStateChanged: ServiceState=" + serviceState); 311 updateServiceState(serviceState); 312 updateRadioPowerState(); 313 updateNetworkType(); 314 updateImsProvisionedState(); 315 } 316 317 }; 318 updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs)319 private void updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) { 320 StringBuilder sb = new StringBuilder(); 321 String div = ""; 322 sb.append("{"); 323 if (configs != null) { 324 for(PhysicalChannelConfig c : configs) { 325 sb.append(div).append(c); 326 div = ","; 327 } 328 } 329 sb.append("}"); 330 mPhyChanConfig.setText(sb.toString()); 331 } 332 updatePreferredNetworkType(int type)333 private void updatePreferredNetworkType(int type) { 334 if (type >= mPreferredNetworkLabels.length || type < 0) { 335 log("EVENT_QUERY_PREFERRED_TYPE_DONE: unknown " + 336 "type=" + type); 337 type = mPreferredNetworkLabels.length - 1; //set to Unknown 338 } 339 mPreferredNetworkTypeResult = type; 340 341 preferredNetworkType.setSelection(mPreferredNetworkTypeResult, true); 342 } 343 344 private Handler mHandler = new Handler() { 345 @Override 346 public void handleMessage(Message msg) { 347 AsyncResult ar; 348 switch (msg.what) { 349 case EVENT_QUERY_PREFERRED_TYPE_DONE: 350 ar= (AsyncResult) msg.obj; 351 if (ar.exception == null && ar.result != null) { 352 updatePreferredNetworkType(((int[])ar.result)[0]); 353 } else { 354 //In case of an exception, we will set this to unknown 355 updatePreferredNetworkType(mPreferredNetworkLabels.length-1); 356 } 357 break; 358 case EVENT_SET_PREFERRED_TYPE_DONE: 359 ar= (AsyncResult) msg.obj; 360 if (ar.exception != null) { 361 log("Set preferred network type failed."); 362 } 363 break; 364 case EVENT_QUERY_SMSC_DONE: 365 ar= (AsyncResult) msg.obj; 366 if (ar.exception != null) { 367 smsc.setText("refresh error"); 368 } else { 369 smsc.setText((String)ar.result); 370 } 371 break; 372 case EVENT_UPDATE_SMSC_DONE: 373 updateSmscButton.setEnabled(true); 374 ar= (AsyncResult) msg.obj; 375 if (ar.exception != null) { 376 smsc.setText("update error"); 377 } 378 break; 379 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED: 380 ar = (AsyncResult) msg.obj; 381 if (ar.exception != null) { 382 mPhyChanConfig.setText(("update error")); 383 } 384 updatePhysicalChannelConfiguration((List<PhysicalChannelConfig>) ar.result); 385 break; 386 default: 387 super.handleMessage(msg); 388 break; 389 390 } 391 } 392 }; 393 394 @Override onCreate(Bundle icicle)395 public void onCreate(Bundle icicle) { 396 super.onCreate(icicle); 397 if (!android.os.Process.myUserHandle().isSystem()) { 398 Log.e(TAG, "Not run from system user, don't do anything."); 399 finish(); 400 return; 401 } 402 403 setContentView(R.layout.radio_info); 404 405 log("Started onCreate"); 406 407 mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE); 408 mConnectivityManager = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE); 409 phone = PhoneFactory.getDefaultPhone(); 410 411 //TODO: Need to update this if the default phoneId changes? 412 // Better to have an instance per phone? 413 mImsManager = ImsManager.getInstance(getApplicationContext(), 414 SubscriptionManager.getDefaultVoicePhoneId()); 415 416 mDeviceId = (TextView) findViewById(R.id.imei); 417 number = (TextView) findViewById(R.id.number); 418 mSubscriberId = (TextView) findViewById(R.id.imsi); 419 callState = (TextView) findViewById(R.id.call); 420 operatorName = (TextView) findViewById(R.id.operator); 421 roamingState = (TextView) findViewById(R.id.roaming); 422 gsmState = (TextView) findViewById(R.id.gsm); 423 gprsState = (TextView) findViewById(R.id.gprs); 424 voiceNetwork = (TextView) findViewById(R.id.voice_network); 425 dataNetwork = (TextView) findViewById(R.id.data_network); 426 dBm = (TextView) findViewById(R.id.dbm); 427 mMwi = (TextView) findViewById(R.id.mwi); 428 mCfi = (TextView) findViewById(R.id.cfi); 429 mLocation = (TextView) findViewById(R.id.location); 430 mCellInfo = (TextView) findViewById(R.id.cellinfo); 431 mCellInfo.setTypeface(Typeface.MONOSPACE); 432 433 sent = (TextView) findViewById(R.id.sent); 434 received = (TextView) findViewById(R.id.received); 435 smsc = (EditText) findViewById(R.id.smsc); 436 dnsCheckState = (TextView) findViewById(R.id.dnsCheckState); 437 mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4); 438 mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6); 439 mHttpClientTest = (TextView) findViewById(R.id.httpClientTest); 440 441 mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config); 442 443 preferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType); 444 ArrayAdapter<String> adapter = new ArrayAdapter<String> (this, 445 android.R.layout.simple_spinner_item, mPreferredNetworkLabels); 446 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 447 preferredNetworkType.setAdapter(adapter); 448 449 cellInfoRefreshRateSpinner = (Spinner) findViewById(R.id.cell_info_rate_select); 450 ArrayAdapter<String> cellInfoAdapter = new ArrayAdapter<String>(this, 451 android.R.layout.simple_spinner_item, mCellInfoRefreshRateLabels); 452 cellInfoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 453 cellInfoRefreshRateSpinner.setAdapter(cellInfoAdapter); 454 455 imsVolteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch); 456 imsVtProvisionedSwitch = (Switch) findViewById(R.id.vt_provisioned_switch); 457 imsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch); 458 eabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch); 459 460 if (!ImsManager.isImsSupportedOnDevice(phone.getContext())) { 461 imsVolteProvisionedSwitch.setVisibility(View.GONE); 462 imsVtProvisionedSwitch.setVisibility(View.GONE); 463 imsWfcProvisionedSwitch.setVisibility(View.GONE); 464 eabProvisionedSwitch.setVisibility(View.GONE); 465 } 466 467 cbrsDataSwitch = (Switch) findViewById(R.id.cbrs_data_switch); 468 cbrsDataSwitch.setVisibility(isCbrsSupported() ? View.VISIBLE : View.GONE); 469 470 dsdsSwitch = findViewById(R.id.dsds_switch); 471 if (isDsdsSupported()) { 472 dsdsSwitch.setVisibility(View.VISIBLE); 473 dsdsSwitch.setOnClickListener(v -> { 474 if (mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot()) { 475 // Undo the click action until user clicks the confirm dialog. 476 dsdsSwitch.toggle(); 477 showDsdsChangeDialog(); 478 } else { 479 performDsdsSwitch(); 480 } 481 }); 482 dsdsSwitch.setChecked(isDsdsEnabled()); 483 } else { 484 dsdsSwitch.setVisibility(View.GONE); 485 } 486 487 radioPowerOnSwitch = (Switch) findViewById(R.id.radio_power); 488 489 mDownlinkKbps = (TextView) findViewById(R.id.dl_kbps); 490 mUplinkKbps = (TextView) findViewById(R.id.ul_kbps); 491 updateBandwidths(0, 0); 492 493 pingTestButton = (Button) findViewById(R.id.ping_test); 494 pingTestButton.setOnClickListener(mPingButtonHandler); 495 updateSmscButton = (Button) findViewById(R.id.update_smsc); 496 updateSmscButton.setOnClickListener(mUpdateSmscButtonHandler); 497 refreshSmscButton = (Button) findViewById(R.id.refresh_smsc); 498 refreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler); 499 dnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle); 500 dnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler); 501 carrierProvisioningButton = (Button) findViewById(R.id.carrier_provisioning); 502 carrierProvisioningButton.setOnClickListener(mCarrierProvisioningButtonHandler); 503 triggercarrierProvisioningButton = (Button) findViewById(R.id.trigger_carrier_provisioning); 504 triggercarrierProvisioningButton.setOnClickListener( 505 mTriggerCarrierProvisioningButtonHandler); 506 507 oemInfoButton = (Button) findViewById(R.id.oem_info); 508 oemInfoButton.setOnClickListener(mOemInfoButtonHandler); 509 PackageManager pm = getPackageManager(); 510 Intent oemInfoIntent = new Intent("com.android.car.developeroptions.OEM_RADIO_INFO"); 511 List<ResolveInfo> oemInfoIntentList = pm.queryIntentActivities(oemInfoIntent, 0); 512 if (oemInfoIntentList.size() == 0) { 513 oemInfoButton.setEnabled(false); 514 } 515 516 mCellInfoRefreshRateIndex = 0; //disabled 517 mPreferredNetworkTypeResult = mPreferredNetworkLabels.length - 1; //Unknown 518 519 //FIXME: Replace with TelephonyManager call 520 phone.getPreferredNetworkType( 521 mHandler.obtainMessage(EVENT_QUERY_PREFERRED_TYPE_DONE)); 522 523 restoreFromBundle(icicle); 524 } 525 526 @Override onResume()527 protected void onResume() { 528 super.onResume(); 529 530 log("Started onResume"); 531 532 updateMessageWaiting(); 533 updateCallRedirect(); 534 updateDataState(); 535 updateDataStats2(); 536 updateRadioPowerState(); 537 updateImsProvisionedState(); 538 updateProperties(); 539 updateDnsCheckState(); 540 updateNetworkType(); 541 542 updateLocation(mCellLocationResult); 543 updateCellInfo(mCellInfoResult); 544 545 mPingHostnameV4.setText(mPingHostnameResultV4); 546 mPingHostnameV6.setText(mPingHostnameResultV6); 547 mHttpClientTest.setText(mHttpClientTestResult); 548 549 cellInfoRefreshRateSpinner.setOnItemSelectedListener(mCellInfoRefreshRateHandler); 550 //set selection after registering listener to force update 551 cellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex); 552 553 //set selection before registering to prevent update 554 preferredNetworkType.setSelection(mPreferredNetworkTypeResult, true); 555 preferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler); 556 557 radioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener); 558 imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener); 559 imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener); 560 imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener); 561 eabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener); 562 563 if (isCbrsSupported()) { 564 cbrsDataSwitch.setChecked(getCbrsDataState()); 565 cbrsDataSwitch.setOnCheckedChangeListener(mCbrsDataSwitchChangeListener); 566 } 567 568 mTelephonyManager.listen(mPhoneStateListener, 569 PhoneStateListener.LISTEN_CALL_STATE 570 //b/27803938 - RadioInfo currently cannot read PRECISE_CALL_STATE 571 // | PhoneStateListener.LISTEN_PRECISE_CALL_STATE 572 | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE 573 | PhoneStateListener.LISTEN_DATA_ACTIVITY 574 | PhoneStateListener.LISTEN_CELL_LOCATION 575 | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR 576 | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR 577 | PhoneStateListener.LISTEN_CELL_INFO 578 | PhoneStateListener.LISTEN_SERVICE_STATE 579 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); 580 phone.registerForPhysicalChannelConfig(mHandler, 581 EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, null); 582 583 mConnectivityManager.registerNetworkCallback( 584 mDefaultNetworkRequest, mNetworkCallback, mHandler); 585 586 smsc.clearFocus(); 587 } 588 589 @Override onPause()590 protected void onPause() { 591 super.onPause(); 592 593 log("onPause: unregister phone & data intents"); 594 595 mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); 596 mTelephonyManager.setCellInfoListRate(CELL_INFO_LIST_RATE_DISABLED); 597 mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); 598 phone.unregisterForPhysicalChannelConfig(mHandler); 599 } 600 restoreFromBundle(Bundle b)601 private void restoreFromBundle(Bundle b) { 602 if(b == null) { 603 return; 604 } 605 606 mPingHostnameResultV4 = b.getString("mPingHostnameResultV4",""); 607 mPingHostnameResultV6 = b.getString("mPingHostnameResultV6",""); 608 mHttpClientTestResult = b.getString("mHttpClientTestResult",""); 609 610 mPingHostnameV4.setText(mPingHostnameResultV4); 611 mPingHostnameV6.setText(mPingHostnameResultV6); 612 mHttpClientTest.setText(mHttpClientTestResult); 613 614 mPreferredNetworkTypeResult = b.getInt("mPreferredNetworkTypeResult", 615 mPreferredNetworkLabels.length - 1); 616 617 mCellInfoRefreshRateIndex = b.getInt("mCellInfoRefreshRateIndex", 0); 618 } 619 620 @Override onSaveInstanceState(Bundle outState)621 protected void onSaveInstanceState(Bundle outState) { 622 outState.putString("mPingHostnameResultV4", mPingHostnameResultV4); 623 outState.putString("mPingHostnameResultV6", mPingHostnameResultV6); 624 outState.putString("mHttpClientTestResult", mHttpClientTestResult); 625 626 outState.putInt("mPreferredNetworkTypeResult", mPreferredNetworkTypeResult); 627 outState.putInt("mCellInfoRefreshRateIndex", mCellInfoRefreshRateIndex); 628 629 } 630 631 @Override onCreateOptionsMenu(Menu menu)632 public boolean onCreateOptionsMenu(Menu menu) { 633 menu.add(0, MENU_ITEM_SELECT_BAND, 0, R.string.radio_info_band_mode_label) 634 .setOnMenuItemClickListener(mSelectBandCallback) 635 .setAlphabeticShortcut('b'); 636 menu.add(1, MENU_ITEM_VIEW_ADN, 0, 637 R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback); 638 menu.add(1, MENU_ITEM_VIEW_FDN, 0, 639 R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback); 640 menu.add(1, MENU_ITEM_VIEW_SDN, 0, 641 R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback); 642 if (ImsManager.isImsSupportedOnDevice(phone.getContext())) { 643 menu.add(1, MENU_ITEM_GET_IMS_STATUS, 644 0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus); 645 } 646 menu.add(1, MENU_ITEM_TOGGLE_DATA, 647 0, R.string.radio_info_data_connection_disable).setOnMenuItemClickListener(mToggleData); 648 return true; 649 } 650 651 @Override onPrepareOptionsMenu(Menu menu)652 public boolean onPrepareOptionsMenu(Menu menu) { 653 // Get the TOGGLE DATA menu item in the right state. 654 MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA); 655 int state = mTelephonyManager.getDataState(); 656 boolean visible = true; 657 658 switch (state) { 659 case TelephonyManager.DATA_CONNECTED: 660 case TelephonyManager.DATA_SUSPENDED: 661 item.setTitle(R.string.radio_info_data_connection_disable); 662 break; 663 case TelephonyManager.DATA_DISCONNECTED: 664 item.setTitle(R.string.radio_info_data_connection_enable); 665 break; 666 default: 667 visible = false; 668 break; 669 } 670 item.setVisible(visible); 671 return true; 672 } 673 updateDnsCheckState()674 private void updateDnsCheckState() { 675 //FIXME: Replace with a TelephonyManager call 676 dnsCheckState.setText(phone.isDnsCheckDisabled() ? 677 "0.0.0.0 allowed" :"0.0.0.0 not allowed"); 678 } 679 updateBandwidths(int dlbw, int ulbw)680 private void updateBandwidths(int dlbw, int ulbw) { 681 dlbw = (dlbw < 0 || dlbw == Integer.MAX_VALUE) ? -1 : dlbw; 682 ulbw = (ulbw < 0 || ulbw == Integer.MAX_VALUE) ? -1 : ulbw; 683 mDownlinkKbps.setText(String.format("%-5d", dlbw)); 684 mUplinkKbps.setText(String.format("%-5d", ulbw)); 685 } 686 687 688 private final void updateSignalStrength(SignalStrength signalStrength)689 updateSignalStrength(SignalStrength signalStrength) { 690 Resources r = getResources(); 691 692 int signalDbm = signalStrength.getDbm(); 693 694 int signalAsu = signalStrength.getAsuLevel(); 695 696 if (-1 == signalAsu) signalAsu = 0; 697 698 dBm.setText(String.valueOf(signalDbm) + " " 699 + r.getString(R.string.radioInfo_display_dbm) + " " 700 + String.valueOf(signalAsu) + " " 701 + r.getString(R.string.radioInfo_display_asu)); 702 } 703 updateLocation(CellLocation location)704 private final void updateLocation(CellLocation location) { 705 Resources r = getResources(); 706 if (location instanceof GsmCellLocation) { 707 GsmCellLocation loc = (GsmCellLocation)location; 708 int lac = loc.getLac(); 709 int cid = loc.getCid(); 710 mLocation.setText(r.getString(R.string.radioInfo_lac) + " = " 711 + ((lac == -1) ? "unknown" : Integer.toHexString(lac)) 712 + " " 713 + r.getString(R.string.radioInfo_cid) + " = " 714 + ((cid == -1) ? "unknown" : Integer.toHexString(cid))); 715 } else if (location instanceof CdmaCellLocation) { 716 CdmaCellLocation loc = (CdmaCellLocation)location; 717 int bid = loc.getBaseStationId(); 718 int sid = loc.getSystemId(); 719 int nid = loc.getNetworkId(); 720 int lat = loc.getBaseStationLatitude(); 721 int lon = loc.getBaseStationLongitude(); 722 mLocation.setText("BID = " 723 + ((bid == -1) ? "unknown" : Integer.toHexString(bid)) 724 + " " 725 + "SID = " 726 + ((sid == -1) ? "unknown" : Integer.toHexString(sid)) 727 + " " 728 + "NID = " 729 + ((nid == -1) ? "unknown" : Integer.toHexString(nid)) 730 + "\n" 731 + "LAT = " 732 + ((lat == -1) ? "unknown" : Integer.toHexString(lat)) 733 + " " 734 + "LONG = " 735 + ((lon == -1) ? "unknown" : Integer.toHexString(lon))); 736 } else { 737 mLocation.setText("unknown"); 738 } 739 740 741 } 742 getCellInfoDisplayString(int i)743 private final String getCellInfoDisplayString(int i) { 744 return (i != Integer.MAX_VALUE) ? Integer.toString(i) : ""; 745 } 746 getCellInfoDisplayString(long i)747 private final String getCellInfoDisplayString(long i) { 748 return (i != Long.MAX_VALUE) ? Long.toString(i) : ""; 749 } 750 getConnectionStatusString(CellInfo ci)751 private final String getConnectionStatusString(CellInfo ci) { 752 String regStr = ""; 753 String connStatStr = ""; 754 String connector = ""; 755 756 if (ci.isRegistered()) { 757 regStr = "R"; 758 } 759 switch (ci.getCellConnectionStatus()) { 760 case CellInfo.CONNECTION_PRIMARY_SERVING: connStatStr = "P"; break; 761 case CellInfo.CONNECTION_SECONDARY_SERVING: connStatStr = "S"; break; 762 case CellInfo.CONNECTION_NONE: connStatStr = "N"; break; 763 case CellInfo.CONNECTION_UNKNOWN: /* Field is unsupported */ break; 764 default: break; 765 } 766 if (!TextUtils.isEmpty(regStr) && !TextUtils.isEmpty(connStatStr)) { 767 connector = "+"; 768 } 769 770 return regStr + connector + connStatStr; 771 } 772 buildCdmaInfoString(CellInfoCdma ci)773 private final String buildCdmaInfoString(CellInfoCdma ci) { 774 CellIdentityCdma cidCdma = ci.getCellIdentity(); 775 CellSignalStrengthCdma ssCdma = ci.getCellSignalStrength(); 776 777 return String.format("%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s", 778 getConnectionStatusString(ci), 779 getCellInfoDisplayString(cidCdma.getSystemId()), 780 getCellInfoDisplayString(cidCdma.getNetworkId()), 781 getCellInfoDisplayString(cidCdma.getBasestationId()), 782 getCellInfoDisplayString(ssCdma.getCdmaDbm()), 783 getCellInfoDisplayString(ssCdma.getCdmaEcio()), 784 getCellInfoDisplayString(ssCdma.getEvdoDbm()), 785 getCellInfoDisplayString(ssCdma.getEvdoEcio()), 786 getCellInfoDisplayString(ssCdma.getEvdoSnr())); 787 } 788 buildGsmInfoString(CellInfoGsm ci)789 private final String buildGsmInfoString(CellInfoGsm ci) { 790 CellIdentityGsm cidGsm = ci.getCellIdentity(); 791 CellSignalStrengthGsm ssGsm = ci.getCellSignalStrength(); 792 793 return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n", 794 getConnectionStatusString(ci), 795 getCellInfoDisplayString(cidGsm.getMcc()), 796 getCellInfoDisplayString(cidGsm.getMnc()), 797 getCellInfoDisplayString(cidGsm.getLac()), 798 getCellInfoDisplayString(cidGsm.getCid()), 799 getCellInfoDisplayString(cidGsm.getArfcn()), 800 getCellInfoDisplayString(cidGsm.getBsic()), 801 getCellInfoDisplayString(ssGsm.getDbm())); 802 } 803 buildLteInfoString(CellInfoLte ci)804 private final String buildLteInfoString(CellInfoLte ci) { 805 CellIdentityLte cidLte = ci.getCellIdentity(); 806 CellSignalStrengthLte ssLte = ci.getCellSignalStrength(); 807 808 return String.format( 809 "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n", 810 getConnectionStatusString(ci), 811 getCellInfoDisplayString(cidLte.getMcc()), 812 getCellInfoDisplayString(cidLte.getMnc()), 813 getCellInfoDisplayString(cidLte.getTac()), 814 getCellInfoDisplayString(cidLte.getCi()), 815 getCellInfoDisplayString(cidLte.getPci()), 816 getCellInfoDisplayString(cidLte.getEarfcn()), 817 getCellInfoDisplayString(cidLte.getBandwidth()), 818 getCellInfoDisplayString(ssLte.getDbm()), 819 getCellInfoDisplayString(ssLte.getRsrq()), 820 getCellInfoDisplayString(ssLte.getTimingAdvance())); 821 } 822 buildWcdmaInfoString(CellInfoWcdma ci)823 private final String buildWcdmaInfoString(CellInfoWcdma ci) { 824 CellIdentityWcdma cidWcdma = ci.getCellIdentity(); 825 CellSignalStrengthWcdma ssWcdma = ci.getCellSignalStrength(); 826 827 return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n", 828 getConnectionStatusString(ci), 829 getCellInfoDisplayString(cidWcdma.getMcc()), 830 getCellInfoDisplayString(cidWcdma.getMnc()), 831 getCellInfoDisplayString(cidWcdma.getLac()), 832 getCellInfoDisplayString(cidWcdma.getCid()), 833 getCellInfoDisplayString(cidWcdma.getUarfcn()), 834 getCellInfoDisplayString(cidWcdma.getPsc()), 835 getCellInfoDisplayString(ssWcdma.getDbm())); 836 } 837 buildCellInfoString(List<CellInfo> arrayCi)838 private final String buildCellInfoString(List<CellInfo> arrayCi) { 839 String value = new String(); 840 StringBuilder cdmaCells = new StringBuilder(), 841 gsmCells = new StringBuilder(), 842 lteCells = new StringBuilder(), 843 wcdmaCells = new StringBuilder(); 844 845 if (arrayCi != null) { 846 for (CellInfo ci : arrayCi) { 847 848 if (ci instanceof CellInfoLte) { 849 lteCells.append(buildLteInfoString((CellInfoLte) ci)); 850 } else if (ci instanceof CellInfoWcdma) { 851 wcdmaCells.append(buildWcdmaInfoString((CellInfoWcdma) ci)); 852 } else if (ci instanceof CellInfoGsm) { 853 gsmCells.append(buildGsmInfoString((CellInfoGsm) ci)); 854 } else if (ci instanceof CellInfoCdma) { 855 cdmaCells.append(buildCdmaInfoString((CellInfoCdma) ci)); 856 } 857 } 858 if (lteCells.length() != 0) { 859 value += String.format( 860 "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s" 861 + " %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n", 862 "SRV", "MCC", "MNC", "TAC", "CID", "PCI", 863 "EARFCN", "BW", "RSRP", "RSRQ", "TA"); 864 value += lteCells.toString(); 865 } 866 if (wcdmaCells.length() != 0) { 867 value += String.format( 868 "WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n", 869 "SRV", "MCC", "MNC", "LAC", "CID", "UARFCN", "PSC", "RSCP"); 870 value += wcdmaCells.toString(); 871 } 872 if (gsmCells.length() != 0) { 873 value += String.format( 874 "GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n", 875 "SRV", "MCC", "MNC", "LAC", "CID", "ARFCN", "BSIC", "RSSI"); 876 value += gsmCells.toString(); 877 } 878 if (cdmaCells.length() != 0) { 879 value += String.format( 880 "CDMA/EVDO\n%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s\n", 881 "SRV", "SID", "NID", "BSID", "C-RSSI", "C-ECIO", "E-RSSI", "E-ECIO", "E-SNR"); 882 value += cdmaCells.toString(); 883 } 884 } else { 885 value ="unknown"; 886 } 887 888 return value.toString(); 889 } 890 updateCellInfo(List<CellInfo> arrayCi)891 private final void updateCellInfo(List<CellInfo> arrayCi) { 892 mCellInfo.setText(buildCellInfoString(arrayCi)); 893 } 894 895 private final void updateMessageWaiting()896 updateMessageWaiting() { 897 mMwi.setText(String.valueOf(mMwiValue)); 898 } 899 900 private final void updateCallRedirect()901 updateCallRedirect() { 902 mCfi.setText(String.valueOf(mCfiValue)); 903 } 904 905 906 private final void updateServiceState(ServiceState serviceState)907 updateServiceState(ServiceState serviceState) { 908 int state = serviceState.getState(); 909 Resources r = getResources(); 910 String display = r.getString(R.string.radioInfo_unknown); 911 912 switch (state) { 913 case ServiceState.STATE_IN_SERVICE: 914 display = r.getString(R.string.radioInfo_service_in); 915 break; 916 case ServiceState.STATE_OUT_OF_SERVICE: 917 case ServiceState.STATE_EMERGENCY_ONLY: 918 display = r.getString(R.string.radioInfo_service_emergency); 919 break; 920 case ServiceState.STATE_POWER_OFF: 921 display = r.getString(R.string.radioInfo_service_off); 922 break; 923 } 924 925 gsmState.setText(display); 926 927 if (serviceState.getRoaming()) { 928 roamingState.setText(R.string.radioInfo_roaming_in); 929 } else { 930 roamingState.setText(R.string.radioInfo_roaming_not); 931 } 932 933 operatorName.setText(serviceState.getOperatorAlphaLong()); 934 } 935 936 private final void updatePhoneState(int state)937 updatePhoneState(int state) { 938 Resources r = getResources(); 939 String display = r.getString(R.string.radioInfo_unknown); 940 941 switch (state) { 942 case TelephonyManager.CALL_STATE_IDLE: 943 display = r.getString(R.string.radioInfo_phone_idle); 944 break; 945 case TelephonyManager.CALL_STATE_RINGING: 946 display = r.getString(R.string.radioInfo_phone_ringing); 947 break; 948 case TelephonyManager.CALL_STATE_OFFHOOK: 949 display = r.getString(R.string.radioInfo_phone_offhook); 950 break; 951 } 952 953 callState.setText(display); 954 } 955 956 private final void updateDataState()957 updateDataState() { 958 int state = mTelephonyManager.getDataState(); 959 Resources r = getResources(); 960 String display = r.getString(R.string.radioInfo_unknown); 961 962 switch (state) { 963 case TelephonyManager.DATA_CONNECTED: 964 display = r.getString(R.string.radioInfo_data_connected); 965 break; 966 case TelephonyManager.DATA_CONNECTING: 967 display = r.getString(R.string.radioInfo_data_connecting); 968 break; 969 case TelephonyManager.DATA_DISCONNECTED: 970 display = r.getString(R.string.radioInfo_data_disconnected); 971 break; 972 case TelephonyManager.DATA_SUSPENDED: 973 display = r.getString(R.string.radioInfo_data_suspended); 974 break; 975 } 976 977 gprsState.setText(display); 978 } 979 updateNetworkType()980 private final void updateNetworkType() { 981 if(phone != null) { 982 ServiceState ss = phone.getServiceState(); 983 dataNetwork.setText(ServiceState.rilRadioTechnologyToString( 984 phone.getServiceState().getRilDataRadioTechnology())); 985 voiceNetwork.setText(ServiceState.rilRadioTechnologyToString( 986 phone.getServiceState().getRilVoiceRadioTechnology())); 987 } 988 } 989 990 private final void updateProperties()991 updateProperties() { 992 String s; 993 Resources r = getResources(); 994 995 s = phone.getDeviceId(); 996 if (s == null) s = r.getString(R.string.radioInfo_unknown); 997 mDeviceId.setText(s); 998 999 s = phone.getSubscriberId(); 1000 if (s == null) s = r.getString(R.string.radioInfo_unknown); 1001 mSubscriberId.setText(s); 1002 1003 //FIXME: Replace with a TelephonyManager call 1004 s = phone.getLine1Number(); 1005 if (s == null) s = r.getString(R.string.radioInfo_unknown); 1006 number.setText(s); 1007 } 1008 updateDataStats2()1009 private final void updateDataStats2() { 1010 Resources r = getResources(); 1011 1012 long txPackets = TrafficStats.getMobileTxPackets(); 1013 long rxPackets = TrafficStats.getMobileRxPackets(); 1014 long txBytes = TrafficStats.getMobileTxBytes(); 1015 long rxBytes = TrafficStats.getMobileRxBytes(); 1016 1017 String packets = r.getString(R.string.radioInfo_display_packets); 1018 String bytes = r.getString(R.string.radioInfo_display_bytes); 1019 1020 sent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes); 1021 received.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes); 1022 } 1023 1024 /** 1025 * Ping a host name 1026 */ pingHostname()1027 private final void pingHostname() { 1028 try { 1029 try { 1030 Process p4 = Runtime.getRuntime().exec("ping -c 1 www.google.com"); 1031 int status4 = p4.waitFor(); 1032 if (status4 == 0) { 1033 mPingHostnameResultV4 = "Pass"; 1034 } else { 1035 mPingHostnameResultV4 = String.format("Fail(%d)", status4); 1036 } 1037 } catch (IOException e) { 1038 mPingHostnameResultV4 = "Fail: IOException"; 1039 } 1040 try { 1041 Process p6 = Runtime.getRuntime().exec("ping6 -c 1 www.google.com"); 1042 int status6 = p6.waitFor(); 1043 if (status6 == 0) { 1044 mPingHostnameResultV6 = "Pass"; 1045 } else { 1046 mPingHostnameResultV6 = String.format("Fail(%d)", status6); 1047 } 1048 } catch (IOException e) { 1049 mPingHostnameResultV6 = "Fail: IOException"; 1050 } 1051 } catch (InterruptedException e) { 1052 mPingHostnameResultV4 = mPingHostnameResultV6 = "Fail: InterruptedException"; 1053 } 1054 } 1055 1056 /** 1057 * This function checks for basic functionality of HTTP Client. 1058 */ httpClientTest()1059 private void httpClientTest() { 1060 HttpURLConnection urlConnection = null; 1061 try { 1062 // TODO: Hardcoded for now, make it UI configurable 1063 URL url = new URL("https://www.google.com"); 1064 urlConnection = (HttpURLConnection) url.openConnection(); 1065 if (urlConnection.getResponseCode() == 200) { 1066 mHttpClientTestResult = "Pass"; 1067 } else { 1068 mHttpClientTestResult = "Fail: Code: " + urlConnection.getResponseMessage(); 1069 } 1070 } catch (IOException e) { 1071 mHttpClientTestResult = "Fail: IOException"; 1072 } finally { 1073 if (urlConnection != null) { 1074 urlConnection.disconnect(); 1075 } 1076 } 1077 } 1078 refreshSmsc()1079 private void refreshSmsc() { 1080 //FIXME: Replace with a TelephonyManager call 1081 phone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE)); 1082 } 1083 updateAllCellInfo()1084 private final void updateAllCellInfo() { 1085 1086 mCellInfo.setText(""); 1087 mLocation.setText(""); 1088 1089 final Runnable updateAllCellInfoResults = new Runnable() { 1090 public void run() { 1091 updateLocation(mCellLocationResult); 1092 updateCellInfo(mCellInfoResult); 1093 } 1094 }; 1095 1096 Thread locThread = new Thread() { 1097 @Override 1098 public void run() { 1099 mCellInfoResult = mTelephonyManager.getAllCellInfo(); 1100 mCellLocationResult = mTelephonyManager.getCellLocation(); 1101 1102 mHandler.post(updateAllCellInfoResults); 1103 } 1104 }; 1105 locThread.start(); 1106 } 1107 updatePingState()1108 private final void updatePingState() { 1109 // Set all to unknown since the threads will take a few secs to update. 1110 mPingHostnameResultV4 = getResources().getString(R.string.radioInfo_unknown); 1111 mPingHostnameResultV6 = getResources().getString(R.string.radioInfo_unknown); 1112 mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown); 1113 1114 mPingHostnameV4.setText(mPingHostnameResultV4); 1115 mPingHostnameV6.setText(mPingHostnameResultV6); 1116 mHttpClientTest.setText(mHttpClientTestResult); 1117 1118 final Runnable updatePingResults = new Runnable() { 1119 public void run() { 1120 mPingHostnameV4.setText(mPingHostnameResultV4); 1121 mPingHostnameV6.setText(mPingHostnameResultV6); 1122 mHttpClientTest.setText(mHttpClientTestResult); 1123 } 1124 }; 1125 1126 Thread hostname = new Thread() { 1127 @Override 1128 public void run() { 1129 pingHostname(); 1130 mHandler.post(updatePingResults); 1131 } 1132 }; 1133 hostname.start(); 1134 1135 Thread httpClient = new Thread() { 1136 @Override 1137 public void run() { 1138 httpClientTest(); 1139 mHandler.post(updatePingResults); 1140 } 1141 }; 1142 httpClient.start(); 1143 } 1144 1145 private MenuItem.OnMenuItemClickListener mViewADNCallback = new MenuItem.OnMenuItemClickListener() { 1146 public boolean onMenuItemClick(MenuItem item) { 1147 Intent intent = new Intent(Intent.ACTION_VIEW); 1148 // XXX We need to specify the component here because if we don't 1149 // the activity manager will try to resolve the type by calling 1150 // the content provider, which causes it to be loaded in a process 1151 // other than the Dialer process, which causes a lot of stuff to 1152 // break. 1153 intent.setClassName("com.android.phone", 1154 "com.android.phone.SimContacts"); 1155 startActivity(intent); 1156 return true; 1157 } 1158 }; 1159 1160 private MenuItem.OnMenuItemClickListener mViewFDNCallback = new MenuItem.OnMenuItemClickListener() { 1161 public boolean onMenuItemClick(MenuItem item) { 1162 Intent intent = new Intent(Intent.ACTION_VIEW); 1163 // XXX We need to specify the component here because if we don't 1164 // the activity manager will try to resolve the type by calling 1165 // the content provider, which causes it to be loaded in a process 1166 // other than the Dialer process, which causes a lot of stuff to 1167 // break. 1168 intent.setClassName("com.android.phone", 1169 "com.android.phone.settings.fdn.FdnList"); 1170 startActivity(intent); 1171 return true; 1172 } 1173 }; 1174 1175 private MenuItem.OnMenuItemClickListener mViewSDNCallback = new MenuItem.OnMenuItemClickListener() { 1176 public boolean onMenuItemClick(MenuItem item) { 1177 Intent intent = new Intent( 1178 Intent.ACTION_VIEW, Uri.parse("content://icc/sdn")); 1179 // XXX We need to specify the component here because if we don't 1180 // the activity manager will try to resolve the type by calling 1181 // the content provider, which causes it to be loaded in a process 1182 // other than the Dialer process, which causes a lot of stuff to 1183 // break. 1184 intent.setClassName("com.android.phone", 1185 "com.android.phone.ADNList"); 1186 startActivity(intent); 1187 return true; 1188 } 1189 }; 1190 1191 private MenuItem.OnMenuItemClickListener mGetImsStatus = new MenuItem.OnMenuItemClickListener() { 1192 public boolean onMenuItemClick(MenuItem item) { 1193 boolean isImsRegistered = phone.isImsRegistered(); 1194 boolean availableVolte = phone.isVolteEnabled(); 1195 boolean availableWfc = phone.isWifiCallingEnabled(); 1196 boolean availableVt = phone.isVideoEnabled(); 1197 boolean availableUt = phone.isUtEnabled(); 1198 1199 final String imsRegString = isImsRegistered ? 1200 getString(R.string.radio_info_ims_reg_status_registered) : 1201 getString(R.string.radio_info_ims_reg_status_not_registered); 1202 1203 final String available = getString(R.string.radio_info_ims_feature_status_available); 1204 final String unavailable = getString( 1205 R.string.radio_info_ims_feature_status_unavailable); 1206 1207 String imsStatus = getString(R.string.radio_info_ims_reg_status, 1208 imsRegString, 1209 availableVolte ? available : unavailable, 1210 availableWfc ? available : unavailable, 1211 availableVt ? available : unavailable, 1212 availableUt ? available : unavailable); 1213 1214 AlertDialog imsDialog = new AlertDialog.Builder(RadioInfo.this) 1215 .setMessage(imsStatus) 1216 .setTitle(getString(R.string.radio_info_ims_reg_status_title)) 1217 .create(); 1218 1219 imsDialog.show(); 1220 1221 return true; 1222 } 1223 }; 1224 1225 private MenuItem.OnMenuItemClickListener mSelectBandCallback = new MenuItem.OnMenuItemClickListener() { 1226 public boolean onMenuItemClick(MenuItem item) { 1227 Intent intent = new Intent(); 1228 intent.setClass(RadioInfo.this, BandMode.class); 1229 startActivity(intent); 1230 return true; 1231 } 1232 }; 1233 1234 private MenuItem.OnMenuItemClickListener mToggleData = new MenuItem.OnMenuItemClickListener() { 1235 public boolean onMenuItemClick(MenuItem item) { 1236 int state = mTelephonyManager.getDataState(); 1237 switch (state) { 1238 case TelephonyManager.DATA_CONNECTED: 1239 mTelephonyManager.setDataEnabled(false); 1240 break; 1241 case TelephonyManager.DATA_DISCONNECTED: 1242 mTelephonyManager.setDataEnabled(true); 1243 break; 1244 default: 1245 // do nothing 1246 break; 1247 } 1248 return true; 1249 } 1250 }; 1251 isRadioOn()1252 private boolean isRadioOn() { 1253 //FIXME: Replace with a TelephonyManager call 1254 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF; 1255 } 1256 updateRadioPowerState()1257 private void updateRadioPowerState() { 1258 //delightful hack to prevent on-checked-changed calls from 1259 //actually forcing the radio preference to its transient/current value. 1260 radioPowerOnSwitch.setOnCheckedChangeListener(null); 1261 radioPowerOnSwitch.setChecked(isRadioOn()); 1262 radioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener); 1263 } 1264 setImsVolteProvisionedState(boolean state)1265 void setImsVolteProvisionedState(boolean state) { 1266 Log.d(TAG, "setImsVolteProvisioned state: " + ((state)? "on":"off")); 1267 setImsConfigProvisionedState(IMS_VOLTE_PROVISIONED_CONFIG_ID, state); 1268 } 1269 setImsVtProvisionedState(boolean state)1270 void setImsVtProvisionedState(boolean state) { 1271 Log.d(TAG, "setImsVtProvisioned() state: " + ((state)? "on":"off")); 1272 setImsConfigProvisionedState(IMS_VT_PROVISIONED_CONFIG_ID, state); 1273 } 1274 setImsWfcProvisionedState(boolean state)1275 void setImsWfcProvisionedState(boolean state) { 1276 Log.d(TAG, "setImsWfcProvisioned() state: " + ((state)? "on":"off")); 1277 setImsConfigProvisionedState(IMS_WFC_PROVISIONED_CONFIG_ID, state); 1278 } 1279 setEabProvisionedState(boolean state)1280 void setEabProvisionedState(boolean state) { 1281 Log.d(TAG, "setEabProvisioned() state: " + ((state)? "on":"off")); 1282 setImsConfigProvisionedState(EAB_PROVISIONED_CONFIG_ID, state); 1283 } 1284 setImsConfigProvisionedState(int configItem, boolean state)1285 void setImsConfigProvisionedState(int configItem, boolean state) { 1286 if (phone != null && mImsManager != null) { 1287 QueuedWork.queue(new Runnable() { 1288 public void run() { 1289 try { 1290 mImsManager.getConfigInterface().setProvisionedValue( 1291 configItem, 1292 state? 1 : 0); 1293 } catch (ImsException e) { 1294 Log.e(TAG, "setImsConfigProvisioned() exception:", e); 1295 } 1296 } 1297 }, false); 1298 } 1299 } 1300 1301 OnCheckedChangeListener mRadioPowerOnChangeListener = new OnCheckedChangeListener() { 1302 @Override 1303 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1304 log("toggle radio power: currently " + (isRadioOn()?"on":"off")); 1305 phone.setRadioPower(isChecked); 1306 } 1307 }; 1308 isImsVolteProvisioned()1309 private boolean isImsVolteProvisioned() { 1310 if (phone != null && mImsManager != null) { 1311 return mImsManager.isVolteEnabledByPlatform(phone.getContext()) 1312 && mImsManager.isVolteProvisionedOnDevice(phone.getContext()); 1313 } 1314 return false; 1315 } 1316 1317 OnCheckedChangeListener mImsVolteCheckedChangeListener = new OnCheckedChangeListener() { 1318 @Override 1319 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1320 setImsVolteProvisionedState(isChecked); 1321 } 1322 }; 1323 isImsVtProvisioned()1324 private boolean isImsVtProvisioned() { 1325 if (phone != null && mImsManager != null) { 1326 return mImsManager.isVtEnabledByPlatform(phone.getContext()) 1327 && mImsManager.isVtProvisionedOnDevice(phone.getContext()); 1328 } 1329 return false; 1330 } 1331 1332 OnCheckedChangeListener mImsVtCheckedChangeListener = new OnCheckedChangeListener() { 1333 @Override 1334 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1335 setImsVtProvisionedState(isChecked); 1336 } 1337 }; 1338 isImsWfcProvisioned()1339 private boolean isImsWfcProvisioned() { 1340 if (phone != null && mImsManager != null) { 1341 return mImsManager.isWfcEnabledByPlatform(phone.getContext()) 1342 && mImsManager.isWfcProvisionedOnDevice(phone.getContext()); 1343 } 1344 return false; 1345 } 1346 1347 OnCheckedChangeListener mImsWfcCheckedChangeListener = new OnCheckedChangeListener() { 1348 @Override 1349 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1350 setImsWfcProvisionedState(isChecked); 1351 } 1352 }; 1353 isEabProvisioned()1354 private boolean isEabProvisioned() { 1355 return isFeatureProvisioned(EAB_PROVISIONED_CONFIG_ID, false); 1356 } 1357 1358 OnCheckedChangeListener mEabCheckedChangeListener = new OnCheckedChangeListener() { 1359 @Override 1360 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1361 setEabProvisionedState(isChecked); 1362 } 1363 }; 1364 isFeatureProvisioned(int featureId, boolean defaultValue)1365 private boolean isFeatureProvisioned(int featureId, boolean defaultValue) { 1366 boolean provisioned = defaultValue; 1367 if (mImsManager != null) { 1368 try { 1369 ImsConfig imsConfig = mImsManager.getConfigInterface(); 1370 if (imsConfig != null) { 1371 provisioned = 1372 (imsConfig.getProvisionedValue(featureId) 1373 == ImsConfig.FeatureValueConstants.ON); 1374 } 1375 } catch (ImsException ex) { 1376 Log.e(TAG, "isFeatureProvisioned() exception:", ex); 1377 } 1378 } 1379 1380 log("isFeatureProvisioned() featureId=" + featureId + " provisioned=" + provisioned); 1381 return provisioned; 1382 } 1383 isEabEnabledByPlatform(Context context)1384 private static boolean isEabEnabledByPlatform(Context context) { 1385 if (context != null) { 1386 CarrierConfigManager configManager = (CarrierConfigManager) 1387 context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1388 if (configManager != null && configManager.getConfig().getBoolean( 1389 CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL)) { 1390 return true; 1391 } 1392 } 1393 return false; 1394 } 1395 updateImsProvisionedState()1396 private void updateImsProvisionedState() { 1397 if (!ImsManager.isImsSupportedOnDevice(phone.getContext())) { 1398 return; 1399 } 1400 log("updateImsProvisionedState isImsVolteProvisioned()=" + isImsVolteProvisioned()); 1401 //delightful hack to prevent on-checked-changed calls from 1402 //actually forcing the ims provisioning to its transient/current value. 1403 imsVolteProvisionedSwitch.setOnCheckedChangeListener(null); 1404 imsVolteProvisionedSwitch.setChecked(isImsVolteProvisioned()); 1405 imsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener); 1406 imsVolteProvisionedSwitch.setEnabled(!Build.IS_USER 1407 && mImsManager.isVolteEnabledByPlatform(phone.getContext())); 1408 1409 imsVtProvisionedSwitch.setOnCheckedChangeListener(null); 1410 imsVtProvisionedSwitch.setChecked(isImsVtProvisioned()); 1411 imsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener); 1412 imsVtProvisionedSwitch.setEnabled(!Build.IS_USER 1413 && mImsManager.isVtEnabledByPlatform(phone.getContext())); 1414 1415 imsWfcProvisionedSwitch.setOnCheckedChangeListener(null); 1416 imsWfcProvisionedSwitch.setChecked(isImsWfcProvisioned()); 1417 imsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener); 1418 imsWfcProvisionedSwitch.setEnabled(!Build.IS_USER 1419 && mImsManager.isWfcEnabledByPlatform(phone.getContext())); 1420 1421 eabProvisionedSwitch.setOnCheckedChangeListener(null); 1422 eabProvisionedSwitch.setChecked(isEabProvisioned()); 1423 eabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener); 1424 eabProvisionedSwitch.setEnabled(!Build.IS_USER 1425 && isEabEnabledByPlatform(phone.getContext())); 1426 } 1427 1428 OnClickListener mDnsCheckButtonHandler = new OnClickListener() { 1429 public void onClick(View v) { 1430 //FIXME: Replace with a TelephonyManager call 1431 phone.disableDnsCheck(!phone.isDnsCheckDisabled()); 1432 updateDnsCheckState(); 1433 } 1434 }; 1435 1436 OnClickListener mOemInfoButtonHandler = new OnClickListener() { 1437 public void onClick(View v) { 1438 Intent intent = new Intent("com.android.car.developeroptions.OEM_RADIO_INFO"); 1439 try { 1440 startActivity(intent); 1441 } catch (android.content.ActivityNotFoundException ex) { 1442 log("OEM-specific Info/Settings Activity Not Found : " + ex); 1443 // If the activity does not exist, there are no OEM 1444 // settings, and so we can just do nothing... 1445 } 1446 } 1447 }; 1448 1449 OnClickListener mPingButtonHandler = new OnClickListener() { 1450 public void onClick(View v) { 1451 updatePingState(); 1452 } 1453 }; 1454 1455 OnClickListener mUpdateSmscButtonHandler = new OnClickListener() { 1456 public void onClick(View v) { 1457 updateSmscButton.setEnabled(false); 1458 phone.setSmscAddress(smsc.getText().toString(), 1459 mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE)); 1460 } 1461 }; 1462 1463 OnClickListener mRefreshSmscButtonHandler = new OnClickListener() { 1464 public void onClick(View v) { 1465 refreshSmsc(); 1466 } 1467 }; 1468 1469 OnClickListener mCarrierProvisioningButtonHandler = new OnClickListener() { 1470 public void onClick(View v) { 1471 final Intent intent = new Intent("com.android.car.developeroptions.CARRIER_PROVISIONING"); 1472 final ComponentName serviceComponent = ComponentName.unflattenFromString( 1473 "com.android.omadm.service/.DMIntentReceiver"); 1474 intent.setComponent(serviceComponent); 1475 sendBroadcast(intent); 1476 } 1477 }; 1478 1479 OnClickListener mTriggerCarrierProvisioningButtonHandler = new OnClickListener() { 1480 public void onClick(View v) { 1481 final Intent intent = new Intent("com.android.car.developeroptions.TRIGGER_CARRIER_PROVISIONING"); 1482 final ComponentName serviceComponent = ComponentName.unflattenFromString( 1483 "com.android.omadm.service/.DMIntentReceiver"); 1484 intent.setComponent(serviceComponent); 1485 sendBroadcast(intent); 1486 } 1487 }; 1488 1489 AdapterView.OnItemSelectedListener mPreferredNetworkHandler = 1490 new AdapterView.OnItemSelectedListener() { 1491 1492 public void onItemSelected(AdapterView parent, View v, int pos, long id) { 1493 if (mPreferredNetworkTypeResult != pos && pos >= 0 1494 && pos <= mPreferredNetworkLabels.length - 2) { 1495 mPreferredNetworkTypeResult = pos; 1496 1497 // TODO: Possibly migrate this to TelephonyManager.setPreferredNetworkType() 1498 // which today still has some issues (mostly that the "set" is conditional 1499 // on a successful modem call, which is not what we want). Instead we always 1500 // want this setting to be set, so that if the radio hiccups and this setting 1501 // is for some reason unsuccessful, future calls to the radio will reflect 1502 // the users's preference which is set here. 1503 final int subId = phone.getSubId(); 1504 if (SubscriptionManager.isUsableSubIdValue(subId)) { 1505 Settings.Global.putInt(phone.getContext().getContentResolver(), 1506 PREFERRED_NETWORK_MODE + subId, mPreferredNetworkTypeResult); 1507 } 1508 log("Calling setPreferredNetworkType(" + mPreferredNetworkTypeResult + ")"); 1509 Message msg = mHandler.obtainMessage(EVENT_SET_PREFERRED_TYPE_DONE); 1510 phone.setPreferredNetworkType(mPreferredNetworkTypeResult, msg); 1511 } 1512 } 1513 1514 public void onNothingSelected(AdapterView parent) { 1515 } 1516 }; 1517 1518 AdapterView.OnItemSelectedListener mCellInfoRefreshRateHandler = 1519 new AdapterView.OnItemSelectedListener() { 1520 1521 public void onItemSelected(AdapterView parent, View v, int pos, long id) { 1522 mCellInfoRefreshRateIndex = pos; 1523 mTelephonyManager.setCellInfoListRate(mCellInfoRefreshRates[pos]); 1524 updateAllCellInfo(); 1525 } 1526 1527 public void onNothingSelected(AdapterView parent) { 1528 } 1529 }; 1530 isCbrsSupported()1531 boolean isCbrsSupported() { 1532 // No longer possible to access com.android.internal.R.bool.config_cbrs_supported, so 1533 // returning false for now. 1534 // TODO: This needs to be cleaned up in future CL. 1535 return false; 1536 } 1537 updateCbrsDataState(boolean state)1538 void updateCbrsDataState(boolean state) { 1539 Log.d(TAG, "setCbrsDataSwitchState() state:" + ((state)? "on":"off")); 1540 if (mTelephonyManager != null) { 1541 QueuedWork.queue(new Runnable() { 1542 public void run() { 1543 mTelephonyManager.setOpportunisticNetworkState(state); 1544 cbrsDataSwitch.setChecked(getCbrsDataState()); 1545 } 1546 }, false); 1547 } 1548 } 1549 getCbrsDataState()1550 boolean getCbrsDataState() { 1551 boolean state = false; 1552 if (mTelephonyManager != null) { 1553 state = mTelephonyManager.isOpportunisticNetworkEnabled(); 1554 } 1555 Log.d(TAG, "getCbrsDataState() state:" +((state)? "on":"off")); 1556 return state; 1557 } 1558 1559 OnCheckedChangeListener mCbrsDataSwitchChangeListener = new OnCheckedChangeListener() { 1560 @Override 1561 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1562 updateCbrsDataState(isChecked); 1563 } 1564 }; 1565 showDsdsChangeDialog()1566 private void showDsdsChangeDialog() { 1567 final AlertDialog confirmDialog = new Builder(RadioInfo.this) 1568 .setTitle(R.string.dsds_dialog_title) 1569 .setMessage(R.string.dsds_dialog_message) 1570 .setPositiveButton(R.string.dsds_dialog_confirm, mOnDsdsDialogConfirmedListener) 1571 .setNegativeButton(R.string.dsds_dialog_cancel, mOnDsdsDialogConfirmedListener) 1572 .create(); 1573 confirmDialog.show(); 1574 } 1575 isDsdsSupported()1576 private static boolean isDsdsSupported() { 1577 return (TelephonyManager.getDefault().isMultiSimSupported() 1578 == TelephonyManager.MULTISIM_ALLOWED); 1579 } 1580 isDsdsEnabled()1581 private static boolean isDsdsEnabled() { 1582 return TelephonyManager.getDefault().getPhoneCount() > 1; 1583 } 1584 performDsdsSwitch()1585 private void performDsdsSwitch() { 1586 mTelephonyManager.switchMultiSimConfig(dsdsSwitch.isChecked() ? 2 : 1); 1587 } 1588 1589 DialogInterface.OnClickListener mOnDsdsDialogConfirmedListener = 1590 new DialogInterface.OnClickListener() { 1591 @Override 1592 public void onClick(DialogInterface dialog, int which) { 1593 if (which == DialogInterface.BUTTON_POSITIVE) { 1594 dsdsSwitch.toggle(); 1595 performDsdsSwitch(); 1596 } 1597 } 1598 }; 1599 } 1600