[Provider model] Internet picker Part II
- Add mobile internet preference with default data subscription. - Make prefrence to show dynamically when data subscription changed. Video exhibition - http://rcll/gcmsphfhJ1UzfPSvjWOuXK/c1B2CtaFz27rlIQ2LSTJmo Code difference - SubscriptionsPreferenceControllerTest.java between robolectric and junit. - https://diff.googleplex.com/#key=1Zm7JGPhoZwY Bug: 172229552 Test: atest SubscriptionsPreferenceControllerTest Change-Id: Ib50c2c51159f60f19631d1a02081eafde3436e94
This commit is contained in:
@@ -21,10 +21,13 @@ import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
|
||||
|
||||
import static com.android.settings.network.telephony.MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SignalStrength;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
@@ -46,6 +49,7 @@ import com.android.settings.network.telephony.DataConnectivityListener;
|
||||
import com.android.settings.network.telephony.MobileNetworkActivity;
|
||||
import com.android.settings.network.telephony.MobileNetworkUtils;
|
||||
import com.android.settings.network.telephony.SignalStrengthListener;
|
||||
import com.android.settings.widget.GearPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.net.SignalStrengthUtil;
|
||||
|
||||
@@ -55,9 +59,15 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This manages a set of Preferences it places into a PreferenceGroup owned by some parent
|
||||
* If the provider model is not enabled, this controller manages a set of Preferences it places into
|
||||
* a PreferenceGroup owned by some parent
|
||||
* controller class - one for each available subscription. This controller is only considered
|
||||
* available if there are 2 or more subscriptions.
|
||||
*
|
||||
* If the provider model is enabled, this controller manages preference with data subscription
|
||||
* information and make its state display on preference.
|
||||
* TODO this class will clean up the multiple subscriptions functionality after the provider
|
||||
* model is released.
|
||||
*/
|
||||
public class SubscriptionsPreferenceController extends AbstractPreferenceController implements
|
||||
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient,
|
||||
@@ -68,16 +78,30 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
private UpdateListener mUpdateListener;
|
||||
private String mPreferenceGroupKey;
|
||||
private PreferenceGroup mPreferenceGroup;
|
||||
private SubscriptionManager mManager;
|
||||
private TelephonyManager mTelephonyManager;
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
private SubscriptionsChangeListener mSubscriptionsListener;
|
||||
private MobileDataEnabledListener mDataEnabledListener;
|
||||
private DataConnectivityListener mConnectivityListener;
|
||||
private SignalStrengthListener mSignalStrengthListener;
|
||||
|
||||
@VisibleForTesting
|
||||
final BroadcastReceiver mDataSubscriptionChangedReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
|
||||
update();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Map of subscription id to Preference
|
||||
private Map<Integer, Preference> mSubscriptionPreferences;
|
||||
private int mStartOrder;
|
||||
private GearPreference mSubsGearPref;
|
||||
|
||||
private SubsPrefCtrlInjector mSubsPrefCtrlInjector;
|
||||
/**
|
||||
* This interface lets a parent of this class know that some change happened - this could
|
||||
* either be because overall availability changed, or because we've added/removed/updated some
|
||||
@@ -107,21 +131,37 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mUpdateListener = updateListener;
|
||||
mPreferenceGroupKey = preferenceGroupKey;
|
||||
mStartOrder = startOrder;
|
||||
mManager = context.getSystemService(SubscriptionManager.class);
|
||||
mTelephonyManager = context.getSystemService(TelephonyManager.class);
|
||||
mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
|
||||
mSubscriptionPreferences = new ArrayMap<>();
|
||||
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
|
||||
mDataEnabledListener = new MobileDataEnabledListener(context, this);
|
||||
mConnectivityListener = new DataConnectivityListener(context, this);
|
||||
mSignalStrengthListener = new SignalStrengthListener(context, this);
|
||||
lifecycle.addObserver(this);
|
||||
mSubsPrefCtrlInjector = createSubsPrefCtrlInjector();
|
||||
}
|
||||
|
||||
private void registerDataSubscriptionChangedReceiver() {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
|
||||
mContext.registerReceiver(mDataSubscriptionChangedReceiver, filter);
|
||||
}
|
||||
|
||||
private void unRegisterDataSubscriptionChangedReceiver() {
|
||||
if (mDataSubscriptionChangedReceiver != null) {
|
||||
mContext.unregisterReceiver(mDataSubscriptionChangedReceiver);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@OnLifecycleEvent(ON_RESUME)
|
||||
public void onResume() {
|
||||
mSubscriptionsListener.start();
|
||||
mDataEnabledListener.start(SubscriptionManager.getDefaultDataSubscriptionId());
|
||||
mDataEnabledListener.start(mSubsPrefCtrlInjector.getDefaultDataSubscriptionId());
|
||||
mConnectivityListener.start();
|
||||
mSignalStrengthListener.resume();
|
||||
registerDataSubscriptionChangedReceiver();
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -131,6 +171,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mDataEnabledListener.stop();
|
||||
mConnectivityListener.stop();
|
||||
mSignalStrengthListener.pause();
|
||||
unRegisterDataSubscriptionChangedReceiver();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -143,29 +184,116 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
if (mPreferenceGroup == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAvailable()) {
|
||||
if (mSubsGearPref != null) {
|
||||
mPreferenceGroup.removePreference(mSubsGearPref);
|
||||
}
|
||||
for (Preference pref : mSubscriptionPreferences.values()) {
|
||||
mPreferenceGroup.removePreference(pref);
|
||||
}
|
||||
|
||||
mSubscriptionPreferences.clear();
|
||||
mSignalStrengthListener.updateSubscriptionIds(Collections.emptySet());
|
||||
mUpdateListener.onChildrenUpdated();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSubsPrefCtrlInjector.isProviderModelEnabled(mContext)) {
|
||||
updateForProvider();
|
||||
} else {
|
||||
updateForBase();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateForProvider() {
|
||||
SubscriptionInfo subInfo = mSubscriptionManager.getDefaultDataSubscriptionInfo();
|
||||
if (subInfo == null) {
|
||||
mPreferenceGroup.removeAll();
|
||||
return;
|
||||
}
|
||||
if (mSubsGearPref == null) {
|
||||
mPreferenceGroup.removeAll();
|
||||
mSubsGearPref = new GearPreference(mContext, null);
|
||||
mSubsGearPref.setOnPreferenceClickListener(preference -> {
|
||||
//TODO(b/176141379) Wait for wifiManager#selectCarrier(int subscriptionId)
|
||||
return true;
|
||||
});
|
||||
mSubsGearPref.setOnGearClickListener(p ->
|
||||
startMobileNetworkActivity(mContext, subInfo.getSubscriptionId()));
|
||||
}
|
||||
|
||||
mSubsGearPref.setTitle(subInfo.getDisplayName());
|
||||
mSubsGearPref.setOrder(mStartOrder);
|
||||
//TODO(b/176141828) Wait for api provided by system ui.
|
||||
mSubsGearPref.setSummary(getMobilePreferenceSummary());
|
||||
mSubsGearPref.setIcon(getIcon(subInfo.getSubscriptionId()));
|
||||
mPreferenceGroup.addPreference(mSubsGearPref);
|
||||
|
||||
final Set<Integer> activeDataSubIds = new ArraySet<>();
|
||||
activeDataSubIds.add(subInfo.getSubscriptionId());
|
||||
mSignalStrengthListener.updateSubscriptionIds(activeDataSubIds);
|
||||
mUpdateListener.onChildrenUpdated();
|
||||
}
|
||||
|
||||
private String getMobilePreferenceSummary() {
|
||||
//TODO(b/176141828) Waiting for the api provided by system UI.
|
||||
String result = "5G";
|
||||
if (MobileNetworkUtils.activeNetworkIsCellular(mContext)) {
|
||||
result = "Active, " + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Drawable getIcon(int subId) {
|
||||
final TelephonyManager tmForSubId = mTelephonyManager.createForSubscriptionId(subId);
|
||||
final SignalStrength strength = tmForSubId.getSignalStrength();
|
||||
int level = (strength == null) ? 0 : strength.getLevel();
|
||||
|
||||
int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
|
||||
if (shouldInflateSignalStrength(subId)) {
|
||||
level += 1;
|
||||
numLevels += 1;
|
||||
}
|
||||
|
||||
final boolean isMobileDataOn = tmForSubId.isDataEnabled();
|
||||
final boolean isActiveCellularNetwork =
|
||||
mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext);
|
||||
final boolean isMobileDataAccessible = tmForSubId.getDataState()
|
||||
== TelephonyManager.DATA_CONNECTED;
|
||||
final ServiceState serviceState = tmForSubId.getServiceState();
|
||||
final boolean isVoiceOutOfService = (serviceState == null)
|
||||
? true
|
||||
: (serviceState.getState() == ServiceState.STATE_OUT_OF_SERVICE);
|
||||
|
||||
Drawable icon = mSubsPrefCtrlInjector.getIcon(mContext, level, numLevels, false);
|
||||
|
||||
if (isActiveCellularNetwork) {
|
||||
icon.setTint(Utils.getColorAccentDefaultColor(mContext));
|
||||
return icon;
|
||||
}
|
||||
if ((isMobileDataOn && isMobileDataAccessible)
|
||||
|| (!isMobileDataOn && !isVoiceOutOfService)) {
|
||||
return icon;
|
||||
}
|
||||
|
||||
icon = mContext.getDrawable(R.drawable.ic_signal_strength_zero_bar_no_internet);
|
||||
return icon;
|
||||
}
|
||||
|
||||
private void updateForBase() {
|
||||
final Map<Integer, Preference> existingPrefs = mSubscriptionPreferences;
|
||||
mSubscriptionPreferences = new ArrayMap<>();
|
||||
|
||||
int order = mStartOrder;
|
||||
final Set<Integer> activeSubIds = new ArraySet<>();
|
||||
final int dataDefaultSubId = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||
for (SubscriptionInfo info : SubscriptionUtil.getActiveSubscriptions(mManager)) {
|
||||
final int dataDefaultSubId = mSubsPrefCtrlInjector.getDefaultDataSubscriptionId();
|
||||
for (SubscriptionInfo info :
|
||||
SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager)) {
|
||||
final int subId = info.getSubscriptionId();
|
||||
// Avoid from showing subscription(SIM)s which has been marked as hidden
|
||||
// For example, only one subscription will be shown when there're multiple
|
||||
// subscriptions with same group UUID.
|
||||
if (!canSubscriptionBeDisplayed(mContext, subId)) {
|
||||
if (!mSubsPrefCtrlInjector.canSubscriptionBeDisplayed(mContext, subId)) {
|
||||
continue;
|
||||
}
|
||||
activeSubIds.add(subId);
|
||||
@@ -181,9 +309,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
pref.setOrder(order++);
|
||||
|
||||
pref.setOnPreferenceClickListener(clickedPref -> {
|
||||
final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
|
||||
intent.putExtra(Settings.EXTRA_SUB_ID, subId);
|
||||
mContext.startActivity(intent);
|
||||
startMobileNetworkActivity(mContext, subId);
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -198,6 +324,12 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mUpdateListener.onChildrenUpdated();
|
||||
}
|
||||
|
||||
private static void startMobileNetworkActivity(Context context, int subId) {
|
||||
final Intent intent = new Intent(context, MobileNetworkActivity.class);
|
||||
intent.putExtra(Settings.EXTRA_SUB_ID, subId);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean shouldInflateSignalStrength(int subId) {
|
||||
return SignalStrengthUtil.shouldInflateSignalStrength(mContext, subId);
|
||||
@@ -214,14 +346,9 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
level += 1;
|
||||
numLevels += 1;
|
||||
}
|
||||
final boolean showCutOut = !isDefaultForData || !mgr.isDataEnabled();
|
||||
pref.setIcon(getIcon(level, numLevels, showCutOut));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Drawable getIcon(int level, int numLevels, boolean cutOut) {
|
||||
return MobileNetworkUtils.getSignalStrengthIcon(mContext, level, numLevels,
|
||||
NO_CELL_DATA_TYPE_ICON, cutOut);
|
||||
final boolean showCutOut = !isDefaultForData || !mgr.isDataEnabled();
|
||||
pref.setIcon(mSubsPrefCtrlInjector.getIcon(mContext, level, numLevels, showCutOut));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,8 +363,8 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
* If a subscription isn't the default for anything, we just say it is available.
|
||||
*/
|
||||
protected String getSummary(int subId, boolean isDefaultForData) {
|
||||
final int callsDefaultSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
|
||||
final int smsDefaultSubId = SubscriptionManager.getDefaultSmsSubscriptionId();
|
||||
final int callsDefaultSubId = mSubsPrefCtrlInjector.getDefaultVoiceSubscriptionId();
|
||||
final int smsDefaultSubId = mSubsPrefCtrlInjector.getDefaultSmsSubscriptionId();
|
||||
|
||||
String line1 = null;
|
||||
if (subId == callsDefaultSubId && subId == smsDefaultSubId) {
|
||||
@@ -253,7 +380,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
final TelephonyManager telMgrForSub = mContext.getSystemService(
|
||||
TelephonyManager.class).createForSubscriptionId(subId);
|
||||
final boolean dataEnabled = telMgrForSub.isDataEnabled();
|
||||
if (dataEnabled && MobileNetworkUtils.activeNetworkIsCellular(mContext)) {
|
||||
if (dataEnabled && mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext)) {
|
||||
line2 = mContext.getString(R.string.mobile_data_active);
|
||||
} else if (!dataEnabled) {
|
||||
line2 = mContext.getString(R.string.mobile_data_off);
|
||||
@@ -274,14 +401,16 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if there are at least 2 available subscriptions.
|
||||
* @return true if there are at least 2 available subscriptions,
|
||||
* or if there is at least 1 available subscription for provider model.
|
||||
*/
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (mSubscriptionsListener.isAirplaneModeOn()) {
|
||||
return false;
|
||||
}
|
||||
List<SubscriptionInfo> subInfoList = SubscriptionUtil.getActiveSubscriptions(mManager);
|
||||
List<SubscriptionInfo> subInfoList =
|
||||
SubscriptionUtil.getActiveSubscriptions(mSubscriptionManager);
|
||||
if (subInfoList == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -290,8 +419,9 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
// For example, only one subscription will be shown when there're multiple
|
||||
// subscriptions with same group UUID.
|
||||
.filter(subInfo ->
|
||||
canSubscriptionBeDisplayed(mContext, subInfo.getSubscriptionId()))
|
||||
.count() >= (Utils.isProviderModelEnabled(mContext) ? 1 : 2);
|
||||
mSubsPrefCtrlInjector.canSubscriptionBeDisplayed(mContext,
|
||||
subInfo.getSubscriptionId()))
|
||||
.count() >= (mSubsPrefCtrlInjector.isProviderModelEnabled(mContext) ? 1 : 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -307,7 +437,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
@Override
|
||||
public void onSubscriptionsChanged() {
|
||||
// See if we need to change which sub id we're using to listen for enabled/disabled changes.
|
||||
int defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||
int defaultDataSubId = mSubsPrefCtrlInjector.getDefaultDataSubscriptionId();
|
||||
if (defaultDataSubId != mDataEnabledListener.getSubId()) {
|
||||
mDataEnabledListener.stop();
|
||||
mDataEnabledListener.start(defaultDataSubId);
|
||||
@@ -335,4 +465,65 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
return (SubscriptionUtil.getAvailableSubscription(context,
|
||||
ProxySubscriptionManager.getInstance(context), subId) != null);
|
||||
}
|
||||
}
|
||||
|
||||
SubsPrefCtrlInjector createSubsPrefCtrlInjector() {
|
||||
return new SubsPrefCtrlInjector();
|
||||
}
|
||||
|
||||
/**
|
||||
* To inject necessary data from each static api.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static class SubsPrefCtrlInjector {
|
||||
/**
|
||||
* Use to inject function and value for class and test class.
|
||||
*/
|
||||
public boolean canSubscriptionBeDisplayed(Context context, int subId) {
|
||||
return (SubscriptionUtil.getAvailableSubscription(context,
|
||||
ProxySubscriptionManager.getInstance(context), subId) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check SIM be able to display on UI.
|
||||
*/
|
||||
public int getDefaultSmsSubscriptionId() {
|
||||
return SubscriptionManager.getDefaultSmsSubscriptionId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default voice subscription ID.
|
||||
*/
|
||||
public int getDefaultVoiceSubscriptionId() {
|
||||
return SubscriptionManager.getDefaultVoiceSubscriptionId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default data subscription ID.
|
||||
*/
|
||||
public int getDefaultDataSubscriptionId() {
|
||||
return SubscriptionManager.getDefaultDataSubscriptionId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the current network is cellular and active.
|
||||
*/
|
||||
public boolean isActiveCellularNetwork(Context context) {
|
||||
return MobileNetworkUtils.activeNetworkIsCellular(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm the flag of Provider Model switch is turned on or not.
|
||||
*/
|
||||
public boolean isProviderModelEnabled(Context context) {
|
||||
return Utils.isProviderModelEnabled(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get signal icon with different signal level.
|
||||
*/
|
||||
public Drawable getIcon(Context context, int level, int numLevels, boolean cutOut) {
|
||||
return MobileNetworkUtils.getSignalStrengthIcon(context, level, numLevels,
|
||||
NO_CELL_DATA_TYPE_ICON, cutOut);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user