am a8fb5803: Merge "Offer to "merge" subscribers for data usage." into lmp-mr1-dev

* commit 'a8fb580379b83b7fc76ee5b99149bbc8a2ce44ab':
  Offer to "merge" subscribers for data usage.
This commit is contained in:
Jeff Sharkey
2014-12-08 18:04:02 +00:00
committed by Android Git Automerger
14 changed files with 266 additions and 222 deletions

View File

@@ -68,9 +68,6 @@ interface IConnectivityManager
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
/** Policy control over specific {@link NetworkStateTracker}. */
void setPolicyDataEnable(int networkType, boolean enabled);
int tether(String iface);
int untether(String iface);

View File

@@ -25,6 +25,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.telephony.TelephonyManager;
import android.util.Slog;
import java.util.Objects;
@@ -35,6 +36,8 @@ import java.util.Objects;
* @hide
*/
public class NetworkIdentity implements Comparable<NetworkIdentity> {
private static final String TAG = "NetworkIdentity";
/**
* When enabled, combine all {@link #mSubType} together under
* {@link #SUBTYPE_COMBINED}.
@@ -132,6 +135,18 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
}
}
/**
* Scrub given IMSI on production builds.
*/
public static String[] scrubSubscriberId(String[] subscriberId) {
if (subscriberId == null) return null;
final String[] res = new String[subscriberId.length];
for (int i = 0; i < res.length; i++) {
res[i] = NetworkIdentity.scrubSubscriberId(subscriberId[i]);
}
return res;
}
/**
* Build a {@link NetworkIdentity} from the given {@link NetworkState},
* assuming that any mobile networks are using the current IMSI.
@@ -140,23 +155,18 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
final int type = state.networkInfo.getType();
final int subType = state.networkInfo.getSubtype();
// TODO: consider moving subscriberId over to LinkCapabilities, so it
// comes from an authoritative source.
String subscriberId = null;
String networkId = null;
boolean roaming = false;
if (isNetworkTypeMobile(type)) {
final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
Context.TELEPHONY_SERVICE);
roaming = telephony.isNetworkRoaming();
if (state.subscriberId != null) {
subscriberId = state.subscriberId;
} else {
subscriberId = telephony.getSubscriberId();
if (state.subscriberId == null) {
Slog.w(TAG, "Active mobile network without subscriber!");
}
subscriberId = state.subscriberId;
roaming = state.networkInfo.isRoaming();
} else if (type == TYPE_WIFI) {
if (state.networkId != null) {
networkId = state.networkId;

View File

@@ -20,15 +20,18 @@ import android.os.Parcel;
import android.os.Parcelable;
/**
* A grab-bag of information (metadata, policies, properties, etc) about a {@link Network}.
* A grab-bag of information (metadata, policies, properties, etc) about a
* {@link Network}. Since this contains PII, it should not be sent outside the
* system.
*
* @hide
*/
public class NetworkMisc implements Parcelable {
/**
* If the {@link Network} is a VPN, whether apps are allowed to bypass the VPN. This is set by
* a {@link VpnService} and used by {@link ConnectivityService} when creating a VPN.
* If the {@link Network} is a VPN, whether apps are allowed to bypass the
* VPN. This is set by a {@link VpnService} and used by
* {@link ConnectivityManager} when creating a VPN.
*/
public boolean allowBypass;
@@ -41,6 +44,11 @@ public class NetworkMisc implements Parcelable {
*/
public boolean explicitlySelected;
/**
* For mobile networks, this is the subscriber ID (such as IMSI).
*/
public String subscriberId;
public NetworkMisc() {
}
@@ -48,6 +56,7 @@ public class NetworkMisc implements Parcelable {
if (nm != null) {
allowBypass = nm.allowBypass;
explicitlySelected = nm.explicitlySelected;
subscriberId = nm.subscriberId;
}
}
@@ -60,6 +69,7 @@ public class NetworkMisc implements Parcelable {
public void writeToParcel(Parcel out, int flags) {
out.writeInt(allowBypass ? 1 : 0);
out.writeInt(explicitlySelected ? 1 : 0);
out.writeString(subscriberId);
}
public static final Creator<NetworkMisc> CREATOR = new Creator<NetworkMisc>() {
@@ -68,6 +78,7 @@ public class NetworkMisc implements Parcelable {
NetworkMisc networkMisc = new NetworkMisc();
networkMisc.allowBypass = in.readInt() != 0;
networkMisc.explicitlySelected = in.readInt() != 0;
networkMisc.subscriberId = in.readString();
return networkMisc;
}

View File

@@ -35,7 +35,7 @@ public class NetworkPolicy implements Parcelable, Comparable<NetworkPolicy> {
public static final long LIMIT_DISABLED = -1;
public static final long SNOOZE_NEVER = -1;
public final NetworkTemplate template;
public NetworkTemplate template;
public int cycleDay;
public String cycleTimezone;
public long warningBytes;

View File

@@ -30,15 +30,9 @@ public class NetworkState implements Parcelable {
public final LinkProperties linkProperties;
public final NetworkCapabilities networkCapabilities;
public final Network network;
/** Currently only used by testing. */
public final String subscriberId;
public final String networkId;
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
NetworkCapabilities networkCapabilities, Network network) {
this(networkInfo, linkProperties, networkCapabilities, network, null, null);
}
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
NetworkCapabilities networkCapabilities, Network network, String subscriberId,
String networkId) {
@@ -85,5 +79,4 @@ public class NetworkState implements Parcelable {
return new NetworkState[size];
}
};
}

View File

@@ -22,7 +22,6 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
import static android.net.NetworkIdentity.scrubSubscriberId;
import static android.net.wifi.WifiInfo.removeDoubleQuotes;
import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
@@ -36,7 +35,9 @@ import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import java.util.Arrays;
import java.util.Objects;
/**
@@ -146,17 +147,35 @@ public class NetworkTemplate implements Parcelable {
private final int mMatchRule;
private final String mSubscriberId;
/**
* Ugh, templates are designed to target a single subscriber, but we might
* need to match several "merged" subscribers. These are the subscribers
* that should be considered to match this template.
* <p>
* Since the merge set is dynamic, it should <em>not</em> be persisted or
* used for determining equality.
*/
private final String[] mMatchSubscriberIds;
private final String mNetworkId;
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
}
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId) {
mMatchRule = matchRule;
mSubscriberId = subscriberId;
mMatchSubscriberIds = matchSubscriberIds;
mNetworkId = networkId;
}
private NetworkTemplate(Parcel in) {
mMatchRule = in.readInt();
mSubscriberId = in.readString();
mMatchSubscriberIds = in.createStringArray();
mNetworkId = in.readString();
}
@@ -164,6 +183,7 @@ public class NetworkTemplate implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mMatchRule);
dest.writeString(mSubscriberId);
dest.writeStringArray(mMatchSubscriberIds);
dest.writeString(mNetworkId);
}
@@ -177,7 +197,12 @@ public class NetworkTemplate implements Parcelable {
final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
if (mSubscriberId != null) {
builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
builder.append(", subscriberId=").append(
NetworkIdentity.scrubSubscriberId(mSubscriberId));
}
if (mMatchSubscriberIds != null) {
builder.append(", matchSubscriberIds=").append(
Arrays.toString(NetworkIdentity.scrubSubscriberId(mMatchSubscriberIds)));
}
if (mNetworkId != null) {
builder.append(", networkId=").append(mNetworkId);
@@ -201,6 +226,18 @@ public class NetworkTemplate implements Parcelable {
return false;
}
public boolean isMatchRuleMobile() {
switch (mMatchRule) {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
case MATCH_MOBILE_ALL:
case MATCH_MOBILE_WILDCARD:
return true;
default:
return false;
}
}
public int getMatchRule() {
return mMatchRule;
}
@@ -247,8 +284,9 @@ public class NetworkTemplate implements Parcelable {
// TODO: consider matching against WiMAX subscriber identity
return true;
} else {
return ((sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType))
&& Objects.equals(mSubscriberId, ident.mSubscriberId));
final boolean matchesType = (sForceAllNetworkTypes
|| contains(DATA_USAGE_NETWORK_TYPES, ident.mType));
return matchesType && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
}
}
@@ -368,6 +406,27 @@ public class NetworkTemplate implements Parcelable {
}
}
/**
* Examine the given template and normalize if it refers to a "merged"
* mobile subscriber. We pick the "lowest" merged subscriber as the primary
* for key purposes, and expand the template to match all other merged
* subscribers.
* <p>
* For example, given an incoming template matching B, and the currently
* active merge set [A,B], we'd return a new template that primarily matches
* A, but also matches B.
*/
public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) {
if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) {
// Requested template subscriber is part of the merge group; return
// a template that matches all merged subscribers.
return new NetworkTemplate(template.mMatchRule, merged[0], merged,
template.mNetworkId);
} else {
return template;
}
}
public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
@Override
public NetworkTemplate createFromParcel(Parcel in) {

View File

@@ -127,6 +127,20 @@ public class ArrayUtils
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
public static boolean isEmpty(int[] array) {
return array == null || array.length == 0;
}
/**
* Checks if given array is null or has zero elements.
*/
public static boolean isEmpty(long[] array) {
return array == null || array.length == 0;
}
/**
* Checks that value is present as at least one of the elements of the array.
* @param array the array to check in
@@ -157,6 +171,7 @@ public class ArrayUtils
* Test if all {@code check} items are contained in {@code array}.
*/
public static <T> boolean containsAll(T[] array, T[] check) {
if (check == null) return true;
for (T checkItem : check) {
if (!contains(array, checkItem)) {
return false;

View File

@@ -20,22 +20,8 @@ import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_DUMMY;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_CBS;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
import static android.net.ConnectivityManager.TYPE_MOBILE_IA;
import static android.net.ConnectivityManager.TYPE_MOBILE_IMS;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
import static android.net.ConnectivityManager.TYPE_NONE;
import static android.net.ConnectivityManager.TYPE_PROXY;
import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
@@ -45,11 +31,9 @@ import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
@@ -62,7 +46,6 @@ import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties.CompareResult;
import android.net.MobileDataStateTracker;
@@ -72,7 +55,6 @@ import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkFactory;
import android.net.NetworkMisc;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
@@ -80,16 +62,12 @@ import android.net.NetworkState;
import android.net.NetworkStateTracker;
import android.net.NetworkUtils;
import android.net.Proxy;
import android.net.ProxyDataTracker;
import android.net.ProxyInfo;
import android.net.RouteInfo;
import android.net.SamplingDataTracker;
import android.net.UidRange;
import android.net.Uri;
import android.net.wimax.WimaxManagerConstants;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.FileUtils;
import android.os.Handler;
@@ -103,7 +81,6 @@ import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -126,9 +103,6 @@ import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnProfile;
import com.android.internal.telephony.DctConstants;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
@@ -146,8 +120,6 @@ import com.android.server.net.LockdownVpnTracker;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
import dalvik.system.DexClassLoader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -157,31 +129,20 @@ import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.net.HttpURLConnection;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
/**
* @hide
*/
@@ -327,12 +288,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = 11;
/**
* Used internally to
* {@link NetworkStateTracker#setPolicyDataEnable(boolean)}.
*/
private static final int EVENT_SET_POLICY_DATA_ENABLE = 12;
/**
* Used internally to disable fail fast of mobile data
*/
@@ -850,6 +805,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
LinkProperties lp = null;
NetworkCapabilities nc = null;
Network network = null;
String subscriberId = null;
if (mLegacyTypeTracker.isTypeSupported(networkType)) {
NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
@@ -859,6 +815,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
lp = new LinkProperties(nai.linkProperties);
nc = new NetworkCapabilities(nai.networkCapabilities);
network = new Network(nai.network);
subscriberId = (nai.networkMisc != null) ? nai.networkMisc.subscriberId : null;
}
info.setType(networkType);
} else {
@@ -872,7 +829,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
info = getFilteredNetworkInfo(info, lp, uid);
}
return new NetworkState(info, lp, nc, network);
return new NetworkState(info, lp, nc, network, subscriberId, null);
}
private NetworkAgentInfo getNetworkAgentInfoForNetwork(Network network) {
@@ -889,6 +846,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
LinkProperties lp = null;
NetworkCapabilities nc = null;
Network network = null;
String subscriberId = null;
NetworkAgentInfo nai = mNetworkForRequestId.get(mDefaultRequest.requestId);
@@ -920,10 +878,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
lp = new LinkProperties(nai.linkProperties);
nc = new NetworkCapabilities(nai.networkCapabilities);
network = new Network(nai.network);
subscriberId = (nai.networkMisc != null) ? nai.networkMisc.subscriberId : null;
}
}
return new NetworkState(info, lp, nc, network);
return new NetworkState(info, lp, nc, network, subscriberId, null);
}
/**
@@ -1220,14 +1179,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public NetworkState[] getAllNetworkState() {
enforceAccessPermission();
final int uid = Binder.getCallingUid();
// Require internal since we're handing out IMSI details
enforceConnectivityInternalPermission();
final ArrayList<NetworkState> result = Lists.newArrayList();
for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
networkType++) {
NetworkState state = getFilteredNetworkState(networkType, uid);
if (state.networkInfo != null) {
result.add(state);
for (Network network : getAllNetworks()) {
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
if (nai != null) {
synchronized (nai) {
final String subscriberId = (nai.networkMisc != null)
? nai.networkMisc.subscriberId : null;
result.add(new NetworkState(nai.networkInfo, nai.linkProperties,
nai.networkCapabilities, network, subscriberId, null));
}
}
}
return result.toArray(new NetworkState[result.size()]);
@@ -1452,25 +1416,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
};
@Override
public void setPolicyDataEnable(int networkType, boolean enabled) {
// only someone like NPMS should only be calling us
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
mHandler.sendMessage(mHandler.obtainMessage(
EVENT_SET_POLICY_DATA_ENABLE, networkType, (enabled ? ENABLED : DISABLED)));
}
private void handleSetPolicyDataEnable(int networkType, boolean enabled) {
// TODO - handle this passing to factories
// if (isNetworkTypeValid(networkType)) {
// final NetworkStateTracker tracker = mNetTrackers[networkType];
// if (tracker != null) {
// tracker.setPolicyDataEnable(enabled);
// }
// }
}
private void enforceInternetPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERNET,
@@ -2457,12 +2402,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
sendStickyBroadcast(intent);
break;
}
case EVENT_SET_POLICY_DATA_ENABLE: {
final int networkType = msg.arg1;
final boolean enabled = msg.arg2 == ENABLED;
handleSetPolicyDataEnable(networkType, enabled);
break;
}
case EVENT_ENABLE_FAIL_FAST_MOBILE_DATA: {
int tag = mEnableFailFastMobileDataTag.get();
if (msg.arg1 == tag) {
@@ -3858,7 +3797,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
mNumDnsEntries = last;
}
private void updateCapabilities(NetworkAgentInfo networkAgent,
NetworkCapabilities networkCapabilities) {
if (!Objects.equals(networkAgent.networkCapabilities, networkCapabilities)) {

View File

@@ -120,7 +120,9 @@ import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.text.format.Time;
import android.util.ArrayMap;
@@ -136,16 +138,17 @@ import android.util.SparseIntArray;
import android.util.TrustedTime;
import android.util.Xml;
import libcore.io.IoUtils;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.google.android.collect.Lists;
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -160,7 +163,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* Service that maintains low-level network policy rules, using
@@ -253,38 +255,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private final boolean mSuppressDefaultPolicy;
/** Defined network policies. */
final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<
NetworkTemplate, NetworkPolicy>();
final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<>();
/** Currently active network rules for ifaces. */
private final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<
NetworkPolicy, String[]>();
final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>();
/** Defined UID policies. */
final SparseIntArray mUidPolicy = new SparseIntArray();
/** Currently derived rules for each UID. */
private final SparseIntArray mUidRules = new SparseIntArray();
final SparseIntArray mUidRules = new SparseIntArray();
/** UIDs that have been white-listed to always be able to have network access in
* power save mode. */
/**
* UIDs that have been white-listed to always be able to have network access
* in power save mode.
*/
private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
/** Set of ifaces that are metered. */
private ArraySet<String> mMeteredIfaces = new ArraySet<String>();
private ArraySet<String> mMeteredIfaces = new ArraySet<>();
/** Set of over-limit templates that have been notified. */
private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<NetworkTemplate>();
private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<>();
/** Set of currently active {@link Notification} tags. */
private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
/** Foreground at both UID and PID granularity. */
private final SparseIntArray mUidState = new SparseIntArray();
final SparseArray<SparseIntArray> mUidPidState = new SparseArray<SparseIntArray>();
final SparseIntArray mUidState = new SparseIntArray();
final SparseArray<SparseIntArray> mUidPidState = new SparseArray<>();
/** The current maximum process state that we are considering to be foreground. */
private int mCurForegroundState = ActivityManager.PROCESS_STATE_TOP;
private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
INetworkPolicyListener>();
private final RemoteCallbackList<INetworkPolicyListener>
mListeners = new RemoteCallbackList<>();
final Handler mHandler;
@@ -740,21 +742,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* data connection status.
*/
private boolean isTemplateRelevant(NetworkTemplate template) {
final TelephonyManager tele = TelephonyManager.from(mContext);
if (template.isMatchRuleMobile()) {
final TelephonyManager tele = TelephonyManager.from(mContext);
final SubscriptionManager sub = SubscriptionManager.from(mContext);
switch (template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
case MATCH_MOBILE_ALL:
// mobile templates are relevant when SIM is ready and
// subscriberId matches.
if (tele.getSimState() == SIM_STATE_READY) {
return Objects.equals(tele.getSubscriberId(), template.getSubscriberId());
} else {
return false;
// Mobile template is relevant when any active subscriber matches
final int[] subIds = sub.getActiveSubscriptionIdList();
for (int subId : subIds) {
final String subscriberId = tele.getSubscriberId(subId);
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
if (template.matches(probeIdent)) {
return true;
}
}
return false;
} else {
return true;
}
return true;
}
/**
@@ -961,6 +966,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
maybeRefreshTrustedTime();
synchronized (mRulesLock) {
ensureActiveMobilePolicyLocked();
normalizePoliciesLocked();
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
updateNotificationsLocked();
@@ -1001,33 +1007,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
* Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}
* for the given {@link NetworkTemplate}.
* Proactively disable networks that match the given
* {@link NetworkTemplate}.
*/
private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
final TelephonyManager tele = TelephonyManager.from(mContext);
switch (template.getMatchRule()) {
case MATCH_MOBILE_3G_LOWER:
case MATCH_MOBILE_4G:
case MATCH_MOBILE_ALL:
// TODO: offer more granular control over radio states once
// 4965893 is available.
if (tele.getSimState() == SIM_STATE_READY
&& Objects.equals(tele.getSubscriberId(), template.getSubscriberId())) {
setPolicyDataEnable(TYPE_MOBILE, enabled);
setPolicyDataEnable(TYPE_WIMAX, enabled);
}
break;
case MATCH_WIFI:
setPolicyDataEnable(TYPE_WIFI, enabled);
break;
case MATCH_ETHERNET:
setPolicyDataEnable(TYPE_ETHERNET, enabled);
break;
default:
throw new IllegalArgumentException("unexpected template");
}
// TODO: reach into ConnectivityManager to proactively disable bringing
// up this network, since we know that traffic will be blocked.
}
/**
@@ -1036,7 +1021,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
* remaining quota based on usage cycle and historical stats.
*/
void updateNetworkRulesLocked() {
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
if (LOGV) Slog.v(TAG, "updateNetworkRulesLocked()");
final NetworkState[] states;
try {
@@ -1203,42 +1188,47 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (mSuppressDefaultPolicy) return;
final TelephonyManager tele = TelephonyManager.from(mContext);
final SubscriptionManager sub = SubscriptionManager.from(mContext);
// avoid creating policy when SIM isn't ready
if (tele.getSimState() != SIM_STATE_READY) return;
final int[] subIds = sub.getActiveSubscriptionIdList();
for (int subId : subIds) {
final String subscriberId = tele.getSubscriberId(subId);
ensureActiveMobilePolicyLocked(subscriberId);
}
}
final String subscriberId = tele.getSubscriberId();
final NetworkIdentity probeIdent = new NetworkIdentity(
TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
// examine to see if any policy is defined for active mobile
boolean mobileDefined = false;
for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
if (mNetworkPolicy.valueAt(i).template.matches(probeIdent)) {
mobileDefined = true;
break;
private void ensureActiveMobilePolicyLocked(String subscriberId) {
// Poke around to see if we already have a policy
final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
final NetworkTemplate template = mNetworkPolicy.keyAt(i);
if (template.matches(probeIdent)) {
if (LOGD) {
Slog.d(TAG, "Found template " + template + " which matches subscriber "
+ NetworkIdentity.scrubSubscriberId(subscriberId));
}
return;
}
}
if (!mobileDefined) {
Slog.i(TAG, "no policy for active mobile network; generating default policy");
Slog.i(TAG, "No policy for subscriber " + NetworkIdentity.scrubSubscriberId(subscriberId)
+ "; generating default policy");
// build default mobile policy, and assume usage cycle starts today
final long warningBytes = mContext.getResources().getInteger(
com.android.internal.R.integer.config_networkPolicyDefaultWarning)
* MB_IN_BYTES;
// Build default mobile policy, and assume usage cycle starts today
final long warningBytes = mContext.getResources().getInteger(
com.android.internal.R.integer.config_networkPolicyDefaultWarning) * MB_IN_BYTES;
final Time time = new Time();
time.setToNow();
final Time time = new Time();
time.setToNow();
final int cycleDay = time.monthDay;
final String cycleTimezone = time.timezone;
final int cycleDay = time.monthDay;
final String cycleTimezone = time.timezone;
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
addNetworkPolicyLocked(policy);
}
final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
addNetworkPolicyLocked(policy);
}
private void readPolicyLocked() {
@@ -1321,8 +1311,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
inferred = false;
}
final NetworkTemplate template = new NetworkTemplate(
networkTemplate, subscriberId, networkId);
final NetworkTemplate template = new NetworkTemplate(networkTemplate,
subscriberId, networkId);
mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
lastLimitSnooze, metered, inferred));
@@ -1593,11 +1583,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
maybeRefreshTrustedTime();
synchronized (mRulesLock) {
mNetworkPolicy.clear();
for (NetworkPolicy policy : policies) {
mNetworkPolicy.put(policy.template, policy);
}
normalizePoliciesLocked(policies);
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
updateNotificationsLocked();
@@ -1606,12 +1592,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
void addNetworkPolicyLocked(NetworkPolicy policy) {
mNetworkPolicy.put(policy.template, policy);
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
updateNotificationsLocked();
writePolicyLocked();
NetworkPolicy[] policies = getNetworkPolicies();
policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy);
setNetworkPolicies(policies);
}
@Override
@@ -1620,7 +1603,35 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
synchronized (mRulesLock) {
return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
final int size = mNetworkPolicy.size();
final NetworkPolicy[] policies = new NetworkPolicy[size];
for (int i = 0; i < size; i++) {
policies[i] = mNetworkPolicy.valueAt(i);
}
return policies;
}
}
private void normalizePoliciesLocked() {
normalizePoliciesLocked(getNetworkPolicies());
}
private void normalizePoliciesLocked(NetworkPolicy[] policies) {
final TelephonyManager tele = TelephonyManager.from(mContext);
final String[] merged = tele.getMergedSubscriberIds();
mNetworkPolicy.clear();
for (NetworkPolicy policy : policies) {
// When two normalized templates conflict, prefer the most
// restrictive policy
policy.template = NetworkTemplate.normalize(policy.template, merged);
final NetworkPolicy existing = mNetworkPolicy.get(policy.template);
if (existing == null || existing.compareTo(policy) > 0) {
if (existing != null) {
Slog.d(TAG, "Normalization replaced " + existing + " with " + policy);
}
mNetworkPolicy.put(policy.template, policy);
}
}
}
@@ -1657,6 +1668,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
throw new IllegalArgumentException("unexpected type");
}
normalizePoliciesLocked();
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
updateNotificationsLocked();
@@ -1784,6 +1796,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNetworkPolicy.valueAt(i).clearSnooze();
}
normalizePoliciesLocked();
updateNetworkEnabledLocked();
updateNetworkRulesLocked();
updateNotificationsLocked();
@@ -1976,6 +1989,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// If the set of restricted networks may have changed, re-evaluate those.
if (restrictedNetworksChanged) {
normalizePoliciesLocked();
updateNetworkRulesLocked();
}
}
@@ -2162,17 +2176,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
/**
* Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}.
*/
private void setPolicyDataEnable(int networkType, boolean enabled) {
try {
mConnManager.setPolicyDataEnable(networkType, enabled);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
}
private long getTotalBytes(NetworkTemplate template, long start, long end) {
try {
return mNetworkStats.getNetworkTotalBytes(template, start, end);

View File

@@ -916,10 +916,8 @@ public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
}
private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
final FutureAnswer future = new FutureAnswer();
mConnManager.setPolicyDataEnable(type, enabled);
expectLastCall().andAnswer(future);
return future;
// TODO: bring back this test
return null;
}
private void expectAdvisePersistThreshold() throws Exception {

View File

@@ -1023,7 +1023,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
info.setDetailedState(DetailedState.CONNECTED, null, null);
final LinkProperties prop = new LinkProperties();
prop.setInterfaceName(iface);
return new NetworkState(info, prop, null, null);
return new NetworkState(info, prop, null, null, null, null);
}
private NetworkStats buildEmptyStats() {

View File

@@ -16,6 +16,7 @@
package android.telephony;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
@@ -1064,7 +1065,7 @@ public class SubscriptionManager {
* is never null but the length maybe 0.
* @hide
*/
public int[] getActiveSubscriptionIdList() {
public @NonNull int[] getActiveSubscriptionIdList() {
int[] subId = null;
try {

View File

@@ -16,6 +16,7 @@
package android.telephony;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -40,6 +41,7 @@ import com.android.internal.telephony.TelephonyProperties;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -1878,6 +1880,23 @@ public class TelephonyManager {
}
}
/**
* Return the set of subscriber IDs that should be considered as "merged
* together" for data usage purposes. This is commonly {@code null} to
* indicate no merging is required. Any returned subscribers are sorted in a
* deterministic order.
*
* @hide
*/
public @Nullable String[] getMergedSubscriberIds() {
try {
return getITelephony().getMergedSubscriberIds();
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
return null;
}
/**
* Returns the MSISDN string.
* for a GSM phone. Return null if it is unavailable.
@@ -3593,5 +3612,3 @@ public class TelephonyManager {
}
}
}

View File

@@ -772,6 +772,8 @@ interface ITelephony {
*/
String getLine1AlphaTagForDisplay(int subId);
String[] getMergedSubscriberIds();
/**
* Override the operator branding for the current ICCID.
*