Excluded certain APNs (e.g. IMS) from mobile data usage.

Added not_metered capability to a mobile network if none
of its associated APN types are metered. Also used not_metered
capability to determine if a network should be accounted for
data usage or not instead of using network type, which is
always MOBILE after refactoring. Will add VT usage support
in next phase.

bug: 20888836
Change-Id: Id692cb856be9a47d0e918371112630128965b1bb
This commit is contained in:
Jack Yu
2016-03-30 11:14:39 -07:00
parent bbb41dd3bd
commit 7e3859251f
3 changed files with 40 additions and 23 deletions

View File

@@ -55,19 +55,22 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
final String mSubscriberId; final String mSubscriberId;
final String mNetworkId; final String mNetworkId;
final boolean mRoaming; final boolean mRoaming;
final boolean mMetered;
public NetworkIdentity( public NetworkIdentity(
int type, int subType, String subscriberId, String networkId, boolean roaming) { int type, int subType, String subscriberId, String networkId, boolean roaming,
boolean metered) {
mType = type; mType = type;
mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType; mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
mSubscriberId = subscriberId; mSubscriberId = subscriberId;
mNetworkId = networkId; mNetworkId = networkId;
mRoaming = roaming; mRoaming = roaming;
mMetered = metered;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming); return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered);
} }
@Override @Override
@@ -76,7 +79,8 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
final NetworkIdentity ident = (NetworkIdentity) obj; final NetworkIdentity ident = (NetworkIdentity) obj;
return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
&& Objects.equals(mSubscriberId, ident.mSubscriberId) && Objects.equals(mSubscriberId, ident.mSubscriberId)
&& Objects.equals(mNetworkId, ident.mNetworkId); && Objects.equals(mNetworkId, ident.mNetworkId)
&& mMetered == ident.mMetered;
} }
return false; return false;
} }
@@ -102,6 +106,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
if (mRoaming) { if (mRoaming) {
builder.append(", ROAMING"); builder.append(", ROAMING");
} }
builder.append(", metered=").append(mMetered);
return builder.append("}").toString(); return builder.append("}").toString();
} }
@@ -125,6 +130,10 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
return mRoaming; return mRoaming;
} }
public boolean getMetered() {
return mMetered;
}
/** /**
* Scrub given IMSI on production builds. * Scrub given IMSI on production builds.
*/ */
@@ -162,6 +171,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
String subscriberId = null; String subscriberId = null;
String networkId = null; String networkId = null;
boolean roaming = false; boolean roaming = false;
boolean metered = false;
if (isNetworkTypeMobile(type)) { if (isNetworkTypeMobile(type)) {
if (state.subscriberId == null) { if (state.subscriberId == null) {
@@ -171,6 +181,9 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
subscriberId = state.subscriberId; subscriberId = state.subscriberId;
roaming = state.networkInfo.isRoaming(); roaming = state.networkInfo.isRoaming();
metered = !state.networkCapabilities.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
} else if (type == TYPE_WIFI) { } else if (type == TYPE_WIFI) {
if (state.networkId != null) { if (state.networkId != null) {
networkId = state.networkId; networkId = state.networkId;
@@ -182,7 +195,7 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
} }
} }
return new NetworkIdentity(type, subType, subscriberId, networkId, roaming); return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered);
} }
@Override @Override
@@ -200,6 +213,9 @@ public class NetworkIdentity implements Comparable<NetworkIdentity> {
if (res == 0) { if (res == 0) {
res = Boolean.compare(mRoaming, another.mRoaming); res = Boolean.compare(mRoaming, another.mRoaming);
} }
if (res == 0) {
res = Boolean.compare(mMetered, another.mMetered);
}
return res; return res;
} }
} }

View File

@@ -19,6 +19,7 @@ package android.net;
import static android.net.ConnectivityManager.TYPE_BLUETOOTH; import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_ETHERNET;
import static android.net.ConnectivityManager.TYPE_PROXY; import static android.net.ConnectivityManager.TYPE_PROXY;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.TYPE_WIFI_P2P; import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.ConnectivityManager.TYPE_WIMAX;
@@ -30,9 +31,6 @@ import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN; import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
import static android.telephony.TelephonyManager.getNetworkClass; import static android.telephony.TelephonyManager.getNetworkClass;
import static com.android.internal.util.ArrayUtils.contains;
import android.content.res.Resources;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.util.BackupUtils; import android.util.BackupUtils;
@@ -71,16 +69,6 @@ public class NetworkTemplate implements Parcelable {
public static final int MATCH_BLUETOOTH = 8; public static final int MATCH_BLUETOOTH = 8;
public static final int MATCH_PROXY = 9; public static final int MATCH_PROXY = 9;
/**
* Set of {@link NetworkInfo#getType()} that reflect data usage.
*/
private static final int[] DATA_USAGE_NETWORK_TYPES;
static {
DATA_USAGE_NETWORK_TYPES = Resources.getSystem().getIntArray(
com.android.internal.R.array.config_data_usage_network_types);
}
private static boolean sForceAllNetworkTypes = false; private static boolean sForceAllNetworkTypes = false;
@VisibleForTesting @VisibleForTesting
@@ -318,9 +306,8 @@ public class NetworkTemplate implements Parcelable {
// TODO: consider matching against WiMAX subscriber identity // TODO: consider matching against WiMAX subscriber identity
return true; return true;
} else { } else {
final boolean matchesType = (sForceAllNetworkTypes return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
|| contains(DATA_USAGE_NETWORK_TYPES, ident.mType)); && !ArrayUtils.isEmpty(mMatchSubscriberIds)
return matchesType && !ArrayUtils.isEmpty(mMatchSubscriberIds)
&& ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId); && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
} }
} }
@@ -389,7 +376,7 @@ public class NetworkTemplate implements Parcelable {
if (ident.mType == TYPE_WIMAX) { if (ident.mType == TYPE_WIMAX) {
return true; return true;
} else { } else {
return sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType); return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered);
} }
} }

View File

@@ -23,6 +23,8 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import static android.net.ConnectivityManager.TYPE_MOBILE;
/** /**
* Identity of a {@code iface}, defined by the set of {@link NetworkIdentity} * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
* active on that interface. * active on that interface.
@@ -34,6 +36,7 @@ public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements
private static final int VERSION_INIT = 1; private static final int VERSION_INIT = 1;
private static final int VERSION_ADD_ROAMING = 2; private static final int VERSION_ADD_ROAMING = 2;
private static final int VERSION_ADD_NETWORK_ID = 3; private static final int VERSION_ADD_NETWORK_ID = 3;
private static final int VERSION_ADD_METERED = 4;
public NetworkIdentitySet() { public NetworkIdentitySet() {
} }
@@ -61,12 +64,22 @@ public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements
roaming = false; roaming = false;
} }
add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming)); final boolean metered;
if (version >= VERSION_ADD_METERED) {
metered = in.readBoolean();
} else {
// If this is the old data and the type is mobile, treat it as metered. (Note that
// if this is a mobile network, TYPE_MOBILE is the only possible type that could be
// used.)
metered = (type == TYPE_MOBILE);
}
add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered));
} }
} }
public void writeToStream(DataOutputStream out) throws IOException { public void writeToStream(DataOutputStream out) throws IOException {
out.writeInt(VERSION_ADD_NETWORK_ID); out.writeInt(VERSION_ADD_METERED);
out.writeInt(size()); out.writeInt(size());
for (NetworkIdentity ident : this) { for (NetworkIdentity ident : this) {
out.writeInt(ident.getType()); out.writeInt(ident.getType());
@@ -74,6 +87,7 @@ public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements
writeOptionalString(out, ident.getSubscriberId()); writeOptionalString(out, ident.getSubscriberId());
writeOptionalString(out, ident.getNetworkId()); writeOptionalString(out, ident.getNetworkId());
out.writeBoolean(ident.getRoaming()); out.writeBoolean(ident.getRoaming());
out.writeBoolean(ident.getMetered());
} }
} }