From a6a78076eeb27084ed815ce0492d4ffe08134bec Mon Sep 17 00:00:00 2001 From: Jeff Davidson Date: Mon, 11 Jan 2016 16:02:17 -0800 Subject: [PATCH] Implement roaming tracking in NetworkStats summary queries. Whether a network is deemed roaming or not was already being tracked as part of the NetworkIdentitySet, so the underlying data store already tracks roaming and native data separately. However, this data was being aggregated together in NetworkStatsCollection#getSummary, since the NetworkIdentitySet is converted to an iface name for the purposes of matching, and the iface name will be identical whether or not the iface is considered roaming. Now it is separated. Also fixes a long-standing bug in NetworkIdentitySet where an identity read from a saved file would always be considered roaming == false, even if it wasn't at the time it was written. Bug: 25813438 Change-Id: I11ab5b51182ed8da7af8fde468df065f9fdc3dad --- core/java/android/app/usage/NetworkStats.java | 13 +- .../app/usage/NetworkStatsManager.java | 25 +- core/java/android/net/NetworkStats.java | 101 +++++- ...droid_internal_net_NetworkStatsFactory.cpp | 7 + .../src/android/net/NetworkStatsTest.java | 341 ++++++++++++------ .../internal/net/NetworkStatsFactoryTest.java | 5 +- .../server/net/NetworkIdentitySet.java | 15 +- .../server/net/NetworkStatsCollection.java | 3 + .../server/NetworkStatsServiceTest.java | 136 +++++-- 9 files changed, 473 insertions(+), 173 deletions(-) diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java index 5f97c9e1d4fd2..d2636467ca72b 100644 --- a/core/java/android/app/usage/NetworkStats.java +++ b/core/java/android/app/usage/NetworkStats.java @@ -208,6 +208,15 @@ public final class NetworkStats implements AutoCloseable { return uid; } + private static int convertRoaming(int roaming) { + switch (roaming) { + case android.net.NetworkStats.ROAMING_ALL : return ROAMING_ALL; + case android.net.NetworkStats.ROAMING_DEFAULT : return ROAMING_DEFAULT; + case android.net.NetworkStats.ROAMING_ROAMING : return ROAMING_ROAMING; + } + return 0; + } + public Bucket() { } @@ -454,9 +463,9 @@ public final class NetworkStats implements AutoCloseable { private void fillBucketFromSummaryEntry(Bucket bucketOut) { bucketOut.mUid = Bucket.convertUid(mRecycledSummaryEntry.uid); bucketOut.mState = Bucket.convertState(mRecycledSummaryEntry.set); - // TODO: Implement metering/roaming tracking. + // TODO: Implement metering tracking. bucketOut.mMetering = Bucket.METERING_ALL; - bucketOut.mRoaming = Bucket.ROAMING_ALL; + bucketOut.mRoaming = Bucket.convertRoaming(mRecycledSummaryEntry.roaming); bucketOut.mBeginTimeStamp = mStartTimeStamp; bucketOut.mEndTimeStamp = mEndTimeStamp; bucketOut.mRxBytes = mRecycledSummaryEntry.rxBytes; diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java index 0fce7a90eaba1..e8373a175e952 100644 --- a/core/java/android/app/usage/NetworkStatsManager.java +++ b/core/java/android/app/usage/NetworkStatsManager.java @@ -40,16 +40,17 @@ import android.util.Log; * {@link #querySummaryForUser}

* {@link #querySummary}

* These queries aggregate network usage across the whole interval. Therefore there will be only one - * bucket for a particular key and state combination. In case of the user-wide and device-wide - * summaries a single bucket containing the totalised network usage is returned. + * bucket for a particular key and state and roaming combination. In case of the user-wide and + * device-wide summaries a single bucket containing the totalised network usage is returned. *

* History queries *

* {@link #queryDetailsForUid}

* {@link #queryDetails}

- * These queries do not aggregate over time but do aggregate over state. Therefore there can be - * multiple buckets for a particular key but all Bucket's state is going to be - * {@link NetworkStats.Bucket#STATE_ALL}. + * These queries do not aggregate over time but do aggregate over state and roaming. Therefore there + * can be multiple buckets for a particular key but all Bucket's state is going to be + * {@link NetworkStats.Bucket#STATE_ALL} and all Bucket's roaming is going to be + * {@link NetworkStats.Bucket#ROAMING_ALL}. *

* NOTE: Accessing stats for apps other than the calling app requires the permission * {@link android.Manifest.permission#PACKAGE_USAGE_STATS}, which is a system-level permission and @@ -81,8 +82,8 @@ public class NetworkStatsManager { * Query network usage statistics summaries. Result is summarised data usage for the whole * device. Result is a single Bucket aggregated over time, state and uid. This means the * bucket's start and end timestamp are going to be the same as the 'startTime' and 'endTime' - * parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid - * {@link NetworkStats.Bucket#UID_ALL}. + * parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid + * {@link NetworkStats.Bucket#UID_ALL}, and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -114,8 +115,8 @@ public class NetworkStatsManager { * Query network usage statistics summaries. Result is summarised data usage for all uids * belonging to calling user. Result is a single Bucket aggregated over time, state and uid. * This means the bucket's start and end timestamp are going to be the same as the 'startTime' - * and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid - * {@link NetworkStats.Bucket#UID_ALL}. + * and 'endTime' parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL}, uid + * {@link NetworkStats.Bucket#UID_ALL}, and roaming {@link NetworkStats.Bucket#ROAMING_ALL}. * * @param networkType As defined in {@link ConnectivityManager}, e.g. * {@link ConnectivityManager#TYPE_MOBILE}, {@link ConnectivityManager#TYPE_WIFI} @@ -146,7 +147,7 @@ public class NetworkStatsManager { /** * Query network usage statistics summaries. Result filtered to include only uids belonging to * calling user. Result is aggregated over time, hence all buckets will have the same start and - * end timestamps. Not aggregated over state or uid. This means buckets' start and end + * end timestamps. Not aggregated over state, uid, or roaming. This means buckets' start and end * timestamps are going to be the same as the 'startTime' and 'endTime' parameters, state and * uid are going to vary. * @@ -179,7 +180,8 @@ public class NetworkStatsManager { * Query network usage statistics details. Only usable for uids belonging to calling user. * Result is aggregated over state but not aggregated over time. This means buckets' start and * end timestamps are going to be between 'startTime' and 'endTime' parameters, state is going - * to be {@link NetworkStats.Bucket#STATE_ALL} and uid the same as the 'uid' parameter. + * to be {@link NetworkStats.Bucket#STATE_ALL} and uid the same as the 'uid' parameter. roaming + * is going to be {@link NetworkStats.Bucket#ROAMING_ALL}. *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. @@ -215,6 +217,7 @@ public class NetworkStatsManager { * calling user. Result is aggregated over state but not aggregated over time or uid. This means * buckets' start and end timestamps are going to be between 'startTime' and 'endTime' * parameters, state is going to be {@link NetworkStats.Bucket#STATE_ALL} and uid will vary. + * roaming is going to be {@link NetworkStats.Bucket#ROAMING_ALL}. *

Only includes buckets that atomically occur in the inclusive time range. Doesn't * interpolate across partial buckets. Since bucket length is in the order of hours, this * method cannot be used to measure data usage on a fine grained time scale. diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 77d7e0cd76b19..8919d516d5593 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -50,7 +50,7 @@ public class NetworkStats implements Parcelable { public static final int UID_ALL = -1; /** {@link #tag} value matching any tag. */ public static final int TAG_ALL = -1; - /** {@link #set} value when all sets combined, not including debug sets. */ + /** {@link #set} value for all sets combined, not including debug sets. */ public static final int SET_ALL = -1; /** {@link #set} value where background data is accounted. */ public static final int SET_DEFAULT = 0; @@ -66,6 +66,13 @@ public class NetworkStats implements Parcelable { /** {@link #tag} value for total data across all tags. */ public static final int TAG_NONE = 0; + /** {@link #set} value for all roaming values. */ + public static final int ROAMING_ALL = -1; + /** {@link #set} value where native, non-roaming data is accounted. */ + public static final int ROAMING_DEFAULT = 0; + /** {@link #set} value where roaming data is accounted. */ + public static final int ROAMING_ROAMING = 1; + // TODO: move fields to "mVariable" notation /** @@ -79,6 +86,7 @@ public class NetworkStats implements Parcelable { private int[] uid; private int[] set; private int[] tag; + private int[] roaming; private long[] rxBytes; private long[] rxPackets; private long[] txBytes; @@ -90,6 +98,12 @@ public class NetworkStats implements Parcelable { public int uid; public int set; public int tag; + /** + * 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 roaming; public long rxBytes; public long rxPackets; public long txBytes; @@ -107,10 +121,17 @@ 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, ROAMING_DEFAULT, rxBytes, rxPackets, txBytes, txPackets, + operations); + } + + public Entry(String iface, int uid, int set, int tag, int roaming, long rxBytes, + long rxPackets, long txBytes, long txPackets, long operations) { this.iface = iface; this.uid = uid; this.set = set; this.tag = tag; + this.roaming = roaming; this.rxBytes = rxBytes; this.rxPackets = rxPackets; this.txBytes = txBytes; @@ -142,6 +163,7 @@ public class NetworkStats implements Parcelable { builder.append(" uid=").append(uid); builder.append(" set=").append(setToString(set)); builder.append(" tag=").append(tagToString(tag)); + builder.append(" roaming=").append(roamingToString(roaming)); builder.append(" rxBytes=").append(rxBytes); builder.append(" rxPackets=").append(rxPackets); builder.append(" txBytes=").append(txBytes); @@ -154,8 +176,8 @@ public class NetworkStats implements Parcelable { public boolean equals(Object o) { if (o instanceof Entry) { final Entry e = (Entry) o; - return uid == e.uid && set == e.set && tag == e.tag && rxBytes == e.rxBytes - && rxPackets == e.rxPackets && txBytes == e.txBytes + return uid == e.uid && set == e.set && tag == e.tag && roaming == e.roaming + && rxBytes == e.rxBytes && rxPackets == e.rxPackets && txBytes == e.txBytes && txPackets == e.txPackets && operations == e.operations && iface.equals(e.iface); } @@ -172,6 +194,7 @@ public class NetworkStats implements Parcelable { this.uid = new int[initialSize]; this.set = new int[initialSize]; this.tag = new int[initialSize]; + this.roaming = new int[initialSize]; this.rxBytes = new long[initialSize]; this.rxPackets = new long[initialSize]; this.txBytes = new long[initialSize]; @@ -184,6 +207,7 @@ public class NetworkStats implements Parcelable { this.uid = EmptyArray.INT; this.set = EmptyArray.INT; this.tag = EmptyArray.INT; + this.roaming = EmptyArray.INT; this.rxBytes = EmptyArray.LONG; this.rxPackets = EmptyArray.LONG; this.txBytes = EmptyArray.LONG; @@ -200,6 +224,7 @@ public class NetworkStats implements Parcelable { uid = parcel.createIntArray(); set = parcel.createIntArray(); tag = parcel.createIntArray(); + roaming = parcel.createIntArray(); rxBytes = parcel.createLongArray(); rxPackets = parcel.createLongArray(); txBytes = parcel.createLongArray(); @@ -216,6 +241,7 @@ public class NetworkStats implements Parcelable { dest.writeIntArray(uid); dest.writeIntArray(set); dest.writeIntArray(tag); + dest.writeIntArray(roaming); dest.writeLongArray(rxBytes); dest.writeLongArray(rxPackets); dest.writeLongArray(txBytes); @@ -248,6 +274,13 @@ public class NetworkStats implements Parcelable { iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); } + @VisibleForTesting + public NetworkStats addValues(String iface, int uid, int set, int tag, int roaming, + long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + return addValues(new Entry( + iface, uid, set, tag, roaming, rxBytes, rxPackets, txBytes, txPackets, operations)); + } + /** * Add new stats entry, copying from given {@link Entry}. The {@link Entry} * object can be recycled across multiple calls. @@ -259,6 +292,7 @@ public class NetworkStats implements Parcelable { uid = Arrays.copyOf(uid, newLength); set = Arrays.copyOf(set, newLength); tag = Arrays.copyOf(tag, newLength); + roaming = Arrays.copyOf(roaming, newLength); rxBytes = Arrays.copyOf(rxBytes, newLength); rxPackets = Arrays.copyOf(rxPackets, newLength); txBytes = Arrays.copyOf(txBytes, newLength); @@ -271,6 +305,7 @@ public class NetworkStats implements Parcelable { uid[size] = entry.uid; set[size] = entry.set; tag[size] = entry.tag; + roaming[size] = entry.roaming; rxBytes[size] = entry.rxBytes; rxPackets[size] = entry.rxPackets; txBytes[size] = entry.txBytes; @@ -290,6 +325,7 @@ public class NetworkStats implements Parcelable { entry.uid = uid[i]; entry.set = set[i]; entry.tag = tag[i]; + entry.roaming = roaming[i]; entry.rxBytes = rxBytes[i]; entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; @@ -327,22 +363,23 @@ public class NetworkStats implements Parcelable { public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { return combineValues( - iface, uid, SET_DEFAULT, tag, rxBytes, rxPackets, txBytes, txPackets, operations); + iface, uid, SET_DEFAULT, tag, rxBytes, rxPackets, txBytes, + txPackets, operations); } - public NetworkStats combineValues(String iface, int uid, int set, int tag, long rxBytes, - long rxPackets, long txBytes, long txPackets, long operations) { + public NetworkStats combineValues(String iface, int uid, int set, int tag, + long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { return combineValues(new Entry( iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations)); } /** * Combine given values with an existing row, or create a new row if - * {@link #findIndex(String, int, int, int)} is unable to find match. Can + * {@link #findIndex(String, int, int, int, int)} is unable to find match. Can * also be used to subtract values from existing rows. */ public NetworkStats combineValues(Entry entry) { - final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag); + final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag, entry.roaming); if (i == -1) { // only create new entry when positive contribution addValues(entry); @@ -370,10 +407,10 @@ 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) { + public int findIndex(String iface, int uid, int set, int tag, int roaming) { for (int i = 0; i < size; i++) { if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i] - && Objects.equals(iface, this.iface[i])) { + && roaming == this.roaming[i] && Objects.equals(iface, this.iface[i])) { return i; } } @@ -385,7 +422,8 @@ public class NetworkStats implements Parcelable { * search around the hinted index as an optimization. */ @VisibleForTesting - public int findIndexHinted(String iface, int uid, int set, int tag, int hintIndex) { + public int findIndexHinted(String iface, int uid, int set, int tag, int roaming, + int hintIndex) { for (int offset = 0; offset < size; offset++) { final int halfOffset = offset / 2; @@ -398,7 +436,7 @@ public class NetworkStats implements Parcelable { } if (uid == this.uid[i] && set == this.set[i] && tag == this.tag[i] - && Objects.equals(iface, this.iface[i])) { + && roaming == this.roaming[i] && Objects.equals(iface, this.iface[i])) { return i; } } @@ -412,7 +450,7 @@ 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]); + final int j = stats.findIndex(iface[i], uid[i], set[i], tag[i], roaming[i]); if (j == -1) { operations[i] = 0; } else { @@ -502,6 +540,7 @@ public class NetworkStats implements Parcelable { entry.uid = limitUid; entry.set = SET_ALL; entry.tag = TAG_NONE; + entry.roaming = ROAMING_ALL; entry.rxBytes = 0; entry.rxPackets = 0; entry.txBytes = 0; @@ -596,9 +635,11 @@ public class NetworkStats implements Parcelable { entry.uid = left.uid[i]; entry.set = left.set[i]; entry.tag = left.tag[i]; + entry.roaming = left.roaming[i]; // find remote row that matches, and subtract - final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, i); + final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, + entry.roaming, i); if (j == -1) { // newly appearing row, return entire value entry.rxBytes = left.rxBytes[i]; @@ -644,6 +685,7 @@ public class NetworkStats implements Parcelable { entry.uid = UID_ALL; entry.set = SET_ALL; entry.tag = TAG_NONE; + entry.roaming = ROAMING_ALL; entry.operations = 0L; for (int i = 0; i < size; i++) { @@ -672,6 +714,7 @@ public class NetworkStats implements Parcelable { entry.iface = IFACE_ALL; entry.set = SET_ALL; entry.tag = TAG_NONE; + entry.roaming = ROAMING_ALL; for (int i = 0; i < size; i++) { // skip specific tags, since already counted in TAG_NONE @@ -717,6 +760,7 @@ public class NetworkStats implements Parcelable { pw.print(" uid="); pw.print(uid[i]); pw.print(" set="); pw.print(setToString(set[i])); pw.print(" tag="); pw.print(tagToString(tag[i])); + pw.print(" roaming="); pw.print(roamingToString(roaming[i])); pw.print(" rxBytes="); pw.print(rxBytes[i]); pw.print(" rxPackets="); pw.print(rxPackets[i]); pw.print(" txBytes="); pw.print(txBytes[i]); @@ -783,6 +827,22 @@ public class NetworkStats implements Parcelable { return "0x" + Integer.toHexString(tag); } + /** + * Return text description of {@link #roaming} value. + */ + public static String roamingToString(int roaming) { + switch (roaming) { + case ROAMING_ALL: + return "ALL"; + case ROAMING_DEFAULT: + return "DEFAULT"; + case ROAMING_ROAMING: + return "ROAMING"; + default: + return "UNKNOWN"; + } + } + @Override public String toString() { final CharArrayWriter writer = new CharArrayWriter(); @@ -932,6 +992,7 @@ public class NetworkStats implements Parcelable { tmpEntry.uid = uid[i]; tmpEntry.tag = tag[i]; tmpEntry.set = set[i]; + tmpEntry.roaming = roaming[i]; combineValues(tmpEntry); if (tag[i] == TAG_NONE) { moved.add(tmpEntry); @@ -950,16 +1011,24 @@ public class NetworkStats implements Parcelable { moved.set = SET_DBG_VPN_OUT; moved.tag = TAG_NONE; moved.iface = underlyingIface; + moved.roaming = ROAMING_ALL; combineValues(moved); // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than // the TAG_NONE traffic. - int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE); + // + // Relies on the fact that the underlying traffic only has state ROAMING_DEFAULT, 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. + int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, + ROAMING_DEFAULT); if (idxVpnBackground != -1) { tunSubtract(idxVpnBackground, this, moved); } - int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE); + int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, + ROAMING_DEFAULT); if (idxVpnForeground != -1) { tunSubtract(idxVpnForeground, this, moved); } diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp index 70134ab04a2ae..9fa90acc02a43 100644 --- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp +++ b/core/jni/com_android_internal_net_NetworkStatsFactory.cpp @@ -43,6 +43,7 @@ static struct { jfieldID uid; jfieldID set; jfieldID tag; + jfieldID roaming; jfieldID rxBytes; jfieldID rxPackets; jfieldID txBytes; @@ -238,6 +239,9 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, ScopedIntArrayRW tag(env, get_int_array(env, stats, gNetworkStatsClassInfo.tag, size, grow)); if (tag.get() == NULL) return -1; + ScopedIntArrayRW roaming(env, get_int_array(env, stats, + gNetworkStatsClassInfo.roaming, size, grow)); + if (roaming.get() == NULL) return -1; ScopedLongArrayRW rxBytes(env, get_long_array(env, stats, gNetworkStatsClassInfo.rxBytes, size, grow)); if (rxBytes.get() == NULL) return -1; @@ -261,6 +265,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; + // Roaming is populated in Java-land by inspecting the iface properties. rxBytes[i] = lines[i].rxBytes; rxPackets[i] = lines[i].rxPackets; txBytes[i] = lines[i].txBytes; @@ -274,6 +279,7 @@ static int readNetworkStatsDetail(JNIEnv* env, jclass clazz, jobject stats, env->SetObjectField(stats, gNetworkStatsClassInfo.uid, uid.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.set, set.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.tag, tag.getJavaArray()); + env->SetObjectField(stats, gNetworkStatsClassInfo.roaming, roaming.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.rxBytes, rxBytes.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.rxPackets, rxPackets.getJavaArray()); env->SetObjectField(stats, gNetworkStatsClassInfo.txBytes, txBytes.getJavaArray()); @@ -305,6 +311,7 @@ int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) { gNetworkStatsClassInfo.uid = GetFieldIDOrDie(env, clazz, "uid", "[I"); gNetworkStatsClassInfo.set = GetFieldIDOrDie(env, clazz, "set", "[I"); gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I"); + gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[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/core/tests/coretests/src/android/net/NetworkStatsTest.java b/core/tests/coretests/src/android/net/NetworkStatsTest.java index a470de1ed3c01..a72397710ef58 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsTest.java @@ -16,6 +16,9 @@ package android.net; +import static android.net.NetworkStats.ROAMING_ALL; +import static android.net.NetworkStats.ROAMING_DEFAULT; +import static android.net.NetworkStats.ROAMING_ROAMING; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; import static android.net.NetworkStats.SET_DBG_VPN_IN; @@ -42,62 +45,103 @@ public class NetworkStatsTest extends TestCase { private static final long TEST_START = 1194220800000L; public void testFindIndex() throws Exception { - final NetworkStats stats = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 10) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 11) - .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 12); + final NetworkStats stats = new NetworkStats(TEST_START, 4) + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, 0L, + 0L, 10) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 1024L, + 8L, 11) + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + 1024L, 8L, 12) + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 1024L, 8L, + 1024L, 8L, 12); - assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE)); - assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE)); - assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE)); - assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE)); + assertEquals(3, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING)); + assertEquals(2, stats.findIndex(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT)); + assertEquals(1, stats.findIndex(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT)); + assertEquals(0, stats.findIndex(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT)); + assertEquals(-1, stats.findIndex(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT)); } public void testFindIndexHinted() { final NetworkStats stats = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1024L, 8L, 0L, 0L, 10) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 1024L, 8L, 11) - .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 12) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 1024L, 8L, 0L, 0L, 10) - .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, 0L, 0L, 1024L, 8L, 11) - .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 12); + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, 0L, + 0L, 10) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 1024L, + 8L, 11) + .addValues(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + 1024L, 8L, 12) + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + 0L, 0L, 10) + .addValues(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 0L, 0L, 1024L, + 8L, 11) + .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + 1024L, 8L, 12) + .addValues(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 1024L, 8L, + 1024L, 8L, 12); // verify that we correctly find across regardless of hinting for (int hint = 0; hint < stats.size(); hint++) { - assertEquals(0, stats.findIndexHinted(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, hint)); - assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, hint)); - assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, hint)); - assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, hint)); - assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, hint)); - assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, hint)); - assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, hint)); + assertEquals(0, stats.findIndexHinted(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, + ROAMING_DEFAULT, hint)); + assertEquals(1, stats.findIndexHinted(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, + ROAMING_DEFAULT, hint)); + assertEquals(2, stats.findIndexHinted(TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, + ROAMING_DEFAULT, hint)); + assertEquals(3, stats.findIndexHinted(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, + ROAMING_DEFAULT, hint)); + assertEquals(4, stats.findIndexHinted(TEST_IFACE2, 101, SET_DEFAULT, 0xF00D, + ROAMING_DEFAULT, hint)); + assertEquals(5, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, + ROAMING_DEFAULT, hint)); + assertEquals(6, stats.findIndexHinted(TEST_IFACE2, 102, SET_DEFAULT, TAG_NONE, + ROAMING_ROAMING, hint)); + assertEquals(-1, stats.findIndexHinted(TEST_IFACE, 6, SET_DEFAULT, TAG_NONE, + ROAMING_DEFAULT, hint)); } } public void testAddEntryGrow() throws Exception { - final NetworkStats stats = new NetworkStats(TEST_START, 2); + final NetworkStats stats = new NetworkStats(TEST_START, 3); assertEquals(0, stats.size()); - assertEquals(2, stats.internalSize()); + assertEquals(3, stats.internalSize()); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 1L, 1L, 2L, 2L, 3); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 2L, 2L, 2L, 2L, 4); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L, 2L, + 2L, 3); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2L, 2L, 2L, + 2L, 4); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 3L, 3L, 2L, + 2L, 5); - assertEquals(2, stats.size()); - assertEquals(2, stats.internalSize()); + assertEquals(3, stats.size()); + assertEquals(3, stats.internalSize()); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 3L, 30L, 4L, 40L, 7); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 4L, 40L, 4L, 40L, 8); - stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 5L, 50L, 5L, 50L, 10); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 4L, 40L, 4L, + 40L, 7); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 5L, 50L, 4L, + 40L, 8); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 6L, 60L, 5L, + 50L, 10); + stats.addValues(TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 7L, 70L, 5L, + 50L, 11); - assertEquals(5, stats.size()); - assertTrue(stats.internalSize() >= 5); + assertEquals(7, stats.size()); + assertTrue(stats.internalSize() >= 7); - assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 1L, 1L, 2L, 2L, 3); - assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 2L, 2L, 2L, 2L, 4); - assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 3L, 30L, 4L, 40L, 7); - assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 4L, 40L, 4L, 40L, 8); - assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, 5L, 50L, 5L, 50L, 10); + assertValues(stats, 0, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L, + 2L, 2L, 3); + assertValues(stats, 1, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2L, 2L, + 2L, 2L, 4); + assertValues(stats, 2, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 3L, 3L, + 2L, 2L, 5); + assertValues(stats, 3, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 4L, + 40L, 4L, 40L, 7); + assertValues(stats, 4, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 5L, + 50L, 4L, 40L, 8); + assertValues(stats, 5, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 6L, + 60L, 5L, 50L, 10); + assertValues(stats, 6, TEST_IFACE, TEST_UID, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 7L, + 70L, 5L, 50L, 11); } public void testCombineExisting() throws Exception { @@ -105,16 +149,23 @@ public class NetworkStatsTest extends TestCase { stats.addValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 10); stats.addValues(TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2); - stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L, -128L, -1L, -1); + stats.combineValues(TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, -128L, -1L, + -128L, -1L, -1); - assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, 384L, 3L, 128L, 1L, 9); - assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, 128L, 1L, 128L, 1L, 2); + assertValues(stats, 0, TEST_IFACE, 1001, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 384L, 3L, + 128L, 1L, 9); + assertValues(stats, 1, TEST_IFACE, 1001, SET_DEFAULT, 0xff, ROAMING_DEFAULT, 128L, 1L, 128L, + 1L, 2); // now try combining that should create row - stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 3); - assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 256L, 2L, 256L, 2L, 6); + stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, + 128L, 1L, 3); + assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 1L, + 128L, 1L, 3); + stats.combineValues(TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, 128L, 1L, + 128L, 1L, 3); + assertValues(stats, 2, TEST_IFACE, 5005, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 256L, 2L, + 256L, 2L, 6); } public void testSubtractIdenticalData() throws Exception { @@ -129,8 +180,10 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // identical data should result in zero delta - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0); + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, + 0L, 0); + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, + 0L, 0); } public void testSubtractIdenticalRows() throws Exception { @@ -145,8 +198,10 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // expect delta between measurements - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 1L, 1L, 2L, 1L, 4); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 3L, 1L, 4L, 1L, 8); + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, 1L, 2L, + 1L, 4); + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 3L, 1L, 4L, + 1L, 8); } public void testSubtractNewRows() throws Exception { @@ -162,9 +217,12 @@ public class NetworkStatsTest extends TestCase { final NetworkStats result = after.subtract(before); // its okay to have new rows - assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0); - assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0); - assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 20); + assertValues(result, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, + 0L, 0); + assertValues(result, 1, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, + 0L, 0); + assertValues(result, 2, TEST_IFACE, 102, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + 1024L, 8L, 20); } public void testSubtractMissingRows() throws Exception { @@ -179,7 +237,8 @@ public class NetworkStatsTest extends TestCase { // should silently drop omitted rows assertEquals(1, result.size()); - assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 1L, 2L, 3L, 4L, 0); + assertValues(result, 0, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1L, + 2L, 3L, 4L, 0); assertEquals(4L, result.getTotalBytes()); } @@ -195,7 +254,7 @@ public class NetworkStatsTest extends TestCase { .addValues(TEST_IFACE, 101, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L); assertEquals(96L, uidSet.getTotalBytes()); - final NetworkStats uidTag = new NetworkStats(TEST_START, 3) + final NetworkStats uidTag = new NetworkStats(TEST_START, 6) .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L) @@ -203,6 +262,15 @@ public class NetworkStatsTest extends TestCase { .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 16L, 0L, 0L, 0L, 0L) .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 8L, 0L, 0L, 0L, 0L); assertEquals(64L, uidTag.getTotalBytes()); + + final NetworkStats uidRoaming = new NetworkStats(TEST_START, 3) + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L, 0L, + 0L); + assertEquals(96L, uidRoaming.getTotalBytes()); } public void testGroupedByIfaceEmpty() throws Exception { @@ -215,62 +283,98 @@ public class NetworkStatsTest extends TestCase { public void testGroupedByIfaceAll() throws Exception { final NetworkStats uidStats = new NetworkStats(TEST_START, 3) - .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, 128L, 8L, 0L, 2L, 20L) - .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, 128L, 8L, 0L, 2L, 20L); + .addValues(IFACE_ALL, 100, SET_ALL, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, 2L, + 20L) + .addValues(IFACE_ALL, 101, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + 2L, 20L) + .addValues(IFACE_ALL, 101, SET_ALL, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L, 2L, + 20L); final NetworkStats grouped = uidStats.groupedByIface(); - assertEquals(2, uidStats.size()); + assertEquals(3, uidStats.size()); assertEquals(1, grouped.size()); - assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, 256L, 16L, 0L, 4L, 0L); + assertValues(grouped, 0, IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 384L, 24L, 0L, + 6L, 0L); } public void testGroupedByIface() throws Exception { - final NetworkStats uidStats = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 64L, 4L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L); + final NetworkStats uidStats = new NetworkStats(TEST_START, 7) + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + 2L, 20L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, 0L, + 0L, 0L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 4L, 0L, 0L, + 0L) + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, + 0L, 0L, 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + 0L, 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L, + 0L, 0L); final NetworkStats grouped = uidStats.groupedByIface(); - assertEquals(6, uidStats.size()); + assertEquals(7, uidStats.size()); assertEquals(2, grouped.size()); - assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, 256L, 16L, 0L, 2L, 0L); - assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, 1024L, 64L, 0L, 0L, 0L); + assertValues(grouped, 0, TEST_IFACE, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 384L, 24L, 0L, + 2L, 0L); + assertValues(grouped, 1, TEST_IFACE2, UID_ALL, SET_ALL, TAG_NONE, ROAMING_ALL, 1024L, 64L, + 0L, 0L, 0L); } public void testAddAllValues() { final NetworkStats first = new NetworkStats(TEST_START, 5) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L); + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, + 0L, 0L) + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L, + 0L, 0L); final NetworkStats second = new NetworkStats(TEST_START, 2) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L); + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, 0L, 0L, + 0L) + .addValues(TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, + 0L, 0L, 0L) + .addValues(TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 32L, 0L, 0L, + 0L, 0L); first.combineAllValues(second); - assertEquals(3, first.size()); - assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 64L, 0L, 0L, 0L, 0L); - assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, 32L, 0L, 0L, 0L, 0L); - assertValues(first, 2, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, 32L, 0L, 0L, 0L, 0L); + assertEquals(4, first.size()); + assertValues(first, 0, TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 64L, 0L, 0L, + 0L, 0L); + assertValues(first, 1, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 0L, + 0L, 0L, 0L); + assertValues(first, 2, TEST_IFACE, 100, SET_FOREGROUND, TAG_NONE, ROAMING_ROAMING, 64L, 0L, + 0L, 0L, 0L); + assertValues(first, 3, TEST_IFACE2, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 32L, + 0L, 0L, 0L, 0L); } public void testGetTotal() { - final NetworkStats stats = new NetworkStats(TEST_START, 3) - .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 2L, 20L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, 64L, 4L, 0L, 0L, 0L) - .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, 512L, 32L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L) - .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L); + final NetworkStats stats = new NetworkStats(TEST_START, 7) + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + 2L, 20L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, 0L, + 0L, 0L) + .addValues(TEST_IFACE2, 100, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 4L, 0L, 0L, + 0L) + .addValues(TEST_IFACE2, 100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 512L, 32L, + 0L, 0L, 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, 0L, + 0L, 0L) + .addValues(TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L, 0L, + 0L) + .addValues(TEST_IFACE, 100, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 8L, 0L, + 0L, 0L); - assertValues(stats.getTotal(null), 1280L, 80L, 0L, 2L, 20L); - assertValues(stats.getTotal(null, 100), 1152L, 72L, 0L, 2L, 20L); + assertValues(stats.getTotal(null), 1408L, 88L, 0L, 2L, 20L); + assertValues(stats.getTotal(null, 100), 1280L, 80L, 0L, 2L, 20L); assertValues(stats.getTotal(null, 101), 128L, 8L, 0L, 0L, 0L); final HashSet ifaces = Sets.newHashSet(); @@ -292,8 +396,10 @@ public class NetworkStatsTest extends TestCase { final NetworkStats after = before.withoutUids(new int[] { 100 }); assertEquals(6, before.size()); assertEquals(2, after.size()); - assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, 128L, 8L, 0L, 0L, 0L); - assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, 128L, 8L, 0L, 0L, 0L); + assertValues(after, 0, TEST_IFACE, 101, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 8L, + 0L, 0L, 0L); + assertValues(after, 1, TEST_IFACE, 101, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 128L, 8L, 0L, + 0L, 0L); } public void testClone() throws Exception { @@ -351,76 +457,83 @@ public class NetworkStatsTest extends TestCase { assertEquals(21, delta.size()); // tunIface and TEST_IFACE entries are not changed. - assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, + assertValues(delta, 0, tunIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 39605L, 46L, 12259L, 55L, 0L); - assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L); - assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, + assertValues(delta, 1, tunIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, + 0L, 0L, 0L); + assertValues(delta, 2, tunIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 72667L, 197L, 43909L, 241L, 0L); - assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, + assertValues(delta, 3, tunIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 9297L, 17L, 4128L, 21L, 0L); - assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, + assertValues(delta, 4, tunIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 4983L, 10L, 1801L, 12L, 0L); - assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, 0L, 0L, 0L, 0L, 0L); - assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, + assertValues(delta, 5, tunIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, + 0L, 0L, 0L); + assertValues(delta, 6, tunIface, 10120, SET_DEFAULT, testTag1, ROAMING_DEFAULT, 21691L, 41L, 13820L, 51L, 0L); - assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, 1281L, 2L, 665L, 2L, 0L); - assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, 1685L, 5L, 2070L, 6L, 0L); + assertValues(delta, 7, tunIface, 10120, SET_FOREGROUND, testTag1, ROAMING_DEFAULT, 1281L, + 2L, 665L, 2L, 0L); + assertValues(delta, 8, TEST_IFACE, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1685L, 5L, + 2070L, 6L, 0L); // Existing underlying Iface entries are updated - assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, + assertValues(delta, 9, underlyingIface, 10100, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 44783L, 54L, 13829L, 60L, 0L); - assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, + assertValues(delta, 10, underlyingIface, 10100, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, 0L, 0L); // VPN underlying Iface entries are updated - assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, + assertValues(delta, 11, underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 28304L, 27L, 1719L, 12L, 0L); - assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, + assertValues(delta, 12, underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 0L, 0L, 0L, 0L, 0L); // New entries are added for new application's underlying Iface traffic - assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, - 72667L, 197L, 41872l, 219L, 0L); - assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, + 72667L, 197L, 41872L, 219L, 0L); + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 9297L, 17L, 3936, 19L, 0L); - assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, + assertContains(delta, underlyingIface, 10120, SET_DEFAULT, testTag1, ROAMING_DEFAULT, 21691L, 41L, 13179L, 46L, 0L); - assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, + assertContains(delta, underlyingIface, 10120, SET_FOREGROUND, testTag1, ROAMING_DEFAULT, 1281L, 2L, 634L, 1L, 0L); // New entries are added for debug purpose - assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, + assertContains(delta, underlyingIface, 10100, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT, 39605L, 46L, 11690, 49, 0); - assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, + assertContains(delta, underlyingIface, 10120, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT, 81964, 214, 45808, 238, 0); - assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_IN, TAG_NONE, ROAMING_DEFAULT, 4983, 10, 1717, 10, 0); - assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, + assertContains(delta, underlyingIface, tunUid, SET_DBG_VPN_OUT, TAG_NONE, ROAMING_ALL, 126552, 270, 59215, 297, 0); } private static void assertContains(NetworkStats stats, String iface, int uid, int set, - int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { - int index = stats.findIndex(iface, uid, set, tag); + int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { + int index = stats.findIndex(iface, uid, set, tag, roaming); assertTrue(index != -1); - assertValues(stats, index, iface, uid, set, tag, + assertValues(stats, index, iface, uid, set, tag, roaming, rxBytes, rxPackets, txBytes, txPackets, operations); } private static void assertValues(NetworkStats stats, int index, String iface, int uid, int set, - int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) { + int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, + long operations) { final NetworkStats.Entry entry = stats.getValues(index, null); - assertValues(entry, iface, uid, set, tag); + assertValues(entry, iface, uid, set, tag, roaming); assertValues(entry, rxBytes, rxPackets, txBytes, txPackets, operations); } private static void assertValues( - NetworkStats.Entry entry, String iface, int uid, int set, int tag) { + NetworkStats.Entry entry, String iface, int uid, int set, int tag, int roaming) { assertEquals(iface, entry.iface); assertEquals(uid, entry.uid); assertEquals(set, entry.set); assertEquals(tag, entry.tag); + assertEquals(roaming, entry.roaming); } private static void assertValues(NetworkStats.Entry entry, long rxBytes, long rxPackets, diff --git a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java index d3dd01a2401fe..12a75b824fb6e 100644 --- a/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java +++ b/core/tests/coretests/src/com/android/internal/net/NetworkStatsFactoryTest.java @@ -16,6 +16,7 @@ package com.android.internal.net; +import static android.net.NetworkStats.ROAMING_DEFAULT; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; @@ -156,7 +157,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase { private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, int tag, long rxBytes, long txBytes) { - final int i = stats.findIndex(iface, uid, set, tag); + final int i = stats.findIndex(iface, uid, set, tag, ROAMING_DEFAULT); final NetworkStats.Entry entry = stats.getValues(i, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected txBytes", txBytes, entry.txBytes); @@ -164,7 +165,7 @@ public class NetworkStatsFactoryTest extends AndroidTestCase { private static void assertStatsEntry(NetworkStats stats, String iface, int uid, int set, int tag, long rxBytes, long rxPackets, long txBytes, long txPackets) { - final int i = stats.findIndex(iface, uid, set, tag); + final int i = stats.findIndex(iface, uid, set, tag, ROAMING_DEFAULT); final NetworkStats.Entry entry = stats.getValues(i, null); assertEquals("unexpected rxBytes", rxBytes, entry.rxBytes); assertEquals("unexpected rxPackets", rxPackets, entry.rxPackets); diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index f230bb39bee4d..68dc715b08afa 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java @@ -61,7 +61,7 @@ public class NetworkIdentitySet extends HashSet implements roaming = false; } - add(new NetworkIdentity(type, subType, subscriberId, networkId, false)); + add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming)); } } @@ -77,6 +77,19 @@ public class NetworkIdentitySet extends HashSet implements } } + /** @return whether any {@link NetworkIdentity} in this set is considered roaming. */ + public boolean isAnyMemberRoaming() { + if (isEmpty()) { + return false; + } + for (NetworkIdentity ident : this) { + if (ident.getRoaming()) { + return true; + } + } + return false; + } + 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 102695e3434af..eec7d931d40ed 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -17,6 +17,8 @@ package com.android.server.net; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.ROAMING_DEFAULT; +import static android.net.NetworkStats.ROAMING_ROAMING; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; @@ -218,6 +220,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { entry.uid = key.uid; entry.set = key.set; entry.tag = key.tag; + entry.roaming = key.ident.isAnyMemberRoaming() ? ROAMING_ROAMING : ROAMING_DEFAULT; entry.rxBytes = historyEntry.rxBytes; entry.rxPackets = historyEntry.rxPackets; entry.txBytes = historyEntry.txBytes; diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index 204bc2ec621a0..8cbd32d2bc653 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -22,6 +22,9 @@ import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.NetworkStats.IFACE_ALL; +import static android.net.NetworkStats.ROAMING_ALL; +import static android.net.NetworkStats.ROAMING_DEFAULT; +import static android.net.NetworkStats.ROAMING_ROAMING; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; @@ -81,6 +84,8 @@ import org.easymock.Capture; import org.easymock.EasyMock; import java.io.File; +import java.util.ArrayList; +import java.util.List; /** * Tests for {@link NetworkStatsService}. @@ -282,8 +287,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // verify service recorded history assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); - assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, 512L, 4L, 256L, 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, 512L, 4L, 256L, 2L, 6); + assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, 4); + assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, + 6); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); verifyAndReset(); @@ -317,8 +323,9 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // after systemReady(), we should have historical stats loaded again assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); assertUidTotal(sTemplateWifi, UID_RED, 1024L, 8L, 512L, 4L, 10); - assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, 512L, 4L, 256L, 2L, 4); - assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, 512L, 4L, 256L, 2L, 6); + assertUidTotal(sTemplateWifi, UID_RED, SET_DEFAULT, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, 4); + assertUidTotal(sTemplateWifi, UID_RED, SET_FOREGROUND, ROAMING_DEFAULT, 512L, 4L, 256L, 2L, + 6); assertUidTotal(sTemplateWifi, UID_BLUE, 128L, 1L, 128L, 1L, 0); verifyAndReset(); @@ -670,16 +677,20 @@ public class NetworkStatsServiceTest extends AndroidTestCase { NetworkStats stats = mSession.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(3, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 1); - assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 50L, 5L, + 50L, 5L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 10L, 1L, 10L, + 1L, 1); + assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 2048L, 16L, + 1024L, 8L, 0); // now verify that recent history only contains one uid final long currentTime = currentTimeMillis(); stats = mSession.getSummaryForAllUid( sTemplateWifi, currentTime - HOUR_IN_MILLIS, currentTime, true); assertEquals(1, stats.size()); - assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0); + assertValues(stats, IFACE_ALL, UID_BLUE, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 1024L, 8L, + 512L, 4L, 0); verifyAndReset(); } @@ -742,10 +753,61 @@ public class NetworkStatsServiceTest extends AndroidTestCase { final NetworkStats stats = mSession.getSummaryForAllUid( sTemplateWifi, Long.MIN_VALUE, Long.MAX_VALUE, true); assertEquals(4, stats.size()); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 1); - assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 2L, + 128L, 2L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 1L, 64L, + 1L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, TAG_NONE, ROAMING_DEFAULT, 32L, 2L, + 32L, 2L, 1); + assertValues(stats, IFACE_ALL, UID_RED, SET_FOREGROUND, 0xFAAD, ROAMING_DEFAULT, 1L, 1L, 1L, + 1L, 1); + + verifyAndReset(); + } + + public void testRoaming() throws Exception { + // pretend that network comes online + expectCurrentTime(); + expectDefaultSettings(); + expectNetworkState(buildMobile3gState(IMSI_1, true /* isRoaming */)); + expectNetworkStatsSummary(buildEmptyStats()); + expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); + expectBandwidthControlCheck(); + + replay(); + mService.forceUpdateIfaces(); + verifyAndReset(); + + // Create some traffic + incrementCurrentTime(HOUR_IN_MILLIS); + expectCurrentTime(); + expectDefaultSettings(); + expectNetworkStatsSummary(buildEmptyStats()); + // Note that all traffic from NetworkManagementService is tagged as ROAMING_DEFAULT, because + // roaming isn't tracked at that layer. We layer it on top by inspecting the iface + // properties. + expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, 128L, 2L, + 128L, 2L, 0L) + .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_DEFAULT, 64L, 1L, 64L, + 1L, 0L)); + expectNetworkStatsPoll(); + + replay(); + mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); + + // verify service recorded history + assertUidTotal(sTemplateImsi1, UID_RED, 128L, 2L, 128L, 2L, 0); + + // verify entire history present + final NetworkStats stats = mSession.getSummaryForAllUid( + sTemplateImsi1, Long.MIN_VALUE, Long.MAX_VALUE, true); + assertEquals(2, stats.size()); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, TAG_NONE, ROAMING_ROAMING, 128L, 2L, + 128L, 2L, 0); + assertValues(stats, IFACE_ALL, UID_RED, SET_DEFAULT, 0xF00D, ROAMING_ROAMING, 64L, 1L, 64L, + 1L, 0); verifyAndReset(); } @@ -805,17 +867,19 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // verify summary API final NetworkStats stats = mSession.getSummaryForNetwork(template, start, end); - assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, - txPackets, operations); + assertValues(stats, IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, ROAMING_DEFAULT, rxBytes, + rxPackets, txBytes, txPackets, operations); } private void assertUidTotal(NetworkTemplate template, int uid, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) throws Exception { - assertUidTotal(template, uid, SET_ALL, rxBytes, rxPackets, txBytes, txPackets, operations); + assertUidTotal(template, uid, SET_ALL, ROAMING_ALL, rxBytes, rxPackets, txBytes, txPackets, + operations); } - private void assertUidTotal(NetworkTemplate template, int uid, int set, long rxBytes, - long rxPackets, long txBytes, long txPackets, int operations) throws Exception { + private void assertUidTotal(NetworkTemplate template, int uid, int set, int roaming, + long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) + throws Exception { // verify history API final NetworkStatsHistory history = mSession.getHistoryForUid( template, uid, set, TAG_NONE, FIELD_ALL); @@ -825,8 +889,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { // verify summary API final NetworkStats stats = mSession.getSummaryForAllUid( template, Long.MIN_VALUE, Long.MAX_VALUE, false); - assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, - operations); + assertValues(stats, IFACE_ALL, uid, set, TAG_NONE, roaming, rxBytes, rxPackets, txBytes, + txPackets, operations); } private void expectSystemReady() throws Exception { @@ -933,18 +997,31 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } private static void assertValues(NetworkStats stats, String iface, int uid, int set, - int tag, long rxBytes, long rxPackets, long txBytes, long txPackets, int operations) { + int tag, int roaming, long rxBytes, long rxPackets, long txBytes, long txPackets, + int operations) { final NetworkStats.Entry entry = new NetworkStats.Entry(); + List sets = new ArrayList<>(); if (set == SET_DEFAULT || set == SET_ALL) { - final int i = stats.findIndex(iface, uid, SET_DEFAULT, tag); - if (i != -1) { - entry.add(stats.getValues(i, null)); - } + sets.add(SET_DEFAULT); } if (set == SET_FOREGROUND || set == SET_ALL) { - final int i = stats.findIndex(iface, uid, SET_FOREGROUND, tag); - if (i != -1) { - entry.add(stats.getValues(i, null)); + sets.add(SET_FOREGROUND); + } + + List roamings = new ArrayList<>(); + if (roaming == ROAMING_DEFAULT || roaming == ROAMING_ALL) { + roamings.add(ROAMING_DEFAULT); + } + if (roaming == ROAMING_ROAMING || roaming == ROAMING_ALL) { + roamings.add(ROAMING_ROAMING); + } + + for (int s : sets) { + for (int r : roamings) { + final int i = stats.findIndex(iface, uid, s, tag, r); + if (i != -1) { + entry.add(stats.getValues(i, null)); + } } } @@ -974,9 +1051,14 @@ public class NetworkStatsServiceTest extends AndroidTestCase { } private static NetworkState buildMobile3gState(String subscriberId) { + return buildMobile3gState(subscriberId, false /* isRoaming */); + } + + private static NetworkState buildMobile3gState(String subscriberId, boolean isRoaming) { final NetworkInfo info = new NetworkInfo( TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UMTS, null, null); info.setDetailedState(DetailedState.CONNECTED, null, null); + info.setRoaming(isRoaming); final LinkProperties prop = new LinkProperties(); prop.setInterfaceName(TEST_IFACE); return new NetworkState(info, prop, null, null, subscriberId, null);