Merge "Add signal strength icons to multi-SIM header" into qt-dev
am: 42c451610e
Change-Id: I99abda9f54a97f0103c926ded07f027fac1d5482
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_RESUME;
|
||||
|
||||
import static com.android.settings.network.telephony.MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.SignalStrength;
|
||||
import android.telephony.SubscriptionInfo;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.collection.ArrayMap;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleObserver;
|
||||
@@ -40,9 +46,14 @@ import androidx.preference.PreferenceScreen;
|
||||
import com.android.settings.R;
|
||||
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.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.net.SignalStrengthUtil;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 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
|
||||
LifecycleObserver, SubscriptionsChangeListener.SubscriptionsChangeListenerClient,
|
||||
MobileDataEnabledListener.Client, DataConnectivityListener.Client {
|
||||
MobileDataEnabledListener.Client, DataConnectivityListener.Client,
|
||||
SignalStrengthListener.Callback {
|
||||
private static final String TAG = "SubscriptionsPrefCntrlr";
|
||||
|
||||
private UpdateListener mUpdateListener;
|
||||
@@ -62,6 +74,8 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
private SubscriptionsChangeListener mSubscriptionsListener;
|
||||
private MobileDataEnabledListener mDataEnabledListener;
|
||||
private DataConnectivityListener mConnectivityListener;
|
||||
private SignalStrengthListener mSignalStrengthListener;
|
||||
|
||||
|
||||
// Map of subscription id to Preference
|
||||
private Map<Integer, Preference> mSubscriptionPreferences;
|
||||
@@ -102,6 +116,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mSubscriptionsListener = new SubscriptionsChangeListener(context, this);
|
||||
mDataEnabledListener = new MobileDataEnabledListener(context, this);
|
||||
mConnectivityListener = new DataConnectivityListener(context, this);
|
||||
mSignalStrengthListener = new SignalStrengthListener(context, this);
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
|
||||
@@ -110,6 +125,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mSubscriptionsListener.start();
|
||||
mDataEnabledListener.start(SubscriptionManager.getDefaultDataSubscriptionId());
|
||||
mConnectivityListener.start();
|
||||
mSignalStrengthListener.resume();
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -118,6 +134,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mSubscriptionsListener.stop();
|
||||
mDataEnabledListener.stop();
|
||||
mConnectivityListener.stop();
|
||||
mSignalStrengthListener.pause();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -136,6 +153,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mPreferenceGroup.removePreference(pref);
|
||||
}
|
||||
mSubscriptionPreferences.clear();
|
||||
mSignalStrengthListener.updateSubscriptionIds(Collections.emptySet());
|
||||
mUpdateListener.onChildrenUpdated();
|
||||
return;
|
||||
}
|
||||
@@ -144,16 +162,20 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
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 subId = info.getSubscriptionId();
|
||||
activeSubIds.add(subId);
|
||||
Preference pref = existingPrefs.remove(subId);
|
||||
if (pref == null) {
|
||||
pref = new Preference(mPreferenceGroup.getContext());
|
||||
mPreferenceGroup.addPreference(pref);
|
||||
}
|
||||
pref.setTitle(info.getDisplayName());
|
||||
pref.setSummary(getSummary(subId));
|
||||
pref.setIcon(R.drawable.ic_network_cell);
|
||||
final boolean isDefaultForData = (subId == dataDefaultSubId);
|
||||
pref.setSummary(getSummary(subId, isDefaultForData));
|
||||
setIcon(pref, subId, isDefaultForData);
|
||||
pref.setOrder(order++);
|
||||
|
||||
pref.setOnPreferenceClickListener(clickedPref -> {
|
||||
@@ -165,6 +187,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
|
||||
mSubscriptionPreferences.put(subId, pref);
|
||||
}
|
||||
mSignalStrengthListener.updateSubscriptionIds(activeSubIds);
|
||||
|
||||
// Remove any old preferences that no longer map to a subscription.
|
||||
for (Preference pref : existingPrefs.values()) {
|
||||
@@ -173,6 +196,32 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
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() {
|
||||
final Network activeNetwork = mConnectivityManager.getActiveNetwork();
|
||||
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.
|
||||
*/
|
||||
protected String getSummary(int subId) {
|
||||
protected String getSummary(int subId, boolean isDefaultForData) {
|
||||
final int callsDefaultSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
|
||||
final int smsDefaultSubId = SubscriptionManager.getDefaultSmsSubscriptionId();
|
||||
final int dataDefaultSubId = SubscriptionManager.getDefaultDataSubscriptionId();
|
||||
|
||||
String line1 = null;
|
||||
if (subId == callsDefaultSubId && subId == smsDefaultSubId) {
|
||||
@@ -212,10 +260,10 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
}
|
||||
|
||||
String line2 = null;
|
||||
if (subId == dataDefaultSubId) {
|
||||
if (isDefaultForData) {
|
||||
final TelephonyManager telMgrForSub = mContext.getSystemService(
|
||||
TelephonyManager.class).createForSubscriptionId(subId);
|
||||
boolean dataEnabled = telMgrForSub.isDataEnabled();
|
||||
final boolean dataEnabled = telMgrForSub.isDataEnabled();
|
||||
if (dataEnabled && activeNetworkIsCellular()) {
|
||||
line2 = mContext.getString(R.string.mobile_data_active);
|
||||
} else if (!dataEnabled) {
|
||||
@@ -277,4 +325,9 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
public void onDataConnectivityChange() {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSignalStrengthChanged() {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,10 @@ import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
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.SystemProperties;
|
||||
import android.provider.Settings;
|
||||
@@ -37,6 +41,7 @@ import android.telephony.euicc.EuiccManager;
|
||||
import android.telephony.ims.feature.ImsFeature;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
@@ -45,7 +50,10 @@ import com.android.ims.ImsManager;
|
||||
import com.android.internal.telephony.Phone;
|
||||
import com.android.internal.telephony.PhoneConstants;
|
||||
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.settingslib.graph.SignalDrawable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -65,6 +73,10 @@ public class MobileNetworkUtils {
|
||||
private static final String LEGACY_ACTION_CONFIGURE_PHONE_ACCOUNT =
|
||||
"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.
|
||||
*/
|
||||
@@ -495,4 +507,32 @@ public class MobileNetworkUtils {
|
||||
|
||||
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;
|
||||
|
||||
import static android.telephony.SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
|
||||
|
||||
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.CellSignalStrength;
|
||||
import android.telephony.SignalStrength;
|
||||
import android.util.Log;
|
||||
import android.view.Gravity;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settingslib.graph.SignalDrawable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -45,18 +40,12 @@ public class NetworkOperatorPreference extends Preference {
|
||||
|
||||
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 List<String> mForbiddenPlmns;
|
||||
private int mLevel = LEVEL_NONE;
|
||||
private boolean mShow4GForLTE;
|
||||
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(
|
||||
CellInfo cellinfo, Context context, List<String> forbiddenPlmns, boolean show4GForLTE) {
|
||||
super(context);
|
||||
@@ -113,39 +102,16 @@ public class NetworkOperatorPreference extends Preference {
|
||||
case CellInfo.TYPE_CDMA:
|
||||
return R.drawable.signal_strength_1x;
|
||||
default:
|
||||
return 0;
|
||||
return MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateIcon(int level) {
|
||||
if (!mUseNewApi || level < 0 || level >= NUMBER_OF_LEVELS) {
|
||||
if (!mUseNewApi || level < 0 || level >= NUM_SIGNAL_STRENGTH_BINS) {
|
||||
return;
|
||||
}
|
||||
Context context = getContext();
|
||||
SignalDrawable signalDrawable = new SignalDrawable(getContext());
|
||||
signalDrawable.setLevel(
|
||||
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);
|
||||
setIcon(MobileNetworkUtils.getSignalStrengthIcon(context, level, NUM_SIGNAL_STRENGTH_BINS,
|
||||
getIconIdForCell(mCellInfo), false));
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ import android.telephony.CellIdentity;
|
||||
import android.telephony.CellInfo;
|
||||
import android.telephony.NetworkRegistrationInfo;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SignalStrength;
|
||||
import android.telephony.SubscriptionManager;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
@@ -336,7 +337,7 @@ public class NetworkSelectSettings extends DashboardFragment {
|
||||
pref.setSummary(R.string.network_connected);
|
||||
// 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)
|
||||
pref.setIcon(NetworkOperatorPreference.NUMBER_OF_LEVELS - 1);
|
||||
pref.setIcon(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1);
|
||||
mConnectedPreferenceCategory.addPreference(pref);
|
||||
} else {
|
||||
// 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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user