Loading core/java/android/net/NetworkStats.java +40 −56 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package android.net; import static com.android.internal.util.Preconditions.checkNotNull; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; Loading @@ -40,8 +38,6 @@ import java.util.HashSet; * @hide */ public class NetworkStats implements Parcelable { private static final String TAG = "NetworkStats"; /** {@link #iface} value when interface details unavailable. */ public static final String IFACE_ALL = null; /** {@link #uid} value when UID details unavailable. */ Loading Loading @@ -463,62 +459,64 @@ public class NetworkStats implements Parcelable { * between two snapshots in time. Assumes that statistics rows collect over * time, and that none of them have disappeared. */ public NetworkStats subtract(NetworkStats value) throws NonMonotonicException { return subtract(value, false); public NetworkStats subtract(NetworkStats right) { return subtract(this, right, null); } /** * Subtract the given {@link NetworkStats}, effectively leaving the delta * Subtract the two given {@link NetworkStats} objects, returning 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}. * <p> * If counters have rolled backwards, they are clamped to {@code 0} and * reported to the given {@link NonMonotonicObserver}. */ public NetworkStats subtract(NetworkStats value, boolean clampNonMonotonic) throws NonMonotonicException { final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime; public static NetworkStats subtract( NetworkStats left, NetworkStats right, NonMonotonicObserver observer) { long deltaRealtime = left.elapsedRealtime - right.elapsedRealtime; if (deltaRealtime < 0) { throw new NonMonotonicException(this, value); if (observer != null) { observer.foundNonMonotonic(left, -1, right, -1); } deltaRealtime = 0; } // result will have our rows, and elapsed time between snapshots final Entry entry = new Entry(); final NetworkStats result = new NetworkStats(deltaRealtime, size); for (int i = 0; i < size; i++) { entry.iface = iface[i]; entry.uid = uid[i]; entry.set = set[i]; entry.tag = tag[i]; final NetworkStats result = new NetworkStats(deltaRealtime, left.size); for (int i = 0; i < left.size; i++) { entry.iface = left.iface[i]; entry.uid = left.uid[i]; entry.set = left.set[i]; entry.tag = left.tag[i]; // find remote row that matches, and subtract final int j = value.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, i); final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, i); if (j == -1) { // newly appearing row, return entire value entry.rxBytes = rxBytes[i]; entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; entry.txPackets = txPackets[i]; entry.operations = operations[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]; } else { // existing row, subtract remote value entry.rxBytes = rxBytes[i] - value.rxBytes[j]; entry.rxPackets = rxPackets[i] - value.rxPackets[j]; entry.txBytes = txBytes[i] - value.txBytes[j]; entry.txPackets = txPackets[i] - value.txPackets[j]; entry.operations = operations[i] - value.operations[j]; 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 (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 || entry.txPackets < 0 || entry.operations < 0) { if (clampNonMonotonic) { if (observer != null) { observer.foundNonMonotonic(left, i, right, j); } 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); } } } Loading Loading @@ -665,22 +663,8 @@ public class NetworkStats implements Parcelable { } }; public static class NonMonotonicException extends Exception { public final NetworkStats left; public final NetworkStats right; public final int leftIndex; public final int rightIndex; public NonMonotonicException(NetworkStats left, NetworkStats right) { this(left, -1, right, -1); } public NonMonotonicException( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex) { this.left = checkNotNull(left, "missing left"); this.right = checkNotNull(right, "missing right"); this.leftIndex = leftIndex; this.rightIndex = rightIndex; } public interface NonMonotonicObserver { public void foundNonMonotonic( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex); } } core/java/android/net/TrafficStats.java +6 −10 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.DownloadManager; import android.app.backup.BackupManager; import android.content.Context; import android.media.MediaPlayer; import android.net.NetworkStats.NonMonotonicException; import android.os.RemoteException; import android.os.ServiceManager; Loading Loading @@ -193,15 +192,12 @@ public class TrafficStats { throw new IllegalStateException("not profiling data"); } try { // subtract starting values and return delta final NetworkStats profilingStop = getDataLayerSnapshotForUid(context); final NetworkStats profilingDelta = profilingStop.subtract(sActiveProfilingStart); final NetworkStats profilingDelta = NetworkStats.subtract( profilingStop, sActiveProfilingStart, null); sActiveProfilingStart = null; return profilingDelta; } catch (NonMonotonicException e) { throw new RuntimeException(e); } } } Loading services/java/com/android/server/net/NetworkStatsService.java +27 −22 Original line number Diff line number Diff line Loading @@ -71,7 +71,7 @@ import android.net.NetworkIdentity; import android.net.NetworkInfo; import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicException; import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.Binder; Loading Loading @@ -1551,34 +1551,39 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } /** * Return the delta between two {@link NetworkStats} snapshots, where {@code * before} can be {@code null}. */ private NetworkStats computeStatsDelta( NetworkStats before, NetworkStats current, boolean collectStale, String type) { if (before != null) { try { return current.subtract(before, false); } catch (NonMonotonicException e) { private StatsObserver mStatsObserver = new StatsObserver(); private class StatsObserver implements NonMonotonicObserver { private String mCurrentType; public void setCurrentType(String type) { mCurrentType = type; } /** {@inheritDoc} */ public void foundNonMonotonic( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex) { Log.w(TAG, "found non-monotonic values; saving to dropbox"); // record error for debugging final StringBuilder builder = new StringBuilder(); builder.append("found non-monotonic " + type + " values at left[" + e.leftIndex + "] - right[" + e.rightIndex + "]\n"); builder.append("left=").append(e.left).append('\n'); builder.append("right=").append(e.right).append('\n'); builder.append("found non-monotonic " + mCurrentType + " values at left[" + leftIndex + "] - right[" + rightIndex + "]\n"); builder.append("left=").append(left).append('\n'); builder.append("right=").append(right).append('\n'); mDropBox.addText(TAG_NETSTATS_ERROR, builder.toString()); 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); } } /** * Return the delta between two {@link NetworkStats} snapshots, where {@code * before} can be {@code null}. */ private NetworkStats computeStatsDelta( NetworkStats before, NetworkStats current, boolean collectStale, String type) { if (before != null) { mStatsObserver.setCurrentType(type); return NetworkStats.subtract(current, before, mStatsObserver); } else if (collectStale) { // caller is okay collecting stale stats for first call. return current; Loading Loading
core/java/android/net/NetworkStats.java +40 −56 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package android.net; import static com.android.internal.util.Preconditions.checkNotNull; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; Loading @@ -40,8 +38,6 @@ import java.util.HashSet; * @hide */ public class NetworkStats implements Parcelable { private static final String TAG = "NetworkStats"; /** {@link #iface} value when interface details unavailable. */ public static final String IFACE_ALL = null; /** {@link #uid} value when UID details unavailable. */ Loading Loading @@ -463,62 +459,64 @@ public class NetworkStats implements Parcelable { * between two snapshots in time. Assumes that statistics rows collect over * time, and that none of them have disappeared. */ public NetworkStats subtract(NetworkStats value) throws NonMonotonicException { return subtract(value, false); public NetworkStats subtract(NetworkStats right) { return subtract(this, right, null); } /** * Subtract the given {@link NetworkStats}, effectively leaving the delta * Subtract the two given {@link NetworkStats} objects, returning 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}. * <p> * If counters have rolled backwards, they are clamped to {@code 0} and * reported to the given {@link NonMonotonicObserver}. */ public NetworkStats subtract(NetworkStats value, boolean clampNonMonotonic) throws NonMonotonicException { final long deltaRealtime = this.elapsedRealtime - value.elapsedRealtime; public static NetworkStats subtract( NetworkStats left, NetworkStats right, NonMonotonicObserver observer) { long deltaRealtime = left.elapsedRealtime - right.elapsedRealtime; if (deltaRealtime < 0) { throw new NonMonotonicException(this, value); if (observer != null) { observer.foundNonMonotonic(left, -1, right, -1); } deltaRealtime = 0; } // result will have our rows, and elapsed time between snapshots final Entry entry = new Entry(); final NetworkStats result = new NetworkStats(deltaRealtime, size); for (int i = 0; i < size; i++) { entry.iface = iface[i]; entry.uid = uid[i]; entry.set = set[i]; entry.tag = tag[i]; final NetworkStats result = new NetworkStats(deltaRealtime, left.size); for (int i = 0; i < left.size; i++) { entry.iface = left.iface[i]; entry.uid = left.uid[i]; entry.set = left.set[i]; entry.tag = left.tag[i]; // find remote row that matches, and subtract final int j = value.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, i); final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag, i); if (j == -1) { // newly appearing row, return entire value entry.rxBytes = rxBytes[i]; entry.rxPackets = rxPackets[i]; entry.txBytes = txBytes[i]; entry.txPackets = txPackets[i]; entry.operations = operations[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]; } else { // existing row, subtract remote value entry.rxBytes = rxBytes[i] - value.rxBytes[j]; entry.rxPackets = rxPackets[i] - value.rxPackets[j]; entry.txBytes = txBytes[i] - value.txBytes[j]; entry.txPackets = txPackets[i] - value.txPackets[j]; entry.operations = operations[i] - value.operations[j]; 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 (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0 || entry.txPackets < 0 || entry.operations < 0) { if (clampNonMonotonic) { if (observer != null) { observer.foundNonMonotonic(left, i, right, j); } 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); } } } Loading Loading @@ -665,22 +663,8 @@ public class NetworkStats implements Parcelable { } }; public static class NonMonotonicException extends Exception { public final NetworkStats left; public final NetworkStats right; public final int leftIndex; public final int rightIndex; public NonMonotonicException(NetworkStats left, NetworkStats right) { this(left, -1, right, -1); } public NonMonotonicException( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex) { this.left = checkNotNull(left, "missing left"); this.right = checkNotNull(right, "missing right"); this.leftIndex = leftIndex; this.rightIndex = rightIndex; } public interface NonMonotonicObserver { public void foundNonMonotonic( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex); } }
core/java/android/net/TrafficStats.java +6 −10 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import android.app.DownloadManager; import android.app.backup.BackupManager; import android.content.Context; import android.media.MediaPlayer; import android.net.NetworkStats.NonMonotonicException; import android.os.RemoteException; import android.os.ServiceManager; Loading Loading @@ -193,15 +192,12 @@ public class TrafficStats { throw new IllegalStateException("not profiling data"); } try { // subtract starting values and return delta final NetworkStats profilingStop = getDataLayerSnapshotForUid(context); final NetworkStats profilingDelta = profilingStop.subtract(sActiveProfilingStart); final NetworkStats profilingDelta = NetworkStats.subtract( profilingStop, sActiveProfilingStart, null); sActiveProfilingStart = null; return profilingDelta; } catch (NonMonotonicException e) { throw new RuntimeException(e); } } } Loading
services/java/com/android/server/net/NetworkStatsService.java +27 −22 Original line number Diff line number Diff line Loading @@ -71,7 +71,7 @@ import android.net.NetworkIdentity; import android.net.NetworkInfo; import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStats.NonMonotonicException; import android.net.NetworkStats.NonMonotonicObserver; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.os.Binder; Loading Loading @@ -1551,34 +1551,39 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } /** * Return the delta between two {@link NetworkStats} snapshots, where {@code * before} can be {@code null}. */ private NetworkStats computeStatsDelta( NetworkStats before, NetworkStats current, boolean collectStale, String type) { if (before != null) { try { return current.subtract(before, false); } catch (NonMonotonicException e) { private StatsObserver mStatsObserver = new StatsObserver(); private class StatsObserver implements NonMonotonicObserver { private String mCurrentType; public void setCurrentType(String type) { mCurrentType = type; } /** {@inheritDoc} */ public void foundNonMonotonic( NetworkStats left, int leftIndex, NetworkStats right, int rightIndex) { Log.w(TAG, "found non-monotonic values; saving to dropbox"); // record error for debugging final StringBuilder builder = new StringBuilder(); builder.append("found non-monotonic " + type + " values at left[" + e.leftIndex + "] - right[" + e.rightIndex + "]\n"); builder.append("left=").append(e.left).append('\n'); builder.append("right=").append(e.right).append('\n'); builder.append("found non-monotonic " + mCurrentType + " values at left[" + leftIndex + "] - right[" + rightIndex + "]\n"); builder.append("left=").append(left).append('\n'); builder.append("right=").append(right).append('\n'); mDropBox.addText(TAG_NETSTATS_ERROR, builder.toString()); 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); } } /** * Return the delta between two {@link NetworkStats} snapshots, where {@code * before} can be {@code null}. */ private NetworkStats computeStatsDelta( NetworkStats before, NetworkStats current, boolean collectStale, String type) { if (before != null) { mStatsObserver.setCurrentType(type); return NetworkStats.subtract(current, before, mStatsObserver); } else if (collectStale) { // caller is okay collecting stale stats for first call. return current; Loading