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 mTelephonyManager.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 initialize()231 public void initialize() { 232 requestForUpdateEid(); 233 234 if (mSubscriptionInfo == null) { 235 return; 236 } 237 mTelephonyManager = 238 mTelephonyManager.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()); 239 mTelephonyCallback = new SimStatusDialogTelephonyCallback(); 240 updateLatestAreaInfo(); 241 updateSubscriptionStatus(); 242 } 243 updateSubscriptionStatus()244 private void updateSubscriptionStatus() { 245 updateNetworkProvider(); 246 247 // getServiceState() may return null when the subscription is inactive 248 // or when there was an error communicating with the phone process. 249 final ServiceState serviceState = mTelephonyManager.getServiceState(); 250 final SignalStrength signalStrength = mTelephonyManager.getSignalStrength(); 251 252 updatePhoneNumber(); 253 updateServiceState(serviceState); 254 updateSignalStrength(signalStrength); 255 updateNetworkType(); 256 updateRoamingStatus(serviceState); 257 updateIccidNumber(); 258 updateImsRegistrationState(); 259 } 260 261 /** 262 * Deinitialization works 263 */ deinitialize()264 public void deinitialize() { 265 if (mShowLatestAreaInfo) { 266 if (mCellBroadcastServiceConnection != null 267 && mCellBroadcastServiceConnection.getService() != null) { 268 mContext.unbindService(mCellBroadcastServiceConnection); 269 } 270 mCellBroadcastServiceConnection = null; 271 } 272 } 273 274 /** 275 * OnResume lifecycle event, resume listening for phone state or subscription changes. 276 */ 277 @OnLifecycleEvent(Event.ON_RESUME) onResume()278 public void onResume() { 279 if (mSubscriptionInfo == null) { 280 return; 281 } 282 mTelephonyManager = mTelephonyManager.createForSubscriptionId( 283 mSubscriptionInfo.getSubscriptionId()); 284 mTelephonyManager.registerTelephonyCallback(mContext.getMainExecutor(), mTelephonyCallback); 285 mSubscriptionManager.addOnSubscriptionsChangedListener( 286 mContext.getMainExecutor(), mOnSubscriptionsChangedListener); 287 registerImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId()); 288 289 if (mShowLatestAreaInfo) { 290 updateAreaInfoText(); 291 mContext.registerReceiver(mAreaInfoReceiver, 292 new IntentFilter(CellBroadcastIntents.ACTION_AREA_INFO_UPDATED)); 293 } 294 295 mIsRegisteredListener = true; 296 } 297 298 /** 299 * onPause lifecycle event, no longer listen for phone state or subscription changes. 300 */ 301 @OnLifecycleEvent(Event.ON_PAUSE) onPause()302 public void onPause() { 303 if (mSubscriptionInfo == null) { 304 if (mIsRegisteredListener) { 305 mSubscriptionManager.removeOnSubscriptionsChangedListener( 306 mOnSubscriptionsChangedListener); 307 mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback); 308 if (mShowLatestAreaInfo) { 309 mContext.unregisterReceiver(mAreaInfoReceiver); 310 } 311 mIsRegisteredListener = false; 312 } 313 return; 314 } 315 316 unregisterImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId()); 317 mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 318 mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback); 319 320 if (mShowLatestAreaInfo) { 321 mContext.unregisterReceiver(mAreaInfoReceiver); 322 } 323 } 324 updateNetworkProvider()325 private void updateNetworkProvider() { 326 final CharSequence carrierName = 327 mSubscriptionInfo != null ? mSubscriptionInfo.getCarrierName() : null; 328 mDialog.setText(NETWORK_PROVIDER_VALUE_ID, carrierName); 329 } 330 331 @VisibleForTesting updatePhoneNumber()332 protected void updatePhoneNumber() { 333 // If formattedNumber is null or empty, it'll display as "Unknown". 334 mDialog.setText(PHONE_NUMBER_VALUE_ID, 335 DeviceInfoUtils.getBidiFormattedPhoneNumber(mContext, mSubscriptionInfo)); 336 } 337 updateDataState(int state)338 private void updateDataState(int state) { 339 String networkStateValue; 340 341 switch (state) { 342 case TelephonyManager.DATA_CONNECTED: 343 networkStateValue = mRes.getString(R.string.radioInfo_data_connected); 344 break; 345 case TelephonyManager.DATA_SUSPENDED: 346 networkStateValue = mRes.getString(R.string.radioInfo_data_suspended); 347 break; 348 case TelephonyManager.DATA_CONNECTING: 349 networkStateValue = mRes.getString(R.string.radioInfo_data_connecting); 350 break; 351 case TelephonyManager.DATA_DISCONNECTED: 352 networkStateValue = mRes.getString(R.string.radioInfo_data_disconnected); 353 break; 354 default: 355 networkStateValue = mRes.getString(R.string.radioInfo_unknown); 356 break; 357 } 358 359 mDialog.setText(CELLULAR_NETWORK_STATE, networkStateValue); 360 } 361 362 /** 363 * Update area info text retrieved from 364 * {@link CellBroadcastService#getCellBroadcastAreaInfo(int)} 365 */ updateAreaInfoText()366 private void updateAreaInfoText() { 367 if (!mShowLatestAreaInfo || mCellBroadcastServiceConnection == null) return; 368 ICellBroadcastService cellBroadcastService = 369 ICellBroadcastService.Stub.asInterface( 370 mCellBroadcastServiceConnection.getService()); 371 if (cellBroadcastService == null) return; 372 try { 373 mDialog.setText(OPERATOR_INFO_VALUE_ID, 374 cellBroadcastService.getCellBroadcastAreaInfo(mSlotIndex)); 375 376 } catch (RemoteException e) { 377 Log.d(TAG, "Can't get area info. e=" + e); 378 } 379 } 380 381 /** 382 * Bind cell broadcast service. 383 */ bindCellBroadcastService()384 private void bindCellBroadcastService() { 385 mCellBroadcastServiceConnection = new CellBroadcastServiceConnection(); 386 Intent intent = new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE); 387 String cbsPackage = getCellBroadcastServicePackage(); 388 if (TextUtils.isEmpty(cbsPackage)) return; 389 intent.setPackage(cbsPackage); 390 if (mCellBroadcastServiceConnection != null 391 && mCellBroadcastServiceConnection.getService() == null) { 392 if (!mContext.bindService(intent, mCellBroadcastServiceConnection, 393 Context.BIND_AUTO_CREATE)) { 394 Log.e(TAG, "Unable to bind to service"); 395 } 396 } else { 397 Log.d(TAG, "skipping bindService because connection already exists"); 398 } 399 } 400 401 /** Returns the package name of the cell broadcast service, or null if there is none. */ getCellBroadcastServicePackage()402 private String getCellBroadcastServicePackage() { 403 PackageManager packageManager = mContext.getPackageManager(); 404 List<ResolveInfo> cbsPackages = packageManager.queryIntentServices( 405 new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE), 406 PackageManager.MATCH_SYSTEM_ONLY); 407 if (cbsPackages.size() != 1) { 408 Log.e(TAG, "getCellBroadcastServicePackageName: found " + cbsPackages.size() 409 + " CBS packages"); 410 } 411 for (ResolveInfo info : cbsPackages) { 412 if (info.serviceInfo == null) continue; 413 String packageName = info.serviceInfo.packageName; 414 if (!TextUtils.isEmpty(packageName)) { 415 if (packageManager.checkPermission( 416 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 417 packageName) == PackageManager.PERMISSION_GRANTED) { 418 Log.d(TAG, "getCellBroadcastServicePackageName: " + packageName); 419 return packageName; 420 } else { 421 Log.e(TAG, "getCellBroadcastServicePackageName: " + packageName 422 + " does not have READ_PRIVILEGED_PHONE_STATE permission"); 423 } 424 } else { 425 Log.e(TAG, "getCellBroadcastServicePackageName: found a CBS package but " 426 + "packageName is null/empty"); 427 } 428 } 429 Log.e(TAG, "getCellBroadcastServicePackageName: package name not found"); 430 return null; 431 } 432 updateLatestAreaInfo()433 private void updateLatestAreaInfo() { 434 mShowLatestAreaInfo = Resources.getSystem().getBoolean( 435 com.android.internal.R.bool.config_showAreaUpdateInfoSettings) 436 && mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA; 437 438 if (mShowLatestAreaInfo) { 439 // Bind cell broadcast service to get the area info. The info will be updated once 440 // the service is connected. 441 bindCellBroadcastService(); 442 } else { 443 mDialog.removeSettingFromScreen(OPERATOR_INFO_LABEL_ID); 444 mDialog.removeSettingFromScreen(OPERATOR_INFO_VALUE_ID); 445 } 446 } 447 updateServiceState(ServiceState serviceState)448 private void updateServiceState(ServiceState serviceState) { 449 final int state = Utils.getCombinedServiceState(serviceState); 450 if (!Utils.isInService(serviceState)) { 451 resetSignalStrength(); 452 } else if (!Utils.isInService(mPreviousServiceState)) { 453 // If ServiceState changed from out of service -> in service, update signal strength. 454 updateSignalStrength(mTelephonyManager.getSignalStrength()); 455 } 456 457 String serviceStateValue; 458 459 switch (state) { 460 case ServiceState.STATE_IN_SERVICE: 461 serviceStateValue = mRes.getString(R.string.radioInfo_service_in); 462 break; 463 case ServiceState.STATE_OUT_OF_SERVICE: 464 case ServiceState.STATE_EMERGENCY_ONLY: 465 // Set summary string of service state to radioInfo_service_out when 466 // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY 467 serviceStateValue = mRes.getString(R.string.radioInfo_service_out); 468 break; 469 case ServiceState.STATE_POWER_OFF: 470 serviceStateValue = mRes.getString(R.string.radioInfo_service_off); 471 break; 472 default: 473 serviceStateValue = mRes.getString(R.string.radioInfo_unknown); 474 break; 475 } 476 477 mDialog.setText(SERVICE_STATE_VALUE_ID, serviceStateValue); 478 } 479 updateSignalStrength(SignalStrength signalStrength)480 private void updateSignalStrength(SignalStrength signalStrength) { 481 if (signalStrength == null) { 482 return; 483 } 484 // by default we show the signal strength 485 boolean showSignalStrength = true; 486 if (mSubscriptionInfo != null) { 487 final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); 488 final PersistableBundle carrierConfig = 489 mCarrierConfigManager.getConfigForSubId(subscriptionId); 490 if (carrierConfig != null) { 491 showSignalStrength = carrierConfig.getBoolean( 492 CarrierConfigManager.KEY_SHOW_SIGNAL_STRENGTH_IN_SIM_STATUS_BOOL); 493 } 494 } 495 if (!showSignalStrength) { 496 mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_LABEL_ID); 497 mDialog.removeSettingFromScreen(SIGNAL_STRENGTH_VALUE_ID); 498 return; 499 } 500 501 ServiceState serviceState = mTelephonyManager.getServiceState(); 502 if (!Utils.isInService(serviceState)) { 503 return; 504 } 505 506 int signalDbm = getDbm(signalStrength); 507 int signalAsu = getAsuLevel(signalStrength); 508 509 if (signalDbm == -1) { 510 signalDbm = 0; 511 } 512 513 if (signalAsu == -1) { 514 signalAsu = 0; 515 } 516 517 mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, mRes.getString(R.string.sim_signal_strength, 518 signalDbm, signalAsu)); 519 } 520 resetSignalStrength()521 private void resetSignalStrength() { 522 mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, "0"); 523 } 524 updateNetworkType()525 private void updateNetworkType() { 526 // TODO: all of this should be based on TelephonyDisplayInfo instead of just the 5G logic 527 if (mSubscriptionInfo == null) { 528 final String unknownNetworkType = 529 getNetworkTypeName(TelephonyManager.NETWORK_TYPE_UNKNOWN); 530 mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, unknownNetworkType); 531 mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, unknownNetworkType); 532 return; 533 } 534 535 // Whether EDGE, UMTS, etc... 536 String dataNetworkTypeName = null; 537 String voiceNetworkTypeName = null; 538 final int subId = mSubscriptionInfo.getSubscriptionId(); 539 final int actualDataNetworkType = mTelephonyManager.getDataNetworkType(); 540 final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType(); 541 final int overrideNetworkType = mTelephonyDisplayInfo == null 542 ? TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE 543 : mTelephonyDisplayInfo.getOverrideNetworkType(); 544 545 if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) { 546 dataNetworkTypeName = getNetworkTypeName(actualDataNetworkType); 547 } 548 if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) { 549 voiceNetworkTypeName = getNetworkTypeName(actualVoiceNetworkType); 550 } 551 552 final boolean isOverrideNwTypeNrAdvancedOrNsa = 553 overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED 554 || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA; 555 if (actualDataNetworkType == TelephonyManager.NETWORK_TYPE_LTE 556 && isOverrideNwTypeNrAdvancedOrNsa) { 557 dataNetworkTypeName = "NR NSA"; 558 } 559 560 boolean show4GForLTE = false; 561 final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); 562 if (carrierConfig != null) { 563 show4GForLTE = carrierConfig.getBoolean( 564 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL); 565 } 566 567 if (show4GForLTE) { 568 if ("LTE".equals(dataNetworkTypeName)) { 569 dataNetworkTypeName = "4G"; 570 } 571 if ("LTE".equals(voiceNetworkTypeName)) { 572 voiceNetworkTypeName = "4G"; 573 } 574 } 575 576 mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, voiceNetworkTypeName); 577 mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, dataNetworkTypeName); 578 } 579 updateRoamingStatus(ServiceState serviceState)580 private void updateRoamingStatus(ServiceState serviceState) { 581 // If the serviceState is null, we assume that roaming is disabled. 582 if (serviceState == null) { 583 mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_unknown)); 584 } else if (serviceState.getRoaming()) { 585 mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_in)); 586 } else { 587 mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_not)); 588 } 589 } 590 updateIccidNumber()591 private void updateIccidNumber() { 592 // do not show iccid by default 593 boolean showIccId = false; 594 if (mSubscriptionInfo != null) { 595 final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); 596 final PersistableBundle carrierConfig = 597 mCarrierConfigManager.getConfigForSubId(subscriptionId); 598 if (carrierConfig != null) { 599 showIccId = carrierConfig.getBoolean( 600 CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL); 601 } 602 } 603 if (!showIccId) { 604 mDialog.removeSettingFromScreen(ICCID_INFO_LABEL_ID); 605 mDialog.removeSettingFromScreen(ICCID_INFO_VALUE_ID); 606 } else { 607 mDialog.setText(ICCID_INFO_VALUE_ID, mTelephonyManager.getSimSerialNumber()); 608 } 609 } 610 611 @VisibleForTesting requestForUpdateEid()612 protected void requestForUpdateEid() { 613 ThreadUtils.postOnBackgroundThread(() -> { 614 final AtomicReference<String> eid = getEid(mSlotIndex); 615 ThreadUtils.postOnMainThread(() -> updateEid(eid)); 616 }); 617 } 618 619 @VisibleForTesting getEid(int slotIndex)620 protected AtomicReference<String> getEid(int slotIndex) { 621 boolean shouldHaveEid = false; 622 String eid = null; 623 if (mTelephonyManager.getActiveModemCount() > MAX_PHONE_COUNT_SINGLE_SIM) { 624 // Get EID per-SIM in multi-SIM mode 625 final Map<Integer, Integer> mapping = mTelephonyManager 626 .getLogicalToPhysicalSlotMapping(); 627 final int pSlotId = mapping.getOrDefault(slotIndex, 628 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 629 630 if (pSlotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) { 631 final List<UiccCardInfo> infos = mTelephonyManager.getUiccCardsInfo(); 632 633 for (UiccCardInfo info : infos) { 634 if (info.getSlotIndex() == pSlotId) { 635 if (info.isEuicc()) { 636 shouldHaveEid = true; 637 eid = info.getEid(); 638 if (TextUtils.isEmpty(eid)) { 639 eid = mEuiccManager.createForCardId(info.getCardId()).getEid(); 640 } 641 } 642 break; 643 } 644 } 645 } 646 } else if (mEuiccManager.isEnabled()) { 647 // Get EID of default eSIM in single-SIM mode 648 shouldHaveEid = true; 649 eid = mEuiccManager.getEid(); 650 } 651 if ((!shouldHaveEid) && (eid == null)) { 652 return null; 653 } 654 return new AtomicReference<String>(eid); 655 } 656 657 @VisibleForTesting updateEid(AtomicReference<String> eid)658 protected void updateEid(AtomicReference<String> eid) { 659 if (eid == null) { 660 mDialog.removeSettingFromScreen(EID_INFO_LABEL_ID); 661 mDialog.removeSettingFromScreen(EID_INFO_VALUE_ID); 662 } else if (eid.get() != null) { 663 mDialog.setText(EID_INFO_VALUE_ID, eid.get()); 664 } 665 } 666 isImsRegistrationStateShowUp()667 private boolean isImsRegistrationStateShowUp() { 668 if (mSubscriptionInfo == null) { 669 return false; 670 } 671 final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); 672 final PersistableBundle carrierConfig = 673 mCarrierConfigManager.getConfigForSubId(subscriptionId); 674 return carrierConfig == null ? false : 675 carrierConfig.getBoolean( 676 CarrierConfigManager.KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL); 677 } 678 updateImsRegistrationState()679 private void updateImsRegistrationState() { 680 if (isImsRegistrationStateShowUp()) { 681 return; 682 } 683 mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_LABEL_ID); 684 mDialog.removeSettingFromScreen(IMS_REGISTRATION_STATE_VALUE_ID); 685 } 686 687 private ImsMmTelManager.RegistrationCallback mImsRegStateCallback = 688 new ImsMmTelManager.RegistrationCallback() { 689 @Override 690 public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) { 691 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( 692 R.string.ims_reg_status_registered)); 693 } 694 @Override 695 public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) { 696 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( 697 R.string.ims_reg_status_not_registered)); 698 } 699 @Override 700 public void onUnregistered(@Nullable ImsReasonInfo info) { 701 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( 702 R.string.ims_reg_status_not_registered)); 703 } 704 @Override 705 public void onTechnologyChangeFailed( 706 @AccessNetworkConstants.TransportType int imsTransportType, 707 @Nullable ImsReasonInfo info) { 708 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString( 709 R.string.ims_reg_status_not_registered)); 710 } 711 }; 712 registerImsRegistrationCallback(int subId)713 private void registerImsRegistrationCallback(int subId) { 714 if (!isImsRegistrationStateShowUp()) { 715 return; 716 } 717 try { 718 final ImsMmTelManager imsMmTelMgr = ImsMmTelManager.createForSubscriptionId(subId); 719 imsMmTelMgr.registerImsRegistrationCallback(mDialog.getContext().getMainExecutor(), 720 mImsRegStateCallback); 721 } catch (ImsException exception) { 722 Log.w(TAG, "fail to register IMS status for subId=" + subId, exception); 723 } 724 } 725 unregisterImsRegistrationCallback(int subId)726 private void unregisterImsRegistrationCallback(int subId) { 727 if (!isImsRegistrationStateShowUp()) { 728 return; 729 } 730 final ImsMmTelManager imsMmTelMgr = ImsMmTelManager.createForSubscriptionId(subId); 731 imsMmTelMgr.unregisterImsRegistrationCallback(mImsRegStateCallback); 732 } 733 getPhoneSubscriptionInfo(int slotId)734 private SubscriptionInfo getPhoneSubscriptionInfo(int slotId) { 735 return SubscriptionManager.from(mContext).getActiveSubscriptionInfoForSimSlotIndex(slotId); 736 } 737 getDbm(SignalStrength signalStrength)738 private int getDbm(SignalStrength signalStrength) { 739 List<CellSignalStrength> cellSignalStrengthList = signalStrength.getCellSignalStrengths(); 740 int dbm = -1; 741 if (cellSignalStrengthList == null) { 742 return dbm; 743 } 744 745 for (CellSignalStrength cell : cellSignalStrengthList) { 746 if (cell.getDbm() != -1) { 747 dbm = cell.getDbm(); 748 break; 749 } 750 } 751 752 return dbm; 753 } 754 getAsuLevel(SignalStrength signalStrength)755 private int getAsuLevel(SignalStrength signalStrength) { 756 List<CellSignalStrength> cellSignalStrengthList = signalStrength.getCellSignalStrengths(); 757 int asu = -1; 758 if (cellSignalStrengthList == null) { 759 return asu; 760 } 761 762 for (CellSignalStrength cell : cellSignalStrengthList) { 763 if (cell.getAsuLevel() != -1) { 764 asu = cell.getAsuLevel(); 765 break; 766 } 767 } 768 769 return asu; 770 } 771 772 @VisibleForTesting 773 class SimStatusDialogTelephonyCallback extends TelephonyCallback implements 774 TelephonyCallback.DataConnectionStateListener, 775 TelephonyCallback.SignalStrengthsListener, 776 TelephonyCallback.ServiceStateListener, 777 TelephonyCallback.DisplayInfoListener { 778 @Override onDataConnectionStateChanged(int state, int networkType)779 public void onDataConnectionStateChanged(int state, int networkType) { 780 updateDataState(state); 781 updateNetworkType(); 782 } 783 784 @Override onSignalStrengthsChanged(SignalStrength signalStrength)785 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 786 updateSignalStrength(signalStrength); 787 } 788 789 @Override onServiceStateChanged(ServiceState serviceState)790 public void onServiceStateChanged(ServiceState serviceState) { 791 updateNetworkProvider(); 792 updateServiceState(serviceState); 793 updateRoamingStatus(serviceState); 794 mPreviousServiceState = serviceState; 795 } 796 797 @Override onDisplayInfoChanged(@onNull TelephonyDisplayInfo displayInfo)798 public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo displayInfo) { 799 mTelephonyDisplayInfo = displayInfo; 800 updateNetworkType(); 801 } 802 } 803 804 @VisibleForTesting getNetworkTypeName(@nnotation.NetworkType int type)805 static String getNetworkTypeName(@Annotation.NetworkType int type) { 806 switch (type) { 807 case TelephonyManager.NETWORK_TYPE_GPRS: 808 return "GPRS"; 809 case TelephonyManager.NETWORK_TYPE_EDGE: 810 return "EDGE"; 811 case TelephonyManager.NETWORK_TYPE_UMTS: 812 return "UMTS"; 813 case TelephonyManager.NETWORK_TYPE_HSDPA: 814 return "HSDPA"; 815 case TelephonyManager.NETWORK_TYPE_HSUPA: 816 return "HSUPA"; 817 case TelephonyManager.NETWORK_TYPE_HSPA: 818 return "HSPA"; 819 case TelephonyManager.NETWORK_TYPE_CDMA: 820 return "CDMA"; 821 case TelephonyManager.NETWORK_TYPE_EVDO_0: 822 return "CDMA - EvDo rev. 0"; 823 case TelephonyManager.NETWORK_TYPE_EVDO_A: 824 return "CDMA - EvDo rev. A"; 825 case TelephonyManager.NETWORK_TYPE_EVDO_B: 826 return "CDMA - EvDo rev. B"; 827 case TelephonyManager.NETWORK_TYPE_1xRTT: 828 return "CDMA - 1xRTT"; 829 case TelephonyManager.NETWORK_TYPE_LTE: 830 return "LTE"; 831 case TelephonyManager.NETWORK_TYPE_EHRPD: 832 return "CDMA - eHRPD"; 833 case TelephonyManager.NETWORK_TYPE_IDEN: 834 return "iDEN"; 835 case TelephonyManager.NETWORK_TYPE_HSPAP: 836 return "HSPA+"; 837 case TelephonyManager.NETWORK_TYPE_GSM: 838 return "GSM"; 839 case TelephonyManager.NETWORK_TYPE_TD_SCDMA: 840 return "TD_SCDMA"; 841 case TelephonyManager.NETWORK_TYPE_IWLAN: 842 return "IWLAN"; 843 // case TelephonyManager.NETWORK_TYPE_LTE_CA: 844 // return "LTE_CA"; 845 case TelephonyManager.NETWORK_TYPE_NR: 846 return "NR SA"; 847 default: 848 return "UNKNOWN"; 849 } 850 } 851 } 852