Persist network stats using AtomicFile.

Implements read/write of network stats using AtomicFile, along with
magic number and versioning.  Stores in "/data/system/netstats.bin"
for now.  Tests to verify that stats are persisted across a simulated
reboot, and to verify that TEMPLATE_WIFI is working.

Fixed bug where kernel counters rolling backwards would cause negative
stats to be recorded; now we clamp deltas at 0.

Change-Id: I53bce26fc8fd3f4ab1e34ce135d302edfa34db34
This commit is contained in:
Jeff Sharkey
2011-06-05 17:42:53 -07:00
parent 0b1cfc0d55
commit 98693eb89a
5 changed files with 160 additions and 20 deletions

View File

@@ -28,6 +28,6 @@ interface INetworkStatsService {
NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate);
/** Return usage summary per UID for traffic that matches template. */
NetworkStats getSummaryPerUid(long start, long end, int networkTemplate);
NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate);
}

View File

@@ -153,6 +153,30 @@ public class NetworkStats implements Parcelable {
return result;
}
/**
* Subtract the given {@link NetworkStats}, effectively leaving the delta
* between two snapshots in time. Assumes that statistics rows collect over
* time, and that none of them have disappeared.
*
* @throws IllegalArgumentException when given {@link NetworkStats} is
* non-monotonic.
*/
public NetworkStats subtract(NetworkStats value) {
return subtract(value, true, false);
}
/**
* Subtract the given {@link NetworkStats}, effectively leaving the delta
* between two snapshots in time. Assumes that statistics rows collect over
* time, and that none of them have disappeared.
* <p>
* Instead of throwing when counters are non-monotonic, this variant clamps
* results to never be negative.
*/
public NetworkStats subtractClamped(NetworkStats value) {
return subtract(value, false, true);
}
/**
* Subtract the given {@link NetworkStats}, effectively leaving the delta
* between two snapshots in time. Assumes that statistics rows collect over
@@ -160,8 +184,11 @@ public class NetworkStats implements Parcelable {
*
* @param enforceMonotonic Validate that incoming value is strictly
* monotonic compared to this object.
* @param clampNegative Instead of throwing like {@code enforceMonotonic},
* clamp resulting counters at 0 to prevent negative values.
*/
public NetworkStats subtract(NetworkStats value, boolean enforceMonotonic) {
private NetworkStats subtract(
NetworkStats value, boolean enforceMonotonic, boolean clampNegative) {
final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime;
if (enforceMonotonic && deltaRealtime < 0) {
throw new IllegalArgumentException("found non-monotonic realtime");
@@ -181,11 +208,15 @@ public class NetworkStats implements Parcelable {
result.addEntry(iface, uid, this.rx[i], this.tx[i]);
} else {
// existing row, subtract remote value
final long rx = this.rx[i] - value.rx[j];
final long tx = this.tx[i] - value.tx[j];
long rx = this.rx[i] - value.rx[j];
long tx = this.tx[i] - value.tx[j];
if (enforceMonotonic && (rx < 0 || tx < 0)) {
throw new IllegalArgumentException("found non-monotonic values");
}
if (clampNegative) {
rx = Math.max(0, rx);
tx = Math.max(0, tx);
}
result.addEntry(iface, uid, rx, tx);
}
}

View File

@@ -218,7 +218,7 @@ public class NetworkStatsHistory implements Parcelable {
* Return interpolated data usage across the requested range. Interpolates
* across buckets, so values may be rounded slightly.
*/
public void getTotalData(long start, long end, long[] outTotal) {
public long[] getTotalData(long start, long end, long[] outTotal) {
long rx = 0;
long tx = 0;
@@ -238,8 +238,12 @@ public class NetworkStatsHistory implements Parcelable {
}
}
if (outTotal == null || outTotal.length != 2) {
outTotal = new long[2];
}
outTotal[0] = rx;
outTotal[1] = tx;
return outTotal;
}
/**

View File

@@ -177,8 +177,8 @@ public class TrafficStats {
// subtract starting values and return delta
final NetworkStats profilingStop = getNetworkStatsForUid(context);
final NetworkStats profilingDelta = profilingStop.subtract(
sActiveProfilingStart, false);
final NetworkStats profilingDelta = profilingStop.subtractClamped(
sActiveProfilingStart);
sActiveProfilingStart = null;
return profilingDelta;
}