Support metered Wi-Fi NetworkPolicy.

Add networkId field to NetworkIdentity to identify Wi-Fi networks by
SSID.  Add support for policies without usage cycles.

Only apply mobile policies when SIM state is ready, which is cleaner
than just checking for airplane mode.  Also avoids creating no-op
default policies when subscriberId is null.

Bug: 3001465, 3291052
Change-Id: I1f8aaa49a5db306df022c402ea7f3f5d4bc0cfc7
This commit is contained in:
Jeff Sharkey
2012-04-04 20:40:58 -07:00
parent f3f68819df
commit 3bd888f411
5 changed files with 139 additions and 89 deletions

View File

@@ -16,9 +16,13 @@
package android.net;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeMobile;
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.telephony.TelephonyManager;
@@ -42,18 +46,21 @@ public class NetworkIdentity {
final int mType;
final int mSubType;
final String mSubscriberId;
final String mNetworkId;
final boolean mRoaming;
public NetworkIdentity(int type, int subType, String subscriberId, boolean roaming) {
this.mType = type;
this.mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
this.mSubscriberId = subscriberId;
this.mRoaming = roaming;
public NetworkIdentity(
int type, int subType, String subscriberId, String networkId, boolean roaming) {
mType = type;
mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
mSubscriberId = subscriberId;
mNetworkId = networkId;
mRoaming = roaming;
}
@Override
public int hashCode() {
return Objects.hashCode(mType, mSubType, mSubscriberId, mRoaming);
return Objects.hashCode(mType, mSubType, mSubscriberId, mNetworkId, mRoaming);
}
@Override
@@ -61,27 +68,34 @@ public class NetworkIdentity {
if (obj instanceof NetworkIdentity) {
final NetworkIdentity ident = (NetworkIdentity) obj;
return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
&& Objects.equal(mSubscriberId, ident.mSubscriberId);
&& Objects.equal(mSubscriberId, ident.mSubscriberId)
&& Objects.equal(mNetworkId, ident.mNetworkId);
}
return false;
}
@Override
public String toString() {
final String typeName = ConnectivityManager.getNetworkTypeName(mType);
final String subTypeName;
final StringBuilder builder = new StringBuilder("[");
builder.append("type=").append(getNetworkTypeName(mType));
builder.append(", subType=");
if (COMBINE_SUBTYPE_ENABLED) {
subTypeName = "COMBINED";
builder.append("COMBINED");
} else if (ConnectivityManager.isNetworkTypeMobile(mType)) {
subTypeName = TelephonyManager.getNetworkTypeName(mSubType);
builder.append(TelephonyManager.getNetworkTypeName(mSubType));
} else {
subTypeName = Integer.toString(mSubType);
builder.append(mSubType);
}
final String scrubSubscriberId = scrubSubscriberId(mSubscriberId);
final String roaming = mRoaming ? ", ROAMING" : "";
return "[type=" + typeName + ", subType=" + subTypeName + ", subscriberId="
+ scrubSubscriberId + roaming + "]";
if (mSubscriberId != null) {
builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
}
if (mNetworkId != null) {
builder.append(", networkId=").append(mNetworkId);
}
if (mRoaming) {
builder.append(", ROAMING");
}
return builder.append("]").toString();
}
public int getType() {
@@ -96,6 +110,10 @@ public class NetworkIdentity {
return mSubscriberId;
}
public String getNetworkId() {
return mNetworkId;
}
public boolean getRoaming() {
return mRoaming;
}
@@ -106,8 +124,11 @@ public class NetworkIdentity {
public static String scrubSubscriberId(String subscriberId) {
if ("eng".equals(Build.TYPE)) {
return subscriberId;
} else if (subscriberId != null) {
// TODO: parse this as MCC+MNC instead of hard-coding
return subscriberId.substring(0, Math.min(6, subscriberId.length())) + "...";
} else {
return subscriberId != null ? "valid" : "null";
return "null";
}
}
@@ -122,8 +143,10 @@ public class NetworkIdentity {
// TODO: consider moving subscriberId over to LinkCapabilities, so it
// comes from an authoritative source.
final String subscriberId;
final boolean roaming;
String subscriberId = null;
String networkId = null;
boolean roaming = false;
if (isNetworkTypeMobile(type)) {
final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
Context.TELEPHONY_SERVICE);
@@ -133,10 +156,13 @@ public class NetworkIdentity {
} else {
subscriberId = telephony.getSubscriberId();
}
} else {
subscriberId = null;
roaming = false;
} else if (type == TYPE_WIFI) {
final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
final WifiInfo info = wifi.getConnectionInfo();
networkId = info != null ? info.getSSID() : null;
}
return new NetworkIdentity(type, subType, subscriberId, roaming);
return new NetworkIdentity(type, subType, subscriberId, networkId, roaming);
}
}

View File

@@ -43,15 +43,10 @@ import com.android.internal.util.Objects;
*/
public class NetworkTemplate implements Parcelable {
/** {@hide} */
public static final int MATCH_MOBILE_ALL = 1;
/** {@hide} */
public static final int MATCH_MOBILE_3G_LOWER = 2;
/** {@hide} */
public static final int MATCH_MOBILE_4G = 3;
/** {@hide} */
public static final int MATCH_WIFI = 4;
/** {@hide} */
public static final int MATCH_ETHERNET = 5;
/**
@@ -65,37 +60,50 @@ public class NetworkTemplate implements Parcelable {
}
/**
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
* networks together. Only uses statistics for requested IMSI.
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
* the given IMSI.
*/
public static NetworkTemplate buildTemplateMobileAll(String subscriberId) {
return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId);
return new NetworkTemplate(MATCH_MOBILE_ALL, subscriberId, null);
}
/**
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
* networks together that roughly meet a "3G" definition, or lower. Only
* uses statistics for requested IMSI.
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
* the given IMSI that roughly meet a "3G" definition, or lower.
*/
@Deprecated
public static NetworkTemplate buildTemplateMobile3gLower(String subscriberId) {
return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId);
return new NetworkTemplate(MATCH_MOBILE_3G_LOWER, subscriberId, null);
}
/**
* Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
* networks together that meet a "4G" definition. Only uses statistics for
* requested IMSI.
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
* the given IMSI that roughly meet a "4G" definition.
*/
@Deprecated
public static NetworkTemplate buildTemplateMobile4g(String subscriberId) {
return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId);
return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null);
}
/**
* Template to combine all {@link ConnectivityManager#TYPE_WIFI} style
* networks together.
* Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
* regardless of SSID.
*/
public static NetworkTemplate buildTemplateWifiWildcard() {
return new NetworkTemplate(MATCH_WIFI, null, null);
}
@Deprecated
public static NetworkTemplate buildTemplateWifi() {
return new NetworkTemplate(MATCH_WIFI, null);
return buildTemplateWifiWildcard();
}
/**
* Template to match {@link ConnectivityManager#TYPE_WIFI} networks with the
* given SSID.
*/
public static NetworkTemplate buildTemplateWifi(String networkId) {
return new NetworkTemplate(MATCH_WIFI, null, networkId);
}
/**
@@ -103,44 +111,53 @@ public class NetworkTemplate implements Parcelable {
* networks together.
*/
public static NetworkTemplate buildTemplateEthernet() {
return new NetworkTemplate(MATCH_ETHERNET, null);
return new NetworkTemplate(MATCH_ETHERNET, null, null);
}
private final int mMatchRule;
private final String mSubscriberId;
private final String mNetworkId;
/** {@hide} */
public NetworkTemplate(int matchRule, String subscriberId) {
this.mMatchRule = matchRule;
this.mSubscriberId = subscriberId;
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
mMatchRule = matchRule;
mSubscriberId = subscriberId;
mNetworkId = networkId;
}
private NetworkTemplate(Parcel in) {
mMatchRule = in.readInt();
mSubscriberId = in.readString();
mNetworkId = in.readString();
}
/** {@inheritDoc} */
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mMatchRule);
dest.writeString(mSubscriberId);
dest.writeString(mNetworkId);
}
/** {@inheritDoc} */
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
final String scrubSubscriberId = scrubSubscriberId(mSubscriberId);
return "NetworkTemplate: matchRule=" + getMatchRuleName(mMatchRule) + ", subscriberId="
+ scrubSubscriberId;
final StringBuilder builder = new StringBuilder("NetworkTemplate: ");
builder.append("matchRule=").append(getMatchRuleName(mMatchRule));
if (mSubscriberId != null) {
builder.append(", subscriberId=").append(scrubSubscriberId(mSubscriberId));
}
if (mNetworkId != null) {
builder.append(", networkId=").append(mNetworkId);
}
return builder.toString();
}
@Override
public int hashCode() {
return Objects.hashCode(mMatchRule, mSubscriberId);
return Objects.hashCode(mMatchRule, mSubscriberId, mNetworkId);
}
@Override
@@ -148,21 +165,24 @@ public class NetworkTemplate implements Parcelable {
if (obj instanceof NetworkTemplate) {
final NetworkTemplate other = (NetworkTemplate) obj;
return mMatchRule == other.mMatchRule
&& Objects.equal(mSubscriberId, other.mSubscriberId);
&& Objects.equal(mSubscriberId, other.mSubscriberId)
&& Objects.equal(mNetworkId, other.mNetworkId);
}
return false;
}
/** {@hide} */
public int getMatchRule() {
return mMatchRule;
}
/** {@hide} */
public String getSubscriberId() {
return mSubscriberId;
}
public String getNetworkId() {
return mNetworkId;
}
/**
* Test if given {@link NetworkIdentity} matches this template.
*/
@@ -237,8 +257,13 @@ public class NetworkTemplate implements Parcelable {
private boolean matchesWifi(NetworkIdentity ident) {
switch (ident.mType) {
case TYPE_WIFI:
if (mNetworkId == null) {
return true;
} else {
return Objects.equal(mNetworkId, ident.mNetworkId);
}
case TYPE_WIFI_P2P:
return true;
return mNetworkId == null;
default:
return false;
}
@@ -279,10 +304,12 @@ public class NetworkTemplate implements Parcelable {
}
public static final Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() {
@Override
public NetworkTemplate createFromParcel(Parcel in) {
return new NetworkTemplate(in);
}
@Override
public NetworkTemplate[] newArray(int size) {
return new NetworkTemplate[size];
}

View File

@@ -16,7 +16,7 @@
package com.android.internal.net;
import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
@@ -101,7 +101,7 @@ public class NetworkStatsFactory {
while (reader.hasMoreData()) {
entry.iface = reader.nextString();
entry.uid = UID_ALL;
entry.set = SET_DEFAULT;
entry.set = SET_ALL;
entry.tag = TAG_NONE;
final boolean active = reader.nextInt() != 0;
@@ -165,7 +165,7 @@ public class NetworkStatsFactory {
entry.iface = iface;
entry.uid = UID_ALL;
entry.set = SET_DEFAULT;
entry.set = SET_ALL;
entry.tag = TAG_NONE;
entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
@@ -193,7 +193,7 @@ public class NetworkStatsFactory {
try {
entry.iface = values.get(0);
entry.uid = UID_ALL;
entry.set = SET_DEFAULT;
entry.set = SET_ALL;
entry.tag = TAG_NONE;
entry.rxBytes = Long.parseLong(values.get(1));
entry.rxPackets = Long.parseLong(values.get(2));