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.phone.settings; 18 19 import static android.net.ConnectivityManager.NetworkCallback; 20 21 import static java.util.concurrent.TimeUnit.MILLISECONDS; 22 23 import android.content.ComponentName; 24 import android.content.Context; 25 import android.content.DialogInterface; 26 import android.content.Intent; 27 import android.content.pm.ComponentInfo; 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.hardware.radio.modem.ImeiInfo; 33 import android.net.ConnectivityManager; 34 import android.net.Network; 35 import android.net.NetworkCapabilities; 36 import android.net.NetworkRequest; 37 import android.net.TrafficStats; 38 import android.net.Uri; 39 import android.os.AsyncResult; 40 import android.os.Build; 41 import android.os.Bundle; 42 import android.os.Handler; 43 import android.os.HandlerExecutor; 44 import android.os.Message; 45 import android.os.PersistableBundle; 46 import android.os.SystemProperties; 47 import android.telephony.AccessNetworkConstants; 48 import android.telephony.CarrierConfigManager; 49 import android.telephony.CellIdentityCdma; 50 import android.telephony.CellIdentityGsm; 51 import android.telephony.CellIdentityLte; 52 import android.telephony.CellIdentityNr; 53 import android.telephony.CellIdentityWcdma; 54 import android.telephony.CellInfo; 55 import android.telephony.CellInfoCdma; 56 import android.telephony.CellInfoGsm; 57 import android.telephony.CellInfoLte; 58 import android.telephony.CellInfoNr; 59 import android.telephony.CellInfoWcdma; 60 import android.telephony.CellSignalStrengthCdma; 61 import android.telephony.CellSignalStrengthGsm; 62 import android.telephony.CellSignalStrengthLte; 63 import android.telephony.CellSignalStrengthNr; 64 import android.telephony.CellSignalStrengthWcdma; 65 import android.telephony.DataSpecificRegistrationInfo; 66 import android.telephony.NetworkRegistrationInfo; 67 import android.telephony.PhysicalChannelConfig; 68 import android.telephony.RadioAccessFamily; 69 import android.telephony.ServiceState; 70 import android.telephony.SignalStrength; 71 import android.telephony.SubscriptionManager; 72 import android.telephony.TelephonyCallback; 73 import android.telephony.TelephonyDisplayInfo; 74 import android.telephony.TelephonyManager; 75 import android.telephony.data.NetworkSlicingConfig; 76 import android.telephony.ims.ImsException; 77 import android.telephony.ims.ImsManager; 78 import android.telephony.ims.ImsMmTelManager; 79 import android.telephony.ims.ImsRcsManager; 80 import android.telephony.ims.ProvisioningManager; 81 import android.telephony.ims.feature.MmTelFeature; 82 import android.telephony.ims.stub.ImsRegistrationImplBase; 83 import android.text.TextUtils; 84 import android.util.Log; 85 import android.view.Menu; 86 import android.view.MenuItem; 87 import android.view.View; 88 import android.view.View.OnClickListener; 89 import android.widget.AdapterView; 90 import android.widget.ArrayAdapter; 91 import android.widget.Button; 92 import android.widget.CompoundButton; 93 import android.widget.CompoundButton.OnCheckedChangeListener; 94 import android.widget.EditText; 95 import android.widget.Spinner; 96 import android.widget.Switch; 97 import android.widget.TextView; 98 99 import androidx.appcompat.app.AlertDialog; 100 import androidx.appcompat.app.AlertDialog.Builder; 101 import androidx.appcompat.app.AppCompatActivity; 102 103 import com.android.internal.telephony.Phone; 104 import com.android.internal.telephony.PhoneFactory; 105 import com.android.internal.telephony.euicc.EuiccConnector; 106 import com.android.internal.telephony.util.TelephonyUtils; 107 import com.android.phone.R; 108 109 import java.io.IOException; 110 import java.net.HttpURLConnection; 111 import java.net.URL; 112 import java.util.List; 113 import java.util.concurrent.CompletableFuture; 114 import java.util.concurrent.ExecutionException; 115 import java.util.concurrent.LinkedBlockingDeque; 116 import java.util.concurrent.ThreadPoolExecutor; 117 import java.util.concurrent.TimeUnit; 118 import java.util.concurrent.TimeoutException; 119 120 /** 121 * Radio Information Class 122 * 123 * Allows user to read and alter some of the radio related information. 124 * 125 */ 126 public class RadioInfo extends AppCompatActivity { 127 private static final String TAG = "RadioInfo"; 128 129 private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE); 130 131 private static final String[] PREFERRED_NETWORK_LABELS = { 132 "GSM/WCDMA preferred", 133 "GSM only", 134 "WCDMA only", 135 "GSM/WCDMA auto (PRL)", 136 "CDMA/EvDo auto (PRL)", 137 "CDMA only", 138 "EvDo only", 139 "CDMA/EvDo/GSM/WCDMA (PRL)", 140 "CDMA + LTE/EvDo (PRL)", 141 "GSM/WCDMA/LTE (PRL)", 142 "LTE/CDMA/EvDo/GSM/WCDMA (PRL)", 143 "LTE only", 144 "LTE/WCDMA", 145 "TDSCDMA only", 146 "TDSCDMA/WCDMA", 147 "LTE/TDSCDMA", 148 "TDSCDMA/GSM", 149 "LTE/TDSCDMA/GSM", 150 "TDSCDMA/GSM/WCDMA", 151 "LTE/TDSCDMA/WCDMA", 152 "LTE/TDSCDMA/GSM/WCDMA", 153 "TDSCDMA/CDMA/EvDo/GSM/WCDMA ", 154 "LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA", 155 "NR only", 156 "NR/LTE", 157 "NR/LTE/CDMA/EvDo", 158 "NR/LTE/GSM/WCDMA", 159 "NR/LTE/CDMA/EvDo/GSM/WCDMA", 160 "NR/LTE/WCDMA", 161 "NR/LTE/TDSCDMA", 162 "NR/LTE/TDSCDMA/GSM", 163 "NR/LTE/TDSCDMA/WCDMA", 164 "NR/LTE/TDSCDMA/GSM/WCDMA", 165 "NR/LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA", 166 "Unknown" 167 }; 168 169 private static String[] sPhoneIndexLabels; 170 171 private static final int sCellInfoListRateDisabled = Integer.MAX_VALUE; 172 private static final int sCellInfoListRateMax = 0; 173 174 private static final String OEM_RADIO_INFO_INTENT = 175 "com.android.phone.settings.OEM_RADIO_INFO"; 176 177 private static final String DSDS_MODE_PROPERTY = "ro.boot.hardware.dsds"; 178 179 /** 180 * A value indicates the device is always on dsds mode. 181 * @see {@link #DSDS_MODE_PROPERTY} 182 */ 183 private static final int ALWAYS_ON_DSDS_MODE = 1; 184 185 //Values in must match CELL_INFO_REFRESH_RATES 186 private static final String[] CELL_INFO_REFRESH_RATE_LABELS = { 187 "Disabled", 188 "Immediate", 189 "Min 5s", 190 "Min 10s", 191 "Min 60s" 192 }; 193 194 //Values in seconds, must match CELL_INFO_REFRESH_RATE_LABELS 195 private static final int [] CELL_INFO_REFRESH_RATES = { 196 sCellInfoListRateDisabled, 197 sCellInfoListRateMax, 198 5000, 199 10000, 200 60000 201 }; 202 log(String s)203 private static void log(String s) { 204 Log.d(TAG, s); 205 } 206 207 private static final int EVENT_QUERY_SMSC_DONE = 1005; 208 private static final int EVENT_UPDATE_SMSC_DONE = 1006; 209 private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 1007; 210 private static final int EVENT_UPDATE_NR_STATS = 1008; 211 212 private static final int MENU_ITEM_VIEW_ADN = 1; 213 private static final int MENU_ITEM_VIEW_FDN = 2; 214 private static final int MENU_ITEM_VIEW_SDN = 3; 215 private static final int MENU_ITEM_GET_IMS_STATUS = 4; 216 private static final int MENU_ITEM_TOGGLE_DATA = 5; 217 218 private static final String CARRIER_PROVISIONING_ACTION = 219 "com.android.phone.settings.CARRIER_PROVISIONING"; 220 private static final String TRIGGER_CARRIER_PROVISIONING_ACTION = 221 "com.android.phone.settings.TRIGGER_CARRIER_PROVISIONING"; 222 223 private static final String ACTION_REMOVABLE_ESIM_AS_DEFAULT = 224 "android.telephony.euicc.action.REMOVABLE_ESIM_AS_DEFAULT"; 225 226 private TextView mDeviceId; //DeviceId is the IMEI in GSM and the MEID in CDMA 227 private TextView mLine1Number; 228 private TextView mSubscriptionId; 229 private TextView mDds; 230 private TextView mSubscriberId; 231 private TextView mCallState; 232 private TextView mOperatorName; 233 private TextView mRoamingState; 234 private TextView mGsmState; 235 private TextView mGprsState; 236 private TextView mVoiceNetwork; 237 private TextView mDataNetwork; 238 private TextView mVoiceRawReg; 239 private TextView mDataRawReg; 240 private TextView mWlanDataRawReg; 241 private TextView mOverrideNetwork; 242 private TextView mDBm; 243 private TextView mMwi; 244 private TextView mCfi; 245 private TextView mCellInfo; 246 private TextView mSent; 247 private TextView mReceived; 248 private TextView mPingHostnameV4; 249 private TextView mPingHostnameV6; 250 private TextView mHttpClientTest; 251 private TextView mPhyChanConfig; 252 private TextView mDnsCheckState; 253 private TextView mDownlinkKbps; 254 private TextView mUplinkKbps; 255 private TextView mEndcAvailable; 256 private TextView mDcnrRestricted; 257 private TextView mNrAvailable; 258 private TextView mNrState; 259 private TextView mNrFrequency; 260 private TextView mNetworkSlicingConfig; 261 private EditText mSmsc; 262 private Switch mRadioPowerOnSwitch; 263 private Switch mSimulateOutOfServiceSwitch; 264 private Button mDnsCheckToggleButton; 265 private Button mPingTestButton; 266 private Button mUpdateSmscButton; 267 private Button mRefreshSmscButton; 268 private Button mOemInfoButton; 269 private Button mCarrierProvisioningButton; 270 private Button mTriggerCarrierProvisioningButton; 271 private Switch mImsVolteProvisionedSwitch; 272 private Switch mImsVtProvisionedSwitch; 273 private Switch mImsWfcProvisionedSwitch; 274 private Switch mEabProvisionedSwitch; 275 private Switch mCbrsDataSwitch; 276 private Switch mDsdsSwitch; 277 private Switch mRemovableEsimSwitch; 278 private Spinner mPreferredNetworkType; 279 private Spinner mSelectPhoneIndex; 280 private Spinner mCellInfoRefreshRateSpinner; 281 282 private static final long RUNNABLE_TIMEOUT_MS = 5 * 60 * 1000L; 283 284 private ThreadPoolExecutor mQueuedWork; 285 286 private ConnectivityManager mConnectivityManager; 287 private TelephonyManager mTelephonyManager; 288 private ImsManager mImsManager = null; 289 private Phone mPhone = null; 290 private ProvisioningManager mProvisioningManager = null; 291 292 private String mPingHostnameResultV4; 293 private String mPingHostnameResultV6; 294 private String mHttpClientTestResult; 295 private boolean mMwiValue = false; 296 private boolean mCfiValue = false; 297 298 private List<CellInfo> mCellInfoResult = null; 299 private final boolean[] mSimulateOos = new boolean[2]; 300 301 private int mPreferredNetworkTypeResult; 302 private int mCellInfoRefreshRateIndex; 303 private int mSelectedPhoneIndex; 304 305 private final NetworkRequest mDefaultNetworkRequest = new NetworkRequest.Builder() 306 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) 307 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 308 .build(); 309 310 private final NetworkCallback mNetworkCallback = new NetworkCallback() { 311 public void onCapabilitiesChanged(Network n, NetworkCapabilities nc) { 312 int dlbw = nc.getLinkDownstreamBandwidthKbps(); 313 int ulbw = nc.getLinkUpstreamBandwidthKbps(); 314 updateBandwidths(dlbw, ulbw); 315 } 316 }; 317 318 private static final int DEFAULT_TIMEOUT_MS = 1000; 319 320 // not final because we need to recreate this object to register on a new subId (b/117555407) 321 private TelephonyCallback mTelephonyCallback = new RadioInfoTelephonyCallback(); 322 private class RadioInfoTelephonyCallback extends TelephonyCallback implements 323 TelephonyCallback.DataConnectionStateListener, 324 TelephonyCallback.DataActivityListener, 325 TelephonyCallback.CallStateListener, 326 TelephonyCallback.MessageWaitingIndicatorListener, 327 TelephonyCallback.CallForwardingIndicatorListener, 328 TelephonyCallback.CellInfoListener, 329 TelephonyCallback.SignalStrengthsListener, 330 TelephonyCallback.ServiceStateListener, 331 TelephonyCallback.DisplayInfoListener { 332 333 @Override onDataConnectionStateChanged(int state, int networkType)334 public void onDataConnectionStateChanged(int state, int networkType) { 335 updateDataState(); 336 updateNetworkType(); 337 } 338 339 @Override onDataActivity(int direction)340 public void onDataActivity(int direction) { 341 updateDataStats2(); 342 } 343 344 @Override onCallStateChanged(int state)345 public void onCallStateChanged(int state) { 346 updateNetworkType(); 347 updatePhoneState(state); 348 } 349 350 @Override onMessageWaitingIndicatorChanged(boolean mwi)351 public void onMessageWaitingIndicatorChanged(boolean mwi) { 352 mMwiValue = mwi; 353 updateMessageWaiting(); 354 } 355 356 @Override onCallForwardingIndicatorChanged(boolean cfi)357 public void onCallForwardingIndicatorChanged(boolean cfi) { 358 mCfiValue = cfi; 359 updateCallRedirect(); 360 } 361 362 @Override onCellInfoChanged(List<CellInfo> arrayCi)363 public void onCellInfoChanged(List<CellInfo> arrayCi) { 364 log("onCellInfoChanged: arrayCi=" + arrayCi); 365 mCellInfoResult = arrayCi; 366 updateCellInfo(mCellInfoResult); 367 } 368 369 @Override onSignalStrengthsChanged(SignalStrength signalStrength)370 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 371 log("onSignalStrengthChanged: SignalStrength=" + signalStrength); 372 updateSignalStrength(signalStrength); 373 } 374 375 @Override onServiceStateChanged(ServiceState serviceState)376 public void onServiceStateChanged(ServiceState serviceState) { 377 log("onServiceStateChanged: ServiceState=" + serviceState); 378 updateServiceState(serviceState); 379 updateRadioPowerState(); 380 updateNetworkType(); 381 updateRawRegistrationState(serviceState); 382 updateImsProvisionedState(); 383 384 // Since update NR stats includes a ril message to get slicing information, it runs 385 // as blocking during the timeout period of 1 second. if ServiceStateChanged event 386 // fires consecutively, RadioInfo can run for more than 10 seconds. This can cause ANR. 387 // Therefore, send event only when there is no same event being processed. 388 if (!mHandler.hasMessages(EVENT_UPDATE_NR_STATS)) { 389 mHandler.obtainMessage(EVENT_UPDATE_NR_STATS).sendToTarget(); 390 } 391 } 392 393 @Override onDisplayInfoChanged(TelephonyDisplayInfo displayInfo)394 public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfo) { 395 updateNetworkType(); 396 } 397 } 398 updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs)399 private void updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) { 400 StringBuilder sb = new StringBuilder(); 401 String div = ""; 402 sb.append("{"); 403 if (configs != null) { 404 for (PhysicalChannelConfig c : configs) { 405 sb.append(div).append(c); 406 div = ","; 407 } 408 } 409 sb.append("}"); 410 mPhyChanConfig.setText(sb.toString()); 411 } 412 updatePreferredNetworkType(int type)413 private void updatePreferredNetworkType(int type) { 414 if (type >= PREFERRED_NETWORK_LABELS.length || type < 0) { 415 log("Network type: unknown type value=" + type); 416 type = PREFERRED_NETWORK_LABELS.length - 1; //set to Unknown 417 } 418 mPreferredNetworkTypeResult = type; 419 420 mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true); 421 } 422 updatePhoneIndex(int phoneIndex, int subId)423 private void updatePhoneIndex(int phoneIndex, int subId) { 424 // unregister listeners on the old subId 425 unregisterPhoneStateListener(); 426 mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mPhone.getSubId()); 427 428 if (phoneIndex == SubscriptionManager.INVALID_PHONE_INDEX) { 429 log("Invalid phone index " + phoneIndex + ", subscription ID " + subId); 430 return; 431 } 432 433 // update the subId 434 mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId); 435 436 // update the phoneId 437 mPhone = PhoneFactory.getPhone(phoneIndex); 438 mImsManager = new ImsManager(mPhone.getContext()); 439 try { 440 mProvisioningManager = ProvisioningManager.createForSubscriptionId(subId); 441 } catch (IllegalArgumentException e) { 442 log("updatePhoneIndex : IllegalArgumentException " + e.getMessage()); 443 mProvisioningManager = null; 444 } 445 446 updateAllFields(); 447 } 448 449 private Handler mHandler = new Handler() { 450 @Override 451 public void handleMessage(Message msg) { 452 AsyncResult ar; 453 switch (msg.what) { 454 case EVENT_QUERY_SMSC_DONE: 455 ar = (AsyncResult) msg.obj; 456 if (ar.exception != null) { 457 mSmsc.setText("refresh error"); 458 } else { 459 mSmsc.setText((String) ar.result); 460 } 461 break; 462 case EVENT_UPDATE_SMSC_DONE: 463 mUpdateSmscButton.setEnabled(true); 464 ar = (AsyncResult) msg.obj; 465 if (ar.exception != null) { 466 mSmsc.setText("update error"); 467 } 468 break; 469 case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED: 470 ar = (AsyncResult) msg.obj; 471 if (ar.exception != null) { 472 mPhyChanConfig.setText(("update error")); 473 } 474 updatePhysicalChannelConfiguration((List<PhysicalChannelConfig>) ar.result); 475 break; 476 case EVENT_UPDATE_NR_STATS: 477 log("got EVENT_UPDATE_NR_STATS"); 478 updateNrStats(); 479 break; 480 default: 481 super.handleMessage(msg); 482 break; 483 484 } 485 } 486 }; 487 488 @Override onCreate(Bundle icicle)489 public void onCreate(Bundle icicle) { 490 super.onCreate(icicle); 491 if (!android.os.Process.myUserHandle().isSystem()) { 492 Log.e(TAG, "Not run from system user, don't do anything."); 493 finish(); 494 return; 495 } 496 497 setContentView(R.layout.radio_info); 498 499 log("Started onCreate"); 500 501 mQueuedWork = new ThreadPoolExecutor(1, 1, RUNNABLE_TIMEOUT_MS, TimeUnit.MICROSECONDS, 502 new LinkedBlockingDeque<Runnable>()); 503 mConnectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE); 504 mPhone = getPhone(SubscriptionManager.getDefaultSubscriptionId()); 505 mTelephonyManager = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE)) 506 .createForSubscriptionId(mPhone.getSubId()); 507 508 mImsManager = new ImsManager(mPhone.getContext()); 509 try { 510 mProvisioningManager = ProvisioningManager.createForSubscriptionId(mPhone.getSubId()); 511 } catch (IllegalArgumentException e) { 512 log("onCreate : IllegalArgumentException " + e.getMessage()); 513 mProvisioningManager = null; 514 } 515 516 sPhoneIndexLabels = getPhoneIndexLabels(mTelephonyManager); 517 518 mDeviceId = (TextView) findViewById(R.id.imei); 519 mLine1Number = (TextView) findViewById(R.id.number); 520 mSubscriptionId = (TextView) findViewById(R.id.subid); 521 mDds = (TextView) findViewById(R.id.dds); 522 mSubscriberId = (TextView) findViewById(R.id.imsi); 523 mCallState = (TextView) findViewById(R.id.call); 524 mOperatorName = (TextView) findViewById(R.id.operator); 525 mRoamingState = (TextView) findViewById(R.id.roaming); 526 mGsmState = (TextView) findViewById(R.id.gsm); 527 mGprsState = (TextView) findViewById(R.id.gprs); 528 mVoiceNetwork = (TextView) findViewById(R.id.voice_network); 529 mDataNetwork = (TextView) findViewById(R.id.data_network); 530 mVoiceRawReg = (TextView) findViewById(R.id.voice_raw_registration_state); 531 mDataRawReg = (TextView) findViewById(R.id.data_raw_registration_state); 532 mWlanDataRawReg = (TextView) findViewById(R.id.wlan_data_raw_registration_state); 533 mOverrideNetwork = (TextView) findViewById(R.id.override_network); 534 mDBm = (TextView) findViewById(R.id.dbm); 535 mMwi = (TextView) findViewById(R.id.mwi); 536 mCfi = (TextView) findViewById(R.id.cfi); 537 mCellInfo = (TextView) findViewById(R.id.cellinfo); 538 mCellInfo.setTypeface(Typeface.MONOSPACE); 539 540 mSent = (TextView) findViewById(R.id.sent); 541 mReceived = (TextView) findViewById(R.id.received); 542 mSmsc = (EditText) findViewById(R.id.smsc); 543 mDnsCheckState = (TextView) findViewById(R.id.dnsCheckState); 544 mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4); 545 mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6); 546 mHttpClientTest = (TextView) findViewById(R.id.httpClientTest); 547 mEndcAvailable = (TextView) findViewById(R.id.endc_available); 548 mDcnrRestricted = (TextView) findViewById(R.id.dcnr_restricted); 549 mNrAvailable = (TextView) findViewById(R.id.nr_available); 550 mNrState = (TextView) findViewById(R.id.nr_state); 551 mNrFrequency = (TextView) findViewById(R.id.nr_frequency); 552 mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config); 553 mNetworkSlicingConfig = (TextView) findViewById(R.id.network_slicing_config); 554 555 // hide 5G stats on devices that don't support 5G 556 if ((mTelephonyManager.getSupportedRadioAccessFamily() 557 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) { 558 setNrStatsVisibility(View.GONE); 559 } 560 561 mPreferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType); 562 ArrayAdapter<String> mPreferredNetworkTypeAdapter = new ArrayAdapter<String>(this, 563 android.R.layout.simple_spinner_item, PREFERRED_NETWORK_LABELS); 564 mPreferredNetworkTypeAdapter 565 .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 566 mPreferredNetworkType.setAdapter(mPreferredNetworkTypeAdapter); 567 568 mSelectPhoneIndex = (Spinner) findViewById(R.id.phoneIndex); 569 ArrayAdapter<String> phoneIndexAdapter = new ArrayAdapter<String>(this, 570 android.R.layout.simple_spinner_item, sPhoneIndexLabels); 571 phoneIndexAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 572 mSelectPhoneIndex.setAdapter(phoneIndexAdapter); 573 574 mCellInfoRefreshRateSpinner = (Spinner) findViewById(R.id.cell_info_rate_select); 575 ArrayAdapter<String> cellInfoAdapter = new ArrayAdapter<String>(this, 576 android.R.layout.simple_spinner_item, CELL_INFO_REFRESH_RATE_LABELS); 577 cellInfoAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 578 mCellInfoRefreshRateSpinner.setAdapter(cellInfoAdapter); 579 580 mImsVolteProvisionedSwitch = (Switch) findViewById(R.id.volte_provisioned_switch); 581 mImsVtProvisionedSwitch = (Switch) findViewById(R.id.vt_provisioned_switch); 582 mImsWfcProvisionedSwitch = (Switch) findViewById(R.id.wfc_provisioned_switch); 583 mEabProvisionedSwitch = (Switch) findViewById(R.id.eab_provisioned_switch); 584 585 if (!isImsSupportedOnDevice(mPhone.getContext())) { 586 mImsVolteProvisionedSwitch.setVisibility(View.GONE); 587 mImsVtProvisionedSwitch.setVisibility(View.GONE); 588 mImsWfcProvisionedSwitch.setVisibility(View.GONE); 589 mEabProvisionedSwitch.setVisibility(View.GONE); 590 } 591 592 mCbrsDataSwitch = (Switch) findViewById(R.id.cbrs_data_switch); 593 mCbrsDataSwitch.setVisibility(isCbrsSupported() ? View.VISIBLE : View.GONE); 594 595 mDsdsSwitch = findViewById(R.id.dsds_switch); 596 if (isDsdsSupported() && !dsdsModeOnly()) { 597 mDsdsSwitch.setVisibility(View.VISIBLE); 598 mDsdsSwitch.setOnClickListener(v -> { 599 if (mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot()) { 600 // Undo the click action until user clicks the confirm dialog. 601 mDsdsSwitch.toggle(); 602 showDsdsChangeDialog(); 603 } else { 604 performDsdsSwitch(); 605 } 606 }); 607 mDsdsSwitch.setChecked(isDsdsEnabled()); 608 } else { 609 mDsdsSwitch.setVisibility(View.GONE); 610 } 611 612 mRemovableEsimSwitch = (Switch) findViewById(R.id.removable_esim_switch); 613 if (!IS_USER_BUILD) { 614 mRemovableEsimSwitch.setEnabled(true); 615 mRemovableEsimSwitch.setChecked(mTelephonyManager.isRemovableEsimDefaultEuicc()); 616 mRemovableEsimSwitch.setOnCheckedChangeListener(mRemovableEsimChangeListener); 617 } 618 619 mRadioPowerOnSwitch = (Switch) findViewById(R.id.radio_power); 620 621 mSimulateOutOfServiceSwitch = (Switch) findViewById(R.id.simulate_out_of_service); 622 if (!TelephonyUtils.IS_DEBUGGABLE) { 623 mSimulateOutOfServiceSwitch.setVisibility(View.GONE); 624 } 625 626 mDownlinkKbps = (TextView) findViewById(R.id.dl_kbps); 627 mUplinkKbps = (TextView) findViewById(R.id.ul_kbps); 628 updateBandwidths(0, 0); 629 630 mPingTestButton = (Button) findViewById(R.id.ping_test); 631 mPingTestButton.setOnClickListener(mPingButtonHandler); 632 mUpdateSmscButton = (Button) findViewById(R.id.update_smsc); 633 mUpdateSmscButton.setOnClickListener(mUpdateSmscButtonHandler); 634 mRefreshSmscButton = (Button) findViewById(R.id.refresh_smsc); 635 mRefreshSmscButton.setOnClickListener(mRefreshSmscButtonHandler); 636 mDnsCheckToggleButton = (Button) findViewById(R.id.dns_check_toggle); 637 mDnsCheckToggleButton.setOnClickListener(mDnsCheckButtonHandler); 638 mCarrierProvisioningButton = (Button) findViewById(R.id.carrier_provisioning); 639 if (!TextUtils.isEmpty(getCarrierProvisioningAppString())) { 640 mCarrierProvisioningButton.setOnClickListener(mCarrierProvisioningButtonHandler); 641 } else { 642 mCarrierProvisioningButton.setEnabled(false); 643 } 644 645 mTriggerCarrierProvisioningButton = (Button) findViewById( 646 R.id.trigger_carrier_provisioning); 647 if (!TextUtils.isEmpty(getCarrierProvisioningAppString())) { 648 mTriggerCarrierProvisioningButton.setOnClickListener( 649 mTriggerCarrierProvisioningButtonHandler); 650 } else { 651 mTriggerCarrierProvisioningButton.setEnabled(false); 652 } 653 654 mOemInfoButton = (Button) findViewById(R.id.oem_info); 655 mOemInfoButton.setOnClickListener(mOemInfoButtonHandler); 656 PackageManager pm = getPackageManager(); 657 Intent oemInfoIntent = new Intent(OEM_RADIO_INFO_INTENT); 658 List<ResolveInfo> oemInfoIntentList = pm.queryIntentActivities(oemInfoIntent, 0); 659 if (oemInfoIntentList.size() == 0) { 660 mOemInfoButton.setEnabled(false); 661 } 662 663 mCellInfoRefreshRateIndex = 0; //disabled 664 mPreferredNetworkTypeResult = PREFERRED_NETWORK_LABELS.length - 1; //Unknown 665 mSelectedPhoneIndex = mPhone.getPhoneId(); 666 667 new Thread(() -> { 668 int networkType = (int) mTelephonyManager.getPreferredNetworkTypeBitmask(); 669 runOnUiThread(() -> updatePreferredNetworkType( 670 RadioAccessFamily.getNetworkTypeFromRaf(networkType))); 671 }).start(); 672 673 restoreFromBundle(icicle); 674 } 675 676 @Override getParentActivityIntent()677 public Intent getParentActivityIntent() { 678 Intent parentActivity = super.getParentActivityIntent(); 679 if (parentActivity == null) { 680 parentActivity = (new Intent()).setClassName("com.android.settings", 681 "com.android.settings.Settings$TestingSettingsActivity"); 682 } 683 return parentActivity; 684 } 685 686 @Override onResume()687 protected void onResume() { 688 super.onResume(); 689 690 log("Started onResume"); 691 692 updateAllFields(); 693 } 694 updateAllFields()695 private void updateAllFields() { 696 updateMessageWaiting(); 697 updateCallRedirect(); 698 updateDataState(); 699 updateDataStats2(); 700 updateRadioPowerState(); 701 updateImsProvisionedState(); 702 updateProperties(); 703 updateDnsCheckState(); 704 updateNetworkType(); 705 updateNrStats(); 706 707 updateCellInfo(mCellInfoResult); 708 updateSubscriptionIds(); 709 710 mPingHostnameV4.setText(mPingHostnameResultV4); 711 mPingHostnameV6.setText(mPingHostnameResultV6); 712 mHttpClientTest.setText(mHttpClientTestResult); 713 714 mCellInfoRefreshRateSpinner.setOnItemSelectedListener(mCellInfoRefreshRateHandler); 715 //set selection after registering listener to force update 716 mCellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex); 717 // Request cell information update from RIL. 718 mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[mCellInfoRefreshRateIndex], 719 mPhone.getSubId()); 720 721 //set selection before registering to prevent update 722 mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true); 723 mPreferredNetworkType.setOnItemSelectedListener(mPreferredNetworkHandler); 724 725 new Thread(() -> { 726 int networkType = (int) mTelephonyManager.getPreferredNetworkTypeBitmask(); 727 runOnUiThread(() -> updatePreferredNetworkType( 728 RadioAccessFamily.getNetworkTypeFromRaf(networkType))); 729 }).start(); 730 731 // set phone index 732 mSelectPhoneIndex.setSelection(mSelectedPhoneIndex, true); 733 mSelectPhoneIndex.setOnItemSelectedListener(mSelectPhoneIndexHandler); 734 735 mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener); 736 mSimulateOutOfServiceSwitch.setOnCheckedChangeListener(mSimulateOosOnChangeListener); 737 mSimulateOutOfServiceSwitch.setChecked(mSimulateOos[mPhone.getPhoneId()]); 738 mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener); 739 mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener); 740 mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener); 741 mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener); 742 743 if (isCbrsSupported()) { 744 mCbrsDataSwitch.setChecked(getCbrsDataState()); 745 mCbrsDataSwitch.setOnCheckedChangeListener(mCbrsDataSwitchChangeListener); 746 } 747 748 unregisterPhoneStateListener(); 749 registerPhoneStateListener(); 750 mPhone.registerForPhysicalChannelConfig(mHandler, 751 EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, null); 752 753 mConnectivityManager.registerNetworkCallback( 754 mDefaultNetworkRequest, mNetworkCallback, mHandler); 755 756 mSmsc.clearFocus(); 757 } 758 759 @Override onPause()760 protected void onPause() { 761 super.onPause(); 762 763 log("onPause: unregister phone & data intents"); 764 765 mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback); 766 mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mPhone.getSubId()); 767 mConnectivityManager.unregisterNetworkCallback(mNetworkCallback); 768 769 } 770 restoreFromBundle(Bundle b)771 private void restoreFromBundle(Bundle b) { 772 if (b == null) { 773 return; 774 } 775 776 mPingHostnameResultV4 = b.getString("mPingHostnameResultV4", ""); 777 mPingHostnameResultV6 = b.getString("mPingHostnameResultV6", ""); 778 mHttpClientTestResult = b.getString("mHttpClientTestResult", ""); 779 780 mPingHostnameV4.setText(mPingHostnameResultV4); 781 mPingHostnameV6.setText(mPingHostnameResultV6); 782 mHttpClientTest.setText(mHttpClientTestResult); 783 784 mPreferredNetworkTypeResult = b.getInt("mPreferredNetworkTypeResult", 785 PREFERRED_NETWORK_LABELS.length - 1); 786 787 mSelectedPhoneIndex = b.getInt("mSelectedPhoneIndex", 0); 788 789 mCellInfoRefreshRateIndex = b.getInt("mCellInfoRefreshRateIndex", 0); 790 } 791 792 @SuppressWarnings("MissingSuperCall") // TODO: Fix me 793 @Override onSaveInstanceState(Bundle outState)794 protected void onSaveInstanceState(Bundle outState) { 795 outState.putString("mPingHostnameResultV4", mPingHostnameResultV4); 796 outState.putString("mPingHostnameResultV6", mPingHostnameResultV6); 797 outState.putString("mHttpClientTestResult", mHttpClientTestResult); 798 799 outState.putInt("mPreferredNetworkTypeResult", mPreferredNetworkTypeResult); 800 outState.putInt("mSelectedPhoneIndex", mSelectedPhoneIndex); 801 outState.putInt("mCellInfoRefreshRateIndex", mCellInfoRefreshRateIndex); 802 803 } 804 805 @Override onCreateOptionsMenu(Menu menu)806 public boolean onCreateOptionsMenu(Menu menu) { 807 // Removed "select Radio band". If need it back, use setSystemSelectionChannels() 808 menu.add(1, MENU_ITEM_VIEW_ADN, 0, 809 R.string.radioInfo_menu_viewADN).setOnMenuItemClickListener(mViewADNCallback); 810 menu.add(1, MENU_ITEM_VIEW_FDN, 0, 811 R.string.radioInfo_menu_viewFDN).setOnMenuItemClickListener(mViewFDNCallback); 812 menu.add(1, MENU_ITEM_VIEW_SDN, 0, 813 R.string.radioInfo_menu_viewSDN).setOnMenuItemClickListener(mViewSDNCallback); 814 if (isImsSupportedOnDevice(mPhone.getContext())) { 815 menu.add(1, MENU_ITEM_GET_IMS_STATUS, 816 0, R.string.radioInfo_menu_getIMS).setOnMenuItemClickListener(mGetImsStatus); 817 } 818 menu.add(1, MENU_ITEM_TOGGLE_DATA, 819 0, R.string.radio_info_data_connection_disable) 820 .setOnMenuItemClickListener(mToggleData); 821 return true; 822 } 823 824 @Override onPrepareOptionsMenu(Menu menu)825 public boolean onPrepareOptionsMenu(Menu menu) { 826 // Get the TOGGLE DATA menu item in the right state. 827 MenuItem item = menu.findItem(MENU_ITEM_TOGGLE_DATA); 828 int state = mTelephonyManager.getDataState(); 829 boolean visible = true; 830 831 switch (state) { 832 case TelephonyManager.DATA_CONNECTED: 833 case TelephonyManager.DATA_SUSPENDED: 834 item.setTitle(R.string.radio_info_data_connection_disable); 835 break; 836 case TelephonyManager.DATA_DISCONNECTED: 837 item.setTitle(R.string.radio_info_data_connection_enable); 838 break; 839 default: 840 visible = false; 841 break; 842 } 843 item.setVisible(visible); 844 return true; 845 } 846 847 @Override onDestroy()848 protected void onDestroy() { 849 super.onDestroy(); 850 mQueuedWork.shutdown(); 851 } 852 853 // returns array of string labels for each phone index. The array index is equal to the phone 854 // index. getPhoneIndexLabels(TelephonyManager tm)855 private static String[] getPhoneIndexLabels(TelephonyManager tm) { 856 int phones = tm.getPhoneCount(); 857 String[] labels = new String[phones]; 858 for (int i = 0; i < phones; i++) { 859 labels[i] = "Phone " + i; 860 } 861 return labels; 862 } 863 unregisterPhoneStateListener()864 private void unregisterPhoneStateListener() { 865 mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback); 866 mPhone.unregisterForPhysicalChannelConfig(mHandler); 867 868 // clear all fields so they are blank until the next listener event occurs 869 mOperatorName.setText(""); 870 mGprsState.setText(""); 871 mDataNetwork.setText(""); 872 mDataRawReg.setText(""); 873 mOverrideNetwork.setText(""); 874 mVoiceNetwork.setText(""); 875 mVoiceRawReg.setText(""); 876 mWlanDataRawReg.setText(""); 877 mSent.setText(""); 878 mReceived.setText(""); 879 mCallState.setText(""); 880 mMwiValue = false; 881 mMwi.setText(""); 882 mCfiValue = false; 883 mCfi.setText(""); 884 mCellInfo.setText(""); 885 mDBm.setText(""); 886 mGsmState.setText(""); 887 mRoamingState.setText(""); 888 mPhyChanConfig.setText(""); 889 } 890 891 // register mTelephonyCallback for relevant fields using the current TelephonyManager registerPhoneStateListener()892 private void registerPhoneStateListener() { 893 mTelephonyCallback = new RadioInfoTelephonyCallback(); 894 mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(mHandler), 895 mTelephonyCallback); 896 } 897 setNrStatsVisibility(int visibility)898 private void setNrStatsVisibility(int visibility) { 899 ((TextView) findViewById(R.id.endc_available_label)).setVisibility(visibility); 900 mEndcAvailable.setVisibility(visibility); 901 ((TextView) findViewById(R.id.dcnr_restricted_label)).setVisibility(visibility); 902 mDcnrRestricted.setVisibility(visibility); 903 ((TextView) findViewById(R.id.nr_available_label)).setVisibility(visibility); 904 mNrAvailable.setVisibility(visibility); 905 ((TextView) findViewById(R.id.nr_state_label)).setVisibility(visibility); 906 mNrState.setVisibility(visibility); 907 ((TextView) findViewById(R.id.nr_frequency_label)).setVisibility(visibility); 908 mNrFrequency.setVisibility(visibility); 909 ((TextView) findViewById(R.id.network_slicing_config_label)).setVisibility(visibility); 910 mNetworkSlicingConfig.setVisibility(visibility); 911 } 912 updateDnsCheckState()913 private void updateDnsCheckState() { 914 //FIXME: Replace with a TelephonyManager call 915 mDnsCheckState.setText(mPhone.isDnsCheckDisabled() 916 ? "0.0.0.0 allowed" : "0.0.0.0 not allowed"); 917 } 918 updateBandwidths(int dlbw, int ulbw)919 private void updateBandwidths(int dlbw, int ulbw) { 920 dlbw = (dlbw < 0 || dlbw == Integer.MAX_VALUE) ? -1 : dlbw; 921 ulbw = (ulbw < 0 || ulbw == Integer.MAX_VALUE) ? -1 : ulbw; 922 mDownlinkKbps.setText(String.format("%-5d", dlbw)); 923 mUplinkKbps.setText(String.format("%-5d", ulbw)); 924 } 925 updateSignalStrength(SignalStrength signalStrength)926 private void updateSignalStrength(SignalStrength signalStrength) { 927 Resources r = getResources(); 928 929 int signalDbm = signalStrength.getDbm(); 930 931 int signalAsu = signalStrength.getAsuLevel(); 932 933 if (-1 == signalAsu) signalAsu = 0; 934 935 mDBm.setText(String.valueOf(signalDbm) + " " 936 + r.getString(R.string.radioInfo_display_dbm) + " " 937 + String.valueOf(signalAsu) + " " 938 + r.getString(R.string.radioInfo_display_asu)); 939 } 940 getCellInfoDisplayString(int i)941 private String getCellInfoDisplayString(int i) { 942 return (i != Integer.MAX_VALUE) ? Integer.toString(i) : ""; 943 } 944 getCellInfoDisplayString(long i)945 private String getCellInfoDisplayString(long i) { 946 return (i != Long.MAX_VALUE) ? Long.toString(i) : ""; 947 } 948 getConnectionStatusString(CellInfo ci)949 private String getConnectionStatusString(CellInfo ci) { 950 String regStr = ""; 951 String connStatStr = ""; 952 String connector = ""; 953 954 if (ci.isRegistered()) { 955 regStr = "R"; 956 } 957 switch (ci.getCellConnectionStatus()) { 958 case CellInfo.CONNECTION_PRIMARY_SERVING: connStatStr = "P"; break; 959 case CellInfo.CONNECTION_SECONDARY_SERVING: connStatStr = "S"; break; 960 case CellInfo.CONNECTION_NONE: connStatStr = "N"; break; 961 case CellInfo.CONNECTION_UNKNOWN: /* Field is unsupported */ break; 962 default: break; 963 } 964 if (!TextUtils.isEmpty(regStr) && !TextUtils.isEmpty(connStatStr)) { 965 connector = "+"; 966 } 967 968 return regStr + connector + connStatStr; 969 } 970 buildCdmaInfoString(CellInfoCdma ci)971 private String buildCdmaInfoString(CellInfoCdma ci) { 972 CellIdentityCdma cidCdma = ci.getCellIdentity(); 973 CellSignalStrengthCdma ssCdma = ci.getCellSignalStrength(); 974 975 return String.format("%-3.3s %-5.5s %-5.5s %-5.5s %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s", 976 getConnectionStatusString(ci), 977 getCellInfoDisplayString(cidCdma.getSystemId()), 978 getCellInfoDisplayString(cidCdma.getNetworkId()), 979 getCellInfoDisplayString(cidCdma.getBasestationId()), 980 getCellInfoDisplayString(ssCdma.getCdmaDbm()), 981 getCellInfoDisplayString(ssCdma.getCdmaEcio()), 982 getCellInfoDisplayString(ssCdma.getEvdoDbm()), 983 getCellInfoDisplayString(ssCdma.getEvdoEcio()), 984 getCellInfoDisplayString(ssCdma.getEvdoSnr())); 985 } 986 buildGsmInfoString(CellInfoGsm ci)987 private String buildGsmInfoString(CellInfoGsm ci) { 988 CellIdentityGsm cidGsm = ci.getCellIdentity(); 989 CellSignalStrengthGsm ssGsm = ci.getCellSignalStrength(); 990 991 return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n", 992 getConnectionStatusString(ci), 993 getCellInfoDisplayString(cidGsm.getMcc()), 994 getCellInfoDisplayString(cidGsm.getMnc()), 995 getCellInfoDisplayString(cidGsm.getLac()), 996 getCellInfoDisplayString(cidGsm.getCid()), 997 getCellInfoDisplayString(cidGsm.getArfcn()), 998 getCellInfoDisplayString(cidGsm.getBsic()), 999 getCellInfoDisplayString(ssGsm.getDbm())); 1000 } 1001 buildLteInfoString(CellInfoLte ci)1002 private String buildLteInfoString(CellInfoLte ci) { 1003 CellIdentityLte cidLte = ci.getCellIdentity(); 1004 CellSignalStrengthLte ssLte = ci.getCellSignalStrength(); 1005 1006 return String.format( 1007 "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n", 1008 getConnectionStatusString(ci), 1009 getCellInfoDisplayString(cidLte.getMcc()), 1010 getCellInfoDisplayString(cidLte.getMnc()), 1011 getCellInfoDisplayString(cidLte.getTac()), 1012 getCellInfoDisplayString(cidLte.getCi()), 1013 getCellInfoDisplayString(cidLte.getPci()), 1014 getCellInfoDisplayString(cidLte.getEarfcn()), 1015 getCellInfoDisplayString(cidLte.getBandwidth()), 1016 getCellInfoDisplayString(ssLte.getDbm()), 1017 getCellInfoDisplayString(ssLte.getRsrq()), 1018 getCellInfoDisplayString(ssLte.getTimingAdvance())); 1019 } 1020 buildNrInfoString(CellInfoNr ci)1021 private String buildNrInfoString(CellInfoNr ci) { 1022 CellIdentityNr cidNr = (CellIdentityNr) ci.getCellIdentity(); 1023 CellSignalStrengthNr ssNr = (CellSignalStrengthNr) ci.getCellSignalStrength(); 1024 1025 return String.format( 1026 "%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s %-6.6s %-4.4s %-4.4s\n", 1027 getConnectionStatusString(ci), 1028 cidNr.getMccString(), 1029 cidNr.getMncString(), 1030 getCellInfoDisplayString(cidNr.getTac()), 1031 getCellInfoDisplayString(cidNr.getNci()), 1032 getCellInfoDisplayString(cidNr.getPci()), 1033 getCellInfoDisplayString(cidNr.getNrarfcn()), 1034 getCellInfoDisplayString(ssNr.getSsRsrp()), 1035 getCellInfoDisplayString(ssNr.getSsRsrq())); 1036 } 1037 buildWcdmaInfoString(CellInfoWcdma ci)1038 private String buildWcdmaInfoString(CellInfoWcdma ci) { 1039 CellIdentityWcdma cidWcdma = ci.getCellIdentity(); 1040 CellSignalStrengthWcdma ssWcdma = ci.getCellSignalStrength(); 1041 1042 return String.format("%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n", 1043 getConnectionStatusString(ci), 1044 getCellInfoDisplayString(cidWcdma.getMcc()), 1045 getCellInfoDisplayString(cidWcdma.getMnc()), 1046 getCellInfoDisplayString(cidWcdma.getLac()), 1047 getCellInfoDisplayString(cidWcdma.getCid()), 1048 getCellInfoDisplayString(cidWcdma.getUarfcn()), 1049 getCellInfoDisplayString(cidWcdma.getPsc()), 1050 getCellInfoDisplayString(ssWcdma.getDbm())); 1051 } 1052 buildCellInfoString(List<CellInfo> arrayCi)1053 private String buildCellInfoString(List<CellInfo> arrayCi) { 1054 String value = new String(); 1055 StringBuilder cdmaCells = new StringBuilder(), 1056 gsmCells = new StringBuilder(), 1057 lteCells = new StringBuilder(), 1058 wcdmaCells = new StringBuilder(), 1059 nrCells = new StringBuilder(); 1060 1061 if (arrayCi != null) { 1062 for (CellInfo ci : arrayCi) { 1063 1064 if (ci instanceof CellInfoLte) { 1065 lteCells.append(buildLteInfoString((CellInfoLte) ci)); 1066 } else if (ci instanceof CellInfoWcdma) { 1067 wcdmaCells.append(buildWcdmaInfoString((CellInfoWcdma) ci)); 1068 } else if (ci instanceof CellInfoGsm) { 1069 gsmCells.append(buildGsmInfoString((CellInfoGsm) ci)); 1070 } else if (ci instanceof CellInfoCdma) { 1071 cdmaCells.append(buildCdmaInfoString((CellInfoCdma) ci)); 1072 } else if (ci instanceof CellInfoNr) { 1073 nrCells.append(buildNrInfoString((CellInfoNr) ci)); 1074 } 1075 } 1076 if (nrCells.length() != 0) { 1077 value += String.format( 1078 "NR\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s" 1079 + " %-6.6s %-4.4s %-4.4s\n", 1080 "SRV", "MCC", "MNC", "TAC", "NCI", "PCI", 1081 "NRARFCN", "SS-RSRP", "SS-RSRQ"); 1082 value += nrCells.toString(); 1083 } 1084 1085 if (lteCells.length() != 0) { 1086 value += String.format( 1087 "LTE\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-3.3s" 1088 + " %-6.6s %-2.2s %-4.4s %-4.4s %-2.2s\n", 1089 "SRV", "MCC", "MNC", "TAC", "CID", "PCI", 1090 "EARFCN", "BW", "RSRP", "RSRQ", "TA"); 1091 value += lteCells.toString(); 1092 } 1093 if (wcdmaCells.length() != 0) { 1094 value += String.format( 1095 "WCDMA\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-3.3s %-4.4s\n", 1096 "SRV", "MCC", "MNC", "LAC", "CID", "UARFCN", "PSC", "RSCP"); 1097 value += wcdmaCells.toString(); 1098 } 1099 if (gsmCells.length() != 0) { 1100 value += String.format( 1101 "GSM\n%-3.3s %-3.3s %-3.3s %-5.5s %-5.5s %-6.6s %-4.4s %-4.4s\n", 1102 "SRV", "MCC", "MNC", "LAC", "CID", "ARFCN", "BSIC", "RSSI"); 1103 value += gsmCells.toString(); 1104 } 1105 if (cdmaCells.length() != 0) { 1106 value += String.format( 1107 "CDMA/EVDO\n%-3.3s %-5.5s %-5.5s %-5.5s" 1108 + " %-6.6s %-6.6s %-6.6s %-6.6s %-5.5s\n", 1109 "SRV", "SID", "NID", "BSID", 1110 "C-RSSI", "C-ECIO", "E-RSSI", "E-ECIO", "E-SNR"); 1111 value += cdmaCells.toString(); 1112 } 1113 } else { 1114 value = "unknown"; 1115 } 1116 1117 return value.toString(); 1118 } 1119 updateCellInfo(List<CellInfo> arrayCi)1120 private void updateCellInfo(List<CellInfo> arrayCi) { 1121 mCellInfo.setText(buildCellInfoString(arrayCi)); 1122 } 1123 updateSubscriptionIds()1124 private void updateSubscriptionIds() { 1125 mSubscriptionId.setText(Integer.toString(mPhone.getSubId())); 1126 mDds.setText(Integer.toString(SubscriptionManager.getDefaultDataSubscriptionId())); 1127 } 1128 updateMessageWaiting()1129 private void updateMessageWaiting() { 1130 mMwi.setText(String.valueOf(mMwiValue)); 1131 } 1132 updateCallRedirect()1133 private void updateCallRedirect() { 1134 mCfi.setText(String.valueOf(mCfiValue)); 1135 } 1136 1137 updateServiceState(ServiceState serviceState)1138 private void updateServiceState(ServiceState serviceState) { 1139 int state = serviceState.getState(); 1140 Resources r = getResources(); 1141 String display = r.getString(R.string.radioInfo_unknown); 1142 1143 switch (state) { 1144 case ServiceState.STATE_IN_SERVICE: 1145 display = r.getString(R.string.radioInfo_service_in); 1146 break; 1147 case ServiceState.STATE_OUT_OF_SERVICE: 1148 display = r.getString(R.string.radioInfo_service_out); 1149 break; 1150 case ServiceState.STATE_EMERGENCY_ONLY: 1151 display = r.getString(R.string.radioInfo_service_emergency); 1152 break; 1153 case ServiceState.STATE_POWER_OFF: 1154 display = r.getString(R.string.radioInfo_service_off); 1155 break; 1156 } 1157 1158 mGsmState.setText(display); 1159 1160 if (serviceState.getRoaming()) { 1161 mRoamingState.setText(R.string.radioInfo_roaming_in); 1162 } else { 1163 mRoamingState.setText(R.string.radioInfo_roaming_not); 1164 } 1165 1166 mOperatorName.setText(serviceState.getOperatorAlphaLong()); 1167 } 1168 updatePhoneState(int state)1169 private void updatePhoneState(int state) { 1170 Resources r = getResources(); 1171 String display = r.getString(R.string.radioInfo_unknown); 1172 1173 switch (state) { 1174 case TelephonyManager.CALL_STATE_IDLE: 1175 display = r.getString(R.string.radioInfo_phone_idle); 1176 break; 1177 case TelephonyManager.CALL_STATE_RINGING: 1178 display = r.getString(R.string.radioInfo_phone_ringing); 1179 break; 1180 case TelephonyManager.CALL_STATE_OFFHOOK: 1181 display = r.getString(R.string.radioInfo_phone_offhook); 1182 break; 1183 } 1184 1185 mCallState.setText(display); 1186 } 1187 updateDataState()1188 private void updateDataState() { 1189 int state = mTelephonyManager.getDataState(); 1190 Resources r = getResources(); 1191 String display = r.getString(R.string.radioInfo_unknown); 1192 1193 switch (state) { 1194 case TelephonyManager.DATA_CONNECTED: 1195 display = r.getString(R.string.radioInfo_data_connected); 1196 break; 1197 case TelephonyManager.DATA_CONNECTING: 1198 display = r.getString(R.string.radioInfo_data_connecting); 1199 break; 1200 case TelephonyManager.DATA_DISCONNECTED: 1201 display = r.getString(R.string.radioInfo_data_disconnected); 1202 break; 1203 case TelephonyManager.DATA_SUSPENDED: 1204 display = r.getString(R.string.radioInfo_data_suspended); 1205 break; 1206 } 1207 1208 mGprsState.setText(display); 1209 } 1210 updateNetworkType()1211 private void updateNetworkType() { 1212 if (mPhone != null) { 1213 mDataNetwork.setText(ServiceState.rilRadioTechnologyToString( 1214 mPhone.getServiceState().getRilDataRadioTechnology())); 1215 mVoiceNetwork.setText(ServiceState.rilRadioTechnologyToString( 1216 mPhone.getServiceState().getRilVoiceRadioTechnology())); 1217 int overrideNetwork = mPhone.getDisplayInfoController().getTelephonyDisplayInfo() 1218 .getOverrideNetworkType(); 1219 mOverrideNetwork.setText( 1220 TelephonyDisplayInfo.overrideNetworkTypeToString(overrideNetwork)); 1221 } 1222 } 1223 getRawRegistrationStateText(ServiceState ss, int domain, int transportType)1224 private String getRawRegistrationStateText(ServiceState ss, int domain, int transportType) { 1225 if (ss != null) { 1226 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(domain, transportType); 1227 if (nri != null) { 1228 return NetworkRegistrationInfo.registrationStateToString( 1229 nri.getNetworkRegistrationState()) 1230 + (nri.isEmergencyEnabled() ? "_EM" : ""); 1231 } 1232 } 1233 return ""; 1234 } 1235 updateRawRegistrationState(ServiceState serviceState)1236 private void updateRawRegistrationState(ServiceState serviceState) { 1237 ServiceState ss = serviceState; 1238 if (ss == null && mPhone != null) { 1239 ss = mPhone.getServiceState(); 1240 } 1241 1242 mVoiceRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_CS, 1243 AccessNetworkConstants.TRANSPORT_TYPE_WWAN)); 1244 mDataRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_PS, 1245 AccessNetworkConstants.TRANSPORT_TYPE_WWAN)); 1246 mWlanDataRawReg.setText(getRawRegistrationStateText(ss, NetworkRegistrationInfo.DOMAIN_PS, 1247 AccessNetworkConstants.TRANSPORT_TYPE_WLAN)); 1248 } 1249 updateNrStats()1250 private void updateNrStats() { 1251 if ((mTelephonyManager.getSupportedRadioAccessFamily() 1252 & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) { 1253 return; 1254 } 1255 ServiceState ss = (mPhone == null) ? null : mPhone.getServiceState(); 1256 if (ss != null) { 1257 NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( 1258 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 1259 if (nri != null) { 1260 DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo(); 1261 if (dsri != null) { 1262 mEndcAvailable.setText(String.valueOf(dsri.isEnDcAvailable)); 1263 mDcnrRestricted.setText(String.valueOf(dsri.isDcNrRestricted)); 1264 mNrAvailable.setText(String.valueOf(dsri.isNrAvailable)); 1265 } 1266 } 1267 mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState())); 1268 mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange())); 1269 } else { 1270 Log.e(TAG, "Clear Nr stats by null service state"); 1271 mEndcAvailable.setText(""); 1272 mDcnrRestricted.setText(""); 1273 mNrAvailable.setText(""); 1274 mNrState.setText(""); 1275 mNrFrequency.setText(""); 1276 } 1277 1278 CompletableFuture<NetworkSlicingConfig> resultFuture = new CompletableFuture<>(); 1279 mTelephonyManager.getNetworkSlicingConfiguration(Runnable::run, resultFuture::complete); 1280 try { 1281 NetworkSlicingConfig networkSlicingConfig = 1282 resultFuture.get(DEFAULT_TIMEOUT_MS, MILLISECONDS); 1283 mNetworkSlicingConfig.setText(networkSlicingConfig.toString()); 1284 } catch (ExecutionException | InterruptedException | TimeoutException e) { 1285 Log.e(TAG, "Unable to get slicing config: " + e.toString()); 1286 mNetworkSlicingConfig.setText("Unable to get slicing config."); 1287 } 1288 1289 } 1290 updateProperties()1291 private void updateProperties() { 1292 String s; 1293 Resources r = getResources(); 1294 1295 s = mPhone.getDeviceId(); 1296 if (s == null) { 1297 s = r.getString(R.string.radioInfo_unknown); 1298 } else if (mPhone.getImeiType() == ImeiInfo.ImeiType.PRIMARY) { 1299 s = s + " (" + r.getString(R.string.radioInfo_imei_primary) + ")"; 1300 } 1301 mDeviceId.setText(s); 1302 1303 s = mPhone.getSubscriberId(); 1304 if (s == null) s = r.getString(R.string.radioInfo_unknown); 1305 1306 mSubscriberId.setText(s); 1307 1308 SubscriptionManager subMgr = getSystemService(SubscriptionManager.class); 1309 int subId = mPhone.getSubId(); 1310 s = subMgr.getPhoneNumber(subId) 1311 + " { CARRIER:" 1312 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER) 1313 + ", UICC:" 1314 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_UICC) 1315 + ", IMS:" 1316 + subMgr.getPhoneNumber(subId, SubscriptionManager.PHONE_NUMBER_SOURCE_IMS) 1317 + " }"; 1318 mLine1Number.setText(s); 1319 } 1320 updateDataStats2()1321 private void updateDataStats2() { 1322 Resources r = getResources(); 1323 1324 long txPackets = TrafficStats.getMobileTxPackets(); 1325 long rxPackets = TrafficStats.getMobileRxPackets(); 1326 long txBytes = TrafficStats.getMobileTxBytes(); 1327 long rxBytes = TrafficStats.getMobileRxBytes(); 1328 1329 String packets = r.getString(R.string.radioInfo_display_packets); 1330 String bytes = r.getString(R.string.radioInfo_display_bytes); 1331 1332 mSent.setText(txPackets + " " + packets + ", " + txBytes + " " + bytes); 1333 mReceived.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes); 1334 } 1335 1336 /** 1337 * Ping a host name 1338 */ pingHostname()1339 private void pingHostname() { 1340 try { 1341 try { 1342 Process p4 = Runtime.getRuntime().exec("ping -c 1 www.google.com"); 1343 int status4 = p4.waitFor(); 1344 if (status4 == 0) { 1345 mPingHostnameResultV4 = "Pass"; 1346 } else { 1347 mPingHostnameResultV4 = String.format("Fail(%d)", status4); 1348 } 1349 } catch (IOException e) { 1350 mPingHostnameResultV4 = "Fail: IOException"; 1351 } 1352 try { 1353 Process p6 = Runtime.getRuntime().exec("ping6 -c 1 www.google.com"); 1354 int status6 = p6.waitFor(); 1355 if (status6 == 0) { 1356 mPingHostnameResultV6 = "Pass"; 1357 } else { 1358 mPingHostnameResultV6 = String.format("Fail(%d)", status6); 1359 } 1360 } catch (IOException e) { 1361 mPingHostnameResultV6 = "Fail: IOException"; 1362 } 1363 } catch (InterruptedException e) { 1364 mPingHostnameResultV4 = mPingHostnameResultV6 = "Fail: InterruptedException"; 1365 } 1366 } 1367 1368 /** 1369 * This function checks for basic functionality of HTTP Client. 1370 */ httpClientTest()1371 private void httpClientTest() { 1372 HttpURLConnection urlConnection = null; 1373 try { 1374 // TODO: Hardcoded for now, make it UI configurable 1375 URL url = new URL("https://www.google.com"); 1376 urlConnection = (HttpURLConnection) url.openConnection(); 1377 if (urlConnection.getResponseCode() == 200) { 1378 mHttpClientTestResult = "Pass"; 1379 } else { 1380 mHttpClientTestResult = "Fail: Code: " + urlConnection.getResponseMessage(); 1381 } 1382 } catch (IOException e) { 1383 mHttpClientTestResult = "Fail: IOException"; 1384 } finally { 1385 if (urlConnection != null) { 1386 urlConnection.disconnect(); 1387 } 1388 } 1389 } 1390 refreshSmsc()1391 private void refreshSmsc() { 1392 mQueuedWork.execute(new Runnable() { 1393 public void run() { 1394 //FIXME: Replace with a TelephonyManager call 1395 mPhone.getSmscAddress(mHandler.obtainMessage(EVENT_QUERY_SMSC_DONE)); 1396 } 1397 }); 1398 } 1399 updateAllCellInfo()1400 private void updateAllCellInfo() { 1401 1402 mCellInfo.setText(""); 1403 1404 final Runnable updateAllCellInfoResults = new Runnable() { 1405 public void run() { 1406 updateCellInfo(mCellInfoResult); 1407 } 1408 }; 1409 1410 mQueuedWork.execute(new Runnable() { 1411 @Override 1412 public void run() { 1413 mCellInfoResult = mTelephonyManager.getAllCellInfo(); 1414 1415 mHandler.post(updateAllCellInfoResults); 1416 } 1417 }); 1418 } 1419 updatePingState()1420 private void updatePingState() { 1421 // Set all to unknown since the threads will take a few secs to update. 1422 mPingHostnameResultV4 = getResources().getString(R.string.radioInfo_unknown); 1423 mPingHostnameResultV6 = getResources().getString(R.string.radioInfo_unknown); 1424 mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown); 1425 1426 mPingHostnameV4.setText(mPingHostnameResultV4); 1427 mPingHostnameV6.setText(mPingHostnameResultV6); 1428 mHttpClientTest.setText(mHttpClientTestResult); 1429 1430 final Runnable updatePingResults = new Runnable() { 1431 public void run() { 1432 mPingHostnameV4.setText(mPingHostnameResultV4); 1433 mPingHostnameV6.setText(mPingHostnameResultV6); 1434 mHttpClientTest.setText(mHttpClientTestResult); 1435 } 1436 }; 1437 1438 Thread hostname = new Thread() { 1439 @Override 1440 public void run() { 1441 pingHostname(); 1442 mHandler.post(updatePingResults); 1443 } 1444 }; 1445 hostname.start(); 1446 1447 Thread httpClient = new Thread() { 1448 @Override 1449 public void run() { 1450 httpClientTest(); 1451 mHandler.post(updatePingResults); 1452 } 1453 }; 1454 httpClient.start(); 1455 } 1456 1457 private MenuItem.OnMenuItemClickListener mViewADNCallback = 1458 new MenuItem.OnMenuItemClickListener() { 1459 public boolean onMenuItemClick(MenuItem item) { 1460 Intent intent = new Intent(Intent.ACTION_VIEW); 1461 // XXX We need to specify the component here because if we don't 1462 // the activity manager will try to resolve the type by calling 1463 // the content provider, which causes it to be loaded in a process 1464 // other than the Dialer process, which causes a lot of stuff to 1465 // break. 1466 intent.setClassName("com.android.phone", "com.android.phone.SimContacts"); 1467 startActivity(intent); 1468 return true; 1469 } 1470 }; 1471 1472 private MenuItem.OnMenuItemClickListener mViewFDNCallback = 1473 new MenuItem.OnMenuItemClickListener() { 1474 public boolean onMenuItemClick(MenuItem item) { 1475 Intent intent = new Intent(Intent.ACTION_VIEW); 1476 // XXX We need to specify the component here because if we don't 1477 // the activity manager will try to resolve the type by calling 1478 // the content provider, which causes it to be loaded in a process 1479 // other than the Dialer process, which causes a lot of stuff to 1480 // break. 1481 intent.setClassName("com.android.phone", "com.android.phone.settings.fdn.FdnList"); 1482 startActivity(intent); 1483 return true; 1484 } 1485 }; 1486 1487 private MenuItem.OnMenuItemClickListener mViewSDNCallback = 1488 new MenuItem.OnMenuItemClickListener() { 1489 public boolean onMenuItemClick(MenuItem item) { 1490 Intent intent = new Intent( 1491 Intent.ACTION_VIEW, Uri.parse("content://icc/sdn")); 1492 // XXX We need to specify the component here because if we don't 1493 // the activity manager will try to resolve the type by calling 1494 // the content provider, which causes it to be loaded in a process 1495 // other than the Dialer process, which causes a lot of stuff to 1496 // break. 1497 intent.setClassName("com.android.phone", "com.android.phone.ADNList"); 1498 startActivity(intent); 1499 return true; 1500 } 1501 }; 1502 1503 private MenuItem.OnMenuItemClickListener mGetImsStatus = 1504 new MenuItem.OnMenuItemClickListener() { 1505 public boolean onMenuItemClick(MenuItem item) { 1506 boolean isImsRegistered = mPhone.isImsRegistered(); 1507 boolean availableVolte = mPhone.isVoiceOverCellularImsEnabled(); 1508 boolean availableWfc = mPhone.isWifiCallingEnabled(); 1509 boolean availableVt = mPhone.isVideoEnabled(); 1510 boolean availableUt = mPhone.isUtEnabled(); 1511 1512 final String imsRegString = isImsRegistered 1513 ? getString(R.string.radio_info_ims_reg_status_registered) 1514 : getString(R.string.radio_info_ims_reg_status_not_registered); 1515 1516 final String available = getString(R.string.radio_info_ims_feature_status_available); 1517 final String unavailable = getString( 1518 R.string.radio_info_ims_feature_status_unavailable); 1519 1520 String imsStatus = getString(R.string.radio_info_ims_reg_status, 1521 imsRegString, 1522 availableVolte ? available : unavailable, 1523 availableWfc ? available : unavailable, 1524 availableVt ? available : unavailable, 1525 availableUt ? available : unavailable); 1526 1527 AlertDialog imsDialog = new AlertDialog.Builder(RadioInfo.this) 1528 .setMessage(imsStatus) 1529 .setTitle(getString(R.string.radio_info_ims_reg_status_title)) 1530 .create(); 1531 1532 imsDialog.show(); 1533 1534 return true; 1535 } 1536 }; 1537 1538 private MenuItem.OnMenuItemClickListener mToggleData = 1539 new MenuItem.OnMenuItemClickListener() { 1540 public boolean onMenuItemClick(MenuItem item) { 1541 int state = mTelephonyManager.getDataState(); 1542 switch (state) { 1543 case TelephonyManager.DATA_CONNECTED: 1544 mTelephonyManager.setDataEnabled(false); 1545 break; 1546 case TelephonyManager.DATA_DISCONNECTED: 1547 mTelephonyManager.setDataEnabled(true); 1548 break; 1549 default: 1550 // do nothing 1551 break; 1552 } 1553 return true; 1554 } 1555 }; 1556 isRadioOn()1557 private boolean isRadioOn() { 1558 //FIXME: Replace with a TelephonyManager call 1559 return mPhone.getServiceState().getState() != ServiceState.STATE_POWER_OFF; 1560 } 1561 updateRadioPowerState()1562 private void updateRadioPowerState() { 1563 //delightful hack to prevent on-checked-changed calls from 1564 //actually forcing the radio preference to its transient/current value. 1565 mRadioPowerOnSwitch.setOnCheckedChangeListener(null); 1566 mRadioPowerOnSwitch.setChecked(isRadioOn()); 1567 mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener); 1568 } 1569 setImsVolteProvisionedState(boolean state)1570 private void setImsVolteProvisionedState(boolean state) { 1571 Log.d(TAG, "setImsVolteProvisioned state: " + ((state) ? "on" : "off")); 1572 setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 1573 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state); 1574 } 1575 setImsVtProvisionedState(boolean state)1576 private void setImsVtProvisionedState(boolean state) { 1577 Log.d(TAG, "setImsVtProvisioned() state: " + ((state) ? "on" : "off")); 1578 setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, 1579 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state); 1580 } 1581 setImsWfcProvisionedState(boolean state)1582 private void setImsWfcProvisionedState(boolean state) { 1583 Log.d(TAG, "setImsWfcProvisioned() state: " + ((state) ? "on" : "off")); 1584 setImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 1585 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, state); 1586 } 1587 setEabProvisionedState(boolean state)1588 private void setEabProvisionedState(boolean state) { 1589 Log.d(TAG, "setEabProvisioned() state: " + ((state) ? "on" : "off")); 1590 setRcsConfigProvisionedState(ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE, 1591 ImsRegistrationImplBase.REGISTRATION_TECH_LTE, state); 1592 } 1593 setImsConfigProvisionedState(int capability, int tech, boolean state)1594 private void setImsConfigProvisionedState(int capability, int tech, boolean state) { 1595 if (mProvisioningManager != null) { 1596 mQueuedWork.execute(new Runnable() { 1597 public void run() { 1598 try { 1599 mProvisioningManager.setProvisioningStatusForCapability( 1600 capability, tech, state); 1601 } catch (RuntimeException e) { 1602 Log.e(TAG, "setImsConfigProvisioned() exception:", e); 1603 } 1604 } 1605 }); 1606 } 1607 } 1608 setRcsConfigProvisionedState(int capability, int tech, boolean state)1609 private void setRcsConfigProvisionedState(int capability, int tech, boolean state) { 1610 if (mProvisioningManager != null) { 1611 mQueuedWork.execute(new Runnable() { 1612 public void run() { 1613 try { 1614 mProvisioningManager.setRcsProvisioningStatusForCapability( 1615 capability, tech, state); 1616 } catch (RuntimeException e) { 1617 Log.e(TAG, "setRcsConfigProvisioned() exception:", e); 1618 } 1619 } 1620 }); 1621 } 1622 } 1623 isImsVolteProvisioningRequired()1624 private boolean isImsVolteProvisioningRequired() { 1625 return isImsConfigProvisioningRequired( 1626 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 1627 ImsRegistrationImplBase.REGISTRATION_TECH_LTE); 1628 } 1629 isImsVtProvisioningRequired()1630 private boolean isImsVtProvisioningRequired() { 1631 return isImsConfigProvisioningRequired( 1632 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, 1633 ImsRegistrationImplBase.REGISTRATION_TECH_LTE); 1634 } 1635 isImsWfcProvisioningRequired()1636 private boolean isImsWfcProvisioningRequired() { 1637 return isImsConfigProvisioningRequired( 1638 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 1639 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN); 1640 } 1641 isEabProvisioningRequired()1642 private boolean isEabProvisioningRequired() { 1643 return isRcsConfigProvisioningRequired( 1644 ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE, 1645 ImsRegistrationImplBase.REGISTRATION_TECH_LTE); 1646 } 1647 isImsConfigProvisioningRequired(int capability, int tech)1648 private boolean isImsConfigProvisioningRequired(int capability, int tech) { 1649 if (mProvisioningManager != null) { 1650 try { 1651 return mProvisioningManager.isProvisioningRequiredForCapability( 1652 capability, tech); 1653 } catch (RuntimeException e) { 1654 Log.e(TAG, "isImsConfigProvisioningRequired() exception:", e); 1655 } 1656 } 1657 1658 return false; 1659 } 1660 isRcsConfigProvisioningRequired(int capability, int tech)1661 private boolean isRcsConfigProvisioningRequired(int capability, int tech) { 1662 if (mProvisioningManager != null) { 1663 try { 1664 return mProvisioningManager.isRcsProvisioningRequiredForCapability( 1665 capability, tech); 1666 } catch (RuntimeException e) { 1667 Log.e(TAG, "isRcsConfigProvisioningRequired() exception:", e); 1668 } 1669 } 1670 1671 return false; 1672 } 1673 1674 OnCheckedChangeListener mRadioPowerOnChangeListener = new OnCheckedChangeListener() { 1675 @Override 1676 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1677 // TODO: b/145681511. Within current design, radio power on all of the phones need 1678 // to be controlled at the same time. 1679 Phone[] phones = PhoneFactory.getPhones(); 1680 if (phones == null) { 1681 return; 1682 } 1683 log("toggle radio power: phone*" + phones.length + " " + (isRadioOn() ? "on" : "off")); 1684 for (int phoneIndex = 0; phoneIndex < phones.length; phoneIndex++) { 1685 if (phones[phoneIndex] != null) { 1686 phones[phoneIndex].setRadioPower(isChecked); 1687 } 1688 } 1689 } 1690 }; 1691 1692 private final OnCheckedChangeListener mSimulateOosOnChangeListener = 1693 (buttonView, isChecked) -> { 1694 Intent intent = new Intent("com.android.internal.telephony.TestServiceState"); 1695 if (isChecked) { 1696 log("Send OOS override broadcast intent."); 1697 intent.putExtra("data_reg_state", 1); 1698 mSimulateOos[mPhone.getPhoneId()] = true; 1699 } else { 1700 log("Remove OOS override."); 1701 intent.putExtra("action", "reset"); 1702 mSimulateOos[mPhone.getPhoneId()] = false; 1703 } 1704 1705 mPhone.getTelephonyTester().setServiceStateTestIntent(intent); 1706 }; 1707 isImsVolteProvisioned()1708 private boolean isImsVolteProvisioned() { 1709 return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 1710 ImsRegistrationImplBase.REGISTRATION_TECH_LTE); 1711 } 1712 1713 OnCheckedChangeListener mImsVolteCheckedChangeListener = new OnCheckedChangeListener() { 1714 @Override 1715 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1716 setImsVolteProvisionedState(isChecked); 1717 } 1718 }; 1719 isImsVtProvisioned()1720 private boolean isImsVtProvisioned() { 1721 return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, 1722 ImsRegistrationImplBase.REGISTRATION_TECH_LTE); 1723 } 1724 1725 OnCheckedChangeListener mImsVtCheckedChangeListener = new OnCheckedChangeListener() { 1726 @Override 1727 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1728 setImsVtProvisionedState(isChecked); 1729 } 1730 }; 1731 isImsWfcProvisioned()1732 private boolean isImsWfcProvisioned() { 1733 return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 1734 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN); 1735 } 1736 1737 OnCheckedChangeListener mImsWfcCheckedChangeListener = new OnCheckedChangeListener() { 1738 @Override 1739 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1740 setImsWfcProvisionedState(isChecked); 1741 } 1742 }; 1743 isEabProvisioned()1744 private boolean isEabProvisioned() { 1745 return getRcsConfigProvisionedState(ImsRcsManager.CAPABILITY_TYPE_PRESENCE_UCE, 1746 ImsRegistrationImplBase.REGISTRATION_TECH_LTE); 1747 } 1748 1749 OnCheckedChangeListener mEabCheckedChangeListener = new OnCheckedChangeListener() { 1750 @Override 1751 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 1752 setEabProvisionedState(isChecked); 1753 } 1754 }; 1755 getImsConfigProvisionedState(int capability, int tech)1756 private boolean getImsConfigProvisionedState(int capability, int tech) { 1757 if (mProvisioningManager != null) { 1758 try { 1759 return mProvisioningManager.getProvisioningStatusForCapability( 1760 capability, tech); 1761 } catch (RuntimeException e) { 1762 Log.e(TAG, "getImsConfigProvisionedState() exception:", e); 1763 } 1764 } 1765 1766 return false; 1767 } 1768 getRcsConfigProvisionedState(int capability, int tech)1769 private boolean getRcsConfigProvisionedState(int capability, int tech) { 1770 if (mProvisioningManager != null) { 1771 try { 1772 return mProvisioningManager.getRcsProvisioningStatusForCapability( 1773 capability, tech); 1774 } catch (RuntimeException e) { 1775 Log.e(TAG, "getRcsConfigProvisionedState() exception:", e); 1776 } 1777 } 1778 1779 return false; 1780 } 1781 isEabEnabledByPlatform()1782 private boolean isEabEnabledByPlatform() { 1783 if (mPhone != null) { 1784 CarrierConfigManager configManager = (CarrierConfigManager) 1785 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 1786 PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId()); 1787 if (b != null) { 1788 return b.getBoolean( 1789 CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL, false) || b.getBoolean( 1790 CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, 1791 false); 1792 } 1793 } 1794 return false; 1795 } 1796 updateImsProvisionedState()1797 private void updateImsProvisionedState() { 1798 if (!isImsSupportedOnDevice(mPhone.getContext())) { 1799 return; 1800 } 1801 1802 updateServiceEnabledByPlatform(); 1803 1804 updateEabProvisionedSwitch(isEabEnabledByPlatform()); 1805 } 1806 updateVolteProvisionedSwitch(boolean isEnabledByPlatform)1807 private void updateVolteProvisionedSwitch(boolean isEnabledByPlatform) { 1808 boolean isProvisioned = isEnabledByPlatform && isImsVolteProvisioned(); 1809 log("updateVolteProvisionedSwitch isProvisioned" + isProvisioned); 1810 1811 mImsVolteProvisionedSwitch.setOnCheckedChangeListener(null); 1812 mImsVolteProvisionedSwitch.setChecked(isProvisioned); 1813 mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener); 1814 mImsVolteProvisionedSwitch.setEnabled(!IS_USER_BUILD 1815 && isEnabledByPlatform && isImsVolteProvisioningRequired()); 1816 } 1817 updateVtProvisionedSwitch(boolean isEnabledByPlatform)1818 private void updateVtProvisionedSwitch(boolean isEnabledByPlatform) { 1819 boolean isProvisioned = isEnabledByPlatform && isImsVtProvisioned(); 1820 log("updateVtProvisionedSwitch isProvisioned" + isProvisioned); 1821 1822 mImsVtProvisionedSwitch.setOnCheckedChangeListener(null); 1823 mImsVtProvisionedSwitch.setChecked(isProvisioned); 1824 mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener); 1825 mImsVtProvisionedSwitch.setEnabled(!IS_USER_BUILD 1826 && isEnabledByPlatform && isImsVtProvisioningRequired()); 1827 } 1828 updateWfcProvisionedSwitch(boolean isEnabledByPlatform)1829 private void updateWfcProvisionedSwitch(boolean isEnabledByPlatform) { 1830 boolean isProvisioned = isEnabledByPlatform && isImsWfcProvisioned(); 1831 log("updateWfcProvisionedSwitch isProvisioned" + isProvisioned); 1832 1833 mImsWfcProvisionedSwitch.setOnCheckedChangeListener(null); 1834 mImsWfcProvisionedSwitch.setChecked(isProvisioned); 1835 mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener); 1836 mImsWfcProvisionedSwitch.setEnabled(!IS_USER_BUILD 1837 && isEnabledByPlatform && isImsWfcProvisioningRequired()); 1838 } 1839 updateEabProvisionedSwitch(boolean isEnabledByPlatform)1840 private void updateEabProvisionedSwitch(boolean isEnabledByPlatform) { 1841 log("updateEabProvisionedSwitch isEabWfcProvisioned()=" + isEabProvisioned()); 1842 1843 mEabProvisionedSwitch.setOnCheckedChangeListener(null); 1844 mEabProvisionedSwitch.setChecked(isEabProvisioned()); 1845 mEabProvisionedSwitch.setOnCheckedChangeListener(mEabCheckedChangeListener); 1846 mEabProvisionedSwitch.setEnabled(!IS_USER_BUILD 1847 && isEnabledByPlatform && isEabProvisioningRequired()); 1848 } 1849 1850 OnClickListener mDnsCheckButtonHandler = new OnClickListener() { 1851 public void onClick(View v) { 1852 //FIXME: Replace with a TelephonyManager call 1853 mPhone.disableDnsCheck(!mPhone.isDnsCheckDisabled()); 1854 updateDnsCheckState(); 1855 } 1856 }; 1857 1858 OnClickListener mOemInfoButtonHandler = new OnClickListener() { 1859 public void onClick(View v) { 1860 Intent intent = new Intent(OEM_RADIO_INFO_INTENT); 1861 try { 1862 startActivity(intent); 1863 } catch (android.content.ActivityNotFoundException ex) { 1864 log("OEM-specific Info/Settings Activity Not Found : " + ex); 1865 // If the activity does not exist, there are no OEM 1866 // settings, and so we can just do nothing... 1867 } 1868 } 1869 }; 1870 1871 OnClickListener mPingButtonHandler = new OnClickListener() { 1872 public void onClick(View v) { 1873 updatePingState(); 1874 } 1875 }; 1876 1877 OnClickListener mUpdateSmscButtonHandler = new OnClickListener() { 1878 public void onClick(View v) { 1879 mUpdateSmscButton.setEnabled(false); 1880 mQueuedWork.execute(new Runnable() { 1881 public void run() { 1882 mPhone.setSmscAddress(mSmsc.getText().toString(), 1883 mHandler.obtainMessage(EVENT_UPDATE_SMSC_DONE)); 1884 } 1885 }); 1886 } 1887 }; 1888 1889 OnClickListener mRefreshSmscButtonHandler = new OnClickListener() { 1890 public void onClick(View v) { 1891 refreshSmsc(); 1892 } 1893 }; 1894 1895 OnClickListener mCarrierProvisioningButtonHandler = v -> { 1896 String carrierProvisioningApp = getCarrierProvisioningAppString(); 1897 if (!TextUtils.isEmpty(carrierProvisioningApp)) { 1898 final Intent intent = new Intent(CARRIER_PROVISIONING_ACTION); 1899 final ComponentName serviceComponent = 1900 ComponentName.unflattenFromString(carrierProvisioningApp); 1901 intent.setComponent(serviceComponent); 1902 sendBroadcast(intent); 1903 } 1904 }; 1905 1906 OnClickListener mTriggerCarrierProvisioningButtonHandler = v -> { 1907 String carrierProvisioningApp = getCarrierProvisioningAppString(); 1908 if (!TextUtils.isEmpty(carrierProvisioningApp)) { 1909 final Intent intent = new Intent(TRIGGER_CARRIER_PROVISIONING_ACTION); 1910 final ComponentName serviceComponent = 1911 ComponentName.unflattenFromString(carrierProvisioningApp); 1912 intent.setComponent(serviceComponent); 1913 sendBroadcast(intent); 1914 } 1915 }; 1916 1917 AdapterView.OnItemSelectedListener mPreferredNetworkHandler = 1918 new AdapterView.OnItemSelectedListener() { 1919 1920 public void onItemSelected(AdapterView parent, View v, int pos, long id) { 1921 if (mPreferredNetworkTypeResult != pos && pos >= 0 1922 && pos <= PREFERRED_NETWORK_LABELS.length - 2) { 1923 mPreferredNetworkTypeResult = pos; 1924 new Thread(() -> { 1925 mTelephonyManager.setAllowedNetworkTypesForReason( 1926 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, 1927 RadioAccessFamily.getRafFromNetworkType(mPreferredNetworkTypeResult)); 1928 }).start(); 1929 } 1930 } 1931 1932 public void onNothingSelected(AdapterView parent) { 1933 } 1934 }; 1935 1936 AdapterView.OnItemSelectedListener mSelectPhoneIndexHandler = 1937 new AdapterView.OnItemSelectedListener() { 1938 1939 public void onItemSelected(AdapterView parent, View v, int pos, long id) { 1940 if (pos >= 0 && pos <= sPhoneIndexLabels.length - 1) { 1941 // the array position is equal to the phone index 1942 int phoneIndex = pos; 1943 Phone[] phones = PhoneFactory.getPhones(); 1944 if (phones == null || phones.length <= phoneIndex) { 1945 return; 1946 } 1947 // getSubId says it takes a slotIndex, but it actually takes a phone index 1948 mSelectedPhoneIndex = phoneIndex; 1949 updatePhoneIndex(phoneIndex, SubscriptionManager.getSubscriptionId(phoneIndex)); 1950 } 1951 } 1952 1953 public void onNothingSelected(AdapterView parent) { 1954 } 1955 }; 1956 1957 AdapterView.OnItemSelectedListener mCellInfoRefreshRateHandler = 1958 new AdapterView.OnItemSelectedListener() { 1959 1960 public void onItemSelected(AdapterView parent, View v, int pos, long id) { 1961 mCellInfoRefreshRateIndex = pos; 1962 mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[pos], mPhone.getSubId()); 1963 updateAllCellInfo(); 1964 } 1965 1966 public void onNothingSelected(AdapterView parent) { 1967 } 1968 }; 1969 getCarrierProvisioningAppString()1970 private String getCarrierProvisioningAppString() { 1971 if (mPhone != null) { 1972 CarrierConfigManager configManager = 1973 mPhone.getContext().getSystemService(CarrierConfigManager.class); 1974 PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId()); 1975 if (b != null) { 1976 return b.getString( 1977 CarrierConfigManager.KEY_CARRIER_PROVISIONING_APP_STRING, ""); 1978 } 1979 } 1980 return ""; 1981 } 1982 isCbrsSupported()1983 boolean isCbrsSupported() { 1984 return getResources().getBoolean( 1985 com.android.internal.R.bool.config_cbrs_supported); 1986 } 1987 updateCbrsDataState(boolean state)1988 void updateCbrsDataState(boolean state) { 1989 Log.d(TAG, "setCbrsDataSwitchState() state:" + ((state) ? "on" : "off")); 1990 if (mTelephonyManager != null) { 1991 mQueuedWork.execute(new Runnable() { 1992 public void run() { 1993 mTelephonyManager.setOpportunisticNetworkState(state); 1994 mHandler.post(() -> mCbrsDataSwitch.setChecked(getCbrsDataState())); 1995 } 1996 }); 1997 } 1998 } 1999 getCbrsDataState()2000 boolean getCbrsDataState() { 2001 boolean state = false; 2002 if (mTelephonyManager != null) { 2003 state = mTelephonyManager.isOpportunisticNetworkEnabled(); 2004 } 2005 Log.d(TAG, "getCbrsDataState() state:" + ((state) ? "on" : "off")); 2006 return state; 2007 } 2008 2009 OnCheckedChangeListener mCbrsDataSwitchChangeListener = new OnCheckedChangeListener() { 2010 @Override 2011 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 2012 updateCbrsDataState(isChecked); 2013 } 2014 }; 2015 showDsdsChangeDialog()2016 private void showDsdsChangeDialog() { 2017 final AlertDialog confirmDialog = new Builder(RadioInfo.this) 2018 .setTitle(R.string.dsds_dialog_title) 2019 .setMessage(R.string.dsds_dialog_message) 2020 .setPositiveButton(R.string.dsds_dialog_confirm, mOnDsdsDialogConfirmedListener) 2021 .setNegativeButton(R.string.dsds_dialog_cancel, mOnDsdsDialogConfirmedListener) 2022 .create(); 2023 confirmDialog.show(); 2024 } 2025 isDsdsSupported()2026 private static boolean isDsdsSupported() { 2027 return (TelephonyManager.getDefault().isMultiSimSupported() 2028 == TelephonyManager.MULTISIM_ALLOWED); 2029 } 2030 isDsdsEnabled()2031 private static boolean isDsdsEnabled() { 2032 return TelephonyManager.getDefault().getPhoneCount() > 1; 2033 } 2034 performDsdsSwitch()2035 private void performDsdsSwitch() { 2036 mTelephonyManager.switchMultiSimConfig(mDsdsSwitch.isChecked() ? 2 : 1); 2037 } 2038 2039 /** 2040 * @return {@code True} if the device is only supported dsds mode. 2041 */ dsdsModeOnly()2042 private boolean dsdsModeOnly() { 2043 String dsdsMode = SystemProperties.get(DSDS_MODE_PROPERTY); 2044 return !TextUtils.isEmpty(dsdsMode) && Integer.parseInt(dsdsMode) == ALWAYS_ON_DSDS_MODE; 2045 } 2046 2047 DialogInterface.OnClickListener mOnDsdsDialogConfirmedListener = 2048 new DialogInterface.OnClickListener() { 2049 @Override 2050 public void onClick(DialogInterface dialog, int which) { 2051 if (which == DialogInterface.BUTTON_POSITIVE) { 2052 mDsdsSwitch.toggle(); 2053 performDsdsSwitch(); 2054 } 2055 } 2056 }; 2057 2058 OnCheckedChangeListener mRemovableEsimChangeListener = new OnCheckedChangeListener() { 2059 @Override 2060 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 2061 setRemovableEsimAsDefaultEuicc(isChecked); 2062 } 2063 }; 2064 setRemovableEsimAsDefaultEuicc(boolean isChecked)2065 private void setRemovableEsimAsDefaultEuicc(boolean isChecked) { 2066 Log.d(TAG, "setRemovableEsimAsDefaultEuicc isChecked: " + isChecked); 2067 mTelephonyManager.setRemovableEsimAsDefaultEuicc(isChecked); 2068 // TODO(b/232528117): Instead of sending intent, add new APIs in platform, 2069 // LPA can directly use the API. 2070 ComponentInfo componentInfo = EuiccConnector.findBestComponent(getPackageManager()); 2071 if (componentInfo == null) { 2072 Log.d(TAG, "setRemovableEsimAsDefaultEuicc: unable to find suitable component info"); 2073 return; 2074 } 2075 final Intent intent = new Intent(ACTION_REMOVABLE_ESIM_AS_DEFAULT); 2076 intent.setPackage(componentInfo.packageName); 2077 intent.putExtra("isDefault", isChecked); 2078 sendBroadcast(intent); 2079 } 2080 isImsSupportedOnDevice(Context context)2081 private boolean isImsSupportedOnDevice(Context context) { 2082 return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS); 2083 } 2084 updateServiceEnabledByPlatform()2085 private void updateServiceEnabledByPlatform() { 2086 int subId = mPhone.getSubId(); 2087 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 2088 log("updateServiceEnabledByPlatform subscription ID is invalid"); 2089 return; 2090 } 2091 2092 ImsMmTelManager imsMmTelManager = mImsManager.getImsMmTelManager(subId); 2093 try { 2094 imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 2095 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getMainExecutor(), (result) -> { 2096 updateVolteProvisionedSwitch(result); 2097 }); 2098 imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, 2099 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, getMainExecutor(), (result) -> { 2100 updateVtProvisionedSwitch(result); 2101 }); 2102 imsMmTelManager.isSupported(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, 2103 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, getMainExecutor(), (result) -> { 2104 updateWfcProvisionedSwitch(result); 2105 }); 2106 } catch (ImsException e) { 2107 e.printStackTrace(); 2108 } 2109 } 2110 getPhone(int subId)2111 private Phone getPhone(int subId) { 2112 log("getPhone subId = " + subId); 2113 Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId)); 2114 if (phone == null) { 2115 log("return the default phone"); 2116 return PhoneFactory.getDefaultPhone(); 2117 } 2118 2119 return phone; 2120 } 2121 } 2122