summaryrefslogtreecommitdiff
path: root/android/os/Binder.java
diff options
context:
space:
mode:
Diffstat (limited to 'android/os/Binder.java')
-rw-r--r--android/os/Binder.java61
1 files changed, 58 insertions, 3 deletions
diff --git a/android/os/Binder.java b/android/os/Binder.java
index b5bcd02c..33470f36 100644
--- a/android/os/Binder.java
+++ b/android/os/Binder.java
@@ -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
@@ -298,7 +301,7 @@ public class Binder implements IBinder {
long callingIdentity = clearCallingIdentity();
Throwable throwableToPropagate = null;
try {
- action.run();
+ action.runOrThrow();
} catch (Throwable throwable) {
throwableToPropagate = throwable;
} finally {
@@ -322,7 +325,7 @@ public class Binder implements IBinder {
long callingIdentity = clearCallingIdentity();
Throwable throwableToPropagate = null;
try {
- return action.get();
+ return action.getOrThrow();
} catch (Throwable throwable) {
throwableToPropagate = throwable;
return null; // overridden by throwing in finally block
@@ -778,6 +781,8 @@ final class BinderProxy implements IBinder {
private static final int LOG_MAIN_INDEX_SIZE = 8;
private static final int MAIN_INDEX_SIZE = 1 << LOG_MAIN_INDEX_SIZE;
private static final int MAIN_INDEX_MASK = MAIN_INDEX_SIZE - 1;
+ // Debuggable builds will throw an AssertionError if the number of map entries exceeds:
+ private static final int CRASH_AT_SIZE = 5_000;
/**
* We next warn when we exceed this bucket size.
@@ -899,10 +904,60 @@ final class BinderProxy implements IBinder {
keyArray[size] = key;
}
if (size >= mWarnBucketSize) {
+ final int totalSize = size();
Log.v(Binder.TAG, "BinderProxy map growth! bucket size = " + size
- + " total = " + size());
+ + " total = " + totalSize);
mWarnBucketSize += WARN_INCREMENT;
+ 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.