summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2011-07-19 23:47:12 -0700
committerJeff Sharkey <jsharkey@android.com>2011-07-29 22:24:01 -0700
commita63ba59260cd1bb3f5c16e395ace45a61f1d4461 (patch)
treef70f8270c45744686c1c6741f39340c0cb644dd3 /core/java
parent1e833b31ee04c35b5a3494db1acb0068350d8391 (diff)
downloadframeworks_base-a63ba59260cd1bb3f5c16e395ace45a61f1d4461.zip
frameworks_base-a63ba59260cd1bb3f5c16e395ace45a61f1d4461.tar.gz
frameworks_base-a63ba59260cd1bb3f5c16e395ace45a61f1d4461.tar.bz2
Add operation counts to network statistics.
Provide API to increment "operation counts" for a UID and tag, used to eventually derive bytes/operation stats. Internally is stored at network layer, but should belong at data layer. Switch profiling to use data layer stats, which are emulated by summarizing network layer details. Read packet counts from new /proc/ columns and collect them into NetworkStatsHistory. Prevent double-counting by ignoring values from first snapshot. Watch for duplicate /proc/ entries. Update tests to verify packet and operation counters. Bug: 5052136, 5097392 Change-Id: I1832f65a2b8a9188f8088f253474a667c21a2f09
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/net/INetworkStatsService.aidl13
-rw-r--r--core/java/android/net/NetworkStats.java85
-rw-r--r--core/java/android/net/NetworkStatsHistory.java227
-rw-r--r--core/java/android/net/TrafficStats.java39
-rw-r--r--core/java/com/android/server/NetworkManagementSocketTagger.java4
5 files changed, 273 insertions, 95 deletions
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 0548250..c41d182 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -23,16 +23,21 @@ import android.net.NetworkTemplate;
/** {@hide} */
interface INetworkStatsService {
- /** Return historical stats for traffic that matches template. */
+ /** Return historical network layer stats for traffic that matches template. */
NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template);
- /** Return historical stats for specific UID traffic that matches template. */
+ /** Return historical network layer stats for specific UID traffic that matches template. */
NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int tag);
- /** Return usage summary for traffic that matches template. */
+ /** Return network layer usage summary for traffic that matches template. */
NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
- /** Return usage summary per UID for traffic that matches template. */
+ /** Return network layer usage summary per UID for traffic that matches template. */
NetworkStats getSummaryForAllUid(in NetworkTemplate template, long start, long end, boolean includeTags);
+ /** Return data layer snapshot of UID network usage. */
+ NetworkStats getDataLayerSnapshotForUid(int uid);
+ /** Increment data layer count of operations performed for UID and tag. */
+ void incrementOperationCount(int uid, int tag, int operationCount);
+
/** Force update of statistics. */
void forceUpdate();
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index fbff7d8..0e8e7fc 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -21,6 +21,8 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.util.SparseBooleanArray;
+import com.android.internal.util.Objects;
+
import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -56,6 +58,7 @@ public class NetworkStats implements Parcelable {
private long[] rxPackets;
private long[] txBytes;
private long[] txPackets;
+ private int[] operations;
public static class Entry {
public String iface;
@@ -65,12 +68,13 @@ public class NetworkStats implements Parcelable {
public long rxPackets;
public long txBytes;
public long txPackets;
+ public int operations;
public Entry() {
}
public Entry(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes,
- long txPackets) {
+ long txPackets, int operations) {
this.iface = iface;
this.uid = uid;
this.tag = tag;
@@ -78,6 +82,7 @@ public class NetworkStats implements Parcelable {
this.rxPackets = rxPackets;
this.txBytes = txBytes;
this.txPackets = txPackets;
+ this.operations = operations;
}
}
@@ -91,6 +96,7 @@ public class NetworkStats implements Parcelable {
this.rxPackets = new long[initialSize];
this.txBytes = new long[initialSize];
this.txPackets = new long[initialSize];
+ this.operations = new int[initialSize];
}
public NetworkStats(Parcel parcel) {
@@ -103,11 +109,32 @@ public class NetworkStats implements Parcelable {
rxPackets = parcel.createLongArray();
txBytes = parcel.createLongArray();
txPackets = parcel.createLongArray();
+ operations = parcel.createIntArray();
+ }
+
+ /** {@inheritDoc} */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(elapsedRealtime);
+ dest.writeInt(size);
+ dest.writeStringArray(iface);
+ dest.writeIntArray(uid);
+ dest.writeIntArray(tag);
+ dest.writeLongArray(rxBytes);
+ dest.writeLongArray(rxPackets);
+ dest.writeLongArray(txBytes);
+ dest.writeLongArray(txPackets);
+ dest.writeIntArray(operations);
}
public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
long txBytes, long txPackets) {
- return addValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets));
+ return addValues(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, 0);
+ }
+
+ public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
+ long txBytes, long txPackets, int operations) {
+ return addValues(
+ new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
}
/**
@@ -124,6 +151,7 @@ public class NetworkStats implements Parcelable {
rxPackets = Arrays.copyOf(rxPackets, newLength);
txBytes = Arrays.copyOf(txBytes, newLength);
txPackets = Arrays.copyOf(txPackets, newLength);
+ operations = Arrays.copyOf(operations, newLength);
}
iface[size] = entry.iface;
@@ -133,6 +161,7 @@ public class NetworkStats implements Parcelable {
rxPackets[size] = entry.rxPackets;
txBytes[size] = entry.txBytes;
txPackets[size] = entry.txPackets;
+ operations[size] = entry.operations;
size++;
return this;
@@ -150,6 +179,7 @@ public class NetworkStats implements Parcelable {
entry.rxPackets = rxPackets[i];
entry.txBytes = txBytes[i];
entry.txPackets = txPackets[i];
+ entry.operations = operations[i];
return entry;
}
@@ -167,8 +197,9 @@ public class NetworkStats implements Parcelable {
}
public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
- long txBytes, long txPackets) {
- return combineValues(new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets));
+ long txBytes, long txPackets, int operations) {
+ return combineValues(
+ new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
}
/**
@@ -186,6 +217,7 @@ public class NetworkStats implements Parcelable {
rxPackets[i] += entry.rxPackets;
txBytes[i] += entry.txBytes;
txPackets[i] += entry.txPackets;
+ operations[i] += entry.operations;
}
return this;
}
@@ -195,7 +227,7 @@ public class NetworkStats implements Parcelable {
*/
public int findIndex(String iface, int uid, int tag) {
for (int i = 0; i < size; i++) {
- if (equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) {
+ if (Objects.equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) {
return i;
}
}
@@ -203,6 +235,22 @@ public class NetworkStats implements Parcelable {
}
/**
+ * Splice in {@link #operations} from the given {@link NetworkStats} based
+ * on matching {@link #uid} and {@link #tag} rows. Ignores {@link #iface},
+ * since operation counts are at data layer.
+ */
+ public void spliceOperationsFrom(NetworkStats stats) {
+ for (int i = 0; i < size; i++) {
+ final int j = stats.findIndex(IFACE_ALL, uid[i], tag[i]);
+ if (j == -1) {
+ operations[i] = 0;
+ } else {
+ operations[i] = stats.operations[j];
+ }
+ }
+ }
+
+ /**
* Return list of unique interfaces known by this data structure.
*/
public String[] getUniqueIfaces() {
@@ -289,15 +337,17 @@ public class NetworkStats implements Parcelable {
entry.rxPackets = rxPackets[i];
entry.txBytes = txBytes[i];
entry.txPackets = txPackets[i];
+ entry.operations = operations[i];
} else {
// existing row, subtract remote value
entry.rxBytes = rxBytes[i] - value.rxBytes[j];
entry.rxPackets = rxPackets[i] - value.rxPackets[j];
entry.txBytes = txBytes[i] - value.txBytes[j];
entry.txPackets = txPackets[i] - value.txPackets[j];
+ entry.operations = operations[i] - value.operations[j];
if (enforceMonotonic
&& (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
- || entry.txPackets < 0)) {
+ || entry.txPackets < 0 || entry.operations < 0)) {
throw new IllegalArgumentException("found non-monotonic values");
}
if (clampNegative) {
@@ -305,6 +355,7 @@ public class NetworkStats implements Parcelable {
entry.rxPackets = Math.max(0, entry.rxPackets);
entry.txBytes = Math.max(0, entry.txBytes);
entry.txPackets = Math.max(0, entry.txPackets);
+ entry.operations = Math.max(0, entry.operations);
}
}
@@ -314,10 +365,6 @@ public class NetworkStats implements Parcelable {
return result;
}
- private static boolean equal(Object a, Object b) {
- return a == b || (a != null && a.equals(b));
- }
-
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix);
pw.print("NetworkStats: elapsedRealtime="); pw.println(elapsedRealtime);
@@ -325,11 +372,12 @@ public class NetworkStats implements Parcelable {
pw.print(prefix);
pw.print(" iface="); pw.print(iface[i]);
pw.print(" uid="); pw.print(uid[i]);
- pw.print(" tag="); pw.print(tag[i]);
+ pw.print(" tag=0x"); pw.print(Integer.toHexString(tag[i]));
pw.print(" rxBytes="); pw.print(rxBytes[i]);
pw.print(" rxPackets="); pw.print(rxPackets[i]);
pw.print(" txBytes="); pw.print(txBytes[i]);
- pw.print(" txPackets="); pw.println(txPackets[i]);
+ pw.print(" txPackets="); pw.print(txPackets[i]);
+ pw.print(" operations="); pw.println(operations[i]);
}
}
@@ -345,19 +393,6 @@ public class NetworkStats implements Parcelable {
return 0;
}
- /** {@inheritDoc} */
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(elapsedRealtime);
- dest.writeInt(size);
- dest.writeStringArray(iface);
- dest.writeIntArray(uid);
- dest.writeIntArray(tag);
- dest.writeLongArray(rxBytes);
- dest.writeLongArray(rxPackets);
- dest.writeLongArray(txBytes);
- dest.writeLongArray(txPackets);
- }
-
public static final Creator<NetworkStats> CREATOR = new Creator<NetworkStats>() {
public NetworkStats createFromParcel(Parcel in) {
return new NetworkStats(in);
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index 8bd1738..4ffabb1 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -16,6 +16,16 @@
package android.net;
+import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
+import static android.net.NetworkStatsHistory.DataStreamUtils.readLongArray;
+import static android.net.NetworkStatsHistory.DataStreamUtils.writeLongArray;
+import static android.net.NetworkStatsHistory.ParcelUtils.readIntArray;
+import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
+import static android.net.NetworkStatsHistory.ParcelUtils.writeIntArray;
+import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
+
import android.os.Parcel;
import android.os.Parcelable;
@@ -43,19 +53,26 @@ public class NetworkStatsHistory implements Parcelable {
private static final int VERSION_INIT = 1;
// TODO: teach about varint encoding to use less disk space
- // TODO: extend to record rxPackets/txPackets
+ // TODO: teach about omitting entire fields to reduce parcel pressure
+ // TODO: persist/restore packet and operation counts
private final long bucketDuration;
private int bucketCount;
private long[] bucketStart;
private long[] rxBytes;
+ private long[] rxPackets;
private long[] txBytes;
+ private long[] txPackets;
+ private int[] operations;
public static class Entry {
public long bucketStart;
public long bucketDuration;
public long rxBytes;
+ public long rxPackets;
public long txBytes;
+ public long txPackets;
+ public int operations;
}
public NetworkStatsHistory(long bucketDuration) {
@@ -66,15 +83,21 @@ public class NetworkStatsHistory implements Parcelable {
this.bucketDuration = bucketDuration;
bucketStart = new long[initialSize];
rxBytes = new long[initialSize];
+ rxPackets = new long[initialSize];
txBytes = new long[initialSize];
+ txPackets = new long[initialSize];
+ operations = new int[initialSize];
bucketCount = 0;
}
public NetworkStatsHistory(Parcel in) {
bucketDuration = in.readLong();
bucketStart = readLongArray(in);
- rxBytes = in.createLongArray();
- txBytes = in.createLongArray();
+ rxBytes = readLongArray(in);
+ rxPackets = readLongArray(in);
+ txBytes = readLongArray(in);
+ txPackets = readLongArray(in);
+ operations = readIntArray(in);
bucketCount = bucketStart.length;
}
@@ -83,17 +106,24 @@ public class NetworkStatsHistory implements Parcelable {
out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount);
writeLongArray(out, rxBytes, bucketCount);
+ writeLongArray(out, rxPackets, bucketCount);
writeLongArray(out, txBytes, bucketCount);
+ writeLongArray(out, txPackets, bucketCount);
+ writeIntArray(out, operations, bucketCount);
}
public NetworkStatsHistory(DataInputStream in) throws IOException {
+ // TODO: read packet and operation counts
final int version = in.readInt();
switch (version) {
case VERSION_INIT: {
bucketDuration = in.readLong();
bucketStart = readLongArray(in);
rxBytes = readLongArray(in);
+ rxPackets = new long[bucketStart.length];
txBytes = readLongArray(in);
+ txPackets = new long[bucketStart.length];
+ operations = new int[bucketStart.length];
bucketCount = bucketStart.length;
break;
}
@@ -104,6 +134,7 @@ public class NetworkStatsHistory implements Parcelable {
}
public void writeToStream(DataOutputStream out) throws IOException {
+ // TODO: write packet and operation counts
out.writeInt(VERSION_INIT);
out.writeLong(bucketDuration);
writeLongArray(out, bucketStart, bucketCount);
@@ -148,7 +179,10 @@ public class NetworkStatsHistory implements Parcelable {
entry.bucketStart = bucketStart[i];
entry.bucketDuration = bucketDuration;
entry.rxBytes = rxBytes[i];
+ entry.rxPackets = rxPackets[i];
entry.txBytes = txBytes[i];
+ entry.txPackets = txPackets[i];
+ entry.operations = operations[i];
return entry;
}
@@ -156,17 +190,27 @@ public class NetworkStatsHistory implements Parcelable {
* Record that data traffic occurred in the given time range. Will
* distribute across internal buckets, creating new buckets as needed.
*/
- public void recordData(long start, long end, long rx, long tx) {
- if (rx < 0 || tx < 0) {
- throw new IllegalArgumentException(
- "tried recording negative data: rx=" + rx + ", tx=" + tx);
+ @Deprecated
+ public void recordData(long start, long end, long rxBytes, long txBytes) {
+ recordData(start, end,
+ new NetworkStats.Entry(IFACE_ALL, UID_ALL, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0));
+ }
+
+ /**
+ * Record that data traffic occurred in the given time range. Will
+ * distribute across internal buckets, creating new buckets as needed.
+ */
+ public void recordData(long start, long end, NetworkStats.Entry entry) {
+ if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 || entry.txPackets < 0
+ || entry.operations < 0) {
+ throw new IllegalArgumentException("tried recording negative data");
}
// create any buckets needed by this range
ensureBuckets(start, end);
// distribute data usage into buckets
- final long duration = end - start;
+ long duration = end - start;
for (int i = bucketCount - 1; i >= 0; i--) {
final long curStart = bucketStart[i];
final long curEnd = curStart + bucketDuration;
@@ -177,10 +221,22 @@ public class NetworkStatsHistory implements Parcelable {
if (curStart > end) continue;
final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
- if (overlap > 0) {
- this.rxBytes[i] += rx * overlap / duration;
- this.txBytes[i] += tx * overlap / duration;
- }
+ if (overlap <= 0) continue;
+
+ // integer math each time is faster than floating point
+ final long fracRxBytes = entry.rxBytes * overlap / duration;
+ final long fracRxPackets = entry.rxPackets * overlap / duration;
+ final long fracTxBytes = entry.txBytes * overlap / duration;
+ final long fracTxPackets = entry.txPackets * overlap / duration;
+ final int fracOperations = (int) (entry.operations * overlap / duration);
+
+ rxBytes[i] += fracRxBytes; entry.rxBytes -= fracRxBytes;
+ rxPackets[i] += fracRxPackets; entry.rxPackets -= fracRxPackets;
+ txBytes[i] += fracTxBytes; entry.txBytes -= fracTxBytes;
+ txPackets[i] += fracTxPackets; entry.txPackets -= fracTxPackets;
+ operations[i] += fracOperations; entry.operations -= fracOperations;
+
+ duration -= overlap;
}
}
@@ -189,10 +245,19 @@ public class NetworkStatsHistory implements Parcelable {
* for combining together stats for external reporting.
*/
public void recordEntireHistory(NetworkStatsHistory input) {
+ final NetworkStats.Entry entry = new NetworkStats.Entry(
+ IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0);
for (int i = 0; i < input.bucketCount; i++) {
final long start = input.bucketStart[i];
final long end = start + input.bucketDuration;
- recordData(start, end, input.rxBytes[i], input.txBytes[i]);
+
+ entry.rxBytes = input.rxBytes[i];
+ entry.rxPackets = input.rxPackets[i];
+ entry.txBytes = input.txBytes[i];
+ entry.txPackets = input.txPackets[i];
+ entry.operations = input.operations[i];
+
+ recordData(start, end, entry);
}
}
@@ -223,7 +288,10 @@ public class NetworkStatsHistory implements Parcelable {
final int newLength = Math.max(bucketStart.length, 10) * 3 / 2;
bucketStart = Arrays.copyOf(bucketStart, newLength);
rxBytes = Arrays.copyOf(rxBytes, newLength);
+ rxPackets = Arrays.copyOf(rxPackets, newLength);
txBytes = Arrays.copyOf(txBytes, newLength);
+ txPackets = Arrays.copyOf(txPackets, newLength);
+ operations = Arrays.copyOf(operations, newLength);
}
// create gap when inserting bucket in middle
@@ -233,12 +301,18 @@ public class NetworkStatsHistory implements Parcelable {
System.arraycopy(bucketStart, index, bucketStart, dstPos, length);
System.arraycopy(rxBytes, index, rxBytes, dstPos, length);
+ System.arraycopy(rxPackets, index, rxPackets, dstPos, length);
System.arraycopy(txBytes, index, txBytes, dstPos, length);
+ System.arraycopy(txPackets, index, txPackets, dstPos, length);
+ System.arraycopy(operations, index, operations, dstPos, length);
}
bucketStart[index] = start;
rxBytes[index] = 0;
+ rxPackets[index] = 0;
txBytes[index] = 0;
+ txPackets[index] = 0;
+ operations[index] = 0;
bucketCount++;
}
@@ -260,7 +334,10 @@ public class NetworkStatsHistory implements Parcelable {
final int length = bucketStart.length;
bucketStart = Arrays.copyOfRange(bucketStart, i, length);
rxBytes = Arrays.copyOfRange(rxBytes, i, length);
+ rxPackets = Arrays.copyOfRange(rxPackets, i, length);
txBytes = Arrays.copyOfRange(txBytes, i, length);
+ txPackets = Arrays.copyOfRange(txPackets, i, length);
+ operations = Arrays.copyOfRange(operations, i, length);
bucketCount -= i;
}
}
@@ -282,7 +359,10 @@ public class NetworkStatsHistory implements Parcelable {
entry.bucketStart = start;
entry.bucketDuration = end - start;
entry.rxBytes = 0;
+ entry.rxPackets = 0;
entry.txBytes = 0;
+ entry.txPackets = 0;
+ entry.operations = 0;
for (int i = bucketCount - 1; i >= 0; i--) {
final long curStart = bucketStart[i];
@@ -295,14 +375,16 @@ public class NetworkStatsHistory implements Parcelable {
// include full value for active buckets, otherwise only fractional
final boolean activeBucket = curStart < now && curEnd > now;
- final long overlap = Math.min(curEnd, end) - Math.max(curStart, start);
- if (activeBucket || overlap == bucketDuration) {
- entry.rxBytes += rxBytes[i];
- entry.txBytes += txBytes[i];
- } else if (overlap > 0) {
- entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
- entry.txBytes += txBytes[i] * overlap / bucketDuration;
- }
+ final long overlap = activeBucket ? bucketDuration
+ : Math.min(curEnd, end) - Math.max(curStart, start);
+ if (overlap <= 0) continue;
+
+ // integer math each time is faster than floating point
+ entry.rxBytes += rxBytes[i] * overlap / bucketDuration;
+ entry.rxPackets += rxPackets[i] * overlap / bucketDuration;
+ entry.txBytes += txBytes[i] * overlap / bucketDuration;
+ entry.txPackets += txPackets[i] * overlap / bucketDuration;
+ entry.operations += operations[i] * overlap / bucketDuration;
}
return entry;
@@ -315,17 +397,19 @@ public class NetworkStatsHistory implements Parcelable {
public void generateRandom(long start, long end, long rx, long tx) {
ensureBuckets(start, end);
+ final NetworkStats.Entry entry = new NetworkStats.Entry(
+ IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0);
final Random r = new Random();
while (rx > 1024 && tx > 1024) {
final long curStart = randomLong(r, start, end);
final long curEnd = randomLong(r, curStart, end);
- final long curRx = randomLong(r, 0, rx);
- final long curTx = randomLong(r, 0, tx);
+ entry.rxBytes = randomLong(r, 0, rx);
+ entry.txBytes = randomLong(r, 0, tx);
- recordData(curStart, curEnd, curRx, curTx);
+ recordData(curStart, curEnd, entry);
- rx -= curRx;
- tx -= curTx;
+ rx -= entry.rxBytes;
+ tx -= entry.txBytes;
}
}
@@ -347,7 +431,10 @@ public class NetworkStatsHistory implements Parcelable {
pw.print(prefix);
pw.print(" bucketStart="); pw.print(bucketStart[i]);
pw.print(" rxBytes="); pw.print(rxBytes[i]);
- pw.print(" txBytes="); pw.println(txBytes[i]);
+ pw.print(" rxPackets="); pw.print(rxPackets[i]);
+ pw.print(" txBytes="); pw.print(txBytes[i]);
+ pw.print(" txPackets="); pw.print(txPackets[i]);
+ pw.print(" operations="); pw.println(operations[i]);
}
}
@@ -368,41 +455,73 @@ public class NetworkStatsHistory implements Parcelable {
}
};
- private static long[] readLongArray(DataInputStream in) throws IOException {
- final int size = in.readInt();
- final long[] values = new long[size];
- for (int i = 0; i < values.length; i++) {
- values[i] = in.readLong();
+ /**
+ * Utility methods for interacting with {@link DataInputStream} and
+ * {@link DataOutputStream}, mostly dealing with writing partial arrays.
+ */
+ public static class DataStreamUtils {
+ public static long[] readLongArray(DataInputStream in) throws IOException {
+ final int size = in.readInt();
+ final long[] values = new long[size];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = in.readLong();
+ }
+ return values;
+ }
+
+ public static void writeLongArray(DataOutputStream out, long[] values, int size)
+ throws IOException {
+ if (size > values.length) {
+ throw new IllegalArgumentException("size larger than length");
+ }
+ out.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ out.writeLong(values[i]);
+ }
}
- return values;
}
- private static void writeLongArray(DataOutputStream out, long[] values, int size) throws IOException {
- if (size > values.length) {
- throw new IllegalArgumentException("size larger than length");
- }
- out.writeInt(size);
- for (int i = 0; i < size; i++) {
- out.writeLong(values[i]);
+ /**
+ * Utility methods for interacting with {@link Parcel} structures, mostly
+ * dealing with writing partial arrays.
+ */
+ public static class ParcelUtils {
+ public static long[] readLongArray(Parcel in) {
+ final int size = in.readInt();
+ final long[] values = new long[size];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = in.readLong();
+ }
+ return values;
}
- }
- private static long[] readLongArray(Parcel in) {
- final int size = in.readInt();
- final long[] values = new long[size];
- for (int i = 0; i < values.length; i++) {
- values[i] = in.readLong();
+ public static void writeLongArray(Parcel out, long[] values, int size) {
+ if (size > values.length) {
+ throw new IllegalArgumentException("size larger than length");
+ }
+ out.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ out.writeLong(values[i]);
+ }
}
- return values;
- }
- private static void writeLongArray(Parcel out, long[] values, int size) {
- if (size > values.length) {
- throw new IllegalArgumentException("size larger than length");
+ public static int[] readIntArray(Parcel in) {
+ final int size = in.readInt();
+ final int[] values = new int[size];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = in.readInt();
+ }
+ return values;
}
- out.writeInt(size);
- for (int i = 0; i < size; i++) {
- out.writeLong(values[i]);
+
+ public static void writeIntArray(Parcel out, int[] values, int size) {
+ if (size > values.length) {
+ throw new IllegalArgumentException("size larger than length");
+ }
+ out.writeInt(size);
+ for (int i = 0; i < size; i++) {
+ out.writeInt(values[i]);
+ }
}
}
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index e054930..f138e49 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -20,14 +20,13 @@ import android.app.DownloadManager;
import android.app.backup.BackupManager;
import android.content.Context;
import android.media.MediaPlayer;
-import android.os.IBinder;
-import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.ServiceManager;
import com.android.server.NetworkManagementSocketTagger;
import dalvik.system.SocketTagger;
+
import java.net.Socket;
import java.net.SocketException;
@@ -172,7 +171,7 @@ public class TrafficStats {
}
// take snapshot in time; we calculate delta later
- sActiveProfilingStart = getNetworkStatsForUid(context);
+ sActiveProfilingStart = getDataLayerSnapshotForUid(context);
}
}
@@ -190,7 +189,7 @@ public class TrafficStats {
}
// subtract starting values and return delta
- final NetworkStats profilingStop = getNetworkStatsForUid(context);
+ final NetworkStats profilingStop = getDataLayerSnapshotForUid(context);
final NetworkStats profilingDelta = profilingStop.subtractClamped(
sActiveProfilingStart);
sActiveProfilingStart = null;
@@ -199,6 +198,28 @@ public class TrafficStats {
}
/**
+ * Increment count of network operations performed under the given
+ * accounting tag. This can be used to derive bytes-per-operation.
+ *
+ * @param tag Accounting tag used in {@link #setThreadStatsTag(int)}.
+ * @param operationCount Number of operations to increment count by.
+ */
+ public static void incrementOperationCount(int tag, int operationCount) {
+ if (operationCount < 0) {
+ throw new IllegalArgumentException("operation count can only be incremented");
+ }
+
+ final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+ final int uid = android.os.Process.myUid();
+ try {
+ statsService.incrementOperationCount(uid, tag, operationCount);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* Get the total number of packets transmitted through the mobile interface.
*
* @return number of packets. If the statistics are not supported by this device,
@@ -461,14 +482,12 @@ public class TrafficStats {
* Return detailed {@link NetworkStats} for the current UID. Requires no
* special permission.
*/
- private static NetworkStats getNetworkStatsForUid(Context context) {
- final IBinder binder = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
- final INetworkManagementService service = INetworkManagementService.Stub.asInterface(
- binder);
-
+ private static NetworkStats getDataLayerSnapshotForUid(Context context) {
+ final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
+ ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
final int uid = android.os.Process.myUid();
try {
- return service.getNetworkStatsUidDetail(uid);
+ return statsService.getDataLayerSnapshotForUid(uid);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
index 59bef92..4667e5f 100644
--- a/core/java/com/android/server/NetworkManagementSocketTagger.java
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -69,8 +69,8 @@ public final class NetworkManagementSocketTagger extends SocketTagger {
public void tag(FileDescriptor fd) throws SocketException {
final SocketTags options = threadSocketTags.get();
if (LOGD) {
- Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=" + options.statsTag
- + ", statsUid=" + options.statsUid);
+ Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
+ + Integer.toHexString(options.statsTag) + ", statsUid=" + options.statsUid);
}
try {
// TODO: skip tagging when options would be no-op