diff options
author | Jeff Sharkey <jsharkey@android.com> | 2014-11-21 21:59:15 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-11-21 21:59:17 +0000 |
commit | c0491a2e2d30eb4bc3e03fccee89d57e9bd575e4 (patch) | |
tree | 483f595c8aa48c4256ebf722e5329e2c7a0c62db | |
parent | 682ed6b60807d5fa971dbd6c76deae788cb65df4 (diff) | |
parent | 55a442e58262e253df965d652bd8219c8d1e72d3 (diff) | |
download | frameworks_base-c0491a2e2d30eb4bc3e03fccee89d57e9bd575e4.zip frameworks_base-c0491a2e2d30eb4bc3e03fccee89d57e9bd575e4.tar.gz frameworks_base-c0491a2e2d30eb4bc3e03fccee89d57e9bd575e4.tar.bz2 |
Merge "Lightweight checkin output for network stats." into lmp-mr1-dev
9 files changed, 295 insertions, 54 deletions
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index 36dd2fdfb..d36707e 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -34,7 +34,7 @@ import java.util.Objects; * * @hide */ -public class NetworkIdentity { +public class NetworkIdentity implements Comparable<NetworkIdentity> { /** * When enabled, combine all {@link #mSubType} together under * {@link #SUBTYPE_COMBINED}. @@ -76,7 +76,7 @@ public class NetworkIdentity { @Override public String toString() { - final StringBuilder builder = new StringBuilder("["); + final StringBuilder builder = new StringBuilder("{"); builder.append("type=").append(getNetworkTypeName(mType)); builder.append(", subType="); if (COMBINE_SUBTYPE_ENABLED) { @@ -95,7 +95,7 @@ public class NetworkIdentity { if (mRoaming) { builder.append(", ROAMING"); } - return builder.append("]").toString(); + return builder.append("}").toString(); } public int getType() { @@ -170,4 +170,22 @@ public class NetworkIdentity { return new NetworkIdentity(type, subType, subscriberId, networkId, roaming); } + + @Override + public int compareTo(NetworkIdentity another) { + int res = Integer.compare(mType, another.mType); + if (res == 0) { + res = Integer.compare(mSubType, another.mSubType); + } + if (res == 0 && mSubscriberId != null && another.mSubscriberId != null) { + res = mSubscriberId.compareTo(another.mSubscriberId); + } + if (res == 0 && mNetworkId != null && another.mNetworkId != null) { + res = mNetworkId.compareTo(another.mNetworkId); + } + if (res == 0) { + res = Boolean.compare(mRoaming, another.mRoaming); + } + return res; + } } diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index ea5dfd1..2afe578 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -733,6 +733,22 @@ public class NetworkStats implements Parcelable { } /** + * Return text description of {@link #set} value. + */ + public static String setToCheckinString(int set) { + switch (set) { + case SET_ALL: + return "all"; + case SET_DEFAULT: + return "def"; + case SET_FOREGROUND: + return "fg"; + default: + return "unk"; + } + } + + /** * Return text description of {@link #tag} value. */ public static String tagToString(int tag) { diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 62d8738..4a4accb 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -26,6 +26,7 @@ import static android.net.NetworkStatsHistory.DataStreamUtils.writeVarLongArray; import static android.net.NetworkStatsHistory.Entry.UNKNOWN; import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray; import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray; +import static android.text.format.DateUtils.SECOND_IN_MILLIS; import static com.android.internal.util.ArrayUtils.total; import android.os.Parcel; @@ -38,6 +39,7 @@ import java.io.CharArrayWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.io.PrintWriter; import java.net.ProtocolException; import java.util.Arrays; import java.util.Random; @@ -573,8 +575,22 @@ public class NetworkStatsHistory implements Parcelable { return (long) (start + (r.nextFloat() * (end - start))); } + /** + * Quickly determine if this history intersects with given window. + */ + public boolean intersects(long start, long end) { + final long dataStart = getStart(); + final long dataEnd = getEnd(); + if (start >= dataStart && start <= dataEnd) return true; + if (end >= dataStart && end <= dataEnd) return true; + if (dataStart >= start && dataStart <= end) return true; + if (dataEnd >= start && dataEnd <= end) return true; + return false; + } + public void dump(IndentingPrintWriter pw, boolean fullHistory) { - pw.print("NetworkStatsHistory: bucketDuration="); pw.println(bucketDuration); + pw.print("NetworkStatsHistory: bucketDuration="); + pw.println(bucketDuration / SECOND_IN_MILLIS); pw.increaseIndent(); final int start = fullHistory ? 0 : Math.max(0, bucketCount - 32); @@ -583,19 +599,35 @@ public class NetworkStatsHistory implements Parcelable { } for (int i = start; i < bucketCount; i++) { - pw.print("bucketStart="); pw.print(bucketStart[i]); - if (activeTime != null) { pw.print(" activeTime="); pw.print(activeTime[i]); } - if (rxBytes != null) { pw.print(" rxBytes="); pw.print(rxBytes[i]); } - if (rxPackets != null) { pw.print(" rxPackets="); pw.print(rxPackets[i]); } - if (txBytes != null) { pw.print(" txBytes="); pw.print(txBytes[i]); } - if (txPackets != null) { pw.print(" txPackets="); pw.print(txPackets[i]); } - if (operations != null) { pw.print(" operations="); pw.print(operations[i]); } + pw.print("st="); pw.print(bucketStart[i] / SECOND_IN_MILLIS); + if (rxBytes != null) { pw.print(" rb="); pw.print(rxBytes[i]); } + if (rxPackets != null) { pw.print(" rp="); pw.print(rxPackets[i]); } + if (txBytes != null) { pw.print(" tb="); pw.print(txBytes[i]); } + if (txPackets != null) { pw.print(" tp="); pw.print(txPackets[i]); } + if (operations != null) { pw.print(" op="); pw.print(operations[i]); } pw.println(); } pw.decreaseIndent(); } + public void dumpCheckin(PrintWriter pw) { + pw.print("d,"); + pw.print(bucketDuration / SECOND_IN_MILLIS); + pw.println(); + + for (int i = 0; i < bucketCount; i++) { + pw.print("b,"); + pw.print(bucketStart[i] / SECOND_IN_MILLIS); pw.print(','); + if (rxBytes != null) { pw.print(rxBytes[i]); } else { pw.print("*"); } pw.print(','); + if (rxPackets != null) { pw.print(rxPackets[i]); } else { pw.print("*"); } pw.print(','); + if (txBytes != null) { pw.print(txBytes[i]); } else { pw.print("*"); } pw.print(','); + if (txPackets != null) { pw.print(txPackets[i]); } else { pw.print("*"); } pw.print(','); + if (operations != null) { pw.print(operations[i]); } else { pw.print("*"); } + pw.println(); + } + } + @Override public String toString() { final CharArrayWriter writer = new CharArrayWriter(); diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java index 27197cc..b839e0a 100644 --- a/core/java/android/net/NetworkTemplate.java +++ b/core/java/android/net/NetworkTemplate.java @@ -16,6 +16,7 @@ package android.net; +import static android.net.ConnectivityManager.TYPE_BLUETOOTH; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI_P2P; @@ -34,10 +35,10 @@ import android.content.res.Resources; import android.os.Parcel; import android.os.Parcelable; -import java.util.Objects; - import com.android.internal.annotations.VisibleForTesting; +import java.util.Objects; + /** * Template definition used to generically match {@link NetworkIdentity}, * usually when collecting statistics. @@ -53,6 +54,7 @@ public class NetworkTemplate implements Parcelable { public static final int MATCH_ETHERNET = 5; public static final int MATCH_MOBILE_WILDCARD = 6; public static final int MATCH_WIFI_WILDCARD = 7; + public static final int MATCH_BLUETOOTH = 8; /** * Set of {@link NetworkInfo#getType()} that reflect data usage. @@ -134,6 +136,14 @@ public class NetworkTemplate implements Parcelable { return new NetworkTemplate(MATCH_ETHERNET, null, null); } + /** + * Template to combine all {@link ConnectivityManager#TYPE_BLUETOOTH} style + * networks together. + */ + public static NetworkTemplate buildTemplateBluetooth() { + return new NetworkTemplate(MATCH_BLUETOOTH, null, null); + } + private final int mMatchRule; private final String mSubscriberId; private final String mNetworkId; @@ -222,6 +232,8 @@ public class NetworkTemplate implements Parcelable { return matchesMobileWildcard(ident); case MATCH_WIFI_WILDCARD: return matchesWifiWildcard(ident); + case MATCH_BLUETOOTH: + return matchesBluetooth(ident); default: throw new IllegalArgumentException("unknown network template"); } @@ -316,6 +328,16 @@ public class NetworkTemplate implements Parcelable { } } + /** + * Check if matches Bluetooth network template. + */ + private boolean matchesBluetooth(NetworkIdentity ident) { + if (ident.mType == TYPE_BLUETOOTH) { + return true; + } + return false; + } + private static String getMatchRuleName(int matchRule) { switch (matchRule) { case MATCH_MOBILE_3G_LOWER: @@ -332,6 +354,8 @@ public class NetworkTemplate implements Parcelable { return "MOBILE_WILDCARD"; case MATCH_WIFI_WILDCARD: return "WIFI_WILDCARD"; + case MATCH_BLUETOOTH: + return "BLUETOOTH"; default: return "UNKNOWN"; } diff --git a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java index b181122..9a08f41 100644 --- a/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java +++ b/core/tests/coretests/src/android/net/NetworkStatsHistoryTest.java @@ -451,6 +451,40 @@ public class NetworkStatsHistoryTest extends AndroidTestCase { assertIndexBeforeAfter(stats, 4, 4, Long.MAX_VALUE); } + public void testIntersects() throws Exception { + final long BUCKET_SIZE = HOUR_IN_MILLIS; + stats = new NetworkStatsHistory(BUCKET_SIZE); + + final long FIRST_START = TEST_START; + final long FIRST_END = FIRST_START + (2 * HOUR_IN_MILLIS); + final long SECOND_START = TEST_START + WEEK_IN_MILLIS; + final long SECOND_END = SECOND_START + HOUR_IN_MILLIS; + final long THIRD_START = TEST_START + (2 * WEEK_IN_MILLIS); + final long THIRD_END = THIRD_START + (2 * HOUR_IN_MILLIS); + + stats.recordData(FIRST_START, FIRST_END, + new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); + stats.recordData(SECOND_START, SECOND_END, + new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); + stats.recordData(THIRD_START, THIRD_END, + new NetworkStats.Entry(1024L, 10L, 2048L, 20L, 2L)); + + assertFalse(stats.intersects(10, 20)); + assertFalse(stats.intersects(TEST_START + YEAR_IN_MILLIS, TEST_START + YEAR_IN_MILLIS + 1)); + assertFalse(stats.intersects(Long.MAX_VALUE, Long.MIN_VALUE)); + + assertTrue(stats.intersects(Long.MIN_VALUE, Long.MAX_VALUE)); + assertTrue(stats.intersects(10, TEST_START + YEAR_IN_MILLIS)); + assertTrue(stats.intersects(TEST_START, TEST_START)); + assertTrue(stats.intersects(TEST_START + DAY_IN_MILLIS, TEST_START + DAY_IN_MILLIS + 1)); + assertTrue(stats.intersects(TEST_START + DAY_IN_MILLIS, Long.MAX_VALUE)); + assertTrue(stats.intersects(TEST_START + 1, Long.MAX_VALUE)); + + assertFalse(stats.intersects(Long.MIN_VALUE, TEST_START - 1)); + assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START)); + assertTrue(stats.intersects(Long.MIN_VALUE, TEST_START + 1)); + } + private static void assertIndexBeforeAfter( NetworkStatsHistory stats, int before, int after, long time) { assertEquals("unexpected before", before, stats.getIndexBefore(time)); diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index 397f9f4..f230bb3 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java @@ -29,7 +29,8 @@ import java.util.HashSet; * * @hide */ -public class NetworkIdentitySet extends HashSet<NetworkIdentity> { +public class NetworkIdentitySet extends HashSet<NetworkIdentity> implements + Comparable<NetworkIdentitySet> { private static final int VERSION_INIT = 1; private static final int VERSION_ADD_ROAMING = 2; private static final int VERSION_ADD_NETWORK_ID = 3; @@ -92,4 +93,14 @@ public class NetworkIdentitySet extends HashSet<NetworkIdentity> { return null; } } + + @Override + public int compareTo(NetworkIdentitySet another) { + if (isEmpty()) return -1; + if (another.isEmpty()) return 1; + + final NetworkIdentity ident = iterator().next(); + final NetworkIdentity anotherIdent = another.iterator().next(); + return ident.compareTo(anotherIdent); + } } diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 475482f..3ac20f7 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -22,15 +22,20 @@ import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_REMOVED; +import static android.text.format.DateUtils.SECOND_IN_MILLIS; +import static android.text.format.DateUtils.WEEK_IN_MILLIS; +import android.net.ConnectivityManager; import android.net.NetworkIdentity; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; -import android.text.format.DateUtils; +import android.util.ArrayMap; import android.util.AtomicFile; +import libcore.io.IoUtils; + import com.android.internal.util.ArrayUtils; import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; @@ -44,15 +49,13 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.io.PrintWriter; import java.net.ProtocolException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Map; import java.util.Objects; -import libcore.io.IoUtils; - /** * Collection of {@link NetworkStatsHistory}, stored based on combined key of * {@link NetworkIdentitySet}, UID, set, and tag. Knows how to persist itself. @@ -70,7 +73,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { private static final int VERSION_UNIFIED_INIT = 16; - private HashMap<Key, NetworkStatsHistory> mStats = Maps.newHashMap(); + private ArrayMap<Key, NetworkStatsHistory> mStats = new ArrayMap<>(); private final long mBucketDuration; @@ -145,12 +148,13 @@ public class NetworkStatsCollection implements FileRotator.Reader { NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end) { final NetworkStatsHistory combined = new NetworkStatsHistory( mBucketDuration, estimateBuckets(), fields); - for (Map.Entry<Key, NetworkStatsHistory> entry : mStats.entrySet()) { - final Key key = entry.getKey(); + for (int i = 0; i < mStats.size(); i++) { + final Key key = mStats.keyAt(i); final boolean setMatches = set == SET_ALL || key.set == set; if (key.uid == uid && setMatches && key.tag == tag && templateMatches(template, key.ident)) { - combined.recordHistory(entry.getValue(), start, end); + final NetworkStatsHistory value = mStats.valueAt(i); + combined.recordHistory(value, start, end); } } return combined; @@ -170,11 +174,11 @@ public class NetworkStatsCollection implements FileRotator.Reader { // shortcut when we know stats will be empty if (start == end) return stats; - for (Map.Entry<Key, NetworkStatsHistory> mapEntry : mStats.entrySet()) { - final Key key = mapEntry.getKey(); + for (int i = 0; i < mStats.size(); i++) { + final Key key = mStats.keyAt(i); if (templateMatches(template, key.ident)) { - final NetworkStatsHistory history = mapEntry.getValue(); - historyEntry = history.getValues(start, end, now, historyEntry); + final NetworkStatsHistory value = mStats.valueAt(i); + historyEntry = value.getValues(start, end, now, historyEntry); entry.iface = IFACE_ALL; entry.uid = key.uid; @@ -225,8 +229,10 @@ public class NetworkStatsCollection implements FileRotator.Reader { * into this collection. */ public void recordCollection(NetworkStatsCollection another) { - for (Map.Entry<Key, NetworkStatsHistory> entry : another.mStats.entrySet()) { - recordHistory(entry.getKey(), entry.getValue()); + for (int i = 0; i < another.mStats.size(); i++) { + final Key key = another.mStats.keyAt(i); + final NetworkStatsHistory value = another.mStats.valueAt(i); + recordHistory(key, value); } } @@ -460,7 +466,7 @@ public class NetworkStatsCollection implements FileRotator.Reader { } private int estimateBuckets() { - return (int) (Math.min(mEndMillis - mStartMillis, DateUtils.WEEK_IN_MILLIS * 5) + return (int) (Math.min(mEndMillis - mStartMillis, WEEK_IN_MILLIS * 5) / mBucketDuration); } @@ -482,6 +488,54 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } + public void dumpCheckin(PrintWriter pw, long start, long end) { + dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell"); + dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi"); + dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateEthernet(), "eth"); + dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateBluetooth(), "bt"); + } + + /** + * Dump all contained stats that match requested parameters, but group + * together all matching {@link NetworkTemplate} under a single prefix. + */ + private void dumpCheckin(PrintWriter pw, long start, long end, NetworkTemplate groupTemplate, + String groupPrefix) { + final ArrayMap<Key, NetworkStatsHistory> grouped = new ArrayMap<>(); + + // Walk through all history, grouping by matching network templates + for (int i = 0; i < mStats.size(); i++) { + final Key key = mStats.keyAt(i); + final NetworkStatsHistory value = mStats.valueAt(i); + + if (!templateMatches(groupTemplate, key.ident)) continue; + + final Key groupKey = new Key(null, key.uid, key.set, key.tag); + NetworkStatsHistory groupHistory = grouped.get(groupKey); + if (groupHistory == null) { + groupHistory = new NetworkStatsHistory(value.getBucketDuration()); + grouped.put(groupKey, groupHistory); + } + groupHistory.recordHistory(value, start, end); + } + + for (int i = 0; i < grouped.size(); i++) { + final Key key = grouped.keyAt(i); + final NetworkStatsHistory value = grouped.valueAt(i); + + if (value.size() == 0) continue; + + pw.print("c,"); + pw.print(groupPrefix); pw.print(','); + pw.print(key.uid); pw.print(','); + pw.print(NetworkStats.setToCheckinString(key.set)); pw.print(','); + pw.print(key.tag); + pw.println(); + + value.dumpCheckin(pw); + } + } + /** * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity} * in the given {@link NetworkIdentitySet}. @@ -528,7 +582,20 @@ public class NetworkStatsCollection implements FileRotator.Reader { @Override public int compareTo(Key another) { - return Integer.compare(uid, another.uid); + int res = 0; + if (ident != null && another.ident != null) { + res = ident.compareTo(another.ident); + } + if (res == 0) { + res = Integer.compare(uid, another.uid); + } + if (res == 0) { + res = Integer.compare(set, another.set); + } + if (res == 0) { + res = Integer.compare(tag, another.tag); + } + return res; } } } diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index cea084b..d5d7667 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -41,6 +41,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashSet; @@ -124,23 +125,36 @@ public class NetworkStatsRecorder { * as reference is valid. */ public NetworkStatsCollection getOrLoadCompleteLocked() { - NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; - if (complete == null) { - if (LOGD) Slog.d(TAG, "getOrLoadCompleteLocked() reading from disk for " + mCookie); - try { - complete = new NetworkStatsCollection(mBucketDuration); - mRotator.readMatching(complete, Long.MIN_VALUE, Long.MAX_VALUE); - complete.recordCollection(mPending); - mComplete = new WeakReference<NetworkStatsCollection>(complete); - } catch (IOException e) { - Log.wtf(TAG, "problem completely reading network stats", e); - recoverFromWtf(); - } catch (OutOfMemoryError e) { - Log.wtf(TAG, "problem completely reading network stats", e); - recoverFromWtf(); - } + NetworkStatsCollection res = mComplete != null ? mComplete.get() : null; + if (res == null) { + res = loadLocked(Long.MIN_VALUE, Long.MAX_VALUE); + mComplete = new WeakReference<NetworkStatsCollection>(res); } - return complete; + return res; + } + + public NetworkStatsCollection getOrLoadPartialLocked(long start, long end) { + NetworkStatsCollection res = mComplete != null ? mComplete.get() : null; + if (res == null) { + res = loadLocked(start, end); + } + return res; + } + + private NetworkStatsCollection loadLocked(long start, long end) { + if (LOGD) Slog.d(TAG, "loadLocked() reading from disk for " + mCookie); + final NetworkStatsCollection res = new NetworkStatsCollection(mBucketDuration); + try { + mRotator.readMatching(res, start, end); + res.recordCollection(mPending); + } catch (IOException e) { + Log.wtf(TAG, "problem completely reading network stats", e); + recoverFromWtf(); + } catch (OutOfMemoryError e) { + Log.wtf(TAG, "problem completely reading network stats", e); + recoverFromWtf(); + } + return res; } /** @@ -384,6 +398,11 @@ public class NetworkStatsRecorder { } } + public void dumpCheckin(PrintWriter pw, long start, long end) { + // Only load and dump stats from the requested window + getOrLoadPartialLocked(start, end).dumpCheckin(pw, start, end); + } + /** * Recover from {@link FileRotator} failure by dumping state to * {@link DropBoxManager} and deleting contents. diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 150ad34..61f9a26 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -104,6 +104,7 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; +import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; @@ -1094,12 +1095,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } @Override - protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); + long duration = DateUtils.DAY_IN_MILLIS; final HashSet<String> argSet = new HashSet<String>(); for (String arg : args) { argSet.add(arg); + + if (arg.startsWith("--duration=")) { + try { + duration = Long.parseLong(arg.substring(11)); + } catch (NumberFormatException ignored) { + } + } } // usage: dumpsys netstats --full --uid --tag --poll --checkin @@ -1109,7 +1118,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail"); final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail"); - final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); + final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " "); synchronized (mStatsLock) { if (poll) { @@ -1119,13 +1128,24 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } if (checkin) { - // list current stats files to verify rotation - pw.println("Current files:"); - pw.increaseIndent(); - for (String file : mBaseDir.list()) { - pw.println(file); + final long end = System.currentTimeMillis(); + final long start = end - duration; + + pw.print("v1,"); + pw.print(start / SECOND_IN_MILLIS); pw.print(','); + pw.print(end / SECOND_IN_MILLIS); pw.println(); + + pw.println("xt"); + mXtRecorder.dumpCheckin(rawWriter, start, end); + + if (includeUid) { + pw.println("uid"); + mUidRecorder.dumpCheckin(rawWriter, start, end); + } + if (includeTag) { + pw.println("tag"); + mUidTagRecorder.dumpCheckin(rawWriter, start, end); } - pw.decreaseIndent(); return; } |