NetworkStats: more robust subtraction for deltas

This patch ensures that subtract() between two NetworkStats object will
return a delta with no negative entries in all cases.

When the stats delta contains some negative values, there are clamped to
0. Some logging is added when this happens.

This is what's expected by NetworkStatsHistory#recordData().

Bug: 64365917
Test: runtest frameworks-net
Change-Id: I16e97e73f600225f80e0ce517e80c07c6f399196
This commit is contained in:
Hugo Benichi
2017-08-07 15:47:35 +09:00
parent 6d7f581187
commit d78311f267

View File

@@ -672,36 +672,33 @@ public class NetworkStats implements Parcelable {
entry.tag = left.tag[i];
entry.metered = left.metered[i];
entry.roaming = left.roaming[i];
entry.rxBytes = left.rxBytes[i];
entry.rxPackets = left.rxPackets[i];
entry.txBytes = left.txBytes[i];
entry.txPackets = left.txPackets[i];
entry.operations = left.operations[i];
// find remote row that matches, and subtract
final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
entry.metered, entry.roaming, i);
if (j == -1) {
// newly appearing row, return entire value
entry.rxBytes = left.rxBytes[i];
entry.rxPackets = left.rxPackets[i];
entry.txBytes = left.txBytes[i];
entry.txPackets = left.txPackets[i];
entry.operations = left.operations[i];
} else {
// existing row, subtract remote value
entry.rxBytes = left.rxBytes[i] - right.rxBytes[j];
entry.rxPackets = left.rxPackets[i] - right.rxPackets[j];
entry.txBytes = left.txBytes[i] - right.txBytes[j];
entry.txPackets = left.txPackets[i] - right.txPackets[j];
entry.operations = left.operations[i] - right.operations[j];
if (j != -1) {
// Found matching row, subtract remote value.
entry.rxBytes -= right.rxBytes[j];
entry.rxPackets -= right.rxPackets[j];
entry.txBytes -= right.txBytes[j];
entry.txPackets -= right.txPackets[j];
entry.operations -= right.operations[j];
}
if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
|| entry.txPackets < 0 || entry.operations < 0) {
if (observer != null) {
observer.foundNonMonotonic(left, i, right, j, cookie);
}
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);
if (entry.isNegative()) {
if (observer != null) {
observer.foundNonMonotonic(left, i, right, j, cookie);
}
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);
}
result.addValues(entry);