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
Bug: 183676249
Test: adb shell am dump binder-proxies
Change-Id: Ifa79e53524197bf1d785210b7504e7f6c6ddc9b7
Merged-In: Ifa79e53524197bf1d785210b7504e7f6c6ddc9b7
(cherry picked from commit f1a22a35e8)
This commit is contained in:
@@ -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,27 +265,45 @@ public final class BinderProxy implements IBinder {
|
||||
Log.e(Binder.TAG, "RemoteException while disabling app freezer");
|
||||
}
|
||||
|
||||
for (WeakReference<BinderProxy> weakRef : proxiesToQuery) {
|
||||
BinderProxy bp = weakRef.get();
|
||||
String key;
|
||||
if (bp == null) {
|
||||
key = "<cleared weak-ref>";
|
||||
} else {
|
||||
try {
|
||||
key = bp.getInterfaceDescriptor();
|
||||
if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) {
|
||||
key = "<proxy to dead node>";
|
||||
// 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;
|
||||
if (bp == null) {
|
||||
key = "<cleared weak-ref>";
|
||||
} else {
|
||||
try {
|
||||
key = bp.getInterfaceDescriptor();
|
||||
if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) {
|
||||
key = "<proxy to dead node>";
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
key = "<exception during getDescriptor>";
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
Integer i = counts.get(key);
|
||||
if (i == null) {
|
||||
counts.put(key, 1);
|
||||
} else {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user