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