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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.net.NetworkIdentity;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolException;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
@@ -33,48 +32,46 @@ import java.util.HashSet;
|
||||
public class NetworkIdentitySet extends HashSet<NetworkIdentity> {
|
||||
private static final int VERSION_INIT = 1;
|
||||
private static final int VERSION_ADD_ROAMING = 2;
|
||||
private static final int VERSION_ADD_NETWORK_ID = 3;
|
||||
|
||||
public NetworkIdentitySet() {
|
||||
}
|
||||
|
||||
public NetworkIdentitySet(DataInputStream in) throws IOException {
|
||||
final int version = in.readInt();
|
||||
switch (version) {
|
||||
case VERSION_INIT: {
|
||||
final int size = in.readInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int ignoredVersion = in.readInt();
|
||||
final int type = in.readInt();
|
||||
final int subType = in.readInt();
|
||||
final String subscriberId = readOptionalString(in);
|
||||
add(new NetworkIdentity(type, subType, subscriberId, false));
|
||||
}
|
||||
break;
|
||||
final int size = in.readInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (version <= VERSION_INIT) {
|
||||
final int ignored = in.readInt();
|
||||
}
|
||||
case VERSION_ADD_ROAMING: {
|
||||
final int size = in.readInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final int type = in.readInt();
|
||||
final int subType = in.readInt();
|
||||
final String subscriberId = readOptionalString(in);
|
||||
final boolean roaming = in.readBoolean();
|
||||
add(new NetworkIdentity(type, subType, subscriberId, roaming));
|
||||
}
|
||||
break;
|
||||
final int type = in.readInt();
|
||||
final int subType = in.readInt();
|
||||
final String subscriberId = readOptionalString(in);
|
||||
final String networkId;
|
||||
if (version >= VERSION_ADD_NETWORK_ID) {
|
||||
networkId = readOptionalString(in);
|
||||
} else {
|
||||
networkId = null;
|
||||
}
|
||||
default: {
|
||||
throw new ProtocolException("unexpected version: " + version);
|
||||
final boolean roaming;
|
||||
if (version >= VERSION_ADD_ROAMING) {
|
||||
roaming = in.readBoolean();
|
||||
} else {
|
||||
roaming = false;
|
||||
}
|
||||
|
||||
add(new NetworkIdentity(type, subType, subscriberId, networkId, false));
|
||||
}
|
||||
}
|
||||
|
||||
public void writeToStream(DataOutputStream out) throws IOException {
|
||||
out.writeInt(VERSION_ADD_ROAMING);
|
||||
out.writeInt(VERSION_ADD_NETWORK_ID);
|
||||
out.writeInt(size());
|
||||
for (NetworkIdentity ident : this) {
|
||||
out.writeInt(ident.getType());
|
||||
out.writeInt(ident.getSubType());
|
||||
writeOptionalString(out, ident.getSubscriberId());
|
||||
writeOptionalString(out, ident.getNetworkId());
|
||||
out.writeBoolean(ident.getRoaming());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ import static android.net.NetworkStats.SET_FOREGROUND;
|
||||
import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.NetworkTemplate.buildTemplateMobileAll;
|
||||
import static android.net.NetworkTemplate.buildTemplateWifi;
|
||||
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
|
||||
import static android.net.TrafficStats.MB_IN_BYTES;
|
||||
import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
|
||||
import static android.provider.Settings.Secure.NETSTATS_DEV_DELETE_AGE;
|
||||
@@ -836,7 +836,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
trustedTime);
|
||||
|
||||
// collect wifi sample
|
||||
template = buildTemplateWifi();
|
||||
template = buildTemplateWifiWildcard();
|
||||
devTotal = mDevRecorder.getTotalSinceBootLocked(template);
|
||||
xtTotal = new NetworkStats.Entry();
|
||||
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
|
||||
|
||||
Reference in New Issue
Block a user