diff options
| -rw-r--r-- | core/java/android/net/NetworkStats.java | 23 | ||||
| -rw-r--r-- | services/java/com/android/server/net/NetworkStatsService.java | 29 |
2 files changed, 45 insertions, 7 deletions
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index 36056529c3a6..f6e627c930d8 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -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); + } } } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index 77b0d96f4242..63655258fe5a 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -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(); } |