summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Martijn Coenen <maco@google.com> 2018-07-06 11:26:26 +0200
committer Martijn Coenen <maco@google.com> 2018-07-17 11:16:11 +0200
commitba75cf11016dc1ffafc9712487dcf542b0136ef8 (patch)
tree395c25c8b802bc175fff9aaa2e80956df540b26a
parent03e6d923c579ec79939944e7a9a8ac1b36aa2bbb (diff)
Dump top binder proxy interface names in dumpsys.
To facilitate real-time debugging. Bug: 109888955 Test: builds, adb shell dumpsys activity binder-proxies shows output Change-Id: Iffcbbb824f4050b6fb8f556c8b4d09115e53da18
-rw-r--r--core/java/android/os/BinderProxy.java76
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java14
2 files changed, 76 insertions, 14 deletions
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 629838c43aff..5e09cc15d982 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -225,10 +225,11 @@ public final class BinderProxy implements IBinder {
}
}
- /**
- * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps.
- */
- private void dumpProxyInterfaceCounts() {
+ private InterfaceCount[] getSortedInterfaceCounts(int maxToReturn) {
+ if (maxToReturn < 0) {
+ throw new IllegalArgumentException("negative interface count");
+ }
+
Map<String, Integer> counts = new HashMap<>();
for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
if (a != null) {
@@ -255,13 +256,30 @@ public final class BinderProxy implements IBinder {
}
Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
new Map.Entry[counts.size()]);
+
Arrays.sort(sorted, (Map.Entry<String, Integer> a, Map.Entry<String, Integer> b)
-> b.getValue().compareTo(a.getValue()));
- Log.v(Binder.TAG, "BinderProxy descriptor histogram (top ten):");
- int printLength = Math.min(10, sorted.length);
- for (int i = 0; i < printLength; i++) {
- Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i].getKey() + " x"
- + sorted[i].getValue());
+
+ int returnCount = Math.min(maxToReturn, sorted.length);
+ InterfaceCount[] ifaceCounts = new InterfaceCount[returnCount];
+ for (int i = 0; i < returnCount; i++) {
+ ifaceCounts[i] = new InterfaceCount(sorted[i].getKey(), sorted[i].getValue());
+ }
+ return ifaceCounts;
+ }
+
+ static final int MAX_NUM_INTERFACES_TO_DUMP = 10;
+
+ /**
+ * Dump a histogram to the logcat. Used to diagnose abnormally large proxy maps.
+ */
+ private void dumpProxyInterfaceCounts() {
+ final InterfaceCount[] sorted = getSortedInterfaceCounts(MAX_NUM_INTERFACES_TO_DUMP);
+
+ Log.v(Binder.TAG, "BinderProxy descriptor histogram "
+ + "(top " + Integer.toString(MAX_NUM_INTERFACES_TO_DUMP) + "):");
+ for (int i = 0; i < sorted.length; i++) {
+ Log.v(Binder.TAG, " #" + (i + 1) + ": " + sorted[i]);
}
}
@@ -297,10 +315,42 @@ public final class BinderProxy implements IBinder {
private static final ProxyMap sProxyMap = new ProxyMap();
/**
- * Dump proxy debug information.
- *
- * @hide
- */
+ * Simple pair-value class to store number of binder proxy interfaces live in this process.
+ */
+ public static final class InterfaceCount {
+ private final String mInterfaceName;
+ private final int mCount;
+
+ InterfaceCount(String interfaceName, int count) {
+ mInterfaceName = interfaceName;
+ mCount = count;
+ }
+
+ @Override
+ public String toString() {
+ return mInterfaceName + " x" + Integer.toString(mCount);
+ }
+ }
+
+ /**
+ * Get a sorted array with entries mapping proxy interface names to the number
+ * of live proxies with those names.
+ *
+ * @param num maximum number of proxy interface counts to return. Use
+ * Integer.MAX_VALUE to retrieve all
+ * @hide
+ */
+ public static InterfaceCount[] getSortedInterfaceCounts(int num) {
+ synchronized (sProxyMap) {
+ return sProxyMap.getSortedInterfaceCounts(num);
+ }
+ }
+
+ /**
+ * Dump proxy debug information.
+ *
+ * @hide
+ */
private static void dumpProxyDebugInfo() {
if (Build.IS_DEBUGGABLE) {
synchronized (sProxyMap) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 438576311d0f..735e922172cf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -242,6 +242,7 @@ import android.net.ProxyInfo;
import android.net.Uri;
import android.os.BatteryStats;
import android.os.Binder;
+import android.os.BinderProxy;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
@@ -12427,8 +12428,10 @@ public class ActivityManagerService extends IActivityManager.Stub
}
} else if ("binder-proxies".equals(cmd)) {
if (opti >= args.length) {
+ dumpBinderProxyInterfaceCounts(pw,
+ "Top proxy interface names held by SYSTEM");
dumpBinderProxiesCounts(pw, BinderInternal.nGetBinderProxyPerUidCounts(),
- "Counts of Binder Proxies held by SYSTEM");
+ "Number of proxies per uid held by SYSTEM");
} else {
String uid = args[opti];
opti++;
@@ -12966,6 +12969,15 @@ public class ActivityManagerService extends IActivityManager.Stub
return printed;
}
+ void dumpBinderProxyInterfaceCounts(PrintWriter pw, String header) {
+ final BinderProxy.InterfaceCount[] proxyCounts = BinderProxy.getSortedInterfaceCounts(50);
+
+ pw.println(header);
+ for (int i = 0; i < proxyCounts.length; i++) {
+ pw.println(" #" + (i + 1) + ": " + proxyCounts[i]);
+ }
+ }
+
boolean dumpBinderProxiesCounts(PrintWriter pw, SparseIntArray counts, String header) {
if(counts != null) {
pw.println(header);