Merge "Add signal strength icons to multi-SIM header" into qt-dev
am: 42c451610e
Change-Id: Ice796e09d1821dedb0ad00ff8218afd1be205374
This commit is contained in:
@@ -19,16 +19,22 @@ package com.android.settings.network;
|
|||||||
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
|
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
|
||||||
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
|
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
|
||||||
|
|
||||||
|
import static com.android.settings.network.telephony.MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.telephony.SignalStrength;
|
||||||
import android.telephony.SubscriptionInfo;
|
import android.telephony.SubscriptionInfo;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
import androidx.collection.ArrayMap;
|
import androidx.collection.ArrayMap;
|
||||||
import androidx.lifecycle.Lifecycle;
|
import androidx.lifecycle.Lifecycle;
|
||||||
import androidx.lifecycle.LifecycleObserver;
|
import androidx.lifecycle.LifecycleObserver;
|
||||||
@@ -40,9 +46,14 @@ import androidx.preference.PreferenceScreen;
|
|||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.network.telephony.DataConnectivityListener;
|
import com.android.settings.network.telephony.DataConnectivityListener;
|
||||||
import com.android.settings.network.telephony.MobileNetworkActivity;
|
import com.android.settings.network.telephony.MobileNetworkActivity;
|
||||||
|
import com.android.settings.network.telephony.MobileNetworkUtils;
|
||||||
|
import com.android.settings.network.telephony.SignalStrengthListener;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
|
import com.android.settingslib.net.SignalStrengthUtil;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This manages a set of Preferences it places into a PreferenceGroup owned by some parent
|
* This manages a set of Preferences it places into a PreferenceGroup owned by some parent
|
||||||
@@ -51,7 +62,8 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class SubscriptionsPreferenceController extends AbstractPreferenceController implements
|
public class SubscriptionsPreferenceController extends AbstractPreferenceController implements
|
||||||
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient,
|
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient,
|
||||||
MobileDataEnabledListener.Client, DataConnectivityListener.Client {
|
MobileDataEnabledListener.Client, DataConnectivityListener.Client,
|
||||||
|
SignalStrengthListener.Callback {
|
||||||
private static final String TAG = "SubscriptionsPrefCntrlr";
|
private static final String TAG = "SubscriptionsPrefCntrlr";
|
||||||
|
|
||||||
private UpdateListener mUpdateListener;
|
private UpdateListener mUpdateListener;
|
||||||
@@ -62,6 +74,8 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
private SubscriptionsChangeListener mSubscriptionsListener;
|
private SubscriptionsChangeListener mSubscriptionsListener;
|
||||||
private MobileDataEnabledListener mDataEnabledListener;
|
private MobileDataEnabledListener mDataEnabledListener;
|
||||||
private DataConnectivityListener mConnectivityListener;
|
private DataConnectivityListener mConnectivityListener;
|
||||||
|
private SignalStrengthListener mSignalStrengthListener;
|
||||||
|
|
||||||
|
|
||||||
// Map of subscription id to Preference
|
// Map of subscription id to Preference
|
||||||
private Map<Integer, Preference> mSubscriptionPreferences;
|
private Map<Integer, Preference> mSubscriptionPreferences;
|
||||||
@@ -102,6 +116,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
|
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
|
||||||
mDataEnabledListener = new MobileDataEnabledListener(context, this);
|
mDataEnabledListener = new MobileDataEnabledListener(context, this);
|
||||||
mConnectivityListener = new DataConnectivityListener(context, this);
|
mConnectivityListener = new DataConnectivityListener(context, this);
|
||||||
|
mSignalStrengthListener = new SignalStrengthListener(context, this);
|
||||||
lifecycle.addObserver(this);
|
lifecycle.addObserver(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +125,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
mSubscriptionsListener.start();
|
mSubscriptionsListener.start();
|
||||||
mDataEnabledListener.start(SubscriptionManager.getDefaultDataSubscriptionId());
|
mDataEnabledListener.start(SubscriptionManager.getDefaultDataSubscriptionId());
|
||||||
mConnectivityListener.start();
|
mConnectivityListener.start();
|
||||||
|
mSignalStrengthListener.resume();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,6 +134,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
mSubscriptionsListener.stop();
|
mSubscriptionsListener.stop();
|
||||||
mDataEnabledListener.stop();
|
mDataEnabledListener.stop();
|
||||||
mConnectivityListener.stop();
|
mConnectivityListener.stop();
|
||||||
|
mSignalStrengthListener.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -136,6 +153,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
mPreferenceGroup.removePreference(pref);
|
mPreferenceGroup.removePreference(pref);
|
||||||
}
|
}
|
||||||
mSubscriptionPreferences.clear();
|
mSubscriptionPreferences.clear();
|
||||||
|
mSignalStrengthListener.updateSubscriptionIds(Collections.emptySet());
|
||||||
mUpdateListener.onChildrenUpdated();
|
mUpdateListener.onChildrenUpdated();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -144,16 +162,20 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
mSubscriptionPreferences = new ArrayMap<>();
|
mSubscriptionPreferences = new ArrayMap<>();
|
||||||
|
|
||||||
int order = mStartOrder;
|
int order = mStartOrder;
|
||||||
|
final Set<Integer> activeSubIds = new ArraySet<>();
|
||||||
|
final int dataDefaultSubId = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||||
for (SubscriptionInfo info : SubscriptionUtil.getActiveSubscriptions(mManager)) {
|
for (SubscriptionInfo info : SubscriptionUtil.getActiveSubscriptions(mManager)) {
|
||||||
final int subId = info.getSubscriptionId();
|
final int subId = info.getSubscriptionId();
|
||||||
|
activeSubIds.add(subId);
|
||||||
Preference pref = existingPrefs.remove(subId);
|
Preference pref = existingPrefs.remove(subId);
|
||||||
if (pref == null) {
|
if (pref == null) {
|
||||||
pref = new Preference(mPreferenceGroup.getContext());
|
pref = new Preference(mPreferenceGroup.getContext());
|
||||||
mPreferenceGroup.addPreference(pref);
|
mPreferenceGroup.addPreference(pref);
|
||||||
}
|
}
|
||||||
pref.setTitle(info.getDisplayName());
|
pref.setTitle(info.getDisplayName());
|
||||||
pref.setSummary(getSummary(subId));
|
final boolean isDefaultForData = (subId == dataDefaultSubId);
|
||||||
pref.setIcon(R.drawable.ic_network_cell);
|
pref.setSummary(getSummary(subId, isDefaultForData));
|
||||||
|
setIcon(pref, subId, isDefaultForData);
|
||||||
pref.setOrder(order++);
|
pref.setOrder(order++);
|
||||||
|
|
||||||
pref.setOnPreferenceClickListener(clickedPref -> {
|
pref.setOnPreferenceClickListener(clickedPref -> {
|
||||||
@@ -165,6 +187,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
|
|
||||||
mSubscriptionPreferences.put(subId, pref);
|
mSubscriptionPreferences.put(subId, pref);
|
||||||
}
|
}
|
||||||
|
mSignalStrengthListener.updateSubscriptionIds(activeSubIds);
|
||||||
|
|
||||||
// Remove any old preferences that no longer map to a subscription.
|
// Remove any old preferences that no longer map to a subscription.
|
||||||
for (Preference pref : existingPrefs.values()) {
|
for (Preference pref : existingPrefs.values()) {
|
||||||
@@ -173,6 +196,32 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
mUpdateListener.onChildrenUpdated();
|
mUpdateListener.onChildrenUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
boolean shouldInflateSignalStrength(int subId) {
|
||||||
|
return SignalStrengthUtil.shouldInflateSignalStrength(mContext, subId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void setIcon(Preference pref, int subId, boolean isDefaultForData) {
|
||||||
|
final TelephonyManager mgr = mContext.getSystemService(
|
||||||
|
TelephonyManager.class).createForSubscriptionId(subId);
|
||||||
|
final SignalStrength strength = mgr.getSignalStrength();
|
||||||
|
int level = (strength == null) ? 0 : strength.getLevel();
|
||||||
|
int numLevels = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
|
||||||
|
if (shouldInflateSignalStrength(subId)) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean activeNetworkIsCellular() {
|
private boolean activeNetworkIsCellular() {
|
||||||
final Network activeNetwork = mConnectivityManager.getActiveNetwork();
|
final Network activeNetwork = mConnectivityManager.getActiveNetwork();
|
||||||
if (activeNetwork == null) {
|
if (activeNetwork == null) {
|
||||||
@@ -197,10 +246,9 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
*
|
*
|
||||||
* If a subscription isn't the default for anything, we just say it is available.
|
* If a subscription isn't the default for anything, we just say it is available.
|
||||||
*/
|
*/
|
||||||
protected String getSummary(int subId) {
|
protected String getSummary(int subId, boolean isDefaultForData) {
|
||||||
final int callsDefaultSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
|
final int callsDefaultSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
|
||||||
final int smsDefaultSubId = SubscriptionManager.getDefaultSmsSubscriptionId();
|
final int smsDefaultSubId = SubscriptionManager.getDefaultSmsSubscriptionId();
|
||||||
final int dataDefaultSubId = SubscriptionManager.getDefaultDataSubscriptionId();
|
|
||||||
|
|
||||||
String line1 = null;
|
String line1 = null;
|
||||||
if (subId == callsDefaultSubId && subId == smsDefaultSubId) {
|
if (subId == callsDefaultSubId && subId == smsDefaultSubId) {
|
||||||
@@ -212,10 +260,10 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
}
|
}
|
||||||
|
|
||||||
String line2 = null;
|
String line2 = null;
|
||||||
if (subId == dataDefaultSubId) {
|
if (isDefaultForData) {
|
||||||
final TelephonyManager telMgrForSub = mContext.getSystemService(
|
final TelephonyManager telMgrForSub = mContext.getSystemService(
|
||||||
TelephonyManager.class).createForSubscriptionId(subId);
|
TelephonyManager.class).createForSubscriptionId(subId);
|
||||||
boolean dataEnabled = telMgrForSub.isDataEnabled();
|
final boolean dataEnabled = telMgrForSub.isDataEnabled();
|
||||||
if (dataEnabled && activeNetworkIsCellular()) {
|
if (dataEnabled && activeNetworkIsCellular()) {
|
||||||
line2 = mContext.getString(R.string.mobile_data_active);
|
line2 = mContext.getString(R.string.mobile_data_active);
|
||||||
} else if (!dataEnabled) {
|
} else if (!dataEnabled) {
|
||||||
@@ -277,4 +325,9 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
|||||||
public void onDataConnectivityChange() {
|
public void onDataConnectivityChange() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSignalStrengthChanged() {
|
||||||
|
update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,10 @@ import android.content.Intent;
|
|||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.LayerDrawable;
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -37,6 +41,7 @@ import android.telephony.euicc.EuiccManager;
|
|||||||
import android.telephony.ims.feature.ImsFeature;
|
import android.telephony.ims.feature.ImsFeature;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.Gravity;
|
||||||
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
@@ -45,7 +50,10 @@ import com.android.ims.ImsManager;
|
|||||||
import com.android.internal.telephony.Phone;
|
import com.android.internal.telephony.Phone;
|
||||||
import com.android.internal.telephony.PhoneConstants;
|
import com.android.internal.telephony.PhoneConstants;
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.core.BasePreferenceController;
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
import com.android.settingslib.graph.SignalDrawable;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -65,6 +73,10 @@ public class MobileNetworkUtils {
|
|||||||
private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT =
|
private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT =
|
||||||
"android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
|
"android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
|
||||||
|
|
||||||
|
// The following constants are used to draw signal icon.
|
||||||
|
public static final int NO_CELL_DATA_TYPE_ICON = 0;
|
||||||
|
public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if DPC APNs are enforced.
|
* Returns if DPC APNs are enforced.
|
||||||
*/
|
*/
|
||||||
@@ -495,4 +507,32 @@ public class MobileNetworkUtils {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Drawable getSignalStrengthIcon(Context context, int level, int numLevels,
|
||||||
|
int iconType, boolean cutOut) {
|
||||||
|
SignalDrawable signalDrawable = new SignalDrawable(context);
|
||||||
|
signalDrawable.setLevel(
|
||||||
|
SignalDrawable.getState(level, numLevels, cutOut));
|
||||||
|
|
||||||
|
// Make the network type drawable
|
||||||
|
Drawable networkDrawable =
|
||||||
|
iconType == NO_CELL_DATA_TYPE_ICON
|
||||||
|
? EMPTY_DRAWABLE
|
||||||
|
: context
|
||||||
|
.getResources().getDrawable(iconType, context.getTheme());
|
||||||
|
|
||||||
|
// Overlay the two drawables
|
||||||
|
final Drawable[] layers = {networkDrawable, signalDrawable};
|
||||||
|
final int iconSize =
|
||||||
|
context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size);
|
||||||
|
|
||||||
|
LayerDrawable icons = new LayerDrawable(layers);
|
||||||
|
// Set the network type icon at the top left
|
||||||
|
icons.setLayerGravity(0 /* index of networkDrawable */, Gravity.TOP | Gravity.LEFT);
|
||||||
|
// Set the signal strength icon at the bottom right
|
||||||
|
icons.setLayerGravity(1 /* index of SignalDrawable */, Gravity.BOTTOM | Gravity.RIGHT);
|
||||||
|
icons.setLayerSize(1 /* index of SignalDrawable */, iconSize, iconSize);
|
||||||
|
icons.setTintList(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
|
||||||
|
return icons;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,22 +16,17 @@
|
|||||||
|
|
||||||
package com.android.settings.network.telephony;
|
package com.android.settings.network.telephony;
|
||||||
|
|
||||||
|
import static android.telephony.SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.drawable.ColorDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.graphics.drawable.LayerDrawable;
|
|
||||||
import android.telephony.CellInfo;
|
import android.telephony.CellInfo;
|
||||||
import android.telephony.CellSignalStrength;
|
import android.telephony.CellSignalStrength;
|
||||||
import android.telephony.SignalStrength;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
import com.android.settingslib.graph.SignalDrawable;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -45,18 +40,12 @@ public class NetworkOperatorPreference extends Preference {
|
|||||||
|
|
||||||
private static final int LEVEL_NONE = -1;
|
private static final int LEVEL_NONE = -1;
|
||||||
|
|
||||||
// number of signal strength level
|
|
||||||
public static final int NUMBER_OF_LEVELS = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
|
|
||||||
private CellInfo mCellInfo;
|
private CellInfo mCellInfo;
|
||||||
private List<String> mForbiddenPlmns;
|
private List<String> mForbiddenPlmns;
|
||||||
private int mLevel = LEVEL_NONE;
|
private int mLevel = LEVEL_NONE;
|
||||||
private boolean mShow4GForLTE;
|
private boolean mShow4GForLTE;
|
||||||
private boolean mUseNewApi;
|
private boolean mUseNewApi;
|
||||||
|
|
||||||
// The following constants are used to draw signal icon.
|
|
||||||
private static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
|
|
||||||
private static final int NO_CELL_DATA_CONNECTED_ICON = 0;
|
|
||||||
|
|
||||||
public NetworkOperatorPreference(
|
public NetworkOperatorPreference(
|
||||||
CellInfo cellinfo, Context context, List<String> forbiddenPlmns, boolean show4GForLTE) {
|
CellInfo cellinfo, Context context, List<String> forbiddenPlmns, boolean show4GForLTE) {
|
||||||
super(context);
|
super(context);
|
||||||
@@ -113,39 +102,16 @@ public class NetworkOperatorPreference extends Preference {
|
|||||||
case CellInfo.TYPE_CDMA:
|
case CellInfo.TYPE_CDMA:
|
||||||
return R.drawable.signal_strength_1x;
|
return R.drawable.signal_strength_1x;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateIcon(int level) {
|
private void updateIcon(int level) {
|
||||||
if (!mUseNewApi || level < 0 || level >= NUMBER_OF_LEVELS) {
|
if (!mUseNewApi || level < 0 || level >= NUM_SIGNAL_STRENGTH_BINS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Context context = getContext();
|
Context context = getContext();
|
||||||
SignalDrawable signalDrawable = new SignalDrawable(getContext());
|
setIcon(MobileNetworkUtils.getSignalStrengthIcon(context, level, NUM_SIGNAL_STRENGTH_BINS,
|
||||||
signalDrawable.setLevel(
|
getIconIdForCell(mCellInfo), false));
|
||||||
SignalDrawable.getState(level, NUMBER_OF_LEVELS, false /* cutOut */));
|
|
||||||
|
|
||||||
// Make the network type drawable
|
|
||||||
int iconType = getIconIdForCell(mCellInfo);
|
|
||||||
Drawable networkDrawable =
|
|
||||||
iconType == NO_CELL_DATA_CONNECTED_ICON
|
|
||||||
? EMPTY_DRAWABLE
|
|
||||||
: getContext()
|
|
||||||
.getResources().getDrawable(iconType, getContext().getTheme());
|
|
||||||
|
|
||||||
// Overlay the two drawables
|
|
||||||
final Drawable[] layers = {networkDrawable, signalDrawable};
|
|
||||||
final int iconSize =
|
|
||||||
context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size);
|
|
||||||
|
|
||||||
LayerDrawable icons = new LayerDrawable(layers);
|
|
||||||
// Set the network type icon at the top left
|
|
||||||
icons.setLayerGravity(0 /* index of networkDrawable */, Gravity.TOP | Gravity.LEFT);
|
|
||||||
// Set the signal strength icon at the bottom right
|
|
||||||
icons.setLayerGravity(1 /* index of SignalDrawable */, Gravity.BOTTOM | Gravity.RIGHT);
|
|
||||||
icons.setLayerSize(1 /* index of SignalDrawable */, iconSize, iconSize);
|
|
||||||
icons.setTintList(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
|
|
||||||
setIcon(icons);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,7 @@ import android.telephony.CellIdentity;
|
|||||||
import android.telephony.CellInfo;
|
import android.telephony.CellInfo;
|
||||||
import android.telephony.NetworkRegistrationInfo;
|
import android.telephony.NetworkRegistrationInfo;
|
||||||
import android.telephony.ServiceState;
|
import android.telephony.ServiceState;
|
||||||
|
import android.telephony.SignalStrength;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -336,7 +337,7 @@ public class NetworkSelectSettings extends DashboardFragment {
|
|||||||
pref.setSummary(R.string.network_connected);
|
pref.setSummary(R.string.network_connected);
|
||||||
// Update the signal strength icon, since the default signalStrength value would be
|
// Update the signal strength icon, since the default signalStrength value would be
|
||||||
// zero (it would be quite confusing why the connected network has no signal)
|
// zero (it would be quite confusing why the connected network has no signal)
|
||||||
pref.setIcon(NetworkOperatorPreference.NUMBER_OF_LEVELS - 1);
|
pref.setIcon(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1);
|
||||||
mConnectedPreferenceCategory.addPreference(pref);
|
mConnectedPreferenceCategory.addPreference(pref);
|
||||||
} else {
|
} else {
|
||||||
// Remove the connected network operators category
|
// Remove the connected network operators category
|
||||||
|
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.network.telephony;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.telephony.PhoneStateListener;
|
||||||
|
import android.telephony.SignalStrength;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.ArraySet;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
/** Helper class to manage listening to signal strength changes on a set of mobile network
|
||||||
|
* subscriptions */
|
||||||
|
public class SignalStrengthListener {
|
||||||
|
|
||||||
|
private TelephonyManager mBaseTelephonyManager;
|
||||||
|
private Callback mCallback;
|
||||||
|
private Map<Integer, PhoneStateListener> mListeners;
|
||||||
|
|
||||||
|
public interface Callback {
|
||||||
|
void onSignalStrengthChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignalStrengthListener(Context context, Callback callback) {
|
||||||
|
mBaseTelephonyManager = context.getSystemService(TelephonyManager.class);
|
||||||
|
mCallback = callback;
|
||||||
|
mListeners = new TreeMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resumes listening for signal strength changes for the set of ids from the last call to
|
||||||
|
* {@link #updateSubscriptionIds(Set)} */
|
||||||
|
public void resume() {
|
||||||
|
for (int subId : mListeners.keySet()) {
|
||||||
|
startListening(subId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pauses listening for signal strength changes */
|
||||||
|
public void pause() {
|
||||||
|
for (int subId : mListeners.keySet()) {
|
||||||
|
stopListening(subId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates the set of ids we want to be listening for, beginning to listen for any new ids and
|
||||||
|
* stopping listening for any ids not contained in the new set */
|
||||||
|
public void updateSubscriptionIds(Set<Integer> ids) {
|
||||||
|
Set<Integer> currentIds = new ArraySet<>(mListeners.keySet());
|
||||||
|
for (int idToRemove : Sets.difference(currentIds, ids)) {
|
||||||
|
stopListening(idToRemove);
|
||||||
|
mListeners.remove(idToRemove);
|
||||||
|
}
|
||||||
|
for (int idToAdd : Sets.difference(ids, currentIds)) {
|
||||||
|
PhoneStateListener listener = new PhoneStateListener() {
|
||||||
|
@Override
|
||||||
|
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
|
||||||
|
mCallback.onSignalStrengthChanged();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mListeners.put(idToAdd, listener);
|
||||||
|
startListening(idToAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startListening(int subId) {
|
||||||
|
TelephonyManager mgr = mBaseTelephonyManager.createForSubscriptionId(subId);
|
||||||
|
mgr.listen(mListeners.get(subId), PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopListening(int subId) {
|
||||||
|
TelephonyManager mgr = mBaseTelephonyManager.createForSubscriptionId(subId);
|
||||||
|
mgr.listen(mListeners.get(subId), PhoneStateListener.LISTEN_NONE);
|
||||||
|
}
|
||||||
|
}
|
@@ -16,11 +16,17 @@
|
|||||||
|
|
||||||
package com.android.settings.network;
|
package com.android.settings.network;
|
||||||
|
|
||||||
|
import static android.telephony.SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
|
||||||
|
import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GOOD;
|
||||||
|
import static android.telephony.SignalStrength.SIGNAL_STRENGTH_GREAT;
|
||||||
|
import static android.telephony.SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
|
||||||
|
import static android.telephony.SignalStrength.SIGNAL_STRENGTH_POOR;
|
||||||
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
@@ -33,16 +39,20 @@ import static org.mockito.Mockito.when;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.LayerDrawable;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.telephony.SignalStrength;
|
||||||
import android.telephony.SubscriptionInfo;
|
import android.telephony.SubscriptionInfo;
|
||||||
import android.telephony.SubscriptionManager;
|
import android.telephony.SubscriptionManager;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||||
|
import com.android.settingslib.graph.SignalDrawable;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -84,6 +94,8 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
private Network mActiveNetwork;
|
private Network mActiveNetwork;
|
||||||
@Mock
|
@Mock
|
||||||
private NetworkCapabilities mCapabilities;
|
private NetworkCapabilities mCapabilities;
|
||||||
|
@Mock
|
||||||
|
private Drawable mSignalStrengthIcon;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private LifecycleOwner mLifecycleOwner;
|
private LifecycleOwner mLifecycleOwner;
|
||||||
@@ -109,8 +121,10 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
mOnChildUpdatedCount = 0;
|
mOnChildUpdatedCount = 0;
|
||||||
mUpdateListener = () -> mOnChildUpdatedCount++;
|
mUpdateListener = () -> mOnChildUpdatedCount++;
|
||||||
|
|
||||||
mController = new SubscriptionsPreferenceController(mContext, mLifecycle, mUpdateListener,
|
mController = spy(
|
||||||
KEY, 5);
|
new SubscriptionsPreferenceController(mContext, mLifecycle, mUpdateListener,
|
||||||
|
KEY, 5));
|
||||||
|
doReturn(mSignalStrengthIcon).when(mController).getIcon(anyInt(), anyInt(), anyBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -120,32 +134,25 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isAvailable_oneSubscription_availableFalse() {
|
public void isAvailable_oneSubscription_availableFalse() {
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(
|
setupMockSubscriptions(1);
|
||||||
Arrays.asList(mock(SubscriptionInfo.class)));
|
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isAvailable_twoSubscriptions_availableTrue() {
|
public void isAvailable_twoSubscriptions_availableTrue() {
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(
|
setupMockSubscriptions(2);
|
||||||
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
|
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
assertThat(mController.isAvailable()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isAvailable_fiveSubscriptions_availableTrue() {
|
public void isAvailable_fiveSubscriptions_availableTrue() {
|
||||||
final ArrayList<SubscriptionInfo> subs = new ArrayList<>();
|
setupMockSubscriptions(5);
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
subs.add(mock(SubscriptionInfo.class));
|
|
||||||
}
|
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(subs);
|
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
assertThat(mController.isAvailable()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isAvailable_airplaneModeOn_availableFalse() {
|
public void isAvailable_airplaneModeOn_availableFalse() {
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(
|
setupMockSubscriptions(2);
|
||||||
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
|
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
assertThat(mController.isAvailable()).isTrue();
|
||||||
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
|
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
@@ -153,8 +160,7 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onAirplaneModeChanged_airplaneModeTurnedOn_eventFired() {
|
public void onAirplaneModeChanged_airplaneModeTurnedOn_eventFired() {
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(
|
setupMockSubscriptions(2);
|
||||||
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
|
|
||||||
mController.onResume();
|
mController.onResume();
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
assertThat(mController.isAvailable()).isTrue();
|
||||||
@@ -169,8 +175,7 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
@Test
|
@Test
|
||||||
public void onAirplaneModeChanged_airplaneModeTurnedOff_eventFired() {
|
public void onAirplaneModeChanged_airplaneModeTurnedOff_eventFired() {
|
||||||
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
|
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(
|
setupMockSubscriptions(2);
|
||||||
Arrays.asList(mock(SubscriptionInfo.class), mock(SubscriptionInfo.class)));
|
|
||||||
mController.onResume();
|
mController.onResume();
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
@@ -184,15 +189,14 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onSubscriptionsChanged_countBecameTwo_eventFired() {
|
public void onSubscriptionsChanged_countBecameTwo_eventFired() {
|
||||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2);
|
||||||
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
|
SubscriptionUtil.setActiveSubscriptionsForTesting(subs.subList(0, 1));
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1));
|
|
||||||
mController.onResume();
|
mController.onResume();
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
|
|
||||||
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
|
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
|
SubscriptionUtil.setActiveSubscriptionsForTesting(subs);
|
||||||
mController.onSubscriptionsChanged();
|
mController.onSubscriptionsChanged();
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
assertThat(mController.isAvailable()).isTrue();
|
||||||
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
|
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
|
||||||
@@ -200,18 +204,14 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onSubscriptionsChanged_countBecameOne_eventFiredAndPrefsRemoved() {
|
public void onSubscriptionsChanged_countBecameOne_eventFiredAndPrefsRemoved() {
|
||||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2);
|
||||||
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
|
|
||||||
when(sub1.getSubscriptionId()).thenReturn(1);
|
|
||||||
when(sub2.getSubscriptionId()).thenReturn(2);
|
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
|
|
||||||
mController.onResume();
|
mController.onResume();
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
assertThat(mController.isAvailable()).isTrue();
|
||||||
verify(mPreferenceCategory, times(2)).addPreference(any(Preference.class));
|
verify(mPreferenceCategory, times(2)).addPreference(any(Preference.class));
|
||||||
|
|
||||||
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
|
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1));
|
SubscriptionUtil.setActiveSubscriptionsForTesting(subs.subList(0, 1));
|
||||||
mController.onSubscriptionsChanged();
|
mController.onSubscriptionsChanged();
|
||||||
assertThat(mController.isAvailable()).isFalse();
|
assertThat(mController.isAvailable()).isFalse();
|
||||||
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
|
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
|
||||||
@@ -219,21 +219,12 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
verify(mPreferenceCategory, times(2)).removePreference(any(Preference.class));
|
verify(mPreferenceCategory, times(2)).removePreference(any(Preference.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onSubscriptionsChanged_subscriptionReplaced_preferencesChanged() {
|
public void onSubscriptionsChanged_subscriptionReplaced_preferencesChanged() {
|
||||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(3);
|
||||||
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
|
|
||||||
final SubscriptionInfo sub3 = mock(SubscriptionInfo.class);
|
|
||||||
when(sub1.getDisplayName()).thenReturn("sub1");
|
|
||||||
when(sub2.getDisplayName()).thenReturn("sub2");
|
|
||||||
when(sub3.getDisplayName()).thenReturn("sub3");
|
|
||||||
when(sub1.getSubscriptionId()).thenReturn(1);
|
|
||||||
when(sub2.getSubscriptionId()).thenReturn(2);
|
|
||||||
when(sub3.getSubscriptionId()).thenReturn(3);
|
|
||||||
|
|
||||||
// Start out with only sub1 and sub2.
|
// Start out with only sub1 and sub2.
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
|
SubscriptionUtil.setActiveSubscriptionsForTesting(subs.subList(0, 2));
|
||||||
mController.onResume();
|
mController.onResume();
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
final ArgumentCaptor<Preference> captor = ArgumentCaptor.forClass(Preference.class);
|
||||||
@@ -245,7 +236,7 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
// Now replace sub2 with sub3, and make sure the old preference was removed and the new
|
// Now replace sub2 with sub3, and make sure the old preference was removed and the new
|
||||||
// preference was added.
|
// preference was added.
|
||||||
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
|
final int updateCountBeforeSubscriptionChange = mOnChildUpdatedCount;
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub3));
|
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(subs.get(0), subs.get(2)));
|
||||||
mController.onSubscriptionsChanged();
|
mController.onSubscriptionsChanged();
|
||||||
assertThat(mController.isAvailable()).isTrue();
|
assertThat(mController.isAvailable()).isTrue();
|
||||||
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
|
assertThat(mOnChildUpdatedCount).isEqualTo(updateCountBeforeSubscriptionChange + 1);
|
||||||
@@ -264,14 +255,8 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
* @param subscriptionCount the number of subscriptions
|
* @param subscriptionCount the number of subscriptions
|
||||||
* @param selectedPrefIndex index of the subscription to click on
|
* @param selectedPrefIndex index of the subscription to click on
|
||||||
*/
|
*/
|
||||||
private void runPreferenceClickTest(int subscriptionCount, int selectedPrefIndex) {
|
private void runPreferenceClickTest(final int subscriptionCount, final int selectedPrefIndex) {
|
||||||
final ArrayList<SubscriptionInfo> subscriptions = new ArrayList<>();
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(subscriptionCount);
|
||||||
for (int i = 0; i < subscriptionCount; i++) {
|
|
||||||
final SubscriptionInfo sub = mock(SubscriptionInfo.class);
|
|
||||||
doReturn(i + 1).when(sub).getSubscriptionId();
|
|
||||||
subscriptions.add(sub);
|
|
||||||
}
|
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(subscriptions);
|
|
||||||
mController.displayPreference(mScreen);
|
mController.displayPreference(mScreen);
|
||||||
final ArgumentCaptor<Preference> prefCaptor = ArgumentCaptor.forClass(Preference.class);
|
final ArgumentCaptor<Preference> prefCaptor = ArgumentCaptor.forClass(Preference.class);
|
||||||
verify(mPreferenceCategory, times(subscriptionCount)).addPreference(prefCaptor.capture());
|
verify(mPreferenceCategory, times(subscriptionCount)).addPreference(prefCaptor.capture());
|
||||||
@@ -286,7 +271,7 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
final int subIdFromIntent = intent.getIntExtra(Settings.EXTRA_SUB_ID,
|
final int subIdFromIntent = intent.getIntExtra(Settings.EXTRA_SUB_ID,
|
||||||
INVALID_SUBSCRIPTION_ID);
|
INVALID_SUBSCRIPTION_ID);
|
||||||
assertThat(subIdFromIntent).isEqualTo(
|
assertThat(subIdFromIntent).isEqualTo(
|
||||||
subscriptions.get(selectedPrefIndex).getSubscriptionId());
|
subs.get(selectedPrefIndex).getSubscriptionId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -311,86 +296,248 @@ public class SubscriptionsPreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSummary_twoSubsOneDefaultForEverythingDataActive() {
|
public void getSummary_twoSubsOneDefaultForEverythingDataActive() {
|
||||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
setupMockSubscriptions(2);
|
||||||
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
|
|
||||||
when(sub1.getSubscriptionId()).thenReturn(11);
|
|
||||||
when(sub2.getSubscriptionId()).thenReturn(22);
|
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
|
|
||||||
|
|
||||||
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
|
|
||||||
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
|
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
|
||||||
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
|
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
|
||||||
when(mTelephonyManager.isDataEnabled()).thenReturn(true);
|
when(mTelephonyManager.isDataEnabled()).thenReturn(true);
|
||||||
when(mCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
|
when(mCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
|
||||||
|
|
||||||
assertThat(mController.getSummary(11)).isEqualTo(
|
assertThat(mController.getSummary(11, true)).isEqualTo(
|
||||||
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
|
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
|
||||||
+ mContext.getString(R.string.mobile_data_active));
|
+ mContext.getString(R.string.mobile_data_active));
|
||||||
|
|
||||||
assertThat(mController.getSummary(22)).isEqualTo(
|
assertThat(mController.getSummary(22, false)).isEqualTo(
|
||||||
mContext.getString(R.string.subscription_available));
|
mContext.getString(R.string.subscription_available));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSummary_twoSubsOneDefaultForEverythingDataNotActive() {
|
public void getSummary_twoSubsOneDefaultForEverythingDataNotActive() {
|
||||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
setupMockSubscriptions(2, 1, true);
|
||||||
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
|
|
||||||
when(sub1.getSubscriptionId()).thenReturn(11);
|
|
||||||
when(sub2.getSubscriptionId()).thenReturn(22);
|
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
|
|
||||||
|
|
||||||
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
|
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(1);
|
||||||
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
|
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(1);
|
||||||
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
|
|
||||||
when(mTelephonyManager.isDataEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
assertThat(mController.getSummary(11)).isEqualTo(
|
assertThat(mController.getSummary(1, true)).isEqualTo(
|
||||||
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
|
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
|
||||||
+ mContext.getString(R.string.default_for_mobile_data));
|
+ mContext.getString(R.string.default_for_mobile_data));
|
||||||
|
|
||||||
assertThat(mController.getSummary(22)).isEqualTo(
|
assertThat(mController.getSummary(2, false)).isEqualTo(
|
||||||
mContext.getString(R.string.subscription_available));
|
mContext.getString(R.string.subscription_available));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSummary_twoSubsOneDefaultForEverythingDataDisabled() {
|
public void getSummary_twoSubsOneDefaultForEverythingDataDisabled() {
|
||||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
setupMockSubscriptions(2);
|
||||||
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
|
|
||||||
when(sub1.getSubscriptionId()).thenReturn(11);
|
|
||||||
when(sub2.getSubscriptionId()).thenReturn(22);
|
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
|
|
||||||
|
|
||||||
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
|
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(1);
|
||||||
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(11);
|
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(1);
|
||||||
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
|
|
||||||
when(mTelephonyManager.isDataEnabled()).thenReturn(false);
|
|
||||||
|
|
||||||
assertThat(mController.getSummary(11)).isEqualTo(
|
assertThat(mController.getSummary(1, true)).isEqualTo(
|
||||||
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
|
mContext.getString(R.string.default_for_calls_and_sms) + System.lineSeparator()
|
||||||
+ mContext.getString(R.string.mobile_data_off));
|
+ mContext.getString(R.string.mobile_data_off));
|
||||||
|
|
||||||
assertThat(mController.getSummary(22)).isEqualTo(
|
assertThat(mController.getSummary(2, false)).isEqualTo(
|
||||||
mContext.getString(R.string.subscription_available));
|
mContext.getString(R.string.subscription_available));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSummary_twoSubsOneForCallsAndDataOneForSms() {
|
public void getSummary_twoSubsOneForCallsAndDataOneForSms() {
|
||||||
final SubscriptionInfo sub1 = mock(SubscriptionInfo.class);
|
setupMockSubscriptions(2, 1, true);
|
||||||
final SubscriptionInfo sub2 = mock(SubscriptionInfo.class);
|
|
||||||
when(sub1.getSubscriptionId()).thenReturn(11);
|
|
||||||
when(sub2.getSubscriptionId()).thenReturn(22);
|
|
||||||
SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2));
|
|
||||||
|
|
||||||
ShadowSubscriptionManager.setDefaultDataSubscriptionId(11);
|
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(2);
|
||||||
ShadowSubscriptionManager.setDefaultSmsSubscriptionId(22);
|
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(1);
|
||||||
ShadowSubscriptionManager.setDefaultVoiceSubscriptionId(11);
|
|
||||||
when(mTelephonyManager.isDataEnabled()).thenReturn(true);
|
|
||||||
|
|
||||||
assertThat(mController.getSummary(11)).isEqualTo(
|
assertThat(mController.getSummary(1, true)).isEqualTo(
|
||||||
mContext.getString(R.string.default_for_calls) + System.lineSeparator()
|
mContext.getString(R.string.default_for_calls) + System.lineSeparator()
|
||||||
+ mContext.getString(R.string.default_for_mobile_data));
|
+ mContext.getString(R.string.default_for_mobile_data));
|
||||||
|
|
||||||
assertThat(mController.getSummary(22)).isEqualTo(
|
assertThat(mController.getSummary(2, false)).isEqualTo(
|
||||||
mContext.getString(R.string.default_for_sms));
|
mContext.getString(R.string.default_for_sms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setIcon_nullStrength_noCrash() {
|
||||||
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2);
|
||||||
|
setMockSubSignalStrength(subs, 0, -1);
|
||||||
|
final Preference pref = mock(Preference.class);
|
||||||
|
|
||||||
|
mController.setIcon(pref, 1, true /* isDefaultForData */);
|
||||||
|
verify(mController).getIcon(eq(0), eq(NUM_SIGNAL_STRENGTH_BINS), eq(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setIcon_noSignal_correctLevels() {
|
||||||
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
|
||||||
|
setMockSubSignalStrength(subs, 0, SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||||
|
setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||||
|
setMockSubDataEnabled(subs, 0, true);
|
||||||
|
final Preference pref = mock(Preference.class);
|
||||||
|
|
||||||
|
mController.setIcon(pref, 1, true /* isDefaultForData */);
|
||||||
|
verify(mController).getIcon(eq(0), eq(NUM_SIGNAL_STRENGTH_BINS), eq(false));
|
||||||
|
|
||||||
|
mController.setIcon(pref, 2, false /* isDefaultForData */);
|
||||||
|
verify(mController).getIcon(eq(0), eq(NUM_SIGNAL_STRENGTH_BINS), eq(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setIcon_noSignal_withInflation_correctLevels() {
|
||||||
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
|
||||||
|
setMockSubSignalStrength(subs, 0, SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||||
|
setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
|
||||||
|
final Preference pref = mock(Preference.class);
|
||||||
|
doReturn(true).when(mController).shouldInflateSignalStrength(anyInt());
|
||||||
|
|
||||||
|
mController.setIcon(pref, 1, true /* isDefaultForData */);
|
||||||
|
verify(mController).getIcon(eq(1), eq(NUM_SIGNAL_STRENGTH_BINS + 1), eq(false));
|
||||||
|
|
||||||
|
mController.setIcon(pref, 2, false /* isDefaultForData */);
|
||||||
|
verify(mController).getIcon(eq(1), eq(NUM_SIGNAL_STRENGTH_BINS + 1), eq(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void setIcon_greatSignal_correctLevels() {
|
||||||
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
|
||||||
|
setMockSubSignalStrength(subs, 0, SIGNAL_STRENGTH_GREAT);
|
||||||
|
setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_GREAT);
|
||||||
|
final Preference pref = mock(Preference.class);
|
||||||
|
|
||||||
|
mController.setIcon(pref, 1, true /* isDefaultForData */);
|
||||||
|
verify(mController).getIcon(eq(4), eq(NUM_SIGNAL_STRENGTH_BINS), eq(false));
|
||||||
|
|
||||||
|
mController.setIcon(pref, 2, false /* isDefaultForData */);
|
||||||
|
verify(mController).getIcon(eq(4), eq(NUM_SIGNAL_STRENGTH_BINS), eq(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onSignalStrengthChanged_subTwoGoesFromGoodToGreat_correctLevels() {
|
||||||
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2);
|
||||||
|
setMockSubSignalStrength(subs, 0, SIGNAL_STRENGTH_POOR);
|
||||||
|
setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_GOOD);
|
||||||
|
|
||||||
|
mController.onResume();
|
||||||
|
mController.displayPreference(mScreen);
|
||||||
|
|
||||||
|
// Now change the signal strength for the 2nd subscription from Good to Great
|
||||||
|
setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_GREAT);
|
||||||
|
mController.onSignalStrengthChanged();
|
||||||
|
|
||||||
|
final ArgumentCaptor<Integer> level = ArgumentCaptor.forClass(Integer.class);
|
||||||
|
verify(mController, times(4)).getIcon(level.capture(), eq(NUM_SIGNAL_STRENGTH_BINS),
|
||||||
|
eq(true));
|
||||||
|
assertThat(level.getAllValues().get(0)).isEqualTo(1);
|
||||||
|
assertThat(level.getAllValues().get(1)).isEqualTo(3); // sub2, first time
|
||||||
|
assertThat(level.getAllValues().get(2)).isEqualTo(1);
|
||||||
|
assertThat(level.getAllValues().get(3)).isEqualTo(4); // sub2, after change
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void displayPreference_mobileDataOff_bothSubsHaveCutOut() {
|
||||||
|
setupMockSubscriptions(2, 1, false);
|
||||||
|
|
||||||
|
mController.onResume();
|
||||||
|
mController.displayPreference(mScreen);
|
||||||
|
|
||||||
|
verify(mController, times(2)).getIcon(eq(SIGNAL_STRENGTH_GOOD),
|
||||||
|
eq(NUM_SIGNAL_STRENGTH_BINS), eq(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void displayPreference_mobileDataOn_onlyNonDefaultSubHasCutOut() {
|
||||||
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
|
||||||
|
setMockSubSignalStrength(subs, 1, SIGNAL_STRENGTH_POOR);
|
||||||
|
|
||||||
|
mController.onResume();
|
||||||
|
mController.displayPreference(mScreen);
|
||||||
|
|
||||||
|
verify(mController).getIcon(eq(SIGNAL_STRENGTH_GOOD), eq(NUM_SIGNAL_STRENGTH_BINS),
|
||||||
|
eq(false));
|
||||||
|
verify(mController).getIcon(eq(SIGNAL_STRENGTH_POOR), eq(NUM_SIGNAL_STRENGTH_BINS),
|
||||||
|
eq(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onMobileDataEnabledChange_mobileDataTurnedOff_bothSubsHaveCutOut() {
|
||||||
|
final List<SubscriptionInfo> subs = setupMockSubscriptions(2, 1, true);
|
||||||
|
|
||||||
|
mController.onResume();
|
||||||
|
mController.displayPreference(mScreen);
|
||||||
|
|
||||||
|
setMockSubDataEnabled(subs, 0, false);
|
||||||
|
mController.onMobileDataEnabledChange();
|
||||||
|
|
||||||
|
final ArgumentCaptor<Boolean> cutOutCaptor = ArgumentCaptor.forClass(Boolean.class);
|
||||||
|
verify(mController, times(4)).getIcon(eq(SIGNAL_STRENGTH_GOOD),
|
||||||
|
eq(NUM_SIGNAL_STRENGTH_BINS), cutOutCaptor.capture());
|
||||||
|
assertThat(cutOutCaptor.getAllValues().get(0)).isEqualTo(false); // sub1, first time
|
||||||
|
assertThat(cutOutCaptor.getAllValues().get(1)).isEqualTo(true);
|
||||||
|
assertThat(cutOutCaptor.getAllValues().get(2)).isEqualTo(true); // sub1, second time
|
||||||
|
assertThat(cutOutCaptor.getAllValues().get(3)).isEqualTo(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SubscriptionInfo> setupMockSubscriptions(int count) {
|
||||||
|
return setupMockSubscriptions(count, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Helper method to setup several mock active subscriptions. The generated subscription id's
|
||||||
|
* start at 1.
|
||||||
|
*
|
||||||
|
* @param count How many subscriptions to create
|
||||||
|
* @param defaultDataSubId The subscription id of the default data subscription - pass
|
||||||
|
* INVALID_SUBSCRIPTION_ID if there should not be one
|
||||||
|
* @param mobileDataEnabled Whether mobile data should be considered enabled for the default
|
||||||
|
* data subscription
|
||||||
|
*/
|
||||||
|
private List<SubscriptionInfo> setupMockSubscriptions(int count, int defaultDataSubId,
|
||||||
|
boolean mobileDataEnabled) {
|
||||||
|
if (defaultDataSubId != INVALID_SUBSCRIPTION_ID) {
|
||||||
|
ShadowSubscriptionManager.setDefaultDataSubscriptionId(defaultDataSubId);
|
||||||
|
}
|
||||||
|
final ArrayList<SubscriptionInfo> infos = new ArrayList<>();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
final int subscriptionId = i + 1;
|
||||||
|
final SubscriptionInfo info = mock(SubscriptionInfo.class);
|
||||||
|
final TelephonyManager mgrForSub = mock(TelephonyManager.class);
|
||||||
|
final SignalStrength signalStrength = mock(SignalStrength.class);
|
||||||
|
|
||||||
|
if (subscriptionId == defaultDataSubId) {
|
||||||
|
when(mgrForSub.isDataEnabled()).thenReturn(mobileDataEnabled);
|
||||||
|
}
|
||||||
|
when(info.getSubscriptionId()).thenReturn(i + 1);
|
||||||
|
when(info.getDisplayName()).thenReturn("sub" + (i + 1));
|
||||||
|
doReturn(mgrForSub).when(mTelephonyManager).createForSubscriptionId(eq(subscriptionId));
|
||||||
|
when(mgrForSub.getSignalStrength()).thenReturn(signalStrength);
|
||||||
|
when(signalStrength.getLevel()).thenReturn(SIGNAL_STRENGTH_GOOD);
|
||||||
|
|
||||||
|
infos.add(info);
|
||||||
|
}
|
||||||
|
SubscriptionUtil.setActiveSubscriptionsForTesting(infos);
|
||||||
|
return infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to set the signal strength returned for a mock subscription
|
||||||
|
* @param subs The list of subscriptions
|
||||||
|
* @param index The index in of the subscription in |subs| to change
|
||||||
|
* @param level The signal strength level to return for the subscription. Pass -1 to force
|
||||||
|
* return of a null SignalStrength object for the subscription.
|
||||||
|
*/
|
||||||
|
private void setMockSubSignalStrength(List<SubscriptionInfo> subs, int index, int level) {
|
||||||
|
final TelephonyManager mgrForSub =
|
||||||
|
mTelephonyManager.createForSubscriptionId(subs.get(index).getSubscriptionId());
|
||||||
|
if (level == -1) {
|
||||||
|
when(mgrForSub.getSignalStrength()).thenReturn(null);
|
||||||
|
} else {
|
||||||
|
final SignalStrength signalStrength = mgrForSub.getSignalStrength();
|
||||||
|
when(signalStrength.getLevel()).thenReturn(level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMockSubDataEnabled(List<SubscriptionInfo> subs, int index, boolean enabled) {
|
||||||
|
final TelephonyManager mgrForSub =
|
||||||
|
mTelephonyManager.createForSubscriptionId(subs.get(index).getSubscriptionId());
|
||||||
|
when(mgrForSub.isDataEnabled()).thenReturn(enabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settings.network.telephony;
|
||||||
|
|
||||||
|
import static android.telephony.PhoneStateListener.LISTEN_NONE;
|
||||||
|
import static android.telephony.PhoneStateListener.LISTEN_SIGNAL_STRENGTHS;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.telephony.PhoneStateListener;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.mockito.internal.util.collections.Sets;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public class SignalStrengthListenerTest {
|
||||||
|
private static final int SUB_ID_1 = 111;
|
||||||
|
private static final int SUB_ID_2 = 222;
|
||||||
|
private static final int SUB_ID_3 = 333;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private SignalStrengthListener.Callback mCallback;
|
||||||
|
@Mock
|
||||||
|
private TelephonyManager mBaseManager;
|
||||||
|
@Mock
|
||||||
|
private TelephonyManager mManager1;
|
||||||
|
@Mock
|
||||||
|
private TelephonyManager mManager2;
|
||||||
|
@Mock
|
||||||
|
private TelephonyManager mManager3;
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private SignalStrengthListener mListener;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mBaseManager);
|
||||||
|
when(mBaseManager.createForSubscriptionId(SUB_ID_1)).thenReturn(mManager1);
|
||||||
|
when(mBaseManager.createForSubscriptionId(SUB_ID_2)).thenReturn(mManager2);
|
||||||
|
when(mBaseManager.createForSubscriptionId(SUB_ID_3)).thenReturn(mManager3);
|
||||||
|
mListener = new SignalStrengthListener(mContext, mCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resume_noIds_noCrash() {
|
||||||
|
mListener.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void pause_noIds_noCrash() {
|
||||||
|
mListener.resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateSubscriptionIds_beforeResume_startedListening() {
|
||||||
|
mListener.updateSubscriptionIds(Sets.newSet(SUB_ID_1, SUB_ID_2));
|
||||||
|
ArgumentCaptor<PhoneStateListener> captor1 = ArgumentCaptor.forClass(
|
||||||
|
PhoneStateListener.class);
|
||||||
|
ArgumentCaptor<PhoneStateListener> captor2 = ArgumentCaptor.forClass(
|
||||||
|
PhoneStateListener.class);
|
||||||
|
verify(mManager1).listen(captor1.capture(), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
verify(mManager2).listen(captor2.capture(), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
verify(mManager3, never()).listen(any(), anyInt());
|
||||||
|
assertThat(captor1.getValue()).isNotNull();
|
||||||
|
assertThat(captor2.getValue()).isNotNull();
|
||||||
|
|
||||||
|
// Make sure the two listeners are separate objects.
|
||||||
|
assertThat(captor1.getValue() != captor2.getValue()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateSubscriptionIds_twoCalls_oneIdAdded() {
|
||||||
|
mListener.updateSubscriptionIds(Sets.newSet(SUB_ID_1, SUB_ID_2));
|
||||||
|
verify(mManager1).listen(any(PhoneStateListener.class), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
verify(mManager2).listen(any(PhoneStateListener.class), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
|
||||||
|
mListener.updateSubscriptionIds(Sets.newSet(SUB_ID_1, SUB_ID_2, SUB_ID_3));
|
||||||
|
verify(mManager1, never()).listen(any(PhoneStateListener.class), eq(LISTEN_NONE));
|
||||||
|
verify(mManager2, never()).listen(any(PhoneStateListener.class), eq(LISTEN_NONE));
|
||||||
|
verify(mManager3).listen(any(PhoneStateListener.class), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateSubscriptionIds_twoCalls_oneIdRemoved() {
|
||||||
|
ArgumentCaptor<PhoneStateListener> captor1 = ArgumentCaptor.forClass(
|
||||||
|
PhoneStateListener.class);
|
||||||
|
|
||||||
|
mListener.updateSubscriptionIds(Sets.newSet(SUB_ID_1, SUB_ID_2));
|
||||||
|
verify(mManager1).listen(captor1.capture(), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
verify(mManager2).listen(any(PhoneStateListener.class), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
|
||||||
|
mListener.updateSubscriptionIds(Sets.newSet(SUB_ID_2));
|
||||||
|
verify(mManager1).listen(captor1.capture(), eq(LISTEN_NONE));
|
||||||
|
verify(mManager2, never()).listen(any(PhoneStateListener.class), eq(LISTEN_NONE));
|
||||||
|
// Make sure the correct listener was removed.
|
||||||
|
assertThat(captor1.getAllValues().get(0) == captor1.getAllValues().get(1)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateSubscriptionIds_twoCalls_twoIdsRemovedOneAdded() {
|
||||||
|
ArgumentCaptor<PhoneStateListener> captor1 = ArgumentCaptor.forClass(
|
||||||
|
PhoneStateListener.class);
|
||||||
|
ArgumentCaptor<PhoneStateListener> captor2 = ArgumentCaptor.forClass(
|
||||||
|
PhoneStateListener.class);
|
||||||
|
|
||||||
|
mListener.updateSubscriptionIds(Sets.newSet(SUB_ID_1, SUB_ID_2));
|
||||||
|
verify(mManager1).listen(captor1.capture(), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
verify(mManager2).listen(captor2.capture(), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
|
||||||
|
mListener.updateSubscriptionIds(Sets.newSet(SUB_ID_3));
|
||||||
|
verify(mManager1).listen(captor1.capture(), eq(LISTEN_NONE));
|
||||||
|
verify(mManager2).listen(captor2.capture(), eq(LISTEN_NONE));
|
||||||
|
verify(mManager3).listen(any(PhoneStateListener.class), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
// Make sure the correct listeners were removed.
|
||||||
|
assertThat(captor1.getValue() != captor2.getValue()).isTrue();
|
||||||
|
assertThat(captor1.getAllValues().get(0) == captor1.getAllValues().get(1)).isTrue();
|
||||||
|
assertThat(captor2.getAllValues().get(0) == captor2.getAllValues().get(1)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void updateSubscriptionIds_thenPauseResume_correctlyStartsAndStops() {
|
||||||
|
mListener.updateSubscriptionIds(Sets.newSet(SUB_ID_1, SUB_ID_2));
|
||||||
|
mListener.pause();
|
||||||
|
mListener.resume();
|
||||||
|
|
||||||
|
ArgumentCaptor<PhoneStateListener> captor1 = ArgumentCaptor.forClass(
|
||||||
|
PhoneStateListener.class);
|
||||||
|
ArgumentCaptor<PhoneStateListener> captor2 = ArgumentCaptor.forClass(
|
||||||
|
PhoneStateListener.class);
|
||||||
|
verify(mManager1, times(2)).listen(captor1.capture(), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
verify(mManager1).listen(captor1.capture(), eq(LISTEN_NONE));
|
||||||
|
|
||||||
|
verify(mManager2, times(2)).listen(captor2.capture(), eq(LISTEN_SIGNAL_STRENGTHS));
|
||||||
|
verify(mManager2).listen(captor2.capture(), eq(LISTEN_NONE));
|
||||||
|
|
||||||
|
assertThat(captor1.getAllValues().get(0) == captor1.getAllValues().get(1)).isTrue();
|
||||||
|
assertThat(captor1.getAllValues().get(0) == captor1.getAllValues().get(2)).isTrue();
|
||||||
|
|
||||||
|
assertThat(captor2.getAllValues().get(0) == captor2.getAllValues().get(1)).isTrue();
|
||||||
|
assertThat(captor2.getAllValues().get(0) == captor2.getAllValues().get(2)).isTrue();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user