diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java index c704ef0c9c..0775bdaaf3 100644 --- a/core/java/android/net/NetworkIdentity.java +++ b/core/java/android/net/NetworkIdentity.java @@ -24,8 +24,10 @@ import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; +import android.service.NetworkIdentityProto; import android.telephony.TelephonyManager; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import java.util.Objects; @@ -110,6 +112,23 @@ public class NetworkIdentity implements Comparable { return builder.append("}").toString(); } + public void writeToProto(ProtoOutputStream proto, long tag) { + final long start = proto.start(tag); + + proto.write(NetworkIdentityProto.TYPE, mType); + + // Not dumping mSubType, subtypes are no longer supported. + + if (mSubscriberId != null) { + proto.write(NetworkIdentityProto.SUBSCRIBER_ID, scrubSubscriberId(mSubscriberId)); + } + proto.write(NetworkIdentityProto.NETWORK_ID, mNetworkId); + proto.write(NetworkIdentityProto.ROAMING, mRoaming); + proto.write(NetworkIdentityProto.METERED, mMetered); + + proto.end(start); + } + public int getType() { return mType; } diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java index 4a4accbba5..5f521de63c 100644 --- a/core/java/android/net/NetworkStatsHistory.java +++ b/core/java/android/net/NetworkStatsHistory.java @@ -31,7 +31,10 @@ import static com.android.internal.util.ArrayUtils.total; import android.os.Parcel; import android.os.Parcelable; +import android.service.NetworkStatsHistoryBucketProto; +import android.service.NetworkStatsHistoryProto; import android.util.MathUtils; +import android.util.proto.ProtoOutputStream; import com.android.internal.util.IndentingPrintWriter; @@ -628,6 +631,33 @@ public class NetworkStatsHistory implements Parcelable { } } + public void writeToProto(ProtoOutputStream proto, long tag) { + final long start = proto.start(tag); + + proto.write(NetworkStatsHistoryProto.BUCKET_DURATION_MS, bucketDuration); + + for (int i = 0; i < bucketCount; i++) { + final long startBucket = proto.start(NetworkStatsHistoryProto.BUCKETS); + + proto.write(NetworkStatsHistoryBucketProto.BUCKET_START_MS, bucketStart[i]); + writeToProto(proto, NetworkStatsHistoryBucketProto.RX_BYTES, rxBytes, i); + writeToProto(proto, NetworkStatsHistoryBucketProto.RX_PACKETS, rxPackets, i); + writeToProto(proto, NetworkStatsHistoryBucketProto.TX_BYTES, txBytes, i); + writeToProto(proto, NetworkStatsHistoryBucketProto.TX_PACKETS, txPackets, i); + writeToProto(proto, NetworkStatsHistoryBucketProto.OPERATIONS, operations, i); + + proto.end(startBucket); + } + + proto.end(start); + } + + private static void writeToProto(ProtoOutputStream proto, long tag, long[] array, int index) { + if (array != null) { + proto.write(tag, array[index]); + } + } + @Override public String toString() { final CharArrayWriter writer = new CharArrayWriter(); diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java index c48f43058f..ee00fdc333 100644 --- a/services/core/java/com/android/server/net/NetworkIdentitySet.java +++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java @@ -17,6 +17,8 @@ package com.android.server.net; import android.net.NetworkIdentity; +import android.service.NetworkIdentitySetProto; +import android.util.proto.ProtoOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -143,4 +145,14 @@ public class NetworkIdentitySet extends HashSet implements final NetworkIdentity anotherIdent = another.iterator().next(); return ident.compareTo(anotherIdent); } + + public void writeToProto(ProtoOutputStream proto, long tag) { + final long start = proto.start(tag); + + for (NetworkIdentity ident : this) { + ident.writeToProto(proto, NetworkIdentitySetProto.IDENTITIES); + } + + proto.end(start); + } } diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index c45b4169f5..03543007c8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -34,9 +34,13 @@ import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; import android.os.Binder; +import android.service.NetworkStatsCollectionKeyProto; +import android.service.NetworkStatsCollectionProto; +import android.service.NetworkStatsCollectionStatsProto; import android.util.ArrayMap; import android.util.AtomicFile; import android.util.IntArray; +import android.util.proto.ProtoOutputStream; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FileRotator; @@ -532,12 +536,15 @@ public class NetworkStatsCollection implements FileRotator.Reader { / mBucketDuration); } - public void dump(IndentingPrintWriter pw) { + private ArrayList getSortedKeys() { final ArrayList keys = Lists.newArrayList(); keys.addAll(mStats.keySet()); Collections.sort(keys); + return keys; + } - for (Key key : keys) { + public void dump(IndentingPrintWriter pw) { + for (Key key : getSortedKeys()) { pw.print("ident="); pw.print(key.ident.toString()); pw.print(" uid="); pw.print(key.uid); pw.print(" set="); pw.print(NetworkStats.setToString(key.set)); @@ -550,6 +557,29 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } + public void writeToProto(ProtoOutputStream proto, long tag) { + final long start = proto.start(tag); + + for (Key key : getSortedKeys()) { + final long startStats = proto.start(NetworkStatsCollectionProto.STATS); + + // Key + final long startKey = proto.start(NetworkStatsCollectionStatsProto.KEY); + key.ident.writeToProto(proto, NetworkStatsCollectionKeyProto.IDENTITY); + proto.write(NetworkStatsCollectionKeyProto.UID, key.uid); + proto.write(NetworkStatsCollectionKeyProto.SET, key.set); + proto.write(NetworkStatsCollectionKeyProto.TAG, key.tag); + proto.end(startKey); + + // Value + final NetworkStatsHistory history = mStats.get(key); + history.writeToProto(proto, NetworkStatsCollectionStatsProto.HISTORY); + proto.end(startStats); + } + + proto.end(start); + } + public void dumpCheckin(PrintWriter pw, long start, long end) { dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateMobileWildcard(), "cell"); dumpCheckin(pw, start, end, NetworkTemplate.buildTemplateWifiWildcard(), "wifi"); diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index 090a0762a4..80309e19eb 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -29,9 +29,11 @@ import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; import android.net.TrafficStats; import android.os.DropBoxManager; +import android.service.NetworkStatsRecorderProto; import android.util.Log; import android.util.MathUtils; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import com.android.internal.net.VpnInfo; import com.android.internal.util.FileRotator; @@ -465,6 +467,15 @@ public class NetworkStatsRecorder { } } + public void writeToProtoLocked(ProtoOutputStream proto, long tag) { + final long start = proto.start(tag); + if (mPending != null) { + proto.write(NetworkStatsRecorderProto.PENDING_TOTAL_BYTES, mPending.getTotalBytes()); + } + getOrLoadCompleteLocked().writeToProto(proto, NetworkStatsRecorderProto.COMPLETE_HISTORY); + proto.end(start); + } + 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); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 386e78b518..104c29619c 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -104,6 +104,8 @@ import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings.Global; +import android.service.NetworkInterfaceProto; +import android.service.NetworkStatsServiceDumpProto; import android.telephony.TelephonyManager; import android.text.format.DateUtils; import android.util.ArrayMap; @@ -115,6 +117,7 @@ import android.util.NtpTrustedTime; import android.util.Slog; import android.util.SparseIntArray; import android.util.TrustedTime; +import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.net.VpnInfo; @@ -1255,6 +1258,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " "); synchronized (mStatsLock) { + if (args.length > 0 && "--proto".equals(args[0])) { + // In this case ignore all other arguments. + dumpProto(fd); + return; + } + if (poll) { performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE); pw.println("Forced poll"); @@ -1327,6 +1336,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + private void dumpProto(FileDescriptor fd) { + final ProtoOutputStream proto = new ProtoOutputStream(fd); + + // TODO Right now it writes all history. Should it limit to the "since-boot" log? + + dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces); + dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces); + mDevRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS); + mXtRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.XT_STATS); + mUidRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.UID_STATS); + mUidTagRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS); + + proto.flush(); + } + + private static void dumpInterfaces(ProtoOutputStream proto, long tag, + ArrayMap ifaces) { + for (int i = 0; i < ifaces.size(); i++) { + final long start = proto.start(tag); + + proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i)); + ifaces.valueAt(i).writeToProto(proto, NetworkInterfaceProto.IDENTITIES); + + proto.end(start); + } + } + /** * Return snapshot of current UID statistics, including any * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.