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