1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.deviceinfo.simstatus; 18 19 import android.annotation.Nullable; 20 import android.content.BroadcastReceiver; 21 import android.content.ComponentName; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.ServiceConnection; 26 import android.content.pm.PackageManager; 27 import android.content.pm.ResolveInfo; 28 import android.content.res.Resources; 29 import android.os.IBinder; 30 import android.os.PersistableBundle; 31 import android.os.RemoteException; 32 import android.telephony.AccessNetworkConstants; 33 import android.telephony.Annotation; 34 import android.telephony.CarrierConfigManager; 35 import android.telephony.CellBroadcastIntents; 36 import android.telephony.CellBroadcastService; 37 import android.telephony.CellSignalStrength; 38 import android.telephony.ICellBroadcastService; 39 import android.telephony.PhoneStateListener; 40 import android.telephony.ServiceState; 41 import android.telephony.SignalStrength; 42 import android.telephony.SubscriptionInfo; 43 import android.telephony.SubscriptionManager; 44 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 45 import android.telephony.TelephonyDisplayInfo; 46 import android.telephony.TelephonyManager; 47 import android.telephony.UiccCardInfo; 48 import android.telephony.euicc.EuiccManager; 49 import android.telephony.ims.ImsException; 50 import android.telephony.ims.ImsMmTelManager; 51 import android.telephony.ims.ImsReasonInfo; 52 import android.text.TextUtils; 53 import android.util.Log; 54 55 import androidx.annotation.NonNull; 56 import androidx.annotation.VisibleForTesting; 57 58 import com.android.settings.R; 59 import com.android.settingslib.DeviceInfoUtils; 60 import com.android.settingslib.Utils; 61 import com.android.settingslib.core.lifecycle.Lifecycle; 62 import com.android.settingslib.core.lifecycle.LifecycleObserver; 63 import com.android.settingslib.core.lifecycle.events.OnPause; 64 import com.android.settingslib.core.lifecycle.events.OnResume; 65 import com.android.settingslib.utils.ThreadUtils; 66 67 import java.util.List; 68 import java.util.Map; 69 import java.util.concurrent.atomic.AtomicReference; 70 71 public class SimStatusDialogController implements LifecycleObserver, OnResume, OnPause { 72 73 private final static String TAG = "SimStatusDialogCtrl"; 74 75 @VisibleForTesting 76 final static int NETWORK_PROVIDER_VALUE_ID = R.id.operator_name_value; 77 @VisibleForTesting 78 final static int PHONE_NUMBER_VALUE_ID = R.id.number_value; 79 @VisibleForTesting 80 final static int CELLULAR_NETWORK_STATE = R.id.data_state_value; 81 @VisibleForTesting 82 final static int OPERATOR_INFO_LABEL_ID = R.id.latest_area_info_label; 83 @VisibleForTesting 84 final static int OPERATOR_INFO_VALUE_ID = R.id.latest_area_info_value; 85 @VisibleForTesting 86 final static int SERVICE_STATE_VALUE_ID = R.id.service_state_value; 87 @VisibleForTesting 88 final static int SIGNAL_STRENGTH_LABEL_ID = R.id.signal_strength_label; 89 @VisibleForTesting 90 final static int SIGNAL_STRENGTH_VALUE_ID = R.id.signal_strength_value; 91 @VisibleForTesting 92 final static int CELL_VOICE_NETWORK_TYPE_VALUE_ID = R.id.voice_network_type_value; 93 @VisibleForTesting 94 final static int CELL_DATA_NETWORK_TYPE_VALUE_ID = R.id.data_network_type_value; 95 @VisibleForTesting 96 final static int ROAMING_INFO_VALUE_ID = R.id.roaming_state_value; 97 @VisibleForTesting 98 final static int ICCID_INFO_LABEL_ID = R.id.icc_id_label; 99 @VisibleForTesting 100 final static int ICCID_INFO_VALUE_ID = R.id.icc_id_value; 101 @VisibleForTesting 102 final static int EID_INFO_LABEL_ID = R.id.esim_id_label; 103 @VisibleForTesting 104 final static int EID_INFO_VALUE_ID = R.id.esim_id_value; 105 @VisibleForTesting 106 final static int IMS_REGISTRATION_STATE_LABEL_ID = R.id.ims_reg_state_label; 107 @VisibleForTesting 108 final static int IMS_REGISTRATION_STATE_VALUE_ID = R.id.ims_reg_state_value; 109 110 @VisibleForTesting 111 static final int MAX_PHONE_COUNT_SINGLE_SIM = 1; 112 113 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener = 114 new OnSubscriptionsChangedListener() { 115 @Override 116 public void onSubscriptionsChanged() { 117 final int prevSubId = (mSubscriptionInfo != null) 118 ? mSubscriptionInfo.getSubscriptionId() 119 : SubscriptionManager.INVALID_SUBSCRIPTION_ID; 120 121 mSubscriptionInfo = getPhoneSubscriptionInfo(mSlotIndex); 122 123 final int nextSubId = (mSubscriptionInfo != null) 124 ? mSubscriptionInfo.getSubscriptionId() 125 : SubscriptionManager.INVALID_SUBSCRIPTION_ID; 126 127 if (prevSubId != nextSubId) { 128 if (SubscriptionManager.isValidSubscriptionId(prevSubId)) { 129 unregisterImsRegistrationCallback(prevSubId); 130 } 131 if (SubscriptionManager.isValidSubscriptionId(nextSubId)) { 132 mTelephonyManager = 133 mTelephonyManager.createForSubscriptionId(nextSubId); 134 registerImsRegistrationCallback(nextSubId); 135 } 136 } 137 updateSubscriptionStatus(); 138 } 139 }; 140 141 private SubscriptionInfo mSubscriptionInfo; 142 private TelephonyDisplayInfo mTelephonyDisplayInfo; 143 144 private final int mSlotIndex; 145 private TelephonyManager mTelephonyManager; 146 147 private final SimStatusDialogFragment mDialog; 148 private final SubscriptionManager mSubscriptionManager; 149 private final CarrierConfigManager mCarrierConfigManager; 150 private final EuiccManager mEuiccManager; 151 private final Resources mRes; 152 private final Context mContext; 153 154 private boolean mShowLatestAreaInfo; 155 156 private final BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() { 157 @Override 158 public void onReceive(Context context, Intent intent) { 159 if (CellBroadcastIntents.ACTION_AREA_INFO_UPDATED.equals(intent.getAction()) 160 && intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0) 161 == mSlotIndex) { 162 updateAreaInfoText(); 163 } 164 } 165 }; 166 167 private PhoneStateListener mPhoneStateListener; 168 169 private CellBroadcastServiceConnection mCellBroadcastServiceConnection; 170 171 private class CellBroadcastServiceConnection implements ServiceConnection { 172 private IBinder mService; 173 174 @Nullable getService()175 public IBinder getService() { 176 return mService; 177 } 178 179 @Override onServiceConnected(ComponentName className, IBinder service)180 public void onServiceConnected(ComponentName className, IBinder service) { 181 Log.d(TAG, "connected to CellBroadcastService"); 182 this.mService = service; 183 updateAreaInfoText(); 184 } 185 186 @Override onServiceDisconnected(ComponentName className)187 public void onServiceDisconnected(ComponentName className) { 188 this.mService = null; 189 Log.d(TAG, "mICellBroadcastService has disconnected unexpectedly"); 190 } 191 192 @Override onBindingDied(ComponentName name)193 public void onBindingDied(ComponentName name) { 194 this.mService = null; 195 Log.d(TAG, "Binding died"); 196 } 197 198 @Override onNullBinding(ComponentName name)199 public void onNullBinding(ComponentName name) { 200 this.mService = null; 201 Log.d(TAG, "Null binding"); 202 } 203 } 204 SimStatusDialogController(@onNull SimStatusDialogFragment dialog, Lifecycle lifecycle, int slotId)205 public SimStatusDialogController(@NonNull SimStatusDialogFragment dialog, Lifecycle lifecycle, 206 int slotId) { 207 mDialog = dialog; 208 mContext = dialog.getContext(); 209 mSlotIndex = slotId; 210 mSubscriptionInfo = getPhoneSubscriptionInfo(slotId); 211 212 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 213 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 214 mEuiccManager = mContext.getSystemService(EuiccManager.class); 215 mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); 216 217 mRes = mContext.getResources(); 218 219 if (lifecycle != null) { 220 lifecycle.addObserver(this); 221 } 222 } 223 initialize()224 public void initialize() { 225 requestForUpdateEid(); 226 227 if (mSubscriptionInfo == null) { 228 return; 229 } 230 231 mPhoneStateListener = getPhoneStateListener(); 232 updateLatestAreaInfo(); 233 updateSubscriptionStatus(); 234 } 235 updateSubscriptionStatus()236 private void updateSubscriptionStatus() { 237 updateNetworkProvider(); 238 239 final ServiceState serviceState = mTelephonyManager.getServiceState(); 240 final SignalStrength signalStrength = mTelephonyManager.getSignalStrength(); 241 242 updatePhoneNumber(); 243 updateServiceState(serviceState); 244 updateSignalStrength(signalStrength); 245 updateNetworkType(); 246 updateRoamingStatus(serviceState); 247 updateIccidNumber(); 248 updateImsRegistrationState(); 249 } 250 251 /** 252 * Deinitialization works 253 */ deinitialize()254 public void deinitialize() { 255 if (mShowLatestAreaInfo) { 256 if (mCellBroadcastServiceConnection != null 257 && mCellBroadcastServiceConnection.getService() != null) { 258 mContext.unbindService(mCellBroadcastServiceConnection); 259 } 260 mCellBroadcastServiceConnection = null; 261 } 262 } 263 264 @Override onResume()265 public void onResume() { 266 if (mSubscriptionInfo == null) { 267 return; 268 } 269 mTelephonyManager = mTelephonyManager.createForSubscriptionId( 270 mSubscriptionInfo.getSubscriptionId()); 271 mTelephonyManager.listen(mPhoneStateListener, 272 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE 273 | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS 274 | PhoneStateListener.LISTEN_SERVICE_STATE 275 | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED); 276 mSubscriptionManager.addOnSubscriptionsChangedListener( 277 mContext.getMainExecutor(), mOnSubscriptionsChangedListener); 278 registerImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId()); 279 280 if (mShowLatestAreaInfo) { 281 updateAreaInfoText(); 282 mContext.registerReceiver(mAreaInfoReceiver, 283 new IntentFilter(CellBroadcastIntents.ACTION_AREA_INFO_UPDATED)); 284 } 285 } 286 287 @Override onPause()288 public void onPause() { 289 if (mSubscriptionInfo == null) { 290 return; 291 } 292 293 unregisterImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId()); 294 mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 295 mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); 296 297 if (mShowLatestAreaInfo) { 298 mContext.unregisterReceiver(mAreaInfoReceiver); 299 } 300 } 301 updateNetworkProvider()302 private void updateNetworkProvider() { 303 final CharSequence carrierName = 304 mSubscriptionInfo != null ? mSubscriptionInfo.getCarrierName() : null; 305 mDialog.setText(NETWORK_PROVIDER_VALUE_ID, carrierName); 306 } 307 updatePhoneNumber()308 private void updatePhoneNumber() { 309 // If formattedNumber is null or empty, it'll display as "Unknown". 310 mDialog.setText(PHONE_NUMBER_VALUE_ID, 311 DeviceInfoUtils.getBidiFormattedPhoneNumber(mContext, mSubscriptionInfo)); 312 } 313 updateDataState(int state)314 private void updateDataState(int state) { 315 String networkStateValue; 316 317 switch (state) { 318 case TelephonyManager.DATA_CONNECTED: 319 networkStateValue = mRes.getString(R.string.radioInfo_data_connected); 320 break; 321 case TelephonyManager.DATA_SUSPENDED: 322 networkStateValue = mRes.getString(R.string.radioInfo_data_suspended); 323 break; 324 case TelephonyManager.DATA_CONNECTING: 325 networkStateValue = mRes.getString(R.string.radioInfo_data_connecting); 326 break; 327 case TelephonyManager.DATA_DISCONNECTED: 328 networkStateValue = mRes.getString(R.string.radioInfo_data_disconnected); 329 break; 330 default: 331 networkStateValue = mRes.getString(R.string.radioInfo_unknown); 332 break; 333 } 334 335 mDialog.setText(CELLULAR_NETWORK_STATE, networkStateValue); 336 } 337 338 /** 339 * Update area info text retrieved from 340 * {@link CellBroadcastService#getCellBroadcastAreaInfo(int)} 341 */ updateAreaInfoText()342 private void updateAreaInfoText() { 343 if (!mShowLatestAreaInfo || mCellBroadcastServiceConnection == null) return; 344 ICellBroadcastService cellBroadcastService = 345 ICellBroadcastService.Stub.asInterface( 346 mCellBroadcastServiceConnection.getService()); 347 if (cellBroadcastService == null) return; 348 try { 349 mDialog.setText(OPERATOR_INFO_VALUE_ID, 350 cellBroadcastService.getCellBroadcastAreaInfo(mSlotIndex)); 351 352 } catch (RemoteException e) { 353 Log.d(TAG, "Can't get area info. e=" + e); 354 } 355 } 356 357 /** 358 * Bind cell broadcast service. 359 */ bindCellBroadcastService()360 private void bindCellBroadcastService() { 361 mCellBroadcastServiceConnection = new CellBroadcastServiceConnection(); 362 Intent intent = new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE); 363 String cbsPackage = getCellBroadcastServicePackage(); 364 if (TextUtils.isEmpty(cbsPackage)) return; 365 intent.setPackage(cbsPackage); 366 if (mCellBroadcastServiceConnection != null 367 && mCellBroadcastServiceConnection.getService() == null) { 368 if (!mContext.bindService(intent, mCellBroadcastServiceConnection, 369 Context.BIND_AUTO_CREATE)) { 370 Log.e(TAG, "Unable to bind to service"); 371 } 372 } else { 373 Log.d(TAG, "skipping bindService because connection already exists"); 374 } 375 } 376 377 /** Returns the package name of the cell broadcast service, or null if there is none. */ getCellBroadcastServicePackage()378 private String getCellBroadcastServicePackage() { 379 PackageManager packageManager = mContext.getPackageManager(); 380 List<ResolveInfo> cbsPackages = packageManager.queryIntentServices( 381 new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE), 382 PackageManager.MATCH_SYSTEM_ONLY); 383 if (cbsPackages.size() != 1) { 384 Log.e(TAG, "getCellBroadcastServicePackageName: found " + cbsPackages.size() 385 + " CBS packages"); 386 } 387 for (ResolveInfo info : cbsPackages) { 388 if (info.serviceInfo == null) continue; 389 String packageName = info.serviceInfo.packageName; 390 if (!TextUtils.isEmpty(packageName)) { 391 if (packageManager.checkPermission( 392 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 393 packageName) == PackageManager.PERMISSION_GRANTED) { 394 Log.d(TAG, "getCellBroadcastServicePackageName: " + packageName); 395 return packageName; 396 } else { 397 Log.e(TAG, "getCellBroadcastServicePackageName: " + packageName 398 + " does not have READ_PRIVILEGED_PHONE_STATE permission"); 399 } 400 } else { 401 Log.e(TAG, "getCellBroadcastServicePackageName: found a CBS package but " 402 + "packageName is null/empty"); 403 } 404 } 405 Log.e(TAG, "getCellBroadcastServicePackageName: package name not found"); 406 return null; 407 } 408 updateLatestAreaInfo()409 private void updateLatestAreaInfo() { 410 mShowLatestAreaInfo = Resources.getSystem().getBoolean( 411 com.android.internal.R.bool.config_showAreaUpdateInfoSettings) 412 && mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA; 413 414 if (mShowLatestAreaInfo) { 415 // Bind cell broadcast service to get the area info. The info will be updated once 416 // the service is connected. 417 bindCellBroadcastService(); 418 } else { 419 mDialog.removeSettingFromScreen(OPERATOR_INFO_LABEL_ID); 420 mDialog.removeSettingFromScreen(OPERATOR_INFO_VALUE_ID); 421 } 422 } 423 updateServiceState(ServiceState serviceState)424 private void updateServiceState(ServiceState serviceState) { 425 final int state = Utils.getCombinedServiceState(serviceState); 426 if (!Utils.isInService(serviceState)) { 427 resetSignalStrength(); 428 } 429 430 String serviceStateValue; 431 432 switch (state) { 433 case ServiceState.STATE_IN_SERVICE: 434 serviceStateValue = mRes.getString(R.string.radioInfo_service_in); 435 break; 436 case ServiceState.STATE_OUT_OF_SERVICE: 437 case ServiceState.STATE_EMERGENCY_ONLY: 438 // Set summary string of service state to radioInfo_service_out when 439 // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY 440 serviceStateValue = mRes.getString(R.string.radioInfo_service_out); 441 break; 442 case ServiceState.STATE_POWER_OFF: 443 serviceStateValue = mRes.getString(R.string.radioInfo_service_off); 444 break; 445 default: 446 serviceStateValue = mRes.getString(R.string.radioInfo_unknown); 447 break; 448 } 449 450 mDialog.setText(SERVICE_STATE_VALUE_ID, serviceStateValue); 451 } 452 updateSignalStrength(SignalStrength signalStrength)453 private void updateSignalStrength(SignalStrength signalStrength) { 454 if (signalStrength == null) { 455 return; 456 } 457 // by default we show the signal strength 458 boolean showSignalStrength = true; 459 if (mSubscriptionInfo != null) { 460 final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); 461 final PersistableBundle carrierConfig = 462 mCarrierConfigManager.getConfigForSubId(subscriptionId); 463 if (carrierConfig != null) { 464 showSignalStrength = carrierConfig.getBoolean( 465 CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL); 466 } 467 } 468 if (!showSignalStrength) { 469 mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_LABEL_ID); 470 mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_VALUE_ID); 471 return; 472 } 473 474 ServiceState serviceState = mTelephonyManager.getServiceState(); 475 if (serviceState == null || !Utils.isInService(serviceState)) { 476 return; 477 } 478 479 int signalDbm = getDbm(signalStrength); 480 int signalAsu = getAsuLevel(signalStrength); 481 482 if (signalDbm == -1) { 483 signalDbm = 0; 484 } 485 486 if (signalAsu == -1) { 487 signalAsu = 0; 488 } 489 490 mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, mRes.getString(R.string.sim_signal_strength, 491 signalDbm, signalAsu)); 492 } 493 resetSignalStrength()494 private void resetSignalStrength() { 495 mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, "0"); 496 } 497 updateNetworkType()498 private void updateNetworkType() { 499 // TODO: all of this should be based on TelephonyDisplayInfo instead of just the 5G logic 500 if (mSubscriptionInfo == null) { 501 final String unknownNetworkType = 502 getNetworkTypeName(TelephonyManager.NETWORK_TYPE_UNKNOWN); 503 mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, unknownNetworkType); 504 mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, unknownNetworkType); 505 return; 506 } 507 508 // Whether EDGE, UMTS, etc... 509 String dataNetworkTypeName = null; 510 String voiceNetworkTypeName = null; 511 final int subId = mSubscriptionInfo.getSubscriptionId(); 512 final int actualDataNetworkType = mTelephonyManager.getDataNetworkType(); 513 final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType(); 514 final int overrideNetworkType = mTelephonyDisplayInfo == null 515 ? TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE 516 : mTelephonyDisplayInfo.getOverrideNetworkType(); 517 518 if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) { 519 dataNetworkTypeName = getNetworkTypeName(actualDataNetworkType); 520 } 521 if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) { 522 voiceNetworkTypeName = getNetworkTypeName(actualVoiceNetworkType); 523 } 524 525 if (overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE 526 || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA) { 527 dataNetworkTypeName = "NR NSA"; 528 } 529 530 boolean show4GForLTE = false; 531 final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); 532 if (carrierConfig != null) { 533 show4GForLTE = carrierConfig.getBoolean( 534 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL); 535 } 536 537 if (show4GForLTE) { 538 if ("LTE".equals(dataNetworkTypeName)) { 539 dataNetworkTypeName = "4G"; 540 } 541 if ("LTE".equals(voiceNetworkTypeName)) { 542 voiceNetworkTypeName = "4G"; 543 } 544 } 545 546 mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, voiceNetworkTypeName); 547 mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, dataNetworkTypeName); 548 } 549 updateRoamingStatus(ServiceState serviceState)550 private void updateRoamingStatus(ServiceState serviceState) { 551 if (serviceState.getRoaming()) { 552 mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_in)); 553 } else { 554 mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_not)); 555 } 556 } 557 updateIccidNumber()558 private void updateIccidNumber() { 559 // do not show iccid by default 560 boolean showIccId = false; 561 if (mSubscriptionInfo != null) { 562 final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); 563 final PersistableBundle carrierConfig = 564 mCarrierConfigManager.getConfigForSubId(subscriptionId); 565 if (carrierConfig != null) { 566 showIccId = carrierConfig.getBoolean( 567 CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL); 568 } 569 } 570 if (!showIccId) { 571 mDialog.removeSettingFromScreen(ICCID_INFO_LABEL_ID); 572 mDialog.removeSettingFromScreen(ICCID_INFO_VALUE_ID); 573 } else { 574 mDialog.setText(ICCID_INFO_VALUE_ID, mTelephonyManager.getSimSerialNumber()); 575 } 576 } 577 578 @VisibleForTesting requestForUpdateEid()579 void requestForUpdateEid() { 580 ThreadUtils.postOnBackgroundThread(() -> { 581 final AtomicReference<String> eid = getEid(mSlotIndex); 582 ThreadUtils.postOnMainThread(() -> updateEid(eid)); 583 }); 584 } 585 586 @VisibleForTesting getEid(int slotIndex)587 AtomicReference<String> getEid(int slotIndex) { 588 boolean shouldHaveEid = false; 589 String eid = null; 590 if (mTelephonyManager.getActiveModemCount() > MAX_PHONE_COUNT_SINGLE_SIM) { 591 // Get EID per-SIM in multi-SIM mode 592 final Map<Integer, Integer> mapping = mTelephonyManager 593 .getLogicalToPhysicalSlotMapping(); 594 final int pSlotId = mapping.getOrDefault(slotIndex, 595 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 596 597 if (pSlotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) { 598 final List<UiccCardInfo> infos = mTelephonyManager.getUiccCardsInfo(); 599 600 for (UiccCardInfo info : infos) { 601 if (info.getSlotIndex() == pSlotId) { 602 if (info.isEuicc()) { 603 shouldHaveEid = true; 604 eid = info.getEid(); 605 if (TextUtils.isEmpty(eid)) { 606 eid = mEuiccManager.createForCardId(info.getCardId()).getEid(); 607 } 608 } 609 break; 610 } 611 } 612 } 613 } else if (mEuiccManager.isEnabled()) { 614 // Get EID of default eSIM in single-SIM mode 615 shouldHaveEid = true; 616 eid = mEuiccManager.getEid(); 617 } 618 if ((!shouldHaveEid) && (eid == null)) { 619 return null; 620 } 621 return new AtomicReference<String>(eid); 622 } 623 624 @VisibleForTesting updateEid(AtomicReference<String> eid)625 void updateEid(AtomicReference<String> eid) { 626 if (eid == null) { 627 mDialog.removeSettingFromScreen(EID_INFO_LABEL_ID); 628 mDialog.removeSettingFromScreen(EID_INFO_VALUE_ID); 629 } else if (eid.get() != null) { 630 mDialog.setText(EID_INFO_VALUE_ID, eid.get()); 631 } 632 } 633 isImsRegistrationStateShowUp()634 private boolean isImsRegistrationStateShowUp() { 635 if (mSubscriptionInfo == null) { 636 return false; 637 } 638 final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); 639 final PersistableBundle carrierConfig = 640 mCarrierConfigManager.getConfigForSubId(subscriptionId); 641 return carrierConfig == null ? false : 642 carrierConfig.getBoolean( 643 CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL); 644 } 645 updateImsRegistrationState()646 private void updateImsRegistrationState() { 647 if (isImsRegistrationStateShowUp()) { 648 return; 649 } 650 mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_LABEL_ID); 651 mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID); 652 } 653 654 private ImsMmTelManager.RegistrationCallback mImsRegStateCallback = 655 new ImsMmTelManager.RegistrationCallback() { 656 @Override 657 public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) { 658 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( 659 R.string.ims_reg_status_registered)); 660 } 661 @Override 662 public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) { 663 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( 664 R.string.ims_reg_status_not_registered)); 665 } 666 @Override 667 public void onUnregistered(@Nullable ImsReasonInfo info) { 668 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( 669 R.string.ims_reg_status_not_registered)); 670 } 671 @Override 672 public void onTechnologyChangeFailed( 673 @AccessNetworkConstants.TransportType int imsTransportType, 674 @Nullable ImsReasonInfo info) { 675 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( 676 R.string.ims_reg_status_not_registered)); 677 } 678 }; 679 registerImsRegistrationCallback(int subId)680 private void registerImsRegistrationCallback(int subId) { 681 if (!isImsRegistrationStateShowUp()) { 682 return; 683 } 684 try { 685 final ImsMmTelManager imsMmTelMgr = ImsMmTelManager.createForSubscriptionId(subId); 686 imsMmTelMgr.registerImsRegistrationCallback(mDialog.getContext().getMainExecutor(), 687 mImsRegStateCallback); 688 } catch (ImsException exception) { 689 Log.w(TAG, "fail to register IMS status for subId=" + subId, exception); 690 } 691 } 692 unregisterImsRegistrationCallback(int subId)693 private void unregisterImsRegistrationCallback(int subId) { 694 if (!isImsRegistrationStateShowUp()) { 695 return; 696 } 697 final ImsMmTelManager imsMmTelMgr = ImsMmTelManager.createForSubscriptionId(subId); 698 imsMmTelMgr.unregisterImsRegistrationCallback(mImsRegStateCallback); 699 } 700 getPhoneSubscriptionInfo(int slotId)701 private SubscriptionInfo getPhoneSubscriptionInfo(int slotId) { 702 return SubscriptionManager.from(mContext).getActiveSubscriptionInfoForSimSlotIndex(slotId); 703 } 704 getDbm(SignalStrength signalStrength)705 private int getDbm(SignalStrength signalStrength) { 706 List<CellSignalStrength> cellSignalStrengthList = signalStrength.getCellSignalStrengths(); 707 int dbm = -1; 708 if (cellSignalStrengthList == null) { 709 return dbm; 710 } 711 712 for (CellSignalStrength cell : cellSignalStrengthList) { 713 if (cell.getDbm() != -1) { 714 dbm = cell.getDbm(); 715 break; 716 } 717 } 718 719 return dbm; 720 } 721 getAsuLevel(SignalStrength signalStrength)722 private int getAsuLevel(SignalStrength signalStrength) { 723 List<CellSignalStrength> cellSignalStrengthList = signalStrength.getCellSignalStrengths(); 724 int asu = -1; 725 if (cellSignalStrengthList == null) { 726 return asu; 727 } 728 729 for (CellSignalStrength cell : cellSignalStrengthList) { 730 if (cell.getAsuLevel() != -1) { 731 asu = cell.getAsuLevel(); 732 break; 733 } 734 } 735 736 return asu; 737 } 738 739 @VisibleForTesting getPhoneStateListener()740 PhoneStateListener getPhoneStateListener() { 741 return new PhoneStateListener() { 742 @Override 743 public void onDataConnectionStateChanged(int state) { 744 updateDataState(state); 745 updateNetworkType(); 746 } 747 748 @Override 749 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 750 updateSignalStrength(signalStrength); 751 } 752 753 @Override 754 public void onServiceStateChanged(ServiceState serviceState) { 755 updateNetworkProvider(); 756 updateServiceState(serviceState); 757 updateRoamingStatus(serviceState); 758 } 759 760 @Override 761 public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo displayInfo) { 762 mTelephonyDisplayInfo = displayInfo; 763 updateNetworkType(); 764 } 765 }; 766 } 767 768 @VisibleForTesting 769 static String getNetworkTypeName(@Annotation.NetworkType int type) { 770 switch (type) { 771 case TelephonyManager.NETWORK_TYPE_GPRS: 772 return "GPRS"; 773 case TelephonyManager.NETWORK_TYPE_EDGE: 774 return "EDGE"; 775 case TelephonyManager.NETWORK_TYPE_UMTS: 776 return "UMTS"; 777 case TelephonyManager.NETWORK_TYPE_HSDPA: 778 return "HSDPA"; 779 case TelephonyManager.NETWORK_TYPE_HSUPA: 780 return "HSUPA"; 781 case TelephonyManager.NETWORK_TYPE_HSPA: 782 return "HSPA"; 783 case TelephonyManager.NETWORK_TYPE_CDMA: 784 return "CDMA"; 785 case TelephonyManager.NETWORK_TYPE_EVDO_0: 786 return "CDMA - EvDo rev. 0"; 787 case TelephonyManager.NETWORK_TYPE_EVDO_A: 788 return "CDMA - EvDo rev. A"; 789 case TelephonyManager.NETWORK_TYPE_EVDO_B: 790 return "CDMA - EvDo rev. B"; 791 case TelephonyManager.NETWORK_TYPE_1xRTT: 792 return "CDMA - 1xRTT"; 793 case TelephonyManager.NETWORK_TYPE_LTE: 794 return "LTE"; 795 case TelephonyManager.NETWORK_TYPE_EHRPD: 796 return "CDMA - eHRPD"; 797 case TelephonyManager.NETWORK_TYPE_IDEN: 798 return "iDEN"; 799 case TelephonyManager.NETWORK_TYPE_HSPAP: 800 return "HSPA+"; 801 case TelephonyManager.NETWORK_TYPE_GSM: 802 return "GSM"; 803 case TelephonyManager.NETWORK_TYPE_TD_SCDMA: 804 return "TD_SCDMA"; 805 case TelephonyManager.NETWORK_TYPE_IWLAN: 806 return "IWLAN"; 807 // case TelephonyManager.NETWORK_TYPE_LTE_CA: 808 // return "LTE_CA"; 809 case TelephonyManager.NETWORK_TYPE_NR: 810 return "NR SA"; 811 default: 812 return "UNKNOWN"; 813 } 814 } 815 } 816