Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba75cf11 authored by Martijn Coenen's avatar Martijn Coenen
Browse files

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
parent 03e6d923
Loading
Loading
Loading
Loading
+63 −13
Original line number Diff line number Diff line
@@ -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]);
            }
        }

@@ -296,6 +314,38 @@ public final class BinderProxy implements IBinder {
    @GuardedBy("sProxyMap")
    private static final ProxyMap sProxyMap = new ProxyMap();

    /**
     * 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.
     *
+13 −1
Original line number Diff line number Diff line
@@ -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);