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