Merge "Foreground/background network stats using sets."
This commit is contained in:
@@ -26,7 +26,7 @@ interface INetworkStatsService {
|
|||||||
/** Return historical network layer stats for traffic that matches template. */
|
/** Return historical network layer stats for traffic that matches template. */
|
||||||
NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
|
NetworkStatsHistory getHistoryForNetwork(in NetworkTemplate template, int fields);
|
||||||
/** Return historical network layer 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, int fields);
|
NetworkStatsHistory getHistoryForUid(in NetworkTemplate template, int uid, int set, int tag, int fields);
|
||||||
|
|
||||||
/** Return network layer 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);
|
NetworkStats getSummaryForNetwork(in NetworkTemplate template, long start, long end);
|
||||||
@@ -38,6 +38,8 @@ interface INetworkStatsService {
|
|||||||
/** Increment data layer count of operations performed for UID and tag. */
|
/** Increment data layer count of operations performed for UID and tag. */
|
||||||
void incrementOperationCount(int uid, int tag, int operationCount);
|
void incrementOperationCount(int uid, int tag, int operationCount);
|
||||||
|
|
||||||
|
/** Mark given UID as being in foreground for stats purposes. */
|
||||||
|
void setUidForeground(int uid, boolean uidForeground);
|
||||||
/** Force update of statistics. */
|
/** Force update of statistics. */
|
||||||
void forceUpdate();
|
void forceUpdate();
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,13 @@ public class NetworkStats implements Parcelable {
|
|||||||
public static final String IFACE_ALL = null;
|
public static final String IFACE_ALL = null;
|
||||||
/** {@link #uid} value when UID details unavailable. */
|
/** {@link #uid} value when UID details unavailable. */
|
||||||
public static final int UID_ALL = -1;
|
public static final int UID_ALL = -1;
|
||||||
/** {@link #tag} value for without tag. */
|
/** {@link #set} value when all sets combined. */
|
||||||
|
public static final int SET_ALL = -1;
|
||||||
|
/** {@link #set} value where background data is accounted. */
|
||||||
|
public static final int SET_DEFAULT = 0;
|
||||||
|
/** {@link #set} value where foreground data is accounted. */
|
||||||
|
public static final int SET_FOREGROUND = 1;
|
||||||
|
/** {@link #tag} value for total data across all tags. */
|
||||||
public static final int TAG_NONE = 0;
|
public static final int TAG_NONE = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,6 +59,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
private int size;
|
private int size;
|
||||||
private String[] iface;
|
private String[] iface;
|
||||||
private int[] uid;
|
private int[] uid;
|
||||||
|
private int[] set;
|
||||||
private int[] tag;
|
private int[] tag;
|
||||||
private long[] rxBytes;
|
private long[] rxBytes;
|
||||||
private long[] rxPackets;
|
private long[] rxPackets;
|
||||||
@@ -63,6 +70,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
public static class Entry {
|
public static class Entry {
|
||||||
public String iface;
|
public String iface;
|
||||||
public int uid;
|
public int uid;
|
||||||
|
public int set;
|
||||||
public int tag;
|
public int tag;
|
||||||
public long rxBytes;
|
public long rxBytes;
|
||||||
public long rxPackets;
|
public long rxPackets;
|
||||||
@@ -71,17 +79,19 @@ public class NetworkStats implements Parcelable {
|
|||||||
public long operations;
|
public long operations;
|
||||||
|
|
||||||
public Entry() {
|
public Entry() {
|
||||||
this(IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
|
this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
|
public Entry(long rxBytes, long rxPackets, long txBytes, long txPackets, long operations) {
|
||||||
this(IFACE_ALL, UID_ALL, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, operations);
|
this(IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets,
|
||||||
|
operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entry(String iface, int uid, int tag, long rxBytes, long rxPackets, long txBytes,
|
public Entry(String iface, int uid, int set, int tag, long rxBytes, long rxPackets,
|
||||||
long txPackets, long operations) {
|
long txBytes, long txPackets, long operations) {
|
||||||
this.iface = iface;
|
this.iface = iface;
|
||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
|
this.set = set;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
this.rxBytes = rxBytes;
|
this.rxBytes = rxBytes;
|
||||||
this.rxPackets = rxPackets;
|
this.rxPackets = rxPackets;
|
||||||
@@ -96,6 +106,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
this.size = 0;
|
this.size = 0;
|
||||||
this.iface = new String[initialSize];
|
this.iface = new String[initialSize];
|
||||||
this.uid = new int[initialSize];
|
this.uid = new int[initialSize];
|
||||||
|
this.set = new int[initialSize];
|
||||||
this.tag = new int[initialSize];
|
this.tag = new int[initialSize];
|
||||||
this.rxBytes = new long[initialSize];
|
this.rxBytes = new long[initialSize];
|
||||||
this.rxPackets = new long[initialSize];
|
this.rxPackets = new long[initialSize];
|
||||||
@@ -109,6 +120,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
size = parcel.readInt();
|
size = parcel.readInt();
|
||||||
iface = parcel.createStringArray();
|
iface = parcel.createStringArray();
|
||||||
uid = parcel.createIntArray();
|
uid = parcel.createIntArray();
|
||||||
|
set = parcel.createIntArray();
|
||||||
tag = parcel.createIntArray();
|
tag = parcel.createIntArray();
|
||||||
rxBytes = parcel.createLongArray();
|
rxBytes = parcel.createLongArray();
|
||||||
rxPackets = parcel.createLongArray();
|
rxPackets = parcel.createLongArray();
|
||||||
@@ -123,6 +135,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
dest.writeInt(size);
|
dest.writeInt(size);
|
||||||
dest.writeStringArray(iface);
|
dest.writeStringArray(iface);
|
||||||
dest.writeIntArray(uid);
|
dest.writeIntArray(uid);
|
||||||
|
dest.writeIntArray(set);
|
||||||
dest.writeIntArray(tag);
|
dest.writeIntArray(tag);
|
||||||
dest.writeLongArray(rxBytes);
|
dest.writeLongArray(rxBytes);
|
||||||
dest.writeLongArray(rxPackets);
|
dest.writeLongArray(rxPackets);
|
||||||
@@ -131,15 +144,18 @@ public class NetworkStats implements Parcelable {
|
|||||||
dest.writeLongArray(operations);
|
dest.writeLongArray(operations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
|
// @VisibleForTesting
|
||||||
long txBytes, long txPackets) {
|
public NetworkStats addIfaceValues(
|
||||||
return addValues(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, 0L);
|
String iface, long rxBytes, long rxPackets, long txBytes, long txPackets) {
|
||||||
|
return addValues(
|
||||||
|
iface, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, rxPackets, txBytes, txPackets, 0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkStats addValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
|
// @VisibleForTesting
|
||||||
long txBytes, long txPackets, long operations) {
|
public NetworkStats addValues(String iface, int uid, int set, int tag, long rxBytes,
|
||||||
return addValues(
|
long rxPackets, long txBytes, long txPackets, long operations) {
|
||||||
new Entry(iface, uid, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
|
return addValues(new Entry(
|
||||||
|
iface, uid, set, tag, rxBytes, rxPackets, txBytes, txPackets, operations));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,6 +167,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
final int newLength = Math.max(iface.length, 10) * 3 / 2;
|
final int newLength = Math.max(iface.length, 10) * 3 / 2;
|
||||||
iface = Arrays.copyOf(iface, newLength);
|
iface = Arrays.copyOf(iface, newLength);
|
||||||
uid = Arrays.copyOf(uid, newLength);
|
uid = Arrays.copyOf(uid, newLength);
|
||||||
|
set = Arrays.copyOf(set, newLength);
|
||||||
tag = Arrays.copyOf(tag, newLength);
|
tag = Arrays.copyOf(tag, newLength);
|
||||||
rxBytes = Arrays.copyOf(rxBytes, newLength);
|
rxBytes = Arrays.copyOf(rxBytes, newLength);
|
||||||
rxPackets = Arrays.copyOf(rxPackets, newLength);
|
rxPackets = Arrays.copyOf(rxPackets, newLength);
|
||||||
@@ -161,6 +178,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
|
|
||||||
iface[size] = entry.iface;
|
iface[size] = entry.iface;
|
||||||
uid[size] = entry.uid;
|
uid[size] = entry.uid;
|
||||||
|
set[size] = entry.set;
|
||||||
tag[size] = entry.tag;
|
tag[size] = entry.tag;
|
||||||
rxBytes[size] = entry.rxBytes;
|
rxBytes[size] = entry.rxBytes;
|
||||||
rxPackets[size] = entry.rxPackets;
|
rxPackets[size] = entry.rxPackets;
|
||||||
@@ -179,6 +197,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
final Entry entry = recycle != null ? recycle : new Entry();
|
final Entry entry = recycle != null ? recycle : new Entry();
|
||||||
entry.iface = iface[i];
|
entry.iface = iface[i];
|
||||||
entry.uid = uid[i];
|
entry.uid = uid[i];
|
||||||
|
entry.set = set[i];
|
||||||
entry.tag = tag[i];
|
entry.tag = tag[i];
|
||||||
entry.rxBytes = rxBytes[i];
|
entry.rxBytes = rxBytes[i];
|
||||||
entry.rxPackets = rxPackets[i];
|
entry.rxPackets = rxPackets[i];
|
||||||
@@ -201,19 +220,26 @@ public class NetworkStats implements Parcelable {
|
|||||||
return iface.length;
|
return iface.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
|
public NetworkStats combineValues(String iface, int uid, int tag, long rxBytes, long rxPackets,
|
||||||
long txBytes, long txPackets, long operations) {
|
long txBytes, long txPackets, long operations) {
|
||||||
return combineValues(
|
return combineValues(
|
||||||
new Entry(iface, uid, 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) {
|
||||||
|
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
|
* Combine given values with an existing row, or create a new row if
|
||||||
* {@link #findIndex(String, int, int)} is unable to find match. Can also be
|
* {@link #findIndex(String, int, int, int)} is unable to find match. Can
|
||||||
* used to subtract values from existing rows.
|
* also be used to subtract values from existing rows.
|
||||||
*/
|
*/
|
||||||
public NetworkStats combineValues(Entry entry) {
|
public NetworkStats combineValues(Entry entry) {
|
||||||
final int i = findIndex(entry.iface, entry.uid, entry.tag);
|
final int i = findIndex(entry.iface, entry.uid, entry.set, entry.tag);
|
||||||
if (i == -1) {
|
if (i == -1) {
|
||||||
// only create new entry when positive contribution
|
// only create new entry when positive contribution
|
||||||
addValues(entry);
|
addValues(entry);
|
||||||
@@ -230,9 +256,10 @@ public class NetworkStats implements Parcelable {
|
|||||||
/**
|
/**
|
||||||
* Find first stats index that matches the requested parameters.
|
* Find first stats index that matches the requested parameters.
|
||||||
*/
|
*/
|
||||||
public int findIndex(String iface, int uid, int tag) {
|
public int findIndex(String iface, int uid, int set, int tag) {
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
if (Objects.equal(iface, this.iface[i]) && uid == this.uid[i] && tag == this.tag[i]) {
|
if (Objects.equal(iface, this.iface[i]) && uid == this.uid[i] && set == this.set[i]
|
||||||
|
&& tag == this.tag[i]) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +273,7 @@ public class NetworkStats implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public void spliceOperationsFrom(NetworkStats stats) {
|
public void spliceOperationsFrom(NetworkStats stats) {
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
final int j = stats.findIndex(IFACE_ALL, uid[i], tag[i]);
|
final int j = stats.findIndex(IFACE_ALL, uid[i], set[i], tag[i]);
|
||||||
if (j == -1) {
|
if (j == -1) {
|
||||||
operations[i] = 0;
|
operations[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -332,10 +359,11 @@ public class NetworkStats implements Parcelable {
|
|||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
entry.iface = iface[i];
|
entry.iface = iface[i];
|
||||||
entry.uid = uid[i];
|
entry.uid = uid[i];
|
||||||
|
entry.set = set[i];
|
||||||
entry.tag = tag[i];
|
entry.tag = tag[i];
|
||||||
|
|
||||||
// find remote row that matches, and subtract
|
// find remote row that matches, and subtract
|
||||||
final int j = value.findIndex(entry.iface, entry.uid, entry.tag);
|
final int j = value.findIndex(entry.iface, entry.uid, entry.set, entry.tag);
|
||||||
if (j == -1) {
|
if (j == -1) {
|
||||||
// newly appearing row, return entire value
|
// newly appearing row, return entire value
|
||||||
entry.rxBytes = rxBytes[i];
|
entry.rxBytes = rxBytes[i];
|
||||||
@@ -377,7 +405,8 @@ public class NetworkStats implements Parcelable {
|
|||||||
pw.print(prefix);
|
pw.print(prefix);
|
||||||
pw.print(" iface="); pw.print(iface[i]);
|
pw.print(" iface="); pw.print(iface[i]);
|
||||||
pw.print(" uid="); pw.print(uid[i]);
|
pw.print(" uid="); pw.print(uid[i]);
|
||||||
pw.print(" tag=0x"); pw.print(Integer.toHexString(tag[i]));
|
pw.print(" set="); pw.print(setToString(set[i]));
|
||||||
|
pw.print(" tag="); pw.print(tagToString(tag[i]));
|
||||||
pw.print(" rxBytes="); pw.print(rxBytes[i]);
|
pw.print(" rxBytes="); pw.print(rxBytes[i]);
|
||||||
pw.print(" rxPackets="); pw.print(rxPackets[i]);
|
pw.print(" rxPackets="); pw.print(rxPackets[i]);
|
||||||
pw.print(" txBytes="); pw.print(txBytes[i]);
|
pw.print(" txBytes="); pw.print(txBytes[i]);
|
||||||
@@ -386,6 +415,29 @@ public class NetworkStats implements Parcelable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return text description of {@link #set} value.
|
||||||
|
*/
|
||||||
|
public static String setToString(int set) {
|
||||||
|
switch (set) {
|
||||||
|
case SET_ALL:
|
||||||
|
return "ALL";
|
||||||
|
case SET_DEFAULT:
|
||||||
|
return "DEFAULT";
|
||||||
|
case SET_FOREGROUND:
|
||||||
|
return "FOREGROUND";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return text description of {@link #tag} value.
|
||||||
|
*/
|
||||||
|
public static String tagToString(int tag) {
|
||||||
|
return "0x" + Integer.toHexString(tag);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final CharArrayWriter writer = new CharArrayWriter();
|
final CharArrayWriter writer = new CharArrayWriter();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package android.net;
|
package android.net;
|
||||||
|
|
||||||
import static android.net.NetworkStats.IFACE_ALL;
|
import static android.net.NetworkStats.IFACE_ALL;
|
||||||
|
import static android.net.NetworkStats.SET_DEFAULT;
|
||||||
import static android.net.NetworkStats.TAG_NONE;
|
import static android.net.NetworkStats.TAG_NONE;
|
||||||
import static android.net.NetworkStats.UID_ALL;
|
import static android.net.NetworkStats.UID_ALL;
|
||||||
import static android.net.NetworkStatsHistory.DataStreamUtils.readFullLongArray;
|
import static android.net.NetworkStatsHistory.DataStreamUtils.readFullLongArray;
|
||||||
@@ -215,8 +216,8 @@ public class NetworkStatsHistory implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void recordData(long start, long end, long rxBytes, long txBytes) {
|
public void recordData(long start, long end, long rxBytes, long txBytes) {
|
||||||
recordData(start, end,
|
recordData(start, end, new NetworkStats.Entry(
|
||||||
new NetworkStats.Entry(IFACE_ALL, UID_ALL, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0L));
|
IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, rxBytes, 0L, txBytes, 0L, 0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -269,7 +270,7 @@ public class NetworkStatsHistory implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public void recordEntireHistory(NetworkStatsHistory input) {
|
public void recordEntireHistory(NetworkStatsHistory input) {
|
||||||
final NetworkStats.Entry entry = new NetworkStats.Entry(
|
final NetworkStats.Entry entry = new NetworkStats.Entry(
|
||||||
IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
|
IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
|
||||||
for (int i = 0; i < input.bucketCount; i++) {
|
for (int i = 0; i < input.bucketCount; i++) {
|
||||||
final long start = input.bucketStart[i];
|
final long start = input.bucketStart[i];
|
||||||
final long end = start + input.bucketDuration;
|
final long end = start + input.bucketDuration;
|
||||||
@@ -422,7 +423,7 @@ public class NetworkStatsHistory implements Parcelable {
|
|||||||
ensureBuckets(start, end);
|
ensureBuckets(start, end);
|
||||||
|
|
||||||
final NetworkStats.Entry entry = new NetworkStats.Entry(
|
final NetworkStats.Entry entry = new NetworkStats.Entry(
|
||||||
IFACE_ALL, UID_ALL, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
|
IFACE_ALL, UID_ALL, SET_DEFAULT, TAG_NONE, 0L, 0L, 0L, 0L, 0L);
|
||||||
final Random r = new Random();
|
final Random r = new Random();
|
||||||
while (rxBytes > 1024 || rxPackets > 128 || txBytes > 1024 || txPackets > 128
|
while (rxBytes > 1024 || rxPackets > 128 || txBytes > 1024 || txPackets > 128
|
||||||
|| operations > 32) {
|
|| operations > 32) {
|
||||||
|
|||||||
@@ -205,10 +205,6 @@ public class TrafficStats {
|
|||||||
* @param operationCount Number of operations to increment count by.
|
* @param operationCount Number of operations to increment count by.
|
||||||
*/
|
*/
|
||||||
public static void incrementOperationCount(int tag, int operationCount) {
|
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(
|
final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
|
||||||
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
||||||
final int uid = android.os.Process.myUid();
|
final int uid = android.os.Process.myUid();
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ import static android.content.Intent.ACTION_UID_REMOVED;
|
|||||||
import static android.content.Intent.EXTRA_UID;
|
import static android.content.Intent.EXTRA_UID;
|
||||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||||
import static android.net.NetworkStats.IFACE_ALL;
|
import static android.net.NetworkStats.IFACE_ALL;
|
||||||
|
import static android.net.NetworkStats.SET_ALL;
|
||||||
|
import static android.net.NetworkStats.SET_DEFAULT;
|
||||||
|
import static android.net.NetworkStats.SET_FOREGROUND;
|
||||||
import static android.net.NetworkStats.TAG_NONE;
|
import static android.net.NetworkStats.TAG_NONE;
|
||||||
import static android.net.NetworkStats.UID_ALL;
|
import static android.net.NetworkStats.UID_ALL;
|
||||||
import static android.net.TrafficStats.UID_REMOVED;
|
import static android.net.TrafficStats.UID_REMOVED;
|
||||||
@@ -40,6 +43,8 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
|
|||||||
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
||||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||||
|
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
|
||||||
|
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.IAlarmManager;
|
import android.app.IAlarmManager;
|
||||||
@@ -63,17 +68,20 @@ import android.os.Environment;
|
|||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
|
import android.os.Message;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.util.LongSparseArray;
|
|
||||||
import android.util.NtpTrustedTime;
|
import android.util.NtpTrustedTime;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.util.SparseIntArray;
|
||||||
import android.util.TrustedTime;
|
import android.util.TrustedTime;
|
||||||
|
|
||||||
import com.android.internal.os.AtomicFile;
|
import com.android.internal.os.AtomicFile;
|
||||||
|
import com.android.internal.util.Objects;
|
||||||
|
import com.google.android.collect.Lists;
|
||||||
import com.google.android.collect.Maps;
|
import com.google.android.collect.Maps;
|
||||||
import com.google.android.collect.Sets;
|
import com.google.android.collect.Sets;
|
||||||
|
|
||||||
@@ -88,6 +96,8 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -109,6 +119,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
private static final int VERSION_UID_INIT = 1;
|
private static final int VERSION_UID_INIT = 1;
|
||||||
private static final int VERSION_UID_WITH_IDENT = 2;
|
private static final int VERSION_UID_WITH_IDENT = 2;
|
||||||
private static final int VERSION_UID_WITH_TAG = 3;
|
private static final int VERSION_UID_WITH_TAG = 3;
|
||||||
|
private static final int VERSION_UID_WITH_SET = 4;
|
||||||
|
|
||||||
|
private static final int MSG_FORCE_UPDATE = 0x1;
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final INetworkManagementService mNetworkManager;
|
private final INetworkManagementService mNetworkManager;
|
||||||
@@ -156,8 +169,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
/** Set of historical network layer stats for known networks. */
|
/** Set of historical network layer stats for known networks. */
|
||||||
private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
|
private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
|
||||||
/** Set of historical network layer stats for known UIDs. */
|
/** Set of historical network layer stats for known UIDs. */
|
||||||
private HashMap<NetworkIdentitySet, LongSparseArray<NetworkStatsHistory>> mUidStats =
|
private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap();
|
||||||
Maps.newHashMap();
|
|
||||||
|
|
||||||
/** Flag if {@link #mUidStats} have been loaded from disk. */
|
/** Flag if {@link #mUidStats} have been loaded from disk. */
|
||||||
private boolean mUidStatsLoaded = false;
|
private boolean mUidStatsLoaded = false;
|
||||||
@@ -167,6 +179,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
private NetworkStats mLastUidSnapshot;
|
private NetworkStats mLastUidSnapshot;
|
||||||
|
|
||||||
|
/** Current counter sets for each UID. */
|
||||||
|
private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
|
||||||
|
|
||||||
/** Data layer operation counters for splicing into other structures. */
|
/** Data layer operation counters for splicing into other structures. */
|
||||||
private NetworkStats mOperations = new NetworkStats(0L, 10);
|
private NetworkStats mOperations = new NetworkStats(0L, 10);
|
||||||
private NetworkStats mLastOperationsSnapshot;
|
private NetworkStats mLastOperationsSnapshot;
|
||||||
@@ -177,11 +192,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
private final AtomicFile mNetworkFile;
|
private final AtomicFile mNetworkFile;
|
||||||
private final AtomicFile mUidFile;
|
private final AtomicFile mUidFile;
|
||||||
|
|
||||||
// TODO: collect detailed uid stats, storing tag-granularity data until next
|
|
||||||
// dropbox, and uid summary for a specific bucket count.
|
|
||||||
|
|
||||||
// TODO: periodically compile statistics and send to dropbox.
|
|
||||||
|
|
||||||
public NetworkStatsService(
|
public NetworkStatsService(
|
||||||
Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
|
Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
|
||||||
this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
|
this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
|
||||||
@@ -207,7 +217,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
mHandlerThread = new HandlerThread(TAG);
|
mHandlerThread = new HandlerThread(TAG);
|
||||||
mHandlerThread.start();
|
mHandlerThread.start();
|
||||||
mHandler = new Handler(mHandlerThread.getLooper());
|
mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
|
||||||
|
|
||||||
mNetworkFile = new AtomicFile(new File(systemDir, "netstats.bin"));
|
mNetworkFile = new AtomicFile(new File(systemDir, "netstats.bin"));
|
||||||
mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin"));
|
mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin"));
|
||||||
@@ -246,6 +256,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Slog.w(TAG, "unable to register poll alarm");
|
Slog.w(TAG, "unable to register poll alarm");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// kick off background poll to bootstrap deltas
|
||||||
|
mHandler.obtainMessage(MSG_FORCE_UPDATE).sendToTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shutdownLocked() {
|
private void shutdownLocked() {
|
||||||
@@ -302,24 +315,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NetworkStatsHistory getHistoryForUid(
|
public NetworkStatsHistory getHistoryForUid(
|
||||||
NetworkTemplate template, int uid, int tag, int fields) {
|
NetworkTemplate template, int uid, int set, int tag, int fields) {
|
||||||
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
|
||||||
|
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
ensureUidStatsLoadedLocked();
|
ensureUidStatsLoadedLocked();
|
||||||
final long packed = packUidAndTag(uid, tag);
|
|
||||||
|
|
||||||
// combine all interfaces that match template
|
// combine all interfaces that match template
|
||||||
final NetworkStatsHistory combined = new NetworkStatsHistory(
|
final NetworkStatsHistory combined = new NetworkStatsHistory(
|
||||||
mSettings.getUidBucketDuration(), estimateUidBuckets(), fields);
|
mSettings.getUidBucketDuration(), estimateUidBuckets(), fields);
|
||||||
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
for (UidStatsKey key : mUidStats.keySet()) {
|
||||||
if (templateMatches(template, ident)) {
|
final boolean setMatches = set == SET_ALL || key.set == set;
|
||||||
final NetworkStatsHistory history = mUidStats.get(ident).get(packed);
|
if (templateMatches(template, key.ident) && key.uid == uid && setMatches
|
||||||
if (history != null) {
|
&& key.tag == tag) {
|
||||||
combined.recordEntireHistory(history);
|
final NetworkStatsHistory history = mUidStats.get(key);
|
||||||
}
|
combined.recordEntireHistory(history);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return combined;
|
return combined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -371,33 +384,27 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
final NetworkStats.Entry entry = new NetworkStats.Entry();
|
final NetworkStats.Entry entry = new NetworkStats.Entry();
|
||||||
NetworkStatsHistory.Entry historyEntry = null;
|
NetworkStatsHistory.Entry historyEntry = null;
|
||||||
|
|
||||||
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
for (UidStatsKey key : mUidStats.keySet()) {
|
||||||
if (templateMatches(template, ident)) {
|
if (templateMatches(template, key.ident)) {
|
||||||
final LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
// always include summary under TAG_NONE, and include
|
||||||
for (int i = 0; i < uidStats.size(); i++) {
|
// other tags when requested.
|
||||||
final long packed = uidStats.keyAt(i);
|
if (key.tag == TAG_NONE || includeTags) {
|
||||||
final int uid = unpackUid(packed);
|
final NetworkStatsHistory history = mUidStats.get(key);
|
||||||
final int tag = unpackTag(packed);
|
historyEntry = history.getValues(start, end, now, historyEntry);
|
||||||
|
|
||||||
// always include summary under TAG_NONE, and include
|
entry.iface = IFACE_ALL;
|
||||||
// other tags when requested.
|
entry.uid = key.uid;
|
||||||
if (tag == TAG_NONE || includeTags) {
|
entry.set = key.set;
|
||||||
final NetworkStatsHistory history = uidStats.valueAt(i);
|
entry.tag = key.tag;
|
||||||
historyEntry = history.getValues(start, end, now, historyEntry);
|
entry.rxBytes = historyEntry.rxBytes;
|
||||||
|
entry.rxPackets = historyEntry.rxPackets;
|
||||||
|
entry.txBytes = historyEntry.txBytes;
|
||||||
|
entry.txPackets = historyEntry.txPackets;
|
||||||
|
entry.operations = historyEntry.operations;
|
||||||
|
|
||||||
entry.iface = IFACE_ALL;
|
if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
|
||||||
entry.uid = uid;
|
|| entry.txPackets > 0 || entry.operations > 0) {
|
||||||
entry.tag = tag;
|
stats.combineValues(entry);
|
||||||
entry.rxBytes = historyEntry.rxBytes;
|
|
||||||
entry.rxPackets = historyEntry.rxPackets;
|
|
||||||
entry.txBytes = historyEntry.txBytes;
|
|
||||||
entry.txPackets = historyEntry.txPackets;
|
|
||||||
entry.operations = historyEntry.operations;
|
|
||||||
|
|
||||||
if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
|
|
||||||
|| entry.txPackets > 0 || entry.operations > 0) {
|
|
||||||
stats.combineValues(entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -437,8 +444,31 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
|
mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (operationCount < 0) {
|
||||||
|
throw new IllegalArgumentException("operation count can only be incremented");
|
||||||
|
}
|
||||||
|
if (tag == TAG_NONE) {
|
||||||
|
throw new IllegalArgumentException("operation count must have specific tag");
|
||||||
|
}
|
||||||
|
|
||||||
synchronized (mStatsLock) {
|
synchronized (mStatsLock) {
|
||||||
mOperations.combineValues(IFACE_ALL, uid, tag, 0L, 0L, 0L, 0L, operationCount);
|
final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
|
||||||
|
mOperations.combineValues(IFACE_ALL, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
|
||||||
|
mOperations.combineValues(IFACE_ALL, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUidForeground(int uid, boolean uidForeground) {
|
||||||
|
mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
|
||||||
|
|
||||||
|
synchronized (mStatsLock) {
|
||||||
|
final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
|
||||||
|
final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
|
||||||
|
if (oldSet != set) {
|
||||||
|
mActiveUidCounterSet.put(uid, set);
|
||||||
|
setKernelCounterSet(uid, set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -601,7 +631,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
NetworkStats.Entry entry = null;
|
NetworkStats.Entry entry = null;
|
||||||
for (String iface : persistDelta.getUniqueIfaces()) {
|
for (String iface : persistDelta.getUniqueIfaces()) {
|
||||||
final int index = persistDelta.findIndex(iface, UID_ALL, TAG_NONE);
|
final int index = persistDelta.findIndex(iface, UID_ALL, SET_DEFAULT, TAG_NONE);
|
||||||
entry = persistDelta.getValues(index, entry);
|
entry = persistDelta.getValues(index, entry);
|
||||||
if (forcePersist || entry.rxBytes > persistThreshold
|
if (forcePersist || entry.rxBytes > persistThreshold
|
||||||
|| entry.txBytes > persistThreshold) {
|
|| entry.txBytes > persistThreshold) {
|
||||||
@@ -676,31 +706,28 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// splice in operation counts since last poll
|
// splice in operation counts since last poll
|
||||||
final int j = operationsDelta.findIndex(IFACE_ALL, entry.uid, entry.tag);
|
final int j = operationsDelta.findIndex(IFACE_ALL, entry.uid, entry.set, entry.tag);
|
||||||
if (j != -1) {
|
if (j != -1) {
|
||||||
operationsEntry = operationsDelta.getValues(j, operationsEntry);
|
operationsEntry = operationsDelta.getValues(j, operationsEntry);
|
||||||
entry.operations = operationsEntry.operations;
|
entry.operations = operationsEntry.operations;
|
||||||
}
|
}
|
||||||
|
|
||||||
final NetworkStatsHistory history = findOrCreateUidStatsLocked(
|
final NetworkStatsHistory history = findOrCreateUidStatsLocked(
|
||||||
ident, entry.uid, entry.tag);
|
ident, entry.uid, entry.set, entry.tag);
|
||||||
history.recordData(timeStart, currentTime, entry);
|
history.recordData(timeStart, currentTime, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// trim any history beyond max
|
// trim any history beyond max
|
||||||
final long maxUidHistory = mSettings.getUidMaxHistory();
|
final long maxUidHistory = mSettings.getUidMaxHistory();
|
||||||
final long maxTagHistory = mSettings.getTagMaxHistory();
|
final long maxTagHistory = mSettings.getTagMaxHistory();
|
||||||
for (LongSparseArray<NetworkStatsHistory> uidStats : mUidStats.values()) {
|
for (UidStatsKey key : mUidStats.keySet()) {
|
||||||
for (int i = 0; i < uidStats.size(); i++) {
|
final NetworkStatsHistory history = mUidStats.get(key);
|
||||||
final long packed = uidStats.keyAt(i);
|
|
||||||
final NetworkStatsHistory history = uidStats.valueAt(i);
|
|
||||||
|
|
||||||
// detailed tags are trimmed sooner than summary in TAG_NONE
|
// detailed tags are trimmed sooner than summary in TAG_NONE
|
||||||
if (unpackTag(packed) == TAG_NONE) {
|
if (key.tag == TAG_NONE) {
|
||||||
history.removeBucketsBefore(currentTime - maxUidHistory);
|
history.removeBucketsBefore(currentTime - maxUidHistory);
|
||||||
} else {
|
} else {
|
||||||
history.removeBucketsBefore(currentTime - maxTagHistory);
|
history.removeBucketsBefore(currentTime - maxTagHistory);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,26 +742,25 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
private void removeUidLocked(int uid) {
|
private void removeUidLocked(int uid) {
|
||||||
ensureUidStatsLoadedLocked();
|
ensureUidStatsLoadedLocked();
|
||||||
|
|
||||||
|
final ArrayList<UidStatsKey> knownKeys = Lists.newArrayList();
|
||||||
|
knownKeys.addAll(mUidStats.keySet());
|
||||||
|
|
||||||
// migrate all UID stats into special "removed" bucket
|
// migrate all UID stats into special "removed" bucket
|
||||||
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
for (UidStatsKey key : knownKeys) {
|
||||||
final LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
if (key.uid == uid) {
|
||||||
for (int i = 0; i < uidStats.size(); i++) {
|
// only migrate combined TAG_NONE history
|
||||||
final long packed = uidStats.keyAt(i);
|
if (key.tag == TAG_NONE) {
|
||||||
if (unpackUid(packed) == uid) {
|
final NetworkStatsHistory uidHistory = mUidStats.get(key);
|
||||||
// only migrate combined TAG_NONE history
|
final NetworkStatsHistory removedHistory = findOrCreateUidStatsLocked(
|
||||||
if (unpackTag(packed) == TAG_NONE) {
|
key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE);
|
||||||
final NetworkStatsHistory uidHistory = uidStats.valueAt(i);
|
removedHistory.recordEntireHistory(uidHistory);
|
||||||
final NetworkStatsHistory removedHistory = findOrCreateUidStatsLocked(
|
|
||||||
ident, UID_REMOVED, TAG_NONE);
|
|
||||||
removedHistory.recordEntireHistory(uidHistory);
|
|
||||||
}
|
|
||||||
uidStats.remove(packed);
|
|
||||||
}
|
}
|
||||||
|
mUidStats.remove(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: push kernel event to wipe stats for UID, otherwise we risk
|
// clear kernel stats associated with UID
|
||||||
// picking them up again during next poll.
|
resetKernelUidStats(uid);
|
||||||
|
|
||||||
// since this was radical rewrite, push to disk
|
// since this was radical rewrite, push to disk
|
||||||
writeUidStatsLocked();
|
writeUidStatsLocked();
|
||||||
@@ -763,17 +789,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private NetworkStatsHistory findOrCreateUidStatsLocked(
|
private NetworkStatsHistory findOrCreateUidStatsLocked(
|
||||||
NetworkIdentitySet ident, int uid, int tag) {
|
NetworkIdentitySet ident, int uid, int set, int tag) {
|
||||||
ensureUidStatsLoadedLocked();
|
ensureUidStatsLoadedLocked();
|
||||||
|
|
||||||
LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
final UidStatsKey key = new UidStatsKey(ident, uid, set, tag);
|
||||||
if (uidStats == null) {
|
final NetworkStatsHistory existing = mUidStats.get(key);
|
||||||
uidStats = new LongSparseArray<NetworkStatsHistory>();
|
|
||||||
mUidStats.put(ident, uidStats);
|
|
||||||
}
|
|
||||||
|
|
||||||
final long packed = packUidAndTag(uid, tag);
|
|
||||||
final NetworkStatsHistory existing = uidStats.get(packed);
|
|
||||||
|
|
||||||
// update when no existing, or when bucket duration changed
|
// update when no existing, or when bucket duration changed
|
||||||
final long bucketDuration = mSettings.getUidBucketDuration();
|
final long bucketDuration = mSettings.getUidBucketDuration();
|
||||||
@@ -787,7 +807,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (updated != null) {
|
if (updated != null) {
|
||||||
uidStats.put(packed, updated);
|
mUidStats.put(key, updated);
|
||||||
return updated;
|
return updated;
|
||||||
} else {
|
} else {
|
||||||
return existing;
|
return existing;
|
||||||
@@ -874,25 +894,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
// for a short time.
|
// for a short time.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VERSION_UID_WITH_TAG: {
|
case VERSION_UID_WITH_TAG:
|
||||||
// uid := size *(NetworkIdentitySet size *(UID tag NetworkStatsHistory))
|
case VERSION_UID_WITH_SET: {
|
||||||
final int ifaceSize = in.readInt();
|
// uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
|
||||||
for (int i = 0; i < ifaceSize; i++) {
|
final int identSize = in.readInt();
|
||||||
|
for (int i = 0; i < identSize; i++) {
|
||||||
final NetworkIdentitySet ident = new NetworkIdentitySet(in);
|
final NetworkIdentitySet ident = new NetworkIdentitySet(in);
|
||||||
|
|
||||||
final int childSize = in.readInt();
|
final int size = in.readInt();
|
||||||
final LongSparseArray<NetworkStatsHistory> uidStats = new LongSparseArray<
|
for (int j = 0; j < size; j++) {
|
||||||
NetworkStatsHistory>(childSize);
|
|
||||||
for (int j = 0; j < childSize; j++) {
|
|
||||||
final int uid = in.readInt();
|
final int uid = in.readInt();
|
||||||
|
final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt()
|
||||||
|
: SET_DEFAULT;
|
||||||
final int tag = in.readInt();
|
final int tag = in.readInt();
|
||||||
final long packed = packUidAndTag(uid, tag);
|
|
||||||
|
|
||||||
|
final UidStatsKey key = new UidStatsKey(ident, uid, set, tag);
|
||||||
final NetworkStatsHistory history = new NetworkStatsHistory(in);
|
final NetworkStatsHistory history = new NetworkStatsHistory(in);
|
||||||
uidStats.put(packed, history);
|
mUidStats.put(key, history);
|
||||||
}
|
}
|
||||||
|
|
||||||
mUidStats.put(ident, uidStats);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -949,29 +968,36 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
// TODO: consider duplicating stats and releasing lock while writing
|
// TODO: consider duplicating stats and releasing lock while writing
|
||||||
|
|
||||||
|
// build UidStatsKey lists grouped by ident
|
||||||
|
final HashMap<NetworkIdentitySet, ArrayList<UidStatsKey>> keysByIdent = Maps.newHashMap();
|
||||||
|
for (UidStatsKey key : mUidStats.keySet()) {
|
||||||
|
ArrayList<UidStatsKey> keys = keysByIdent.get(key.ident);
|
||||||
|
if (keys == null) {
|
||||||
|
keys = Lists.newArrayList();
|
||||||
|
keysByIdent.put(key.ident, keys);
|
||||||
|
}
|
||||||
|
keys.add(key);
|
||||||
|
}
|
||||||
|
|
||||||
FileOutputStream fos = null;
|
FileOutputStream fos = null;
|
||||||
try {
|
try {
|
||||||
fos = mUidFile.startWrite();
|
fos = mUidFile.startWrite();
|
||||||
final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
|
final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
|
||||||
|
|
||||||
out.writeInt(FILE_MAGIC);
|
out.writeInt(FILE_MAGIC);
|
||||||
out.writeInt(VERSION_UID_WITH_TAG);
|
out.writeInt(VERSION_UID_WITH_SET);
|
||||||
|
|
||||||
final int size = mUidStats.size();
|
out.writeInt(keysByIdent.size());
|
||||||
out.writeInt(size);
|
for (NetworkIdentitySet ident : keysByIdent.keySet()) {
|
||||||
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
final ArrayList<UidStatsKey> keys = keysByIdent.get(ident);
|
||||||
final LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
|
||||||
ident.writeToStream(out);
|
ident.writeToStream(out);
|
||||||
|
|
||||||
final int childSize = uidStats.size();
|
out.writeInt(keys.size());
|
||||||
out.writeInt(childSize);
|
for (UidStatsKey key : keys) {
|
||||||
for (int i = 0; i < childSize; i++) {
|
final NetworkStatsHistory history = mUidStats.get(key);
|
||||||
final long packed = uidStats.keyAt(i);
|
out.writeInt(key.uid);
|
||||||
final int uid = unpackUid(packed);
|
out.writeInt(key.set);
|
||||||
final int tag = unpackTag(packed);
|
out.writeInt(key.tag);
|
||||||
final NetworkStatsHistory history = uidStats.valueAt(i);
|
|
||||||
out.writeInt(uid);
|
|
||||||
out.writeInt(tag);
|
|
||||||
history.writeToStream(out);
|
history.writeToStream(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1030,20 +1056,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
// from disk if not already in memory.
|
// from disk if not already in memory.
|
||||||
ensureUidStatsLoadedLocked();
|
ensureUidStatsLoadedLocked();
|
||||||
|
|
||||||
pw.println("Detailed UID stats:");
|
final ArrayList<UidStatsKey> keys = Lists.newArrayList();
|
||||||
for (NetworkIdentitySet ident : mUidStats.keySet()) {
|
keys.addAll(mUidStats.keySet());
|
||||||
pw.print(" ident="); pw.println(ident.toString());
|
Collections.sort(keys);
|
||||||
|
|
||||||
final LongSparseArray<NetworkStatsHistory> uidStats = mUidStats.get(ident);
|
pw.println("Detailed UID stats:");
|
||||||
for (int i = 0; i < uidStats.size(); i++) {
|
for (UidStatsKey key : keys) {
|
||||||
final long packed = uidStats.keyAt(i);
|
pw.print(" ident="); pw.print(key.ident.toString());
|
||||||
final int uid = unpackUid(packed);
|
pw.print(" uid="); pw.print(key.uid);
|
||||||
final int tag = unpackTag(packed);
|
pw.print(" set="); pw.print(NetworkStats.setToString(key.set));
|
||||||
final NetworkStatsHistory history = uidStats.valueAt(i);
|
pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag));
|
||||||
pw.print(" UID="); pw.print(uid);
|
|
||||||
pw.print(" tag=0x"); pw.println(Integer.toHexString(tag));
|
final NetworkStatsHistory history = mUidStats.get(key);
|
||||||
history.dump(" ", pw, fullHistory);
|
history.dump(" ", pw, fullHistory);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1080,8 +1105,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
|
|
||||||
for (ApplicationInfo info : installedApps) {
|
for (ApplicationInfo info : installedApps) {
|
||||||
final int uid = info.uid;
|
final int uid = info.uid;
|
||||||
findOrCreateUidStatsLocked(ident, uid, TAG_NONE).generateRandom(UID_START, UID_END,
|
findOrCreateUidStatsLocked(ident, uid, SET_DEFAULT, TAG_NONE).generateRandom(
|
||||||
UID_RX_BYTES, UID_RX_PACKETS, UID_TX_BYTES, UID_TX_PACKETS, UID_OPERATIONS);
|
UID_START, UID_END, UID_RX_BYTES, UID_RX_PACKETS, UID_TX_BYTES,
|
||||||
|
UID_TX_PACKETS, UID_OPERATIONS);
|
||||||
|
findOrCreateUidStatsLocked(ident, uid, SET_FOREGROUND, TAG_NONE).generateRandom(
|
||||||
|
UID_START, UID_END, UID_RX_BYTES, UID_RX_PACKETS, UID_TX_BYTES,
|
||||||
|
UID_TX_PACKETS, UID_OPERATIONS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1116,23 +1145,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
return (int) (existing.size() * existing.getBucketDuration() / newBucketDuration);
|
return (int) (existing.size() * existing.getBucketDuration() / newBucketDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @VisibleForTesting
|
|
||||||
public static long packUidAndTag(int uid, int tag) {
|
|
||||||
final long uidLong = uid;
|
|
||||||
final long tagLong = tag;
|
|
||||||
return (uidLong << 32) | (tagLong & 0xFFFFFFFFL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @VisibleForTesting
|
|
||||||
public static int unpackUid(long packed) {
|
|
||||||
return (int) (packed >> 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @VisibleForTesting
|
|
||||||
public static int unpackTag(long packed) {
|
|
||||||
return (int) (packed & 0xFFFFFFFFL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
|
* Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
|
||||||
* in the given {@link NetworkIdentitySet}.
|
* in the given {@link NetworkIdentitySet}.
|
||||||
@@ -1146,6 +1158,58 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Handler.Callback mHandlerCallback = new Handler.Callback() {
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public boolean handleMessage(Message msg) {
|
||||||
|
switch (msg.what) {
|
||||||
|
case MSG_FORCE_UPDATE: {
|
||||||
|
forceUpdate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key uniquely identifying a {@link NetworkStatsHistory} for a UID.
|
||||||
|
*/
|
||||||
|
private static class UidStatsKey implements Comparable<UidStatsKey> {
|
||||||
|
public final NetworkIdentitySet ident;
|
||||||
|
public final int uid;
|
||||||
|
public final int set;
|
||||||
|
public final int tag;
|
||||||
|
|
||||||
|
public UidStatsKey(NetworkIdentitySet ident, int uid, int set, int tag) {
|
||||||
|
this.ident = ident;
|
||||||
|
this.uid = uid;
|
||||||
|
this.set = set;
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(ident, uid, set, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj instanceof UidStatsKey) {
|
||||||
|
final UidStatsKey key = (UidStatsKey) obj;
|
||||||
|
return Objects.equal(ident, key.ident) && uid == key.uid && set == key.set
|
||||||
|
&& tag == key.tag;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
public int compareTo(UidStatsKey another) {
|
||||||
|
return Integer.compare(uid, another.uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default external settings that read from {@link Settings.Secure}.
|
* Default external settings that read from {@link Settings.Secure}.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user