diff options
| author | 2018-07-06 11:26:26 +0200 | |
|---|---|---|
| committer | 2018-11-12 14:47:12 -0800 | |
| commit | 345d4c16bbca7d278b378e24f33a43e9074d2381 (patch) | |
| tree | c2db60131d958cee771119f9a27492c3b46be691 | |
| parent | d659ad62f491243ddc05cc73c02e9c7377dfa884 (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
Merged-In: Iffcbbb824f4050b6fb8f556c8b4d09115e53da18
Change-Id: Iffcbbb824f4050b6fb8f556c8b4d09115e53da18
| -rw-r--r-- | core/java/android/os/BinderProxy.java | 79 | ||||
| -rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 14 |
2 files changed, 76 insertions, 17 deletions
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java index e492f88d4329..fd43adff5587 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) { @@ -258,13 +259,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]); } } @@ -299,13 +317,42 @@ public final class BinderProxy implements IBinder { private static ProxyMap sProxyMap = new ProxyMap(); /** - * Dump proxy debug information. - * - * Note: this method is not thread-safe; callers must serialize with other - * accesses to sProxyMap, in particular {@link #getInstance(long, long)}. - * - * @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) { sProxyMap.dumpProxyInterfaceCounts(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 7aadcd400f0e..e35855a9a21b 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -318,6 +318,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; @@ -16061,8 +16062,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++; @@ -16565,6 +16568,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); |