1 /* 2 * Copyright (C) 2018 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.network; 18 19 import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE; 20 import static androidx.lifecycle.Lifecycle.Event.ON_RESUME; 21 22 import static com.android.settings.network.telephony.MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON; 23 import static com.android.settingslib.mobile.MobileMappings.getIconKey; 24 import static com.android.settingslib.mobile.MobileMappings.mapIconSets; 25 26 import android.content.BroadcastReceiver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.IntentFilter; 30 import android.graphics.drawable.Drawable; 31 import android.net.wifi.WifiManager; 32 import android.os.UserManager; 33 import android.provider.Settings; 34 import android.telephony.AccessNetworkConstants; 35 import android.telephony.NetworkRegistrationInfo; 36 import android.telephony.ServiceState; 37 import android.telephony.SignalStrength; 38 import android.telephony.SubscriptionInfo; 39 import android.telephony.SubscriptionManager; 40 import android.telephony.TelephonyDisplayInfo; 41 import android.telephony.TelephonyManager; 42 import android.text.Html; 43 import android.util.ArraySet; 44 import android.util.Log; 45 46 import androidx.annotation.VisibleForTesting; 47 import androidx.collection.ArrayMap; 48 import androidx.lifecycle.Lifecycle; 49 import androidx.lifecycle.LifecycleObserver; 50 import androidx.lifecycle.OnLifecycleEvent; 51 import androidx.preference.Preference; 52 import androidx.preference.PreferenceGroup; 53 import androidx.preference.PreferenceScreen; 54 55 import com.android.settings.R; 56 import com.android.settings.Utils; 57 import com.android.settings.network.telephony.DataConnectivityListener; 58 import com.android.settings.network.telephony.MobileNetworkActivity; 59 import com.android.settings.network.telephony.MobileNetworkUtils; 60 import com.android.settings.network.telephony.SignalStrengthListener; 61 import com.android.settings.network.telephony.TelephonyDisplayInfoListener; 62 import com.android.settings.widget.MutableGearPreference; 63 import com.android.settings.wifi.WifiPickerTrackerHelper; 64 import com.android.settingslib.SignalIcon.MobileIconGroup; 65 import com.android.settingslib.core.AbstractPreferenceController; 66 import com.android.settingslib.mobile.MobileMappings; 67 import com.android.settingslib.mobile.MobileMappings.Config; 68 import com.android.settingslib.mobile.TelephonyIcons; 69 import com.android.settingslib.net.SignalStrengthUtil; 70 71 import java.util.Collections; 72 import java.util.List; 73 import java.util.Map; 74 import java.util.Set; 75 76 /** 77 * This controller manages preference with data subscription information and make its state 78 * display on preference. 79 */ 80 public class SubscriptionsPreferenceController extends AbstractPreferenceController implements 81 LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient, 82 MobileDataEnabledListener.Client, DataConnectivityListener.Client, 83 SignalStrengthListener.Callback, TelephonyDisplayInfoListener.Callback { 84 private static final String TAG = "SubscriptionsPrefCntrlr"; 85 86 private UpdateListener mUpdateListener; 87 private String mPreferenceGroupKey; 88 private PreferenceGroup mPreferenceGroup; 89 private TelephonyManager mTelephonyManager; 90 private SubscriptionManager mSubscriptionManager; 91 private SubscriptionsChangeListener mSubscriptionsListener; 92 private MobileDataEnabledListener mDataEnabledListener; 93 private DataConnectivityListener mConnectivityListener; 94 private SignalStrengthListener mSignalStrengthListener; 95 private TelephonyDisplayInfoListener mTelephonyDisplayInfoListener; 96 private WifiPickerTrackerHelper mWifiPickerTrackerHelper; 97 private final WifiManager mWifiManager; 98 99 @VisibleForTesting 100 final BroadcastReceiver mConnectionChangeReceiver = new BroadcastReceiver() { 101 @Override 102 public void onReceive(Context context, Intent intent) { 103 final String action = intent.getAction(); 104 if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { 105 mConfig = mSubsPrefCtrlInjector.getConfig(mContext); 106 update(); 107 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) { 108 update(); 109 } 110 } 111 }; 112 113 // Map of subscription id to Preference 114 private Map<Integer, Preference> mSubscriptionPreferences; 115 private int mStartOrder; 116 private MutableGearPreference mSubsGearPref; 117 private Config mConfig = null; 118 private SubsPrefCtrlInjector mSubsPrefCtrlInjector; 119 private TelephonyDisplayInfo mTelephonyDisplayInfo = 120 new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN, 121 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE); 122 123 /** 124 * This interface lets a parent of this class know that some change happened - this could 125 * either be because overall availability changed, or because we've added/removed/updated some 126 * preferences. 127 */ 128 public interface UpdateListener { onChildrenUpdated()129 void onChildrenUpdated(); 130 } 131 132 /** 133 * @param context the context for the UI where we're placing these preferences 134 * @param lifecycle for listening to lifecycle events for the UI 135 * @param updateListener called to let our parent controller know that our availability has 136 * changed, or that one or more of the preferences we've placed in the 137 * PreferenceGroup has changed 138 * @param preferenceGroupKey the key used to lookup the PreferenceGroup where Preferences will 139 * be placed 140 * @param startOrder the order that should be given to the first Preference placed into 141 * the PreferenceGroup; the second will use startOrder+1, third will 142 * use startOrder+2, etc. - this is useful for when the parent wants 143 * to have other preferences in the same PreferenceGroup and wants 144 * a specific ordering relative to this controller's prefs. 145 */ SubscriptionsPreferenceController(Context context, Lifecycle lifecycle, UpdateListener updateListener, String preferenceGroupKey, int startOrder)146 public SubscriptionsPreferenceController(Context context, Lifecycle lifecycle, 147 UpdateListener updateListener, String preferenceGroupKey, int startOrder) { 148 super(context); 149 mUpdateListener = updateListener; 150 mPreferenceGroupKey = preferenceGroupKey; 151 mStartOrder = startOrder; 152 mTelephonyManager = context.getSystemService(TelephonyManager.class); 153 mSubscriptionManager = context.getSystemService(SubscriptionManager.class); 154 mWifiManager = context.getSystemService(WifiManager.class); 155 mSubscriptionPreferences = new ArrayMap<>(); 156 mSubscriptionsListener = new SubscriptionsChangeListener(context, this); 157 mDataEnabledListener = new MobileDataEnabledListener(context, this); 158 mConnectivityListener = new DataConnectivityListener(context, this); 159 mSignalStrengthListener = new SignalStrengthListener(context, this); 160 mTelephonyDisplayInfoListener = new TelephonyDisplayInfoListener(context, this); 161 lifecycle.addObserver(this); 162 mSubsPrefCtrlInjector = createSubsPrefCtrlInjector(); 163 mConfig = mSubsPrefCtrlInjector.getConfig(mContext); 164 } 165 registerReceiver()166 private void registerReceiver() { 167 IntentFilter filter = new IntentFilter(); 168 filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); 169 filter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 170 mContext.registerReceiver(mConnectionChangeReceiver, filter); 171 } 172 unRegisterReceiver()173 private void unRegisterReceiver() { 174 if (mConnectionChangeReceiver != null) { 175 mContext.unregisterReceiver(mConnectionChangeReceiver); 176 } 177 } 178 179 @OnLifecycleEvent(ON_RESUME) onResume()180 public void onResume() { 181 mSubscriptionsListener.start(); 182 mDataEnabledListener.start(mSubsPrefCtrlInjector.getDefaultDataSubscriptionId()); 183 mConnectivityListener.start(); 184 mSignalStrengthListener.resume(); 185 mTelephonyDisplayInfoListener.resume(); 186 registerReceiver(); 187 update(); 188 } 189 190 @OnLifecycleEvent(ON_PAUSE) onPause()191 public void onPause() { 192 mSubscriptionsListener.stop(); 193 mDataEnabledListener.stop(); 194 mConnectivityListener.stop(); 195 mSignalStrengthListener.pause(); 196 mTelephonyDisplayInfoListener.pause(); 197 unRegisterReceiver(); 198 resetProviderPreferenceSummary(); 199 } 200 201 @Override displayPreference(PreferenceScreen screen)202 public void displayPreference(PreferenceScreen screen) { 203 mPreferenceGroup = screen.findPreference(mPreferenceGroupKey); 204 update(); 205 } 206 update()207 private void update() { 208 if (mPreferenceGroup == null) { 209 return; 210 } 211 if (!isAvailable()) { 212 if (mSubsGearPref != null) { 213 mPreferenceGroup.removePreference(mSubsGearPref); 214 } 215 for (Preference pref : mSubscriptionPreferences.values()) { 216 mPreferenceGroup.removePreference(pref); 217 } 218 219 mSubscriptionPreferences.clear(); 220 mSignalStrengthListener.updateSubscriptionIds(Collections.emptySet()); 221 mTelephonyDisplayInfoListener.updateSubscriptionIds(Collections.emptySet()); 222 mUpdateListener.onChildrenUpdated(); 223 return; 224 } 225 226 SubscriptionInfo subInfo = mSubscriptionManager.getDefaultDataSubscriptionInfo(); 227 if (subInfo == null) { 228 mPreferenceGroup.removeAll(); 229 return; 230 } 231 if (mSubsGearPref == null) { 232 mPreferenceGroup.removeAll(); 233 mSubsGearPref = new MutableGearPreference(mContext, null); 234 mSubsGearPref.setOnPreferenceClickListener(preference -> { 235 connectCarrierNetwork(); 236 return true; 237 }); 238 239 mSubsGearPref.setOnGearClickListener(p -> 240 startMobileNetworkActivity(mContext, subInfo.getSubscriptionId())); 241 } 242 243 if (!(mContext.getSystemService(UserManager.class)).isAdminUser()) { 244 mSubsGearPref.setGearEnabled(false); 245 } 246 247 mSubsGearPref.setTitle(SubscriptionUtil.getUniqueSubscriptionDisplayName( 248 subInfo, mContext)); 249 mSubsGearPref.setOrder(mStartOrder); 250 mSubsGearPref.setSummary(getMobilePreferenceSummary(subInfo.getSubscriptionId())); 251 mSubsGearPref.setIcon(getIcon(subInfo.getSubscriptionId())); 252 mPreferenceGroup.addPreference(mSubsGearPref); 253 254 final Set<Integer> activeDataSubIds = new ArraySet<>(); 255 activeDataSubIds.add(subInfo.getSubscriptionId()); 256 mSignalStrengthListener.updateSubscriptionIds(activeDataSubIds); 257 mTelephonyDisplayInfoListener.updateSubscriptionIds(activeDataSubIds); 258 mUpdateListener.onChildrenUpdated(); 259 } 260 getMobilePreferenceSummary(int subId)261 private CharSequence getMobilePreferenceSummary(int subId) { 262 final TelephonyManager tmForSubId = mTelephonyManager.createForSubscriptionId(subId); 263 if (!tmForSubId.isDataEnabled()) { 264 return mContext.getString(R.string.mobile_data_off_summary); 265 } 266 final ServiceState serviceState = tmForSubId.getServiceState(); 267 final NetworkRegistrationInfo regInfo = (serviceState == null) 268 ? null 269 : serviceState.getNetworkRegistrationInfo( 270 NetworkRegistrationInfo.DOMAIN_PS, 271 AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 272 273 final boolean isDataInService = (regInfo == null) 274 ? false 275 : regInfo.isRegistered(); 276 final boolean isCarrierNetworkActive = isCarrierNetworkActive(); 277 String result = mSubsPrefCtrlInjector.getNetworkType( 278 mContext, mConfig, mTelephonyDisplayInfo, subId, isCarrierNetworkActive); 279 if (mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext) || isCarrierNetworkActive) { 280 Log.i(TAG, "Active cellular network or active carrier network."); 281 result = mContext.getString(R.string.preference_summary_default_combination, 282 mContext.getString(R.string.mobile_data_connection_active), result); 283 } else if (!isDataInService) { 284 result = mContext.getString(R.string.mobile_data_no_connection); 285 } 286 return Html.fromHtml(result, Html.FROM_HTML_MODE_LEGACY); 287 } 288 getIcon(int subId)289 private Drawable getIcon(int subId) { 290 final TelephonyManager tmForSubId = mTelephonyManager.createForSubscriptionId(subId); 291 final SignalStrength strength = tmForSubId.getSignalStrength(); 292 int level = (strength == null) ? 0 : strength.getLevel(); 293 int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS; 294 boolean isCarrierNetworkActive = isCarrierNetworkActive(); 295 if (shouldInflateSignalStrength(subId) || isCarrierNetworkActive) { 296 level = isCarrierNetworkActive 297 ? SignalStrength.NUM_SIGNAL_STRENGTH_BINS 298 : (level + 1); 299 numLevels += 1; 300 } 301 302 Drawable icon = mContext.getDrawable(R.drawable.ic_signal_strength_zero_bar_no_internet); 303 304 final ServiceState serviceState = tmForSubId.getServiceState(); 305 final NetworkRegistrationInfo regInfo = (serviceState == null) 306 ? null 307 : serviceState.getNetworkRegistrationInfo( 308 NetworkRegistrationInfo.DOMAIN_PS, 309 AccessNetworkConstants.TRANSPORT_TYPE_WWAN); 310 311 final boolean isDataInService = (regInfo == null) 312 ? false 313 : regInfo.isRegistered(); 314 final boolean isVoiceInService = (serviceState == null) 315 ? false 316 : (serviceState.getState() == ServiceState.STATE_IN_SERVICE); 317 if (isDataInService || isVoiceInService || isCarrierNetworkActive) { 318 icon = mSubsPrefCtrlInjector.getIcon(mContext, level, numLevels, 319 !tmForSubId.isDataEnabled()); 320 } 321 322 final boolean isActiveCellularNetwork = 323 mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext); 324 if (isActiveCellularNetwork || isCarrierNetworkActive) { 325 icon.setTint(Utils.getColorAccentDefaultColor(mContext)); 326 } 327 328 return icon; 329 } 330 resetProviderPreferenceSummary()331 private void resetProviderPreferenceSummary() { 332 if (mSubsGearPref == null) { 333 return; 334 } 335 mSubsGearPref.setSummary(""); 336 } 337 startMobileNetworkActivity(Context context, int subId)338 private static void startMobileNetworkActivity(Context context, int subId) { 339 final Intent intent = new Intent(context, MobileNetworkActivity.class); 340 intent.putExtra(Settings.EXTRA_SUB_ID, subId); 341 // MobileNetworkActivity is singleTask, set SplitPairRule to show in 2-pane. 342 MobileNetworkTwoPaneUtils.registerTwoPaneForMobileNetwork(context, intent, null); 343 context.startActivity(intent); 344 } 345 346 @VisibleForTesting shouldInflateSignalStrength(int subId)347 boolean shouldInflateSignalStrength(int subId) { 348 return SignalStrengthUtil.shouldInflateSignalStrength(mContext, subId); 349 } 350 351 @VisibleForTesting setIcon(Preference pref, int subId, boolean isDefaultForData)352 void setIcon(Preference pref, int subId, boolean isDefaultForData) { 353 final TelephonyManager mgr = mContext.getSystemService( 354 TelephonyManager.class).createForSubscriptionId(subId); 355 final SignalStrength strength = mgr.getSignalStrength(); 356 int level = (strength == null) ? 0 : strength.getLevel(); 357 int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS; 358 if (shouldInflateSignalStrength(subId)) { 359 level += 1; 360 numLevels += 1; 361 } 362 363 final boolean showCutOut = !isDefaultForData || !mgr.isDataEnabled(); 364 pref.setIcon(mSubsPrefCtrlInjector.getIcon(mContext, level, numLevels, showCutOut)); 365 } 366 367 /** 368 * The summary can have either 1 or 2 lines depending on which services (calls, SMS, data) this 369 * subscription is the default for. 370 * 371 * If this subscription is the default for calls and/or SMS, we add a line to show that. 372 * 373 * If this subscription is the default for data, we add a line with detail about 374 * whether the data connection is active. 375 * 376 * If a subscription isn't the default for anything, we just say it is available. 377 */ getSummary(int subId, boolean isDefaultForData)378 protected String getSummary(int subId, boolean isDefaultForData) { 379 final int callsDefaultSubId = mSubsPrefCtrlInjector.getDefaultVoiceSubscriptionId(); 380 final int smsDefaultSubId = mSubsPrefCtrlInjector.getDefaultSmsSubscriptionId(); 381 382 String line1 = null; 383 if (subId == callsDefaultSubId && subId == smsDefaultSubId) { 384 line1 = mContext.getString(R.string.default_for_calls_and_sms); 385 } else if (subId == callsDefaultSubId) { 386 line1 = mContext.getString(R.string.default_for_calls); 387 } else if (subId == smsDefaultSubId) { 388 line1 = mContext.getString(R.string.default_for_sms); 389 } 390 391 String line2 = null; 392 if (isDefaultForData) { 393 final TelephonyManager telMgrForSub = mContext.getSystemService( 394 TelephonyManager.class).createForSubscriptionId(subId); 395 final boolean dataEnabled = telMgrForSub.isDataEnabled(); 396 if (dataEnabled && mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext)) { 397 line2 = mContext.getString(R.string.mobile_data_active); 398 } else if (!dataEnabled) { 399 line2 = mContext.getString(R.string.mobile_data_off); 400 } else { 401 line2 = mContext.getString(R.string.default_for_mobile_data); 402 } 403 } 404 405 if (line1 != null && line2 != null) { 406 return String.join(System.lineSeparator(), line1, line2); 407 } else if (line1 != null) { 408 return line1; 409 } else if (line2 != null) { 410 return line2; 411 } else { 412 return mContext.getString(R.string.subscription_available); 413 } 414 } 415 416 /** 417 * @return true if there is at least 1 available subscription. 418 */ 419 @Override isAvailable()420 public boolean isAvailable() { 421 if (mSubscriptionsListener.isAirplaneModeOn() 422 && (!mWifiManager.isWifiEnabled() || !isCarrierNetworkActive())) { 423 return false; 424 } 425 List<SubscriptionInfo> subInfoList = 426 SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager); 427 if (subInfoList == null) { 428 return false; 429 } 430 431 return subInfoList.stream() 432 // Avoid from showing subscription(SIM)s which has been marked as hidden 433 // For example, only one subscription will be shown when there're multiple 434 // subscriptions with same group UUID. 435 .filter(subInfo -> 436 mSubsPrefCtrlInjector.canSubscriptionBeDisplayed(mContext, 437 subInfo.getSubscriptionId())) 438 .count() >= 1; 439 } 440 441 @Override getPreferenceKey()442 public String getPreferenceKey() { 443 return null; 444 } 445 446 @Override onAirplaneModeChanged(boolean airplaneModeEnabled)447 public void onAirplaneModeChanged(boolean airplaneModeEnabled) { 448 update(); 449 } 450 451 @Override onSubscriptionsChanged()452 public void onSubscriptionsChanged() { 453 // See if we need to change which sub id we're using to listen for enabled/disabled changes. 454 int defaultDataSubId = mSubsPrefCtrlInjector.getDefaultDataSubscriptionId(); 455 if (defaultDataSubId != mDataEnabledListener.getSubId()) { 456 mDataEnabledListener.stop(); 457 mDataEnabledListener.start(defaultDataSubId); 458 } 459 update(); 460 } 461 462 @Override onMobileDataEnabledChange()463 public void onMobileDataEnabledChange() { 464 update(); 465 } 466 467 @Override onDataConnectivityChange()468 public void onDataConnectivityChange() { 469 update(); 470 } 471 472 @Override onSignalStrengthChanged()473 public void onSignalStrengthChanged() { 474 update(); 475 } 476 477 @Override onTelephonyDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo)478 public void onTelephonyDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { 479 mTelephonyDisplayInfo = telephonyDisplayInfo; 480 update(); 481 } 482 setWifiPickerTrackerHelper(WifiPickerTrackerHelper helper)483 public void setWifiPickerTrackerHelper(WifiPickerTrackerHelper helper) { 484 mWifiPickerTrackerHelper = helper; 485 } 486 487 @VisibleForTesting connectCarrierNetwork()488 public void connectCarrierNetwork() { 489 if (!MobileNetworkUtils.isMobileDataEnabled(mContext)) { 490 return; 491 } 492 if (mWifiPickerTrackerHelper != null) { 493 mWifiPickerTrackerHelper.connectCarrierNetwork(null /* ConnectCallback */); 494 } 495 } 496 createSubsPrefCtrlInjector()497 SubsPrefCtrlInjector createSubsPrefCtrlInjector() { 498 return new SubsPrefCtrlInjector(); 499 } 500 isCarrierNetworkActive()501 boolean isCarrierNetworkActive() { 502 return mWifiPickerTrackerHelper != null 503 && mWifiPickerTrackerHelper.isCarrierNetworkActive(); 504 } 505 506 /** 507 * To inject necessary data from each static api. 508 */ 509 @VisibleForTesting 510 public static class SubsPrefCtrlInjector { 511 /** 512 * Uses to inject function and value for class and test class. 513 */ canSubscriptionBeDisplayed(Context context, int subId)514 public boolean canSubscriptionBeDisplayed(Context context, int subId) { 515 return (SubscriptionUtil.getAvailableSubscription(context, 516 ProxySubscriptionManager.getInstance(context), subId) != null); 517 } 518 519 /** 520 * Check SIM be able to display on UI. 521 */ getDefaultSmsSubscriptionId()522 public int getDefaultSmsSubscriptionId() { 523 return SubscriptionManager.getDefaultSmsSubscriptionId(); 524 } 525 526 /** 527 * Gets default voice subscription ID. 528 */ getDefaultVoiceSubscriptionId()529 public int getDefaultVoiceSubscriptionId() { 530 return SubscriptionManager.getDefaultVoiceSubscriptionId(); 531 } 532 533 /** 534 * Gets default data subscription ID. 535 */ getDefaultDataSubscriptionId()536 public int getDefaultDataSubscriptionId() { 537 return SubscriptionManager.getDefaultDataSubscriptionId(); 538 } 539 540 /** 541 * Confirms the current network is cellular and active. 542 */ isActiveCellularNetwork(Context context)543 public boolean isActiveCellularNetwork(Context context) { 544 return MobileNetworkUtils.activeNetworkIsCellular(context); 545 } 546 547 /** 548 * Gets config for carrier customization. 549 */ getConfig(Context context)550 public Config getConfig(Context context) { 551 return MobileMappings.Config.readConfig(context); 552 } 553 554 /** 555 * Gets current mobile network type. 556 */ getNetworkType(Context context, Config config, TelephonyDisplayInfo telephonyDisplayInfo, int subId)557 public String getNetworkType(Context context, Config config, 558 TelephonyDisplayInfo telephonyDisplayInfo, int subId) { 559 String iconKey = getIconKey(telephonyDisplayInfo); 560 MobileIconGroup iconGroup = mapIconSets(config).get(iconKey); 561 int resId = 0; 562 if (iconGroup != null) { 563 resId = iconGroup.dataContentDescription; 564 } 565 return resId != 0 566 ? SubscriptionManager.getResourcesForSubId(context, subId).getString(resId) 567 : ""; 568 } 569 570 /** 571 * Gets current network type of Carrier Wi-Fi Network or Cellular. 572 */ getNetworkType(Context context, Config config, TelephonyDisplayInfo telephonyDisplayInfo, int subId, boolean isCarrierWifiNetwork)573 public String getNetworkType(Context context, Config config, 574 TelephonyDisplayInfo telephonyDisplayInfo, int subId, 575 boolean isCarrierWifiNetwork) { 576 if (isCarrierWifiNetwork) { 577 MobileIconGroup carrierMergedWifiIconGroup = TelephonyIcons.CARRIER_MERGED_WIFI; 578 int resId = carrierMergedWifiIconGroup.dataContentDescription; 579 return resId != 0 580 ? SubscriptionManager.getResourcesForSubId(context, subId) 581 .getString(resId) : ""; 582 } else { 583 return getNetworkType(context, config, telephonyDisplayInfo, subId); 584 } 585 } 586 587 /** 588 * Gets signal icon with different signal level. 589 */ getIcon(Context context, int level, int numLevels, boolean cutOut)590 public Drawable getIcon(Context context, int level, int numLevels, boolean cutOut) { 591 return MobileNetworkUtils.getSignalStrengthIcon(context, level, numLevels, 592 NO_CELL_DATA_TYPE_ICON, cutOut); 593 } 594 } 595 } 596