Offer API to detect ContentProvider ANRs.
If a system component calls to a remote provider, and that provider
hangs, we end up burning that Binder thread until the remote process
is killed for some unrelated reason.
This change adds an API to detect these hangs, and kill the remote
process after a specific timeout, but only when the caller holds a
permission that lets them kill other apps.
Bug: 117635768
Test: atest android.content.cts.ContentResolverTest
Change-Id: I81b0d993d9d585cdeb5e2559c68052ba6cbbced9
diff --git a/api/system-current.txt b/api/system-current.txt
index 9873c37..4fbdea0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1036,6 +1036,10 @@
package android.content {
+ public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
+ method public void setDetectNotResponding(long);
+ }
+
public abstract class Context {
method public boolean bindServiceAsUser(android.content.Intent, android.content.ServiceConnection, int, android.os.UserHandle);
method public abstract android.content.Context createCredentialProtectedStorageContext();
diff --git a/api/test-current.txt b/api/test-current.txt
index b6a42ec..e0fe895 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -299,6 +299,10 @@
package android.content {
+ public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
+ method public void setDetectNotResponding(long);
+ }
+
public abstract class ContentResolver implements android.content.ContentInterface {
method public static java.lang.String[] getSyncAdapterPackagesForAuthorityAsUser(java.lang.String, int);
}
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index cd7a1a1..0b5bdb5 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -16,8 +16,12 @@
package android.content;
+import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.CrossProcessCursorWrapper;
@@ -106,8 +110,20 @@
mCloseGuard.open("close");
}
- /** {@hide} */
- public void setDetectNotResponding(long timeoutMillis) {
+ /**
+ * Configure this client to automatically detect and kill the remote
+ * provider when an "application not responding" event is detected.
+ *
+ * @param timeoutMillis the duration for which a pending call is allowed
+ * block before the remote provider is considered to be
+ * unresponsive. Set to {@code 0} to allow pending calls to block
+ * indefinitely with no action taken.
+ * @hide
+ */
+ @SystemApi
+ @TestApi
+ @RequiresPermission(android.Manifest.permission.REMOVE_TASKS)
+ public void setDetectNotResponding(@DurationMillisLong long timeoutMillis) {
synchronized (ContentProviderClient.class) {
mAnrTimeout = timeoutMillis;
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index e564711..5fe08aa 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -51,6 +51,7 @@
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
+ <uses-permission android:name="android.permission.REMOVE_TASKS" />
<uses-permission android:name="android.permission.SET_ANIMATION_SCALE" />
<uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />