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

Commit 4b7abe30 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Binder: Log a histogram of binder proxies to logcat on death"

parents e4e52917 3fc030f0
Loading
Loading
Loading
Loading
+53 −5
Original line number Diff line number Diff line
@@ -35,6 +35,9 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * Base class for a remotable object, the core part of a lightweight
@@ -888,17 +891,62 @@ final class BinderProxy implements IBinder {
                keyArray[size] = key;
            }
            if (size >= mWarnBucketSize) {
                final int total_size = size();
                final int totalSize = size();
                Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
                        + " total = " + total_size);
                        + " total = " + totalSize);
                mWarnBucketSize += WARN_INCREMENT;
                if (Build.IS_DEBUGGABLE && total_size > CRASH_AT_SIZE) {
                    throw new AssertionError("Binder ProxyMap has too many entries. "
                            + "BinderProxy leak?");
                if (Build.IS_DEBUGGABLE && totalSize > CRASH_AT_SIZE) {
                    diagnosticCrash();
                }
            }
        }

        /**
         * Dump a histogram to the logcat, then throw an assertion error. Used to diagnose
         * abnormally large proxy maps.
         */
        private void diagnosticCrash() {
            Map<String, Integer> counts = new HashMap<>();
            for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
                if (a != null) {
                    for (WeakReference<BinderProxy> weakRef : a) {
                        BinderProxy bp = weakRef.get();
                        String key;
                        if (bp == null) {
                            key = "<cleared weak-ref>";
                        } else {
                            try {
                                key = bp.getInterfaceDescriptor();
                            } catch (Throwable t) {
                                key = "<exception during getDescriptor>";
                            }
                        }
                        Integer i = counts.get(key);
                        if (i == null) {
                            counts.put(key, 1);
                        } else {
                            counts.put(key, i + 1);
                        }
                    }
                }
            }
            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());
            }

            // Now throw an assertion.
            final int totalSize = size();
            throw new AssertionError("Binder ProxyMap has too many entries: " + totalSize
                    + ". BinderProxy leak?");
        }

        // Corresponding ArrayLists in the following two arrays always have the same size.
        // They contain no empty entries. However WeakReferences in the values ArrayLists
        // may have been cleared.