Merge "Add getters to NetworkStateSnapshot"
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index d42beae..6ccbab7 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -38,6 +38,7 @@
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
@@ -1423,11 +1424,11 @@
* @hide
*/
public void migrateTun(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces) {
+ @NonNull List<String> underlyingIfaces) {
// Combined usage by all apps using VPN.
final Entry tunIfaceTotal = new Entry();
// Usage by VPN, grouped by its {@code underlyingIfaces}.
- final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length];
+ final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.size()];
// Usage by VPN, summed across all its {@code underlyingIfaces}.
final Entry underlyingIfacesTotal = new Entry();
@@ -1468,7 +1469,7 @@
* {@code underlyingIfaces}
*/
private void tunAdjustmentInit(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
+ @NonNull List<String> underlyingIfaces, @NonNull Entry tunIfaceTotal,
@NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
final Entry recycle = new Entry();
for (int i = 0; i < size; i++) {
@@ -1488,8 +1489,8 @@
if (recycle.uid == tunUid) {
// Add up traffic through tunUid's underlying interfaces.
- for (int j = 0; j < underlyingIfaces.length; j++) {
- if (Objects.equals(underlyingIfaces[j], recycle.iface)) {
+ for (int j = 0; j < underlyingIfaces.size(); j++) {
+ if (Objects.equals(underlyingIfaces.get(j), recycle.iface)) {
perInterfaceTotal[j].add(recycle);
underlyingIfacesTotal.add(recycle);
break;
@@ -1515,12 +1516,12 @@
* underlyingIfaces}
*/
private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface,
- @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
+ @NonNull List<String> underlyingIfaces, @NonNull Entry tunIfaceTotal,
@NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
// Traffic that should be moved off of each underlying interface for tunUid (see
// deductTrafficFromVpnApp below).
- final Entry[] moved = new Entry[underlyingIfaces.length];
- for (int i = 0; i < underlyingIfaces.length; i++) {
+ final Entry[] moved = new Entry[underlyingIfaces.size()];
+ for (int i = 0; i < underlyingIfaces.size(); i++) {
moved[i] = new Entry();
}
@@ -1582,8 +1583,8 @@
}
// In a second pass, distribute these values across interfaces in the proportion that
// each interface represents of the total traffic of the underlying interfaces.
- for (int j = 0; j < underlyingIfaces.length; j++) {
- tmpEntry.iface = underlyingIfaces[j];
+ for (int j = 0; j < underlyingIfaces.size(); j++) {
+ tmpEntry.iface = underlyingIfaces.get(j);
tmpEntry.rxBytes = 0;
// Reset 'set' to correct value since it gets updated when adding debug info below.
tmpEntry.set = set[i];
@@ -1638,14 +1639,14 @@
private void deductTrafficFromVpnApp(
int tunUid,
- @NonNull String[] underlyingIfaces,
+ @NonNull List<String> underlyingIfaces,
@NonNull Entry[] moved) {
- for (int i = 0; i < underlyingIfaces.length; i++) {
+ for (int i = 0; i < underlyingIfaces.size(); i++) {
moved[i].uid = tunUid;
// Add debug info
moved[i].set = SET_DBG_VPN_OUT;
moved[i].tag = TAG_NONE;
- moved[i].iface = underlyingIfaces[i];
+ moved[i].iface = underlyingIfaces.get(i);
moved[i].metered = METERED_ALL;
moved[i].roaming = ROAMING_ALL;
moved[i].defaultNetwork = DEFAULT_NETWORK_ALL;
@@ -1658,7 +1659,7 @@
// METERED_NO, which should be the case as it comes directly from the /proc file.
// We only blend in the roaming data after applying these adjustments, by checking the
// NetworkIdentity of the underlying iface.
- final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT,
+ final int idxVpnBackground = findIndex(underlyingIfaces.get(i), tunUid, SET_DEFAULT,
TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
if (idxVpnBackground != -1) {
// Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed
@@ -1666,7 +1667,7 @@
tunSubtract(idxVpnBackground, this, moved[i]);
}
- final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND,
+ final int idxVpnForeground = findIndex(underlyingIfaces.get(i), tunUid, SET_FOREGROUND,
TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
if (idxVpnForeground != -1) {
tunSubtract(idxVpnForeground, this, moved[i]);
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index c83dd99..d3c8957 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -82,6 +82,24 @@
public static final int MATCH_WIFI_WILDCARD = 7;
public static final int MATCH_BLUETOOTH = 8;
public static final int MATCH_PROXY = 9;
+ public static final int MATCH_CARRIER = 10;
+
+ /**
+ * Value of the match rule of the subscriberId to match networks with specific subscriberId.
+ */
+ public static final int SUBSCRIBER_ID_MATCH_RULE_EXACT = 0;
+ /**
+ * Value of the match rule of the subscriberId to match networks with any subscriberId which
+ * includes null and non-null.
+ */
+ public static final int SUBSCRIBER_ID_MATCH_RULE_ALL = 1;
+
+ /**
+ * Wi-Fi Network ID is never supposed to be null (if it is, it is a bug that
+ * should be fixed), so it's not possible to want to match null vs
+ * non-null. Therefore it's fine to use null as a sentinel for Network ID.
+ */
+ public static final String WIFI_NETWORKID_ALL = null;
/**
* Include all network types when filtering. This is meant to merge in with the
@@ -125,6 +143,7 @@
case MATCH_WIFI_WILDCARD:
case MATCH_BLUETOOTH:
case MATCH_PROXY:
+ case MATCH_CARRIER:
return true;
default:
@@ -168,10 +187,12 @@
@NetworkType int ratType) {
if (TextUtils.isEmpty(subscriberId)) {
return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL);
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+ SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
- METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL);
+ METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+ SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
/**
@@ -189,6 +210,8 @@
*/
@UnsupportedAppUsage
public static NetworkTemplate buildTemplateWifiWildcard() {
+ // TODO: Consider replace this with MATCH_WIFI with NETWORK_ID_ALL
+ // and SUBSCRIBER_ID_MATCH_RULE_ALL.
return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
}
@@ -202,8 +225,27 @@
* 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);
+ public static NetworkTemplate buildTemplateWifi(@NonNull String networkId) {
+ Objects.requireNonNull(networkId);
+ return new NetworkTemplate(MATCH_WIFI, null /* subscriberId */,
+ new String[] { null } /* matchSubscriberIds */,
+ networkId, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ SUBSCRIBER_ID_MATCH_RULE_ALL);
+ }
+
+ /**
+ * Template to match all {@link ConnectivityManager#TYPE_WIFI} networks with the given SSID,
+ * and IMSI.
+ *
+ * Call with {@link #WIFI_NETWORKID_ALL} for {@code networkId} to get result regardless of SSID.
+ */
+ public static NetworkTemplate buildTemplateWifi(@Nullable String networkId,
+ @Nullable String subscriberId) {
+ return new NetworkTemplate(MATCH_WIFI, subscriberId, new String[] { subscriberId },
+ networkId, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
/**
@@ -231,6 +273,14 @@
return new NetworkTemplate(MATCH_PROXY, null, null);
}
+ /**
+ * Template to match all carrier networks with the given IMSI.
+ */
+ public static NetworkTemplate buildTemplateCarrier(@NonNull String subscriberId) {
+ Objects.requireNonNull(subscriberId);
+ return new NetworkTemplate(MATCH_CARRIER, subscriberId, null);
+ }
+
private final int mMatchRule;
private final String mSubscriberId;
@@ -251,10 +301,26 @@
private final int mRoaming;
private final int mDefaultNetwork;
private final int mSubType;
+ private final int mSubscriberIdMatchRule;
// Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
private final int mOemManaged;
+ private void checkValidSubscriberIdMatchRule() {
+ switch (mMatchRule) {
+ case MATCH_MOBILE:
+ case MATCH_CARRIER:
+ // MOBILE and CARRIER templates must always specify a subscriber ID.
+ if (mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
+ throw new IllegalArgumentException("Invalid SubscriberIdMatchRule"
+ + "on match rule: " + getMatchRuleName(mMatchRule));
+ }
+ return;
+ default:
+ return;
+ }
+ }
+
@UnsupportedAppUsage
public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
@@ -263,14 +329,25 @@
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId) {
this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
- DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL);
+ DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
+ SUBSCRIBER_ID_MATCH_RULE_EXACT);
+ }
+
+ // TODO: Remove it after updating all of the caller.
+ public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
+ String networkId, int metered, int roaming, int defaultNetwork, int subType,
+ int oemManaged) {
+ this(matchRule, subscriberId, matchSubscriberIds, networkId, metered, roaming,
+ defaultNetwork, subType, oemManaged, SUBSCRIBER_ID_MATCH_RULE_EXACT);
}
public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
String networkId, int metered, int roaming, int defaultNetwork, int subType,
- int oemManaged) {
+ int oemManaged, int subscriberIdMatchRule) {
mMatchRule = matchRule;
mSubscriberId = subscriberId;
+ // TODO: Check whether mMatchSubscriberIds = null or mMatchSubscriberIds = {null} when
+ // mSubscriberId is null
mMatchSubscriberIds = matchSubscriberIds;
mNetworkId = networkId;
mMetered = metered;
@@ -278,7 +355,8 @@
mDefaultNetwork = defaultNetwork;
mSubType = subType;
mOemManaged = oemManaged;
-
+ mSubscriberIdMatchRule = subscriberIdMatchRule;
+ checkValidSubscriberIdMatchRule();
if (!isKnownMatchRule(matchRule)) {
Log.e(TAG, "Unknown network template rule " + matchRule
+ " will not match any identity.");
@@ -295,6 +373,7 @@
mDefaultNetwork = in.readInt();
mSubType = in.readInt();
mOemManaged = in.readInt();
+ mSubscriberIdMatchRule = in.readInt();
}
@Override
@@ -308,6 +387,7 @@
dest.writeInt(mDefaultNetwork);
dest.writeInt(mSubType);
dest.writeInt(mOemManaged);
+ dest.writeInt(mSubscriberIdMatchRule);
}
@Override
@@ -346,13 +426,15 @@
if (mOemManaged != OEM_MANAGED_ALL) {
builder.append(", oemManaged=").append(mOemManaged);
}
+ builder.append(", subscriberIdMatchRule=")
+ .append(subscriberIdMatchRuleToString(mSubscriberIdMatchRule));
return builder.toString();
}
@Override
public int hashCode() {
return Objects.hash(mMatchRule, mSubscriberId, mNetworkId, mMetered, mRoaming,
- mDefaultNetwork, mSubType, mOemManaged);
+ mDefaultNetwork, mSubType, mOemManaged, mSubscriberIdMatchRule);
}
@Override
@@ -366,11 +448,23 @@
&& mRoaming == other.mRoaming
&& mDefaultNetwork == other.mDefaultNetwork
&& mSubType == other.mSubType
- && mOemManaged == other.mOemManaged;
+ && mOemManaged == other.mOemManaged
+ && mSubscriberIdMatchRule == other.mSubscriberIdMatchRule;
}
return false;
}
+ private String subscriberIdMatchRuleToString(int rule) {
+ switch (rule) {
+ case SUBSCRIBER_ID_MATCH_RULE_EXACT:
+ return "EXACT_MATCH";
+ case SUBSCRIBER_ID_MATCH_RULE_ALL:
+ return "ALL";
+ default:
+ return "Unknown rule " + rule;
+ }
+ }
+
public boolean isMatchRuleMobile() {
switch (mMatchRule) {
case MATCH_MOBILE:
@@ -386,6 +480,14 @@
case MATCH_MOBILE_WILDCARD:
case MATCH_WIFI_WILDCARD:
return false;
+ case MATCH_CARRIER:
+ return mSubscriberId != null;
+ case MATCH_WIFI:
+ if (Objects.equals(mNetworkId, WIFI_NETWORKID_ALL)
+ && mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL) {
+ return false;
+ }
+ return true;
default:
return true;
}
@@ -405,6 +507,10 @@
return mNetworkId;
}
+ public int getSubscriberIdMatchRule() {
+ return mSubscriberIdMatchRule;
+ }
+
/**
* Test if given {@link NetworkIdentity} matches this template.
*/
@@ -429,6 +535,8 @@
return matchesBluetooth(ident);
case MATCH_PROXY:
return matchesProxy(ident);
+ case MATCH_CARRIER:
+ return matchesCarrier(ident);
default:
// We have no idea what kind of network template we are, so we
// just claim not to match anything.
@@ -466,8 +574,23 @@
|| getCollapsedRatType(mSubType) == getCollapsedRatType(ident.mSubType);
}
- public boolean matchesSubscriberId(String subscriberId) {
- return ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
+ /**
+ * Check if this template matches {@code subscriberId}. Returns true if this
+ * template was created with {@code SUBSCRIBER_ID_MATCH_RULE_ALL}, or with a
+ * {@code mMatchSubscriberIds} array that contains {@code subscriberId}.
+ */
+ public boolean matchesSubscriberId(@Nullable String subscriberId) {
+ return mSubscriberIdMatchRule == SUBSCRIBER_ID_MATCH_RULE_ALL
+ || ArrayUtils.contains(mMatchSubscriberIds, subscriberId);
+ }
+
+ /**
+ * Check if network with matching SSID. Returns true when the SSID matches, or when
+ * {@code mNetworkId} is {@code WIFI_NETWORKID_ALL}.
+ */
+ private boolean matchesWifiNetworkId(@Nullable String networkId) {
+ return Objects.equals(mNetworkId, WIFI_NETWORKID_ALL)
+ || Objects.equals(sanitizeSsid(mNetworkId), sanitizeSsid(networkId));
}
/**
@@ -566,8 +689,8 @@
private boolean matchesWifi(NetworkIdentity ident) {
switch (ident.mType) {
case TYPE_WIFI:
- return Objects.equals(
- sanitizeSsid(mNetworkId), sanitizeSsid(ident.mNetworkId));
+ return matchesSubscriberId(ident.mSubscriberId)
+ && matchesWifiNetworkId(ident.mNetworkId);
default:
return false;
}
@@ -583,6 +706,15 @@
return false;
}
+ /**
+ * Check if matches carrier network. The carrier networks means it includes the subscriberId.
+ */
+ private boolean matchesCarrier(NetworkIdentity ident) {
+ return ident.mSubscriberId != null
+ && !ArrayUtils.isEmpty(mMatchSubscriberIds)
+ && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
+ }
+
private boolean matchesMobileWildcard(NetworkIdentity ident) {
if (ident.mType == TYPE_WIMAX) {
return true;
@@ -635,6 +767,8 @@
return "BLUETOOTH";
case MATCH_PROXY:
return "PROXY";
+ case MATCH_CARRIER:
+ return "CARRIER";
default:
return "UNKNOWN(" + matchRule + ")";
}
diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java
index 7bf9231..459fdac 100644
--- a/core/java/android/net/UnderlyingNetworkInfo.java
+++ b/core/java/android/net/UnderlyingNetworkInfo.java
@@ -37,36 +37,56 @@
@SystemApi(client = MODULE_LIBRARIES)
public final class UnderlyingNetworkInfo implements Parcelable {
/** The owner of this network. */
- public final int ownerUid;
+ private final int mOwnerUid;
+
/** The interface name of this network. */
@NonNull
- public final String iface;
+ private final String mIface;
+
/** The names of the interfaces underlying this network. */
@NonNull
- public final List<String> underlyingIfaces;
+ private final List<String> mUnderlyingIfaces;
public UnderlyingNetworkInfo(int ownerUid, @NonNull String iface,
@NonNull List<String> underlyingIfaces) {
Objects.requireNonNull(iface);
Objects.requireNonNull(underlyingIfaces);
- this.ownerUid = ownerUid;
- this.iface = iface;
- this.underlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces));
+ mOwnerUid = ownerUid;
+ mIface = iface;
+ mUnderlyingIfaces = Collections.unmodifiableList(new ArrayList<>(underlyingIfaces));
}
private UnderlyingNetworkInfo(@NonNull Parcel in) {
- this.ownerUid = in.readInt();
- this.iface = in.readString();
- this.underlyingIfaces = new ArrayList<>();
- in.readList(this.underlyingIfaces, null /*classLoader*/);
+ mOwnerUid = in.readInt();
+ mIface = in.readString();
+ List<String> underlyingIfaces = new ArrayList<>();
+ in.readList(underlyingIfaces, null /*classLoader*/);
+ mUnderlyingIfaces = Collections.unmodifiableList(underlyingIfaces);
+ }
+
+ /** Get the owner of this network. */
+ public int getOwnerUid() {
+ return mOwnerUid;
+ }
+
+ /** Get the interface name of this network. */
+ @NonNull
+ public String getIface() {
+ return mIface;
+ }
+
+ /** Get the names of the interfaces underlying this network. */
+ @NonNull
+ public List<String> getUnderlyingIfaces() {
+ return mUnderlyingIfaces;
}
@Override
public String toString() {
return "UnderlyingNetworkInfo{"
- + "ownerUid=" + ownerUid
- + ", iface='" + iface + '\''
- + ", underlyingIfaces='" + underlyingIfaces.toString() + '\''
+ + "ownerUid=" + mOwnerUid
+ + ", iface='" + mIface + '\''
+ + ", underlyingIfaces='" + mUnderlyingIfaces.toString() + '\''
+ '}';
}
@@ -77,9 +97,9 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
- dest.writeInt(ownerUid);
- dest.writeString(iface);
- dest.writeList(underlyingIfaces);
+ dest.writeInt(mOwnerUid);
+ dest.writeString(mIface);
+ dest.writeList(mUnderlyingIfaces);
}
@NonNull
@@ -103,13 +123,13 @@
if (this == o) return true;
if (!(o instanceof UnderlyingNetworkInfo)) return false;
final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o;
- return ownerUid == that.ownerUid
- && Objects.equals(iface, that.iface)
- && Objects.equals(underlyingIfaces, that.underlyingIfaces);
+ return mOwnerUid == that.getOwnerUid()
+ && Objects.equals(mIface, that.getIface())
+ && Objects.equals(mUnderlyingIfaces, that.getUnderlyingIfaces());
}
@Override
public int hashCode() {
- return Objects.hash(ownerUid, iface, underlyingIfaces);
+ return Objects.hash(mOwnerUid, mIface, mUnderlyingIfaces);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index d042b88..e7c0a50 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -382,8 +382,8 @@
// Migrate data usage over a VPN to the TUN network.
for (UnderlyingNetworkInfo info : vpnArray) {
- delta.migrateTun(info.ownerUid, info.iface,
- info.underlyingIfaces.toArray(new String[0]));
+ delta.migrateTun(info.getOwnerUid(), info.getIface(),
+ info.getUnderlyingIfaces());
// Filter out debug entries as that may lead to over counting.
delta.filterDebugEntries();
}