Clamp non-monotonic stats instead of dropping.
When encountering non-monotonic stats rows, recover remaining data by clamping to 0. In particular, this avoids edge-case where persisting threshold checks would never trigger. Also recover when tethering snapshots are missing. Bug: 5600785, 5433871, 5600678 Change-Id: I1871954ce3955cc4ac8846f9841bae0066176ffe
This commit is contained in:
@@ -464,6 +464,19 @@ public class NetworkStats implements Parcelable {
|
||||
* time, and that none of them have disappeared.
|
||||
*/
|
||||
public NetworkStats subtract(NetworkStats value) throws NonMonotonicException {
|
||||
return subtract(value, 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.
|
||||
*
|
||||
* @param clampNonMonotonic When non-monotonic stats are found, just clamp
|
||||
* to 0 instead of throwing {@link NonMonotonicException}.
|
||||
*/
|
||||
public NetworkStats subtract(NetworkStats value, boolean clampNonMonotonic)
|
||||
throws NonMonotonicException {
|
||||
final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime;
|
||||
if (deltaRealtime < 0) {
|
||||
throw new NonMonotonicException(this, value);
|
||||
@@ -497,7 +510,15 @@ public class NetworkStats implements Parcelable {
|
||||
|
||||
if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
|
||||
|| entry.txPackets < 0 || entry.operations < 0) {
|
||||
throw new NonMonotonicException(this, i, value, j);
|
||||
if (clampNonMonotonic) {
|
||||
entry.rxBytes = Math.max(entry.rxBytes, 0);
|
||||
entry.rxPackets = Math.max(entry.rxPackets, 0);
|
||||
entry.txBytes = Math.max(entry.txBytes, 0);
|
||||
entry.txPackets = Math.max(entry.txPackets, 0);
|
||||
entry.operations = Math.max(entry.operations, 0);
|
||||
} else {
|
||||
throw new NonMonotonicException(this, i, value, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -806,9 +806,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
final NetworkStats networkDevSnapshot;
|
||||
try {
|
||||
// collect any tethering stats
|
||||
final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
|
||||
final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
|
||||
tetheredIfacePairs);
|
||||
final NetworkStats tetherSnapshot = getNetworkStatsTethering();
|
||||
|
||||
// record uid stats, folding in tethering stats
|
||||
uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
|
||||
@@ -1505,7 +1503,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
NetworkStats before, NetworkStats current, boolean collectStale, String type) {
|
||||
if (before != null) {
|
||||
try {
|
||||
return current.subtract(before);
|
||||
return current.subtract(before, false);
|
||||
} catch (NonMonotonicException e) {
|
||||
Log.w(TAG, "found non-monotonic values; saving to dropbox");
|
||||
|
||||
@@ -1517,8 +1515,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
builder.append("right=").append(e.right).append('\n');
|
||||
mDropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
|
||||
|
||||
// return empty delta to avoid recording broken stats
|
||||
return new NetworkStats(0L, 10);
|
||||
try {
|
||||
// return clamped delta to help recover
|
||||
return current.subtract(before, true);
|
||||
} catch (NonMonotonicException e1) {
|
||||
Log.wtf(TAG, "found non-monotonic values; returning empty delta", e1);
|
||||
return new NetworkStats(0L, 10);
|
||||
}
|
||||
}
|
||||
} else if (collectStale) {
|
||||
// caller is okay collecting stale stats for first call.
|
||||
@@ -1530,6 +1533,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return snapshot of current tethering statistics. Will return empty
|
||||
* {@link NetworkStats} if any problems are encountered.
|
||||
*/
|
||||
private NetworkStats getNetworkStatsTethering() throws RemoteException {
|
||||
try {
|
||||
final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
|
||||
return mNetworkManager.getNetworkStatsTethering(tetheredIfacePairs);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.wtf(TAG, "problem reading network stats", e);
|
||||
return new NetworkStats(0L, 10);
|
||||
}
|
||||
}
|
||||
|
||||
private static NetworkStats computeNetworkXtSnapshotFromUid(NetworkStats uidSnapshot) {
|
||||
return uidSnapshot.groupedByIface();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user