From d2672bda9c27e16adcf22820567713ca628411d2 Mon Sep 17 00:00:00 2001 From: Mike Ma Date: Wed, 15 Jan 2020 15:57:20 -0800 Subject: [PATCH] Dump connmetrics in protobuf format Add protobuf dumpsys of connmetrics. Primarily used by incident service to capture an incident report proto. Currently, "proto" is used to dump the ring buffer in base64-encoded proto. The newly added "--proto" arg is a dumpsys convention to dump a service in proto wire format. This change reuses most of the code for executing "proto". Other cmds remain unchanged. Command to invoke (any of the following after lunch and env setup): $ adb shell dumpsys connmetrics --proto $ incident_report 3049 Bug: 146086778 Test: $ incident_report 3049, then compare the content with "dumpsys connmetrics" Change-Id: Ief2297d99aeb553224a83894ba3b9695ff0b87aa --- Android.bp | 5 +++ core/proto/android/os/incident.proto | 6 +++ proto/Android.bp | 5 +++ .../connectivity/DefaultNetworkMetrics.java | 7 ++- .../connectivity/IpConnectivityMetrics.java | 43 +++++++++++++++---- .../NetdEventListenerService.java | 11 +++-- 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/Android.bp b/Android.bp index 908274de793ba..b7ca9a6fc7219 100644 --- a/Android.bp +++ b/Android.bp @@ -597,6 +597,7 @@ gensrcs { "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)", srcs: [ + ":ipconnectivity-proto-src", "core/proto/**/*.proto", "libs/incident/**/*.proto", ], @@ -707,6 +708,7 @@ java_library { java_library_host { name: "platformprotos", srcs: [ + ":ipconnectivity-proto-src", "cmds/am/proto/instrumentation_data.proto", "cmds/statsd/src/**/*.proto", "core/proto/**/*.proto", @@ -735,6 +737,7 @@ java_library { ], sdk_version: "9", srcs: [ + ":ipconnectivity-proto-src", "core/proto/**/*.proto", "libs/incident/proto/android/os/**/*.proto", ], @@ -749,6 +752,7 @@ java_library { }, srcs: [ + ":ipconnectivity-proto-src", "core/proto/**/*.proto", "libs/incident/proto/android/os/**/*.proto", ], @@ -779,6 +783,7 @@ cc_defaults { ], srcs: [ + ":ipconnectivity-proto-src", "core/proto/**/*.proto", ], } diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index 8f9c041b4ad2d..1482a3bd22f60 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -56,6 +56,7 @@ import "frameworks/base/core/proto/android/util/event_log_tags.proto"; import "frameworks/base/core/proto/android/util/log.proto"; import "frameworks/base/core/proto/android/privacy.proto"; import "frameworks/base/core/proto/android/section.proto"; +import "frameworks/base/proto/src/ipconnectivity.proto"; package android.os; @@ -475,6 +476,11 @@ message IncidentProto { (section).args = "cpuinfo --proto" ]; + optional .clearcut.connectivity.IpConnectivityLog ip_connectivity_metrics = 3049 [ + (section).type = SECTION_DUMPSYS, + (section).args = "connmetrics --proto" + ]; + // Reserved for OEMs. extensions 50000 to 100000; } diff --git a/proto/Android.bp b/proto/Android.bp index 7cf6ce740969f..01a72eaa6bf89 100644 --- a/proto/Android.bp +++ b/proto/Android.bp @@ -32,3 +32,8 @@ filegroup { name: "system-messages-proto-src", srcs: ["src/system_messages.proto"], } + +filegroup { + name: "ipconnectivity-proto-src", + srcs: ["src/ipconnectivity.proto"], +} diff --git a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java index 96a202fa2b108..299cb66faf0c0 100644 --- a/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java +++ b/services/core/java/com/android/server/connectivity/DefaultNetworkMetrics.java @@ -81,9 +81,12 @@ public class DefaultNetworkMetrics { printEvent(localTimeMs, pw, mCurrentDefaultNetwork); } - public synchronized void listEventsAsProto(PrintWriter pw) { + /** + * Convert events in the ring buffer to protos and add to the given list + */ + public synchronized void listEventsAsProto(List out) { for (DefaultNetworkEvent ev : mEventsLog.toArray()) { - pw.print(IpConnectivityEventBuilder.toProto(ev)); + out.add(IpConnectivityEventBuilder.toProto(ev)); } } diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java index 33f6ed5972042..1337a93476bc2 100644 --- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java +++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java @@ -41,7 +41,9 @@ import com.android.server.SystemService; import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; import java.io.FileDescriptor; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; @@ -239,18 +241,37 @@ final public class IpConnectivityMetrics extends SystemService { mDefaultNetworkMetrics.listEvents(pw); } + private List listEventsAsProtos() { + final List events = IpConnectivityEventBuilder.toProto(getEvents()); + if (mNetdListener != null) { + mNetdListener.listAsProtos(events); + } + mDefaultNetworkMetrics.listEventsAsProto(events); + return events; + } + /* * Print the content of the rolling event buffer in text proto format. */ - private void cmdListAsProto(PrintWriter pw) { - final List events = getEvents(); - for (IpConnectivityEvent ev : IpConnectivityEventBuilder.toProto(events)) { - pw.print(ev.toString()); + private void cmdListAsTextProto(PrintWriter pw) { + listEventsAsProtos().forEach(e -> pw.print(e.toString())); + } + + /* + * Write the content of the rolling event buffer in proto wire format to the given OutputStream. + */ + private void cmdListAsBinaryProto(OutputStream out) { + final int dropped; + synchronized (mLock) { + dropped = mDropped; } - if (mNetdListener != null) { - mNetdListener.listAsProtos(pw); + try { + byte[] data = IpConnectivityEventBuilder.serialize(dropped, listEventsAsProtos()); + out.write(data); + out.flush(); + } catch (IOException e) { + Log.e(TAG, "could not serialize events", e); } - mDefaultNetworkMetrics.listEventsAsProto(pw); } /* @@ -267,6 +288,9 @@ final public class IpConnectivityMetrics extends SystemService { static final String CMD_FLUSH = "flush"; // Dump the rolling buffer of metrics event in human readable proto text format. static final String CMD_PROTO = "proto"; + // Dump the rolling buffer of metrics event in proto wire format. See usage() of + // frameworks/native/cmds/dumpsys/dumpsys.cpp for details. + static final String CMD_PROTO_BIN = "--proto"; // Dump the rolling buffer of metrics event and pretty print events using a human readable // format. Also print network dns/connect statistics and default network event time series. static final String CMD_LIST = "list"; @@ -291,7 +315,10 @@ final public class IpConnectivityMetrics extends SystemService { cmdFlush(pw); return; case CMD_PROTO: - cmdListAsProto(pw); + cmdListAsTextProto(pw); + return; + case CMD_PROTO_BIN: + cmdListAsBinaryProto(new FileOutputStream(fd)); return; case CMD_LIST: default: diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java index dbc339b01c899..0d3105139b883 100644 --- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java +++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java @@ -366,15 +366,18 @@ public class NetdEventListenerService extends INetdEventListener.Stub { } } - public synchronized void listAsProtos(PrintWriter pw) { + /** + * Convert events in the buffer to protos and add to the given list + */ + public synchronized void listAsProtos(List out) { for (int i = 0; i < mNetworkMetrics.size(); i++) { - pw.print(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).connectMetrics)); + out.add(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).connectMetrics)); } for (int i = 0; i < mNetworkMetrics.size(); i++) { - pw.print(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).dnsMetrics)); + out.add(IpConnectivityEventBuilder.toProto(mNetworkMetrics.valueAt(i).dnsMetrics)); } for (int i = 0; i < mWakeupStats.size(); i++) { - pw.print(IpConnectivityEventBuilder.toProto(mWakeupStats.valueAt(i))); + out.add(IpConnectivityEventBuilder.toProto(mWakeupStats.valueAt(i))); } }