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

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

Dump binder proxies interface descriptors on a separate thread.

There are apparently some processes that block getInterfaceDescriptor()
from completing, thus locking up the thread doing the binder proxy dump.
This can cause the watchdog to restart system_server. Move the calls to
a separate thread and give it some time to complete!

Bug: 174722615
Test: adb shell am dump binder-proxies
Change-Id: Ifa79e53524197bf1d785210b7504e7f6c6ddc9b7
parent 6fbb12d2
Loading
Loading
Loading
Loading
+38 −17
Original line number Diff line number Diff line
@@ -34,6 +34,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Java proxy for a native IBinder object.
@@ -262,6 +265,12 @@ public final class BinderProxy implements IBinder {
                Log.e(Binder.TAG, "RemoteException while disabling app freezer");
            }

            // We run the dump on a separate thread, because there are known cases where
            // a process overrides getInterfaceDescriptor() and somehow blocks on it, causing
            // the calling thread (usually AMS) to hit the watchdog.
            // Do the dumping on a separate thread instead, and give up after a while.
            ExecutorService executorService = Executors.newSingleThreadExecutor();
            executorService.submit(() -> {
                for (WeakReference<BinderProxy> weakRef : proxiesToQuery) {
                    BinderProxy bp = weakRef.get();
                    String key;
@@ -284,6 +293,18 @@ public final class BinderProxy implements IBinder {
                        counts.put(key, i + 1);
                    }
                }
            });

            try {
                executorService.shutdown();
                boolean dumpDone = executorService.awaitTermination(20, TimeUnit.SECONDS);
                if (!dumpDone) {
                    Log.e(Binder.TAG, "Failed to complete binder proxy dump,"
                            + " dumping what we have so far.");
                }
            } catch (InterruptedException e) {
                // Ignore
            }
            try {
                ActivityManager.getService().enableAppFreezer(true);
            } catch (RemoteException e) {