From 28d1a529d5ce5c44a5621e67dad9e00666fd6e7c Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Jan 2018 00:50:48 +0900 Subject: [PATCH 1/3] Pass all default networks to NetworkStatsService This will allow NetworkStatsService to treat traffic on these networks differently from traffic where the app selects a network that is not the default. Bug: 35142602 Test: runtest frameworks-net Change-Id: I5ea9d200d9fb153490c6108bb9390bf152f297da --- .../android/net/INetworkStatsService.aidl | 3 ++- .../server/net/NetworkStatsService.java | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl index 95e7f6031c..90e3ffd550 100644 --- a/core/java/android/net/INetworkStatsService.aidl +++ b/core/java/android/net/INetworkStatsService.aidl @@ -18,6 +18,7 @@ package android.net; import android.net.DataUsageRequest; import android.net.INetworkStatsSession; +import android.net.Network; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; @@ -53,7 +54,7 @@ interface INetworkStatsService { void setUidForeground(int uid, boolean uidForeground); /** Force update of ifaces. */ - void forceUpdateIfaces(); + void forceUpdateIfaces(in Network[] defaultNetworks); /** Force update of statistics. */ void forceUpdate(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index db61ef5cd9..0b25573c30 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -83,6 +83,7 @@ import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; import android.net.LinkProperties; +import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkIdentity; import android.net.NetworkInfo; @@ -231,14 +232,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private final Object mStatsLock = new Object(); /** Set of currently active ifaces. */ + @GuardedBy("mStatsLock") private final ArrayMap mActiveIfaces = new ArrayMap<>(); + /** Set of currently active ifaces for UID stats. */ + @GuardedBy("mStatsLock") private final ArrayMap mActiveUidIfaces = new ArrayMap<>(); + /** Current default active iface. */ private String mActiveIface; + /** Set of any ifaces associated with mobile networks since boot. */ + @GuardedBy("mStatsLock") private String[] mMobileIfaces = new String[0]; + /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */ + @GuardedBy("mStatsLock") + private Network[] mDefaultNetworks = new Network[0]; + private final DropBoxNonMonotonicObserver mNonMonotonicObserver = new DropBoxNonMonotonicObserver(); @@ -779,13 +790,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - public void forceUpdateIfaces() { + public void forceUpdateIfaces(Network[] defaultNetworks) { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); assertBandwidthControlEnabled(); final long token = Binder.clearCallingIdentity(); try { - updateIfaces(); + updateIfaces(defaultNetworks); } finally { Binder.restoreCallingIdentity(token); } @@ -996,11 +1007,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; - private void updateIfaces() { + private void updateIfaces(Network[] defaultNetworks) { synchronized (mStatsLock) { mWakeLock.acquire(); try { - updateIfacesLocked(); + updateIfacesLocked(defaultNetworks); } finally { mWakeLock.release(); } @@ -1013,7 +1024,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * are active on a single {@code iface}, they are combined under a single * {@link NetworkIdentitySet}. */ - private void updateIfacesLocked() { + private void updateIfacesLocked(Network[] defaultNetworks) { if (!mSystemReady) return; if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); @@ -1040,6 +1051,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Rebuild active interfaces based on connected networks mActiveIfaces.clear(); mActiveUidIfaces.clear(); + if (defaultNetworks != null) { + // Caller is ConnectivityService. Update the list of default networks. + mDefaultNetworks = defaultNetworks; + } final ArraySet mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { @@ -1511,7 +1526,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return true; } case MSG_UPDATE_IFACES: { - mService.updateIfaces(); + mService.updateIfaces(null); return true; } case MSG_REGISTER_GLOBAL_ALERT: { From 3e85855083b686c4ada8d29126cfa14a663e5d27 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Jan 2018 01:05:20 +0900 Subject: [PATCH 2/3] Add the default network to NetworkStats and NetworkStatsCollection. This allows us to maintain NetworkStats entries that track whether the traffic was on the default network. At the moment, the stats collection code always passes in DEFAULT_NETWORK_NO. However, this value is a no-op, since it is not persisted to disk. Only the ident, the uid/set/tag, and the packet/byte/operation counters are persisted. A future change will add defaultNetwork to the ident and start persisting it. Bug: 35142602 Test: runtest frameworks-net Change-Id: Ifa291c62c0fa389b88e5561086a29dcd7cee2253 --- core/java/android/net/NetworkStats.java | 90 +++++++++++++++---- .../internal/net/NetworkStatsFactory.java | 2 +- ...droid_internal_net_NetworkStatsFactory.cpp | 9 +- .../server/net/NetworkStatsCollection.java | 2 + .../server/net/NetworkStatsService.java | 7 +- 5 files changed, 90 insertions(+), 20 deletions(-) diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 171adc054b..a85f80e38d 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -82,6 +82,13 @@ public class NetworkStats implements Parcelable { /** {@link #roaming} value where roaming data is accounted. */ public static final int ROAMING_YES = 1; + /** {@link #onDefaultNetwork} value to account for all default network states. */ + public static final int DEFAULT_NETWORK_ALL = -1; + /** {@link #onDefaultNetwork} value to account for usage while not the default network. */ + public static final int DEFAULT_NETWORK_NO = 0; + /** {@link #onDefaultNetwork} value to account for usage while the default network. */ + public static final int DEFAULT_NETWORK_YES = 1; + /** Denotes a request for stats at the interface level. */ public static final int STATS_PER_IFACE = 0; /** Denotes a request for stats at the interface and UID level. */ @@ -102,6 +109,7 @@ public class NetworkStats implements Parcelable { private int[] tag; private int[] metered; private int[] roaming; + private int[] defaultNetwork; private long[] rxBytes; private long[] rxPackets; private long[] txBytes; @@ -125,6 +133,12 @@ public class NetworkStats implements Parcelable { * getSummary(). */ public int roaming; + /** + * Note that this is only populated w/ the default value when read from /proc or written + * to disk. We merge in the correct value when reporting this value to clients of + * getSummary(). + */ + public int defaultNetwork; public long rxBytes; public long rxPackets; public long txBytes; @@ -142,18 +156,27 @@ public class NetworkStats implements Parcelable { public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - this(iface, uid, set, tag, METERED_NO, ROAMING_NO, rxBytes, rxPackets, txBytes, - txPackets, operations); + this(iface, uid, set, tag, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, + rxBytes, rxPackets, txBytes, txPackets, operations); + } + + // TODO: fix the the telephony code to pass DEFAULT_NETWORK_YES and remove this constructor. + public Entry(String iface, int uid, int set, int tag, int metered, int roaming, + long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + this(iface, uid, set, tag, metered, roaming, DEFAULT_NETWORK_YES, rxBytes, rxPackets, + txBytes, txPackets, operations); } public Entry(String iface, int uid, int set, int tag, int metered, int roaming, - long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { this.iface = iface; this.uid = uid; this.set = set; this.tag = tag; this.metered = metered; this.roaming = roaming; + this.defaultNetwork = defaultNetwork; this.rxBytes = rxBytes; this.rxPackets = rxPackets; this.txBytes = txBytes; @@ -187,6 +210,7 @@ public class NetworkStats implements Parcelable { builder.append(" tag=").append(tagToString(tag)); builder.append(" metered=").append(meteredToString(metered)); builder.append(" roaming=").append(roamingToString(roaming)); + builder.append(" defaultNetwork=").append(defaultNetworkToString(defaultNetwork)); builder.append(" rxBytes=").append(rxBytes); builder.append(" rxPackets=").append(rxPackets); builder.append(" txBytes=").append(txBytes); @@ -200,7 +224,8 @@ public class NetworkStats implements Parcelable { if (o instanceof Entry) { final Entry e = (Entry) o; return uid == e.uid && set == e.set && tag == e.tag && metered == e.metered - && roaming == e.roaming && rxBytes == e.rxBytes && rxPackets == e.rxPackets + && roaming == e.roaming && defaultNetwork == e.defaultNetwork + && rxBytes == e.rxBytes && rxPackets == e.rxPackets && txBytes == e.txBytes && txPackets == e.txPackets && operations == e.operations && iface.equals(e.iface); } @@ -209,7 +234,7 @@ public class NetworkStats implements Parcelable { @Override public int hashCode() { - return Objects.hash(uid, set, tag, metered, roaming, iface); + return Objects.hash(uid, set, tag, metered, roaming, defaultNetwork, iface); } } @@ -224,6 +249,7 @@ public class NetworkStats implements Parcelable { this.tag = new int[initialSize]; this.metered = new int[initialSize]; this.roaming = new int[initialSize]; + this.defaultNetwork = new int[initialSize]; this.rxBytes = new long[initialSize]; this.rxPackets = new long[initialSize]; this.txBytes = new long[initialSize]; @@ -238,6 +264,7 @@ public class NetworkStats implements Parcelable { this.tag = EmptyArray.INT; this.metered = EmptyArray.INT; this.roaming = EmptyArray.INT; + this.defaultNetwork = EmptyArray.INT; this.rxBytes = EmptyArray.LONG; this.rxPackets = EmptyArray.LONG; this.txBytes = EmptyArray.LONG; @@ -256,6 +283,7 @@ public class NetworkStats implements Parcelable { tag = parcel.createIntArray(); metered = parcel.createIntArray(); roaming = parcel.createIntArray(); + defaultNetwork = parcel.createIntArray(); rxBytes = parcel.createLongArray(); rxPackets = parcel.createLongArray(); txBytes = parcel.createLongArray(); @@ -274,6 +302,7 @@ public class NetworkStats implements Parcelable { dest.writeIntArray(tag); dest.writeIntArray(metered); dest.writeIntArray(roaming); + dest.writeIntArray(defaultNetwork); dest.writeLongArray(rxBytes); dest.writeLongArray(rxPackets); dest.writeLongArray(txBytes); @@ -308,10 +337,11 @@ public class NetworkStats implements Parcelable { @VisibleForTesting public NetworkStats addValues(String iface, int uid, int set, int tag, int metered, int roaming, - long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + int defaultNetwork, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { return addValues(new Entry( - iface, uid, set, tag, metered, roaming, rxBytes, rxPackets, txBytes, txPackets, - operations)); + iface, uid, set, tag, metered, roaming, defaultNetwork, rxBytes, rxPackets, + txBytes, txPackets, operations)); } /** @@ -327,6 +357,7 @@ public class NetworkStats implements Parcelable { tag = Arrays.copyOf(tag, newLength); metered = Arrays.copyOf(metered, newLength); roaming = Arrays.copyOf(roaming, newLength); + defaultNetwork = Arrays.copyOf(defaultNetwork, newLength); rxBytes = Arrays.copyOf(rxBytes, newLength); rxPackets = Arrays.copyOf(rxPackets, newLength); txBytes = Arrays.copyOf(txBytes, newLength); @@ -341,6 +372,7 @@ public class NetworkStats implements Parcelable { tag[size] = entry.tag; metered[size] = entry.metered; roaming[size] = entry.roaming; + defaultNetwork[size] = entry.defaultNetwork; rxBytes[size] = entry.rxBytes; rxPackets[size] = entry.rxPackets; txBytes[size] = entry.txBytes; @@ -362,6 +394,7 @@ public class NetworkStats implements Parcelable { entry.tag = tag[i]; entry.metered = metered[i]; entry.roaming = roaming[i]; + entry.defaultNetwork = defaultNetwork[i]; entry.rxBytes = rxBytes[i]; entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; @@ -416,7 +449,7 @@ public class NetworkStats implements Parcelable { */ public NetworkStats combineValues(Entry entry) { final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.metered, - entry.roaming); + entry.roaming, entry.defaultNetwork); if (i == -1) { // only create new entry when positive contribution addValues(entry); @@ -444,10 +477,12 @@ public class NetworkStats implements Parcelable { /** * Find first stats index that matches the requested parameters. */ - public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming) { + public int findIndex(String iface, int uid, int set, int tag, int metered, int roaming, + int defaultNetwork) { for (int i = 0; i < size; i++) { if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i] && metered == this.metered[i] && roaming == this.roaming[i] + && defaultNetwork == this.defaultNetwork[i] && Objects.equals(iface, this.iface[i])) { return i; } @@ -461,7 +496,7 @@ public class NetworkStats implements Parcelable { */ @VisibleForTesting public int findIndexHinted(String iface, int uid, int set, int tag, int metered, int roaming, - int hintIndex) { + int defaultNetwork, int hintIndex) { for (int offset = 0; offset < size; offset++) { final int halfOffset = offset / 2; @@ -475,6 +510,7 @@ public class NetworkStats implements Parcelable { if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i] && metered == this.metered[i] && roaming == this.roaming[i] + && defaultNetwork == this.defaultNetwork[i] && Objects.equals(iface, this.iface[i])) { return i; } @@ -489,7 +525,8 @@ public class NetworkStats implements Parcelable { */ public void spliceOperationsFrom(NetworkStats stats) { for (int i = 0; i < size; i++) { - final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i]); + final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], metered[i], roaming[i], + defaultNetwork[i]); if (j == -1) { operations[i] = 0; } else { @@ -581,6 +618,7 @@ public class NetworkStats implements Parcelable { entry.tag = TAG_NONE; entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; + entry.defaultNetwork = DEFAULT_NETWORK_ALL; entry.rxBytes = 0; entry.rxPackets = 0; entry.txBytes = 0; @@ -677,6 +715,7 @@ public class NetworkStats implements Parcelable { entry.tag = left.tag[i]; entry.metered = left.metered[i]; entry.roaming = left.roaming[i]; + entry.defaultNetwork = left.defaultNetwork[i]; entry.rxBytes = left.rxBytes[i]; entry.rxPackets = left.rxPackets[i]; entry.txBytes = left.txBytes[i]; @@ -685,7 +724,7 @@ public class NetworkStats implements Parcelable { // find remote row that matches, and subtract final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, - entry.metered, entry.roaming, i); + entry.metered, entry.roaming, entry.defaultNetwork, i); if (j != -1) { // Found matching row, subtract remote value. entry.rxBytes -= right.rxBytes[j]; @@ -725,6 +764,7 @@ public class NetworkStats implements Parcelable { entry.tag = TAG_NONE; entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; + entry.defaultNetwork = DEFAULT_NETWORK_ALL; entry.operations = 0L; for (int i = 0; i < size; i++) { @@ -755,6 +795,7 @@ public class NetworkStats implements Parcelable { entry.tag = TAG_NONE; entry.metered = METERED_ALL; entry.roaming = ROAMING_ALL; + entry.defaultNetwork = DEFAULT_NETWORK_ALL; for (int i = 0; i < size; i++) { // skip specific tags, since already counted in TAG_NONE @@ -802,6 +843,7 @@ public class NetworkStats implements Parcelable { pw.print(" tag="); pw.print(tagToString(tag[i])); pw.print(" metered="); pw.print(meteredToString(metered[i])); pw.print(" roaming="); pw.print(roamingToString(roaming[i])); + pw.print(" defaultNetwork="); pw.print(defaultNetworkToString(defaultNetwork[i])); pw.print(" rxBytes="); pw.print(rxBytes[i]); pw.print(" rxPackets="); pw.print(rxPackets[i]); pw.print(" txBytes="); pw.print(txBytes[i]); @@ -900,6 +942,22 @@ public class NetworkStats implements Parcelable { } } + /** + * Return text description of {@link #defaultNetwork} value. + */ + public static String defaultNetworkToString(int defaultNetwork) { + switch (defaultNetwork) { + case DEFAULT_NETWORK_ALL: + return "ALL"; + case DEFAULT_NETWORK_NO: + return "NO"; + case DEFAULT_NETWORK_YES: + return "YES"; + default: + return "UNKNOWN"; + } + } + @Override public String toString() { final CharArrayWriter writer = new CharArrayWriter(); @@ -1055,6 +1113,7 @@ public class NetworkStats implements Parcelable { tmpEntry.set = set[i]; tmpEntry.metered = metered[i]; tmpEntry.roaming = roaming[i]; + tmpEntry.defaultNetwork = defaultNetwork[i]; combineValues(tmpEntry); if (tag[i] == TAG_NONE) { moved.add(tmpEntry); @@ -1075,6 +1134,7 @@ public class NetworkStats implements Parcelable { moved.iface = underlyingIface; moved.metered = METERED_ALL; moved.roaming = ROAMING_ALL; + moved.defaultNetwork = DEFAULT_NETWORK_ALL; combineValues(moved); // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than @@ -1085,13 +1145,13 @@ public class NetworkStats implements Parcelable { // roaming data after applying these adjustments, by checking the NetworkIdentity of the // underlying iface. int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, - METERED_NO, ROAMING_NO); + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); if (idxVpnBackground != -1) { tunSubtract(idxVpnBackground, this, moved); } int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, - METERED_NO, ROAMING_NO); + METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO); if (idxVpnForeground != -1) { tunSubtract(idxVpnForeground, this, moved); } diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 3d3e148fb3..b576a20db5 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -217,7 +217,7 @@ public class NetworkStatsFactory { } NetworkStats.Entry adjust = - new NetworkStats.Entry(baseIface, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); + new NetworkStats.Entry(baseIface, 0, 0, 0, 0, 0, 0, 0L, 0L, 0L, 0L, 0L); // Subtract any 464lat traffic seen for the root UID on the current base interface. adjust.rxBytes -= (entry.rxBytes + entry.rxPackets * IPV4V6_HEADER_DELTA); adjust.txBytes -= (entry.txBytes + entry.txPackets * IPV4V6_HEADER_DELTA); diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index 0cb6935990..d254de65f7 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -45,6 +45,7 @@ static struct { jfieldID tag; jfieldID metered; jfieldID roaming; + jfieldID defaultNetwork; jfieldID rxBytes; jfieldID rxPackets; jfieldID txBytes; @@ -246,6 +247,9 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, ScopedIntArrayRW roaming(env, get_int_array(env, stats, gNetworkStatsClassInfo.roaming, size, grow)); if (roaming.get() == NULL) return -1; + ScopedIntArrayRW defaultNetwork(env, get_int_array(env, stats, + gNetworkStatsClassInfo.defaultNetwork, size, grow)); + if (defaultNetwork.get() == NULL) return -1; ScopedLongArrayRW rxBytes(env, get_long_array(env, stats, gNetworkStatsClassInfo.rxBytes, size, grow)); if (rxBytes.get() == NULL) return -1; @@ -269,7 +273,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, uid[i] = lines[i].uid; set[i] = lines[i].set; tag[i] = lines[i].tag; - // Metered and Roaming are populated in Java-land by inspecting the iface properties. + // Metered, roaming and defaultNetwork are populated in Java-land. rxBytes[i] = lines[i].rxBytes; rxPackets[i] = lines[i].rxPackets; txBytes[i] = lines[i].txBytes; @@ -285,6 +289,8 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.metered, metered.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.roaming, roaming.getJavaArray()); + env->SetObjectField(stats, gNetworkStatsClassInfo.defaultNetwork, + defaultNetwork.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray()); @@ -318,6 +324,7 @@ int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I"); gNetworkStatsClassInfo.metered = GetFieldIDOrDie(env, clazz, "metered", "[I"); gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[I"); + gNetworkStatsClassInfo.defaultNetwork = GetFieldIDOrDie(env, clazz, "defaultNetwork", "[I"); gNetworkStatsClassInfo.rxBytes = GetFieldIDOrDie(env, clazz, "rxBytes", "[J"); gNetworkStatsClassInfo.rxPackets = GetFieldIDOrDie(env, clazz, "rxPackets", "[J"); gNetworkStatsClassInfo.txBytes = GetFieldIDOrDie(env, clazz, "txBytes", "[J"); diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 4ceb592af0..5f797691be 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -17,6 +17,7 @@ package com.android.server.net; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.DEFAULT_NETWORK_YES; import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.METERED_YES; import static android.net.NetworkStats.ROAMING_NO; @@ -364,6 +365,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; + entry.defaultNetwork = DEFAULT_NETWORK_YES; entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO; entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; entry.rxBytes = historyEntry.rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 0b25573c30..84dd05d326 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -25,6 +25,7 @@ import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.ConnectivityManager.isNetworkTypeMobile; +import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.METERED_ALL; import static android.net.NetworkStats.ROAMING_ALL; @@ -677,9 +678,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); final NetworkStats stats = new NetworkStats(end - start, 1); - stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, METERED_ALL, - ROAMING_ALL, entry.rxBytes, entry.rxPackets, entry.txBytes, entry.txPackets, - entry.operations)); + stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, + METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets, + entry.txBytes, entry.txPackets, entry.operations)); return stats; } From ab7807a5bb4bfa09190f4dd22ef696388f7a7fa0 Mon Sep 17 00:00:00 2001 From: Lorenzo Colitti Date: Fri, 19 Jan 2018 01:12:04 +0900 Subject: [PATCH 3/3] Track and persist in stats whether traffic is on the default network. This change adds the defaultNetwork to the ident based on current system networking state, and persists that value to flash. Bug: 35142602 Test: runtest frameworks-net Test: downloaded files using default/non-default networks while watching dumpsys netstats Change-Id: Id8776d149b2977548a9eb455ad4926af55e25aba --- core/java/android/net/NetworkIdentity.java | 24 ++++++++++++---- .../server/net/NetworkIdentitySet.java | 28 +++++++++++++++++-- .../server/net/NetworkStatsCollection.java | 4 ++- .../server/net/NetworkStatsService.java | 7 +++-- 4 files changed, 53 insertions(+), 10 deletions(-) diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index d3b35998be..fd118f3401 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -58,21 +58,24 @@ public class NetworkIdentity implements Comparable { final String mNetworkId; final boolean mRoaming; final boolean mMetered; + final boolean mDefaultNetwork; public NetworkIdentity( int type, int subType, String subscriberId, String networkId, boolean roaming, - boolean metered) { + boolean metered, boolean defaultNetwork) { mType = type; mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType; mSubscriberId = subscriberId; mNetworkId = networkId; mRoaming = roaming; mMetered = metered; + mDefaultNetwork = defaultNetwork; } @Override public int hashCode() { - return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered); + return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered, + mDefaultNetwork); } @Override @@ -82,7 +85,8 @@ public class NetworkIdentity implements Comparable { return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming && Objects.equals(mSubscriberId, ident.mSubscriberId) && Objects.equals(mNetworkId, ident.mNetworkId) - && mMetered == ident.mMetered; + && mMetered == ident.mMetered + && mDefaultNetwork == ident.mDefaultNetwork; } return false; } @@ -109,6 +113,7 @@ public class NetworkIdentity implements Comparable { builder.append(", ROAMING"); } builder.append(", metered=").append(mMetered); + builder.append(", defaultNetwork=").append(mDefaultNetwork); return builder.append("}").toString(); } @@ -153,6 +158,10 @@ public class NetworkIdentity implements Comparable { return mMetered; } + public boolean getDefaultNetwork() { + return mDefaultNetwork; + } + /** * Scrub given IMSI on production builds. */ @@ -183,7 +192,8 @@ public class NetworkIdentity implements Comparable { * Build a {@link NetworkIdentity} from the given {@link NetworkState}, * assuming that any mobile networks are using the current IMSI. */ - public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state) { + public static NetworkIdentity buildNetworkIdentity(Context context, NetworkState state, + boolean defaultNetwork) { final int type = state.networkInfo.getType(); final int subType = state.networkInfo.getSubtype(); @@ -216,7 +226,8 @@ public class NetworkIdentity implements Comparable { } } - return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered); + return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered, + defaultNetwork); } @Override @@ -237,6 +248,9 @@ public class NetworkIdentity implements Comparable { if (res == 0) { res = Boolean.compare(mMetered, another.mMetered); } + if (res == 0) { + res = Boolean.compare(mDefaultNetwork, another.mDefaultNetwork); + } return res; } } diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index ee00fdc333..68cd5e7aed 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java @@ -39,6 +39,7 @@ public class NetworkIdentitySet extends HashSet implements private static final int VERSION_ADD_ROAMING = 2; private static final int VERSION_ADD_NETWORK_ID = 3; private static final int VERSION_ADD_METERED = 4; + private static final int VERSION_ADD_DEFAULT_NETWORK = 5; public NetworkIdentitySet() { } @@ -76,12 +77,20 @@ public class NetworkIdentitySet extends HashSet implements metered = (type == TYPE_MOBILE); } - add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered)); + final boolean defaultNetwork; + if (version >= VERSION_ADD_DEFAULT_NETWORK) { + defaultNetwork = in.readBoolean(); + } else { + defaultNetwork = true; + } + + add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered, + defaultNetwork)); } } public void writeToStream(DataOutputStream out) throws IOException { - out.writeInt(VERSION_ADD_METERED); + out.writeInt(VERSION_ADD_DEFAULT_NETWORK); out.writeInt(size()); for (NetworkIdentity ident : this) { out.writeInt(ident.getType()); @@ -90,6 +99,7 @@ public class NetworkIdentitySet extends HashSet implements writeOptionalString(out, ident.getNetworkId()); out.writeBoolean(ident.getRoaming()); out.writeBoolean(ident.getMetered()); + out.writeBoolean(ident.getDefaultNetwork()); } } @@ -119,6 +129,20 @@ public class NetworkIdentitySet extends HashSet implements return false; } + /** @return whether any {@link NetworkIdentity} in this set is considered on the default + network. */ + public boolean areAllMembersOnDefaultNetwork() { + if (isEmpty()) { + return true; + } + for (NetworkIdentity ident : this) { + if (!ident.getDefaultNetwork()) { + return false; + } + } + return true; + } + private static void writeOptionalString(DataOutputStream out, String value) throws IOException { if (value != null) { out.writeByte(1); diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 5f797691be..961a451778 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -17,6 +17,7 @@ package com.android.server.net; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.DEFAULT_NETWORK_NO; import static android.net.NetworkStats.DEFAULT_NETWORK_YES; import static android.net.NetworkStats.METERED_NO; import static android.net.NetworkStats.METERED_YES; @@ -365,7 +366,8 @@ public class NetworkStatsCollection implements FileRotator.Reader { entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; - entry.defaultNetwork = DEFAULT_NETWORK_YES; + entry.defaultNetwork = key.ident.areAllMembersOnDefaultNetwork() ? + DEFAULT_NETWORK_YES : DEFAULT_NETWORK_NO; entry.metered = key.ident.isAnyMemberMetered() ? METERED_YES : METERED_NO; entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_YES : ROAMING_NO; entry.rxBytes = historyEntry.rxBytes; diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 84dd05d326..78fd4b4923 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -1061,7 +1061,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { for (NetworkState state : states) { if (state.networkInfo.isConnected()) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); - final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); + final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network); + final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state, + isDefault); // Traffic occurring on the base interface is always counted for // both total usage and UID details. @@ -1081,7 +1083,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // Copy the identify from IMS one but mark it as metered. NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), - ident.getRoaming(), true); + ident.getRoaming(), true /* metered */, + true /* onDefaultNetwork */); findOrCreateNetworkIdentitySet(mActiveIfaces, VT_INTERFACE).add(vtIdent); findOrCreateNetworkIdentitySet(mActiveUidIfaces, VT_INTERFACE).add(vtIdent); }