1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.deviceinfo.simstatus; 18 19 import android.content.BroadcastReceiver; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.ServiceConnection; 25 import android.content.pm.PackageManager; 26 import android.content.pm.ResolveInfo; 27 import android.content.res.Resources; 28 import android.os.IBinder; 29 import android.os.PersistableBundle; 30 import android.os.RemoteException; 31 import android.telephony.Annotation; 32 import android.telephony.CarrierConfigManager; 33 import android.telephony.CellBroadcastIntents; 34 import android.telephony.CellBroadcastService; 35 import android.telephony.ICellBroadcastService; 36 import android.telephony.ServiceState; 37 import android.telephony.SubscriptionInfo; 38 import android.telephony.SubscriptionManager; 39 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 40 import android.telephony.TelephonyCallback; 41 import android.telephony.TelephonyDisplayInfo; 42 import android.telephony.TelephonyManager; 43 import android.telephony.euicc.EuiccManager; 44 import android.text.TextUtils; 45 import android.util.Log; 46 47 import androidx.annotation.NonNull; 48 import androidx.annotation.Nullable; 49 import androidx.annotation.VisibleForTesting; 50 import androidx.lifecycle.DefaultLifecycleObserver; 51 import androidx.lifecycle.LifecycleOwner; 52 53 import com.android.settings.R; 54 import com.android.settings.network.SubscriptionUtil; 55 import com.android.settingslib.Utils; 56 import com.android.settingslib.core.lifecycle.Lifecycle; 57 58 import kotlin.Unit; 59 60 import java.util.List; 61 62 /** 63 * Controller for Sim Status information within the About Phone Settings page. 64 */ 65 public class SimStatusDialogController implements DefaultLifecycleObserver { 66 67 private final static String TAG = "SimStatusDialogCtrl"; 68 69 @VisibleForTesting 70 final static int NETWORK_PROVIDER_VALUE_ID = R.id.operator_name_value; 71 @VisibleForTesting 72 final static int PHONE_NUMBER_VALUE_ID = R.id.number_value; 73 @VisibleForTesting 74 final static int CELLULAR_NETWORK_STATE = R.id.data_state_value; 75 @VisibleForTesting 76 final static int OPERATOR_INFO_LABEL_ID = R.id.latest_area_info_label; 77 @VisibleForTesting 78 final static int OPERATOR_INFO_VALUE_ID = R.id.latest_area_info_value; 79 @VisibleForTesting 80 final static int SERVICE_STATE_VALUE_ID = R.id.service_state_value; 81 @VisibleForTesting 82 final static int SIGNAL_STRENGTH_LABEL_ID = R.id.signal_strength_label; 83 @VisibleForTesting 84 final static int SIGNAL_STRENGTH_VALUE_ID = R.id.signal_strength_value; 85 @VisibleForTesting 86 final static int CELL_VOICE_NETWORK_TYPE_VALUE_ID = R.id.voice_network_type_value; 87 @VisibleForTesting 88 final static int CELL_DATA_NETWORK_TYPE_VALUE_ID = R.id.data_network_type_value; 89 @VisibleForTesting 90 final static int ROAMING_INFO_VALUE_ID = R.id.roaming_state_value; 91 @VisibleForTesting 92 final static int ICCID_INFO_LABEL_ID = R.id.icc_id_label; 93 @VisibleForTesting 94 final static int ICCID_INFO_VALUE_ID = R.id.icc_id_value; 95 @VisibleForTesting 96 final static int IMS_REGISTRATION_STATE_LABEL_ID = R.id.ims_reg_state_label; 97 @VisibleForTesting 98 final static int IMS_REGISTRATION_STATE_VALUE_ID = R.id.ims_reg_state_value; 99 100 @VisibleForTesting 101 static final int MAX_PHONE_COUNT_SINGLE_SIM = 1; 102 103 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener = 104 new OnSubscriptionsChangedListener() { 105 @Override 106 public void onSubscriptionsChanged() { 107 mSubscriptionInfo = getPhoneSubscriptionInfo(mSlotIndex); 108 updateSubscriptionStatus(); 109 } 110 }; 111 112 private SubscriptionInfo mSubscriptionInfo; 113 private TelephonyDisplayInfo mTelephonyDisplayInfo; 114 115 private final int mSlotIndex; 116 private TelephonyManager mTelephonyManager; 117 118 private final SimStatusDialogFragment mDialog; 119 private final SubscriptionManager mSubscriptionManager; 120 private final CarrierConfigManager mCarrierConfigManager; 121 private final EuiccManager mEuiccManager; 122 private final Resources mRes; 123 private final Context mContext; 124 125 private boolean mShowLatestAreaInfo; 126 private boolean mIsRegisteredListener = false; 127 128 private final BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() { 129 @Override 130 public void onReceive(Context context, Intent intent) { 131 if (CellBroadcastIntents.ACTION_AREA_INFO_UPDATED.equals(intent.getAction()) 132 && intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, 0) 133 == mSlotIndex) { 134 updateAreaInfoText(); 135 } 136 } 137 }; 138 139 @VisibleForTesting 140 protected SimStatusDialogTelephonyCallback mTelephonyCallback; 141 142 private CellBroadcastServiceConnection mCellBroadcastServiceConnection; 143 144 private class CellBroadcastServiceConnection implements ServiceConnection { 145 private IBinder mService; 146 147 @Nullable getService()148 public IBinder getService() { 149 return mService; 150 } 151 152 @Override onServiceConnected(ComponentName className, IBinder service)153 public void onServiceConnected(ComponentName className, IBinder service) { 154 Log.d(TAG, "connected to CellBroadcastService"); 155 this.mService = service; 156 updateAreaInfoText(); 157 } 158 159 @Override onServiceDisconnected(ComponentName className)160 public void onServiceDisconnected(ComponentName className) { 161 this.mService = null; 162 Log.d(TAG, "mICellBroadcastService has disconnected unexpectedly"); 163 } 164 165 @Override onBindingDied(ComponentName name)166 public void onBindingDied(ComponentName name) { 167 this.mService = null; 168 Log.d(TAG, "Binding died"); 169 } 170 171 @Override onNullBinding(ComponentName name)172 public void onNullBinding(ComponentName name) { 173 this.mService = null; 174 Log.d(TAG, "Null binding"); 175 } 176 } 177 SimStatusDialogController(@onNull SimStatusDialogFragment dialog, Lifecycle lifecycle, int slotId)178 public SimStatusDialogController(@NonNull SimStatusDialogFragment dialog, Lifecycle lifecycle, 179 int slotId) { 180 mDialog = dialog; 181 mContext = dialog.getContext(); 182 mSlotIndex = slotId; 183 mSubscriptionInfo = getPhoneSubscriptionInfo(slotId); 184 185 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 186 mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); 187 mEuiccManager = mContext.getSystemService(EuiccManager.class); 188 mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); 189 190 mRes = mContext.getResources(); 191 192 if (lifecycle != null) { 193 lifecycle.addObserver(this); 194 } 195 } 196 197 @VisibleForTesting getTelephonyManager()198 public TelephonyManager getTelephonyManager() { 199 return mTelephonyManager; 200 } 201 initialize()202 public void initialize() { 203 if (mSubscriptionInfo == null) { 204 return; 205 } 206 mTelephonyManager = 207 getTelephonyManager().createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()); 208 mTelephonyCallback = new SimStatusDialogTelephonyCallback(); 209 updateLatestAreaInfo(); 210 updateSubscriptionStatus(); 211 } 212 updateSubscriptionStatus()213 private void updateSubscriptionStatus() { 214 updateNetworkProvider(); 215 216 // getServiceState() may return null when the subscription is inactive 217 // or when there was an error communicating with the phone process. 218 final ServiceState serviceState = getTelephonyManager().getServiceState(); 219 220 updatePhoneNumber(); 221 updateServiceState(serviceState); 222 updateNetworkType(); 223 updateRoamingStatus(serviceState); 224 updateIccidNumber(); 225 } 226 227 /** 228 * Deinitialization works 229 */ deinitialize()230 public void deinitialize() { 231 if (mShowLatestAreaInfo) { 232 if (mCellBroadcastServiceConnection != null 233 && mCellBroadcastServiceConnection.getService() != null) { 234 mContext.unbindService(mCellBroadcastServiceConnection); 235 } 236 mCellBroadcastServiceConnection = null; 237 } 238 } 239 240 /** 241 * OnResume lifecycle event, resume listening for phone state or subscription changes. 242 */ 243 @Override onResume(@onNull LifecycleOwner owner)244 public void onResume(@NonNull LifecycleOwner owner) { 245 if (mSubscriptionInfo == null) { 246 return; 247 } 248 mTelephonyManager = getTelephonyManager().createForSubscriptionId( 249 mSubscriptionInfo.getSubscriptionId()); 250 getTelephonyManager() 251 .registerTelephonyCallback(mContext.getMainExecutor(), mTelephonyCallback); 252 mSubscriptionManager.addOnSubscriptionsChangedListener( 253 mContext.getMainExecutor(), mOnSubscriptionsChangedListener); 254 collectSimStatusDialogInfo(owner); 255 256 if (mShowLatestAreaInfo) { 257 updateAreaInfoText(); 258 mContext.registerReceiver(mAreaInfoReceiver, 259 new IntentFilter(CellBroadcastIntents.ACTION_AREA_INFO_UPDATED), 260 Context.RECEIVER_EXPORTED/*UNAUDITED*/); 261 } 262 263 mIsRegisteredListener = true; 264 } 265 266 /** 267 * onPause lifecycle event, no longer listen for phone state or subscription changes. 268 */ 269 @Override onPause(@onNull LifecycleOwner owner)270 public void onPause(@NonNull LifecycleOwner owner) { 271 if (mSubscriptionInfo == null) { 272 if (mIsRegisteredListener) { 273 mSubscriptionManager.removeOnSubscriptionsChangedListener( 274 mOnSubscriptionsChangedListener); 275 getTelephonyManager().unregisterTelephonyCallback(mTelephonyCallback); 276 if (mShowLatestAreaInfo) { 277 mContext.unregisterReceiver(mAreaInfoReceiver); 278 } 279 mIsRegisteredListener = false; 280 } 281 return; 282 } 283 284 mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 285 getTelephonyManager().unregisterTelephonyCallback(mTelephonyCallback); 286 287 if (mShowLatestAreaInfo) { 288 mContext.unregisterReceiver(mAreaInfoReceiver); 289 } 290 } 291 updateNetworkProvider()292 private void updateNetworkProvider() { 293 final CharSequence carrierName = 294 mSubscriptionInfo != null ? mSubscriptionInfo.getCarrierName() : null; 295 mDialog.setText(NETWORK_PROVIDER_VALUE_ID, carrierName); 296 } 297 298 @VisibleForTesting updatePhoneNumber()299 public void updatePhoneNumber() { 300 // If formattedNumber is null or empty, it'll display as "Unknown". 301 mDialog.setText(PHONE_NUMBER_VALUE_ID, 302 SubscriptionUtil.getBidiFormattedPhoneNumber(mContext, mSubscriptionInfo)); 303 } 304 updateDataState(int state)305 private void updateDataState(int state) { 306 String networkStateValue; 307 308 switch (state) { 309 case TelephonyManager.DATA_CONNECTED: 310 networkStateValue = mRes.getString(R.string.radioInfo_data_connected); 311 break; 312 case TelephonyManager.DATA_SUSPENDED: 313 networkStateValue = mRes.getString(R.string.radioInfo_data_suspended); 314 break; 315 case TelephonyManager.DATA_CONNECTING: 316 networkStateValue = mRes.getString(R.string.radioInfo_data_connecting); 317 break; 318 case TelephonyManager.DATA_DISCONNECTED: 319 networkStateValue = mRes.getString(R.string.radioInfo_data_disconnected); 320 break; 321 default: 322 networkStateValue = mRes.getString(R.string.radioInfo_unknown); 323 break; 324 } 325 326 mDialog.setText(CELLULAR_NETWORK_STATE, networkStateValue); 327 } 328 329 /** 330 * Update area info text retrieved from 331 * {@link CellBroadcastService#getCellBroadcastAreaInfo(int)} 332 */ updateAreaInfoText()333 private void updateAreaInfoText() { 334 if (!mShowLatestAreaInfo || mCellBroadcastServiceConnection == null) return; 335 ICellBroadcastService cellBroadcastService = 336 ICellBroadcastService.Stub.asInterface( 337 mCellBroadcastServiceConnection.getService()); 338 if (cellBroadcastService == null) return; 339 try { 340 mDialog.setText(OPERATOR_INFO_VALUE_ID, 341 cellBroadcastService.getCellBroadcastAreaInfo(mSlotIndex)); 342 343 } catch (RemoteException e) { 344 Log.d(TAG, "Can't get area info. e=" + e); 345 } 346 } 347 348 /** 349 * Bind cell broadcast service. 350 */ bindCellBroadcastService()351 private void bindCellBroadcastService() { 352 mCellBroadcastServiceConnection = new CellBroadcastServiceConnection(); 353 Intent intent = new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE); 354 String cbsPackage = getCellBroadcastServicePackage(); 355 if (TextUtils.isEmpty(cbsPackage)) return; 356 intent.setPackage(cbsPackage); 357 if (mCellBroadcastServiceConnection != null 358 && mCellBroadcastServiceConnection.getService() == null) { 359 if (!mContext.bindService(intent, mCellBroadcastServiceConnection, 360 Context.BIND_AUTO_CREATE)) { 361 Log.e(TAG, "Unable to bind to service"); 362 } 363 } else { 364 Log.d(TAG, "skipping bindService because connection already exists"); 365 } 366 } 367 368 /** Returns the package name of the cell broadcast service, or null if there is none. */ getCellBroadcastServicePackage()369 private String getCellBroadcastServicePackage() { 370 PackageManager packageManager = mContext.getPackageManager(); 371 List<ResolveInfo> cbsPackages = packageManager.queryIntentServices( 372 new Intent(CellBroadcastService.CELL_BROADCAST_SERVICE_INTERFACE), 373 PackageManager.MATCH_SYSTEM_ONLY); 374 if (cbsPackages.size() != 1) { 375 Log.e(TAG, "getCellBroadcastServicePackageName: found " + cbsPackages.size() 376 + " CBS packages"); 377 } 378 for (ResolveInfo info : cbsPackages) { 379 if (info.serviceInfo == null) continue; 380 String packageName = info.serviceInfo.packageName; 381 if (!TextUtils.isEmpty(packageName)) { 382 if (packageManager.checkPermission( 383 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 384 packageName) == PackageManager.PERMISSION_GRANTED) { 385 Log.d(TAG, "getCellBroadcastServicePackageName: " + packageName); 386 return packageName; 387 } else { 388 Log.e(TAG, "getCellBroadcastServicePackageName: " + packageName 389 + " does not have READ_PRIVILEGED_PHONE_STATE permission"); 390 } 391 } else { 392 Log.e(TAG, "getCellBroadcastServicePackageName: found a CBS package but " 393 + "packageName is null/empty"); 394 } 395 } 396 Log.e(TAG, "getCellBroadcastServicePackageName: package name not found"); 397 return null; 398 } 399 updateLatestAreaInfo()400 private void updateLatestAreaInfo() { 401 mShowLatestAreaInfo = Resources.getSystem().getBoolean( 402 com.android.internal.R.bool.config_showAreaUpdateInfoSettings) 403 && getTelephonyManager().getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA; 404 405 if (mShowLatestAreaInfo) { 406 // Bind cell broadcast service to get the area info. The info will be updated once 407 // the service is connected. 408 bindCellBroadcastService(); 409 } else { 410 mDialog.removeSettingFromScreen(OPERATOR_INFO_LABEL_ID); 411 mDialog.removeSettingFromScreen(OPERATOR_INFO_VALUE_ID); 412 } 413 } 414 updateServiceState(ServiceState serviceState)415 private void updateServiceState(ServiceState serviceState) { 416 final int state = Utils.getCombinedServiceState(serviceState); 417 418 String serviceStateValue; 419 420 switch (state) { 421 case ServiceState.STATE_IN_SERVICE: 422 serviceStateValue = mRes.getString(R.string.radioInfo_service_in); 423 break; 424 case ServiceState.STATE_OUT_OF_SERVICE: 425 case ServiceState.STATE_EMERGENCY_ONLY: 426 // Set summary string of service state to radioInfo_service_out when 427 // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY 428 serviceStateValue = mRes.getString(R.string.radioInfo_service_out); 429 break; 430 case ServiceState.STATE_POWER_OFF: 431 serviceStateValue = mRes.getString(R.string.radioInfo_service_off); 432 break; 433 default: 434 serviceStateValue = mRes.getString(R.string.radioInfo_unknown); 435 break; 436 } 437 438 mDialog.setText(SERVICE_STATE_VALUE_ID, serviceStateValue); 439 } 440 updateSignalStrength(@ullable String signalStrength)441 private void updateSignalStrength(@Nullable String signalStrength) { 442 boolean isVisible = signalStrength != null; 443 mDialog.setSettingVisibility(SIGNAL_STRENGTH_LABEL_ID, isVisible); 444 mDialog.setSettingVisibility(SIGNAL_STRENGTH_VALUE_ID, isVisible); 445 mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, signalStrength); 446 } 447 updateNetworkType()448 private void updateNetworkType() { 449 // TODO: all of this should be based on TelephonyDisplayInfo instead of just the 5G logic 450 if (mSubscriptionInfo == null) { 451 final String unknownNetworkType = 452 getNetworkTypeName(TelephonyManager.NETWORK_TYPE_UNKNOWN); 453 mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, unknownNetworkType); 454 mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, unknownNetworkType); 455 return; 456 } 457 458 // Whether EDGE, UMTS, etc... 459 String dataNetworkTypeName = null; 460 String voiceNetworkTypeName = null; 461 final int subId = mSubscriptionInfo.getSubscriptionId(); 462 final int actualDataNetworkType = getTelephonyManager().getDataNetworkType(); 463 final int actualVoiceNetworkType = getTelephonyManager().getVoiceNetworkType(); 464 final int overrideNetworkType = mTelephonyDisplayInfo == null 465 ? TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE 466 : mTelephonyDisplayInfo.getOverrideNetworkType(); 467 468 if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) { 469 dataNetworkTypeName = getNetworkTypeName(actualDataNetworkType); 470 } 471 if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) { 472 voiceNetworkTypeName = getNetworkTypeName(actualVoiceNetworkType); 473 } 474 475 final boolean isOverrideNwTypeNrAdvancedOrNsa = 476 overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED 477 || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA; 478 if (actualDataNetworkType == TelephonyManager.NETWORK_TYPE_LTE 479 && isOverrideNwTypeNrAdvancedOrNsa) { 480 dataNetworkTypeName = "NR NSA"; 481 } 482 483 boolean show4GForLTE = false; 484 final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); 485 if (carrierConfig != null) { 486 show4GForLTE = carrierConfig.getBoolean( 487 CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL); 488 } 489 490 if (show4GForLTE) { 491 if ("LTE".equals(dataNetworkTypeName)) { 492 dataNetworkTypeName = "4G"; 493 } 494 if ("LTE".equals(voiceNetworkTypeName)) { 495 voiceNetworkTypeName = "4G"; 496 } 497 } 498 499 mDialog.setText(CELL_VOICE_NETWORK_TYPE_VALUE_ID, voiceNetworkTypeName); 500 mDialog.setText(CELL_DATA_NETWORK_TYPE_VALUE_ID, dataNetworkTypeName); 501 } 502 updateRoamingStatus(ServiceState serviceState)503 private void updateRoamingStatus(ServiceState serviceState) { 504 // If the serviceState is null, we assume that roaming is disabled. 505 if (serviceState == null) { 506 mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_unknown)); 507 } else if (serviceState.getRoaming()) { 508 mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_in)); 509 } else { 510 mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_not)); 511 } 512 } 513 updateIccidNumber()514 private void updateIccidNumber() { 515 // do not show iccid by default 516 boolean showIccId = false; 517 if (mSubscriptionInfo != null) { 518 final int subscriptionId = mSubscriptionInfo.getSubscriptionId(); 519 final PersistableBundle carrierConfig = 520 mCarrierConfigManager.getConfigForSubId(subscriptionId); 521 if (carrierConfig != null) { 522 showIccId = carrierConfig.getBoolean( 523 CarrierConfigManager.KEY_SHOW_ICCID_IN_SIM_STATUS_BOOL); 524 } 525 } 526 if (!showIccId) { 527 mDialog.removeSettingFromScreen(ICCID_INFO_LABEL_ID); 528 mDialog.removeSettingFromScreen(ICCID_INFO_VALUE_ID); 529 } else { 530 mDialog.setText(ICCID_INFO_VALUE_ID, getTelephonyManager().getSimSerialNumber()); 531 } 532 } 533 updateImsRegistrationState(@ullable Boolean imsRegistered)534 private void updateImsRegistrationState(@Nullable Boolean imsRegistered) { 535 boolean isVisible = imsRegistered != null; 536 mDialog.setSettingVisibility(IMS_REGISTRATION_STATE_LABEL_ID, isVisible); 537 mDialog.setSettingVisibility(IMS_REGISTRATION_STATE_VALUE_ID, isVisible); 538 int stringId = Boolean.TRUE.equals(imsRegistered) 539 ? com.android.settingslib.R.string.ims_reg_status_registered 540 : com.android.settingslib.R.string.ims_reg_status_not_registered; 541 mDialog.setText(IMS_REGISTRATION_STATE_VALUE_ID, mRes.getString(stringId)); 542 } 543 collectSimStatusDialogInfo(@onNull LifecycleOwner owner)544 private void collectSimStatusDialogInfo(@NonNull LifecycleOwner owner) { 545 new SimStatusDialogRepository(mContext).collectSimStatusDialogInfo( 546 owner, mSlotIndex, (simStatusDialogInfo) -> { 547 updateSignalStrength(simStatusDialogInfo.getSignalStrength()); 548 updateImsRegistrationState(simStatusDialogInfo.getImsRegistered()); 549 return Unit.INSTANCE; 550 } 551 ); 552 } 553 getPhoneSubscriptionInfo(int slotId)554 private SubscriptionInfo getPhoneSubscriptionInfo(int slotId) { 555 return SubscriptionManager.from(mContext).getActiveSubscriptionInfoForSimSlotIndex(slotId); 556 } 557 558 @VisibleForTesting 559 class SimStatusDialogTelephonyCallback extends TelephonyCallback implements 560 TelephonyCallback.DataConnectionStateListener, 561 TelephonyCallback.ServiceStateListener, 562 TelephonyCallback.DisplayInfoListener { 563 @Override onDataConnectionStateChanged(int state, int networkType)564 public void onDataConnectionStateChanged(int state, int networkType) { 565 updateDataState(state); 566 updateNetworkType(); 567 } 568 569 @Override onServiceStateChanged(ServiceState serviceState)570 public void onServiceStateChanged(ServiceState serviceState) { 571 updateNetworkProvider(); 572 updateServiceState(serviceState); 573 updateRoamingStatus(serviceState); 574 } 575 576 @Override onDisplayInfoChanged(@onNull TelephonyDisplayInfo displayInfo)577 public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo displayInfo) { 578 mTelephonyDisplayInfo = displayInfo; 579 updateNetworkType(); 580 } 581 } 582 583 @VisibleForTesting getNetworkTypeName(@nnotation.NetworkType int type)584 static String getNetworkTypeName(@Annotation.NetworkType int type) { 585 switch (type) { 586 case TelephonyManager.NETWORK_TYPE_GPRS: 587 return "GPRS"; 588 case TelephonyManager.NETWORK_TYPE_EDGE: 589 return "EDGE"; 590 case TelephonyManager.NETWORK_TYPE_UMTS: 591 return "UMTS"; 592 case TelephonyManager.NETWORK_TYPE_HSDPA: 593 return "HSDPA"; 594 case TelephonyManager.NETWORK_TYPE_HSUPA: 595 return "HSUPA"; 596 case TelephonyManager.NETWORK_TYPE_HSPA: 597 return "HSPA"; 598 case TelephonyManager.NETWORK_TYPE_CDMA: 599 return "CDMA"; 600 case TelephonyManager.NETWORK_TYPE_EVDO_0: 601 return "CDMA - EvDo rev. 0"; 602 case TelephonyManager.NETWORK_TYPE_EVDO_A: 603 return "CDMA - EvDo rev. A"; 604 case TelephonyManager.NETWORK_TYPE_EVDO_B: 605 return "CDMA - EvDo rev. B"; 606 case TelephonyManager.NETWORK_TYPE_1xRTT: 607 return "CDMA - 1xRTT"; 608 case TelephonyManager.NETWORK_TYPE_LTE: 609 return "LTE"; 610 case TelephonyManager.NETWORK_TYPE_EHRPD: 611 return "CDMA - eHRPD"; 612 case TelephonyManager.NETWORK_TYPE_IDEN: 613 return "iDEN"; 614 case TelephonyManager.NETWORK_TYPE_HSPAP: 615 return "HSPA+"; 616 case TelephonyManager.NETWORK_TYPE_GSM: 617 return "GSM"; 618 case TelephonyManager.NETWORK_TYPE_TD_SCDMA: 619 return "TD_SCDMA"; 620 case TelephonyManager.NETWORK_TYPE_IWLAN: 621 return "IWLAN"; 622 // case TelephonyManager.NETWORK_TYPE_LTE_CA: 623 // return "LTE_CA"; 624 case TelephonyManager.NETWORK_TYPE_NR: 625 return "NR SA"; 626 default: 627 return "UNKNOWN"; 628 } 629 } 630 } 631