summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/IConnectivityManager.aidl3
-rw-r--r--core/java/android/net/NetworkIdentity.java30
-rw-r--r--core/java/android/net/NetworkMisc.java17
-rw-r--r--core/java/android/net/NetworkPolicy.java2
-rw-r--r--core/java/android/net/NetworkState.java7
-rw-r--r--core/java/android/net/NetworkTemplate.java67
-rw-r--r--core/java/com/android/internal/util/ArrayUtils.java15
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java98
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java217
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java2
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java3
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java21
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl2
14 files changed, 267 insertions, 223 deletions
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 802121093a64..d9921a6df0f9 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -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);
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index d36707e4cb35..68647498755f 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -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}.
@@ -133,6 +136,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;
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index 5d2a43d0f3c9..b92c9e3c5d9f 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -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;
}
diff --git a/core/java/android/net/NetworkPolicy.java b/core/java/android/net/NetworkPolicy.java
index 10c686b9e211..e88bc26851e7 100644
--- a/core/java/android/net/NetworkPolicy.java
+++ b/core/java/android/net/NetworkPolicy.java
@@ -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;
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index d26c70d5569f..933287f6341f 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -30,16 +30,10 @@ 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) {
this.networkInfo = networkInfo;
@@ -85,5 +79,4 @@ public class NetworkState implements Parcelable {
return new NetworkState[size];
}
};
-
}
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index b839e0ac69a2..6cfab92360f6 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -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) {
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 8e786da7cf7e..f908fcbd99eb 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -128,6 +128,20 @@ public class ArrayUtils
}
/**
+ * 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
* @param value the value to check for
@@ -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;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9c0e486af7f6..dde158cdddd9 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -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
*/
@@ -328,12 +289,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
*/
private static final int EVENT_ENABLE_FAIL_FAST_MOBILE_DATA = 14;
@@ -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)) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index cf194165b0af..2be591b39002 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -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);
-
- 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;
+ if (template.isMatchRuleMobile()) {
+ final TelephonyManager tele = TelephonyManager.from(mContext);
+ final SubscriptionManager sub = SubscriptionManager.from(mContext);
+
+ // 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 String subscriberId = tele.getSubscriberId();
- final NetworkIdentity probeIdent = new NetworkIdentity(
- TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
+ final int[] subIds = sub.getActiveSubscriptionIdList();
+ for (int subId : subIds) {
+ final String subscriberId = tele.getSubscriberId(subId);
+ ensureActiveMobilePolicyLocked(subscriberId);
+ }
+ }
- // 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);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index b74716fdcdda..0b4d42e0a172 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -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 {
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index f9a03fc36fab..7383478c44eb 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -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() {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index abf1ead8eef6..20cd0373d81e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -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 {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 751e11b74890..83bf04fec734 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -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;
@@ -1879,6 +1881,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.
* <p>
@@ -3593,5 +3612,3 @@ public class TelephonyManager {
}
}
}
-
-
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index bf7f33273ffe..d19fa2ccf1a8 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -772,6 +772,8 @@ interface ITelephony {
*/
String getLine1AlphaTagForDisplay(int subId);
+ String[] getMergedSubscriberIds();
+
/**
* Override the operator branding for the current ICCID.
*