diff options
| author | Jeff Sharkey <jsharkey@android.com> | 2017-11-09 18:13:43 -0700 |
|---|---|---|
| committer | Jeff Sharkey <jsharkey@android.com> | 2017-11-09 18:32:37 -0700 |
| commit | 5918948db7c5058af30b143e7336090ef8dac202 (patch) | |
| tree | 4bee06d1b6d4d9533ffd0bec408c311874e1782b /core/java | |
| parent | 903ed1b6f9947ac919e9d110d4b82d25a3ff0de0 (diff) | |
Allow blocking calls when protected against ANRs.
ContentProviderClient has a nice setDetectNotResponding() method
that detects hanging calls to remote providers, and it can trigger
an ANR to kill the app and release the blocked thread.
We typically don't want to perform blocking calls from the system
server, but we're okay allowing them on CPCs that are using
setDetectNotResponding() to watch for hung clients.
Test: builds, boots
Bug: 69128093
Change-Id: I223aaf1d0cef0f8dee28f800d9e3c101d7449952
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/content/ContentProviderClient.java | 13 | ||||
| -rw-r--r-- | core/java/android/os/Binder.java | 13 |
2 files changed, 26 insertions, 0 deletions
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java index f8c139feaae3..2d490a03bd76 100644 --- a/core/java/android/content/ContentProviderClient.java +++ b/core/java/android/content/ContentProviderClient.java @@ -22,6 +22,7 @@ import android.content.res.AssetFileDescriptor; import android.database.CrossProcessCursorWrapper; import android.database.Cursor; import android.net.Uri; +import android.os.Binder; import android.os.Bundle; import android.os.CancellationSignal; import android.os.DeadObjectException; @@ -102,8 +103,16 @@ public class ContentProviderClient implements AutoCloseable { if (sAnrHandler == null) { sAnrHandler = new Handler(Looper.getMainLooper(), null, true /* async */); } + + // If the remote process hangs, we're going to kill it, so we're + // technically okay doing blocking calls. + Binder.allowBlocking(mContentProvider.asBinder()); } else { mAnrRunnable = null; + + // If we're no longer watching for hangs, revert back to default + // blocking behavior. + Binder.defaultBlocking(mContentProvider.asBinder()); } } } @@ -511,6 +520,10 @@ public class ContentProviderClient implements AutoCloseable { private boolean closeInternal() { mCloseGuard.close(); if (mClosed.compareAndSet(false, true)) { + // We can't do ANR checks after we cease to exist! Reset any + // blocking behavior changes we might have made. + setDetectNotResponding(0); + if (mStable) { return mContentResolver.releaseProvider(mContentProvider); } else { diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 2bfb0138b7dd..b5bcd02c1a18 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -193,6 +193,19 @@ public class Binder implements IBinder { } /** + * Reset the given interface back to the default blocking behavior, + * reverting any changes made by {@link #allowBlocking(IBinder)}. + * + * @hide + */ + public static IBinder defaultBlocking(IBinder binder) { + if (binder instanceof BinderProxy) { + ((BinderProxy) binder).mWarnOnBlocking = sWarnOnBlocking; + } + return binder; + } + + /** * Inherit the current {@link #allowBlocking(IBinder)} value from one given * interface to another. * |
