Loading core/java/android/content/ContentResolver.java +21 −2 Original line number Diff line number Diff line Loading @@ -700,6 +700,27 @@ public abstract class ContentResolver implements ContentInterface { /** @hide */ public static final String REMOTE_CALLBACK_RESULT = "result"; /** * How long we wait for an attached process to publish its content providers * before we decide it must be hung. * @hide */ public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000; /** * How long we wait for an provider to be published. Should be longer than * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}. * @hide */ public static final int CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS = CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000; // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how // long ActivityManagerService is giving a content provider to get published if a new process // needs to be started for that. private static final int GET_TYPE_TIMEOUT_MILLIS = CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS + 5 * 1000; public ContentResolver(@Nullable Context context) { this(context, null); } Loading Loading @@ -849,8 +870,6 @@ public abstract class ContentResolver implements ContentInterface { } } private static final int GET_TYPE_TIMEOUT_MILLIS = 3000; private static class GetTypeResultListener implements RemoteCallback.OnResultListener { @GuardedBy("this") public boolean done; Loading core/tests/coretests/AndroidManifest.xml +6 −0 Original line number Diff line number Diff line Loading @@ -1330,6 +1330,12 @@ android:process=":FakeProvider"> </provider> <provider android:name="android.content.SlowProvider" android:authorities="android.content.SlowProvider" android:process=":SlowProvider"> </provider> <!-- Application components used for os tests --> <service android:name="android.os.MessengerService" Loading core/tests/coretests/src/android/content/ContentResolverTest.java +25 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.content; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; Loading @@ -31,6 +33,7 @@ import android.graphics.Paint; import android.net.Uri; import android.os.MemoryFile; import android.os.ParcelFileDescriptor; import android.os.SystemClock; import android.util.Size; import androidx.test.InstrumentationRegistry; Loading Loading @@ -209,4 +212,26 @@ public class ContentResolverTest { String type = mResolver.getType(Uri.parse("content://android.content.FakeProviderRemote")); assertEquals("fake/remote", type); } @Test public void testGetType_slowProvider() { // This provider is running in a different process and is intentionally slow to start. // We are trying to confirm that it does not cause an ANR long start = SystemClock.uptimeMillis(); String type = mResolver.getType(Uri.parse("content://android.content.SlowProvider")); long end = SystemClock.uptimeMillis(); assertEquals("slow", type); assertThat(end).isLessThan(start + 5000); } @Test public void testGetType_unknownProvider() { // This provider does not exist. // We are trying to confirm that getType returns null and does not cause an ANR long start = SystemClock.uptimeMillis(); String type = mResolver.getType(Uri.parse("content://android.content.NonexistentProvider")); long end = SystemClock.uptimeMillis(); assertThat(type).isNull(); assertThat(end).isLessThan(start + 5000); } } core/tests/coretests/src/android/content/SlowProvider.java 0 → 100644 +65 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content; import android.database.Cursor; import android.net.Uri; /** * A dummy content provider for tests. This provider runs in a different process from the test and * is intentionally slow. */ public class SlowProvider extends ContentProvider { private static final int ON_CREATE_LATENCY_MILLIS = 3000; @Override public boolean onCreate() { try { Thread.sleep(ON_CREATE_LATENCY_MILLIS); } catch (InterruptedException e) { // Ignore } return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } @Override public String getType(Uri uri) { return "slow"; } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } } services/core/java/com/android/server/am/ActivityManagerService.java +13 −16 Original line number Diff line number Diff line Loading @@ -468,18 +468,9 @@ public class ActivityManagerService extends IActivityManager.Stub // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real. static final int PROC_START_TIMEOUT = 10*1000; // How long we wait for an attached process to publish its content providers // before we decide it must be hung. static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000; // How long we wait to kill an application zygote, after the last process using // it has gone away. static final int KILL_APP_ZYGOTE_DELAY_MS = 5 * 1000; /** * How long we wait for an provider to be published. Should be longer than * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT}. */ static final int CONTENT_PROVIDER_WAIT_TIMEOUT = 20 * 1000; // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real, when the process was Loading Loading @@ -4984,7 +4975,8 @@ public class ActivityManagerService extends IActivityManager.Stub if (providers != null && checkAppInLaunchingProvidersLocked(app)) { Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT); mHandler.sendMessageDelayed(msg, ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS); } checkTime(startTime, "attachApplicationLocked: before bindApplication"); Loading Loading @@ -7273,7 +7265,8 @@ public class ActivityManagerService extends IActivityManager.Stub } // Wait for the provider to be published... final long timeout = SystemClock.uptimeMillis() + CONTENT_PROVIDER_WAIT_TIMEOUT; final long timeout = SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS; boolean timedOut = false; synchronized (cpr) { while (cpr.provider == null) { Loading Loading @@ -7310,14 +7303,16 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (timedOut) { // Note we do it afer releasing the lock. // Note we do it after releasing the lock. String callerName = "unknown"; if (caller != null) { synchronized (this) { final ProcessRecord record = mProcessList.getLRURecordForAppLocked(caller); if (record != null) { callerName = record.processName; } } } Slog.wtf(TAG, "Timeout waiting for provider " + cpi.applicationInfo.packageName + "/" Loading Loading @@ -7949,6 +7944,8 @@ public class ActivityManagerService extends IActivityManager.Stub } resultCallback.sendResult(result); })); } else { resultCallback.sendResult(Bundle.EMPTY); } } catch (RemoteException e) { Log.w(TAG, "Content provider dead retrieving " + uri, e); Loading Loading
core/java/android/content/ContentResolver.java +21 −2 Original line number Diff line number Diff line Loading @@ -700,6 +700,27 @@ public abstract class ContentResolver implements ContentInterface { /** @hide */ public static final String REMOTE_CALLBACK_RESULT = "result"; /** * How long we wait for an attached process to publish its content providers * before we decide it must be hung. * @hide */ public static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS = 10 * 1000; /** * How long we wait for an provider to be published. Should be longer than * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}. * @hide */ public static final int CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS = CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000; // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how // long ActivityManagerService is giving a content provider to get published if a new process // needs to be started for that. private static final int GET_TYPE_TIMEOUT_MILLIS = CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS + 5 * 1000; public ContentResolver(@Nullable Context context) { this(context, null); } Loading Loading @@ -849,8 +870,6 @@ public abstract class ContentResolver implements ContentInterface { } } private static final int GET_TYPE_TIMEOUT_MILLIS = 3000; private static class GetTypeResultListener implements RemoteCallback.OnResultListener { @GuardedBy("this") public boolean done; Loading
core/tests/coretests/AndroidManifest.xml +6 −0 Original line number Diff line number Diff line Loading @@ -1330,6 +1330,12 @@ android:process=":FakeProvider"> </provider> <provider android:name="android.content.SlowProvider" android:authorities="android.content.SlowProvider" android:process=":SlowProvider"> </provider> <!-- Application components used for os tests --> <service android:name="android.os.MessengerService" Loading
core/tests/coretests/src/android/content/ContentResolverTest.java +25 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.content; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; Loading @@ -31,6 +33,7 @@ import android.graphics.Paint; import android.net.Uri; import android.os.MemoryFile; import android.os.ParcelFileDescriptor; import android.os.SystemClock; import android.util.Size; import androidx.test.InstrumentationRegistry; Loading Loading @@ -209,4 +212,26 @@ public class ContentResolverTest { String type = mResolver.getType(Uri.parse("content://android.content.FakeProviderRemote")); assertEquals("fake/remote", type); } @Test public void testGetType_slowProvider() { // This provider is running in a different process and is intentionally slow to start. // We are trying to confirm that it does not cause an ANR long start = SystemClock.uptimeMillis(); String type = mResolver.getType(Uri.parse("content://android.content.SlowProvider")); long end = SystemClock.uptimeMillis(); assertEquals("slow", type); assertThat(end).isLessThan(start + 5000); } @Test public void testGetType_unknownProvider() { // This provider does not exist. // We are trying to confirm that getType returns null and does not cause an ANR long start = SystemClock.uptimeMillis(); String type = mResolver.getType(Uri.parse("content://android.content.NonexistentProvider")); long end = SystemClock.uptimeMillis(); assertThat(type).isNull(); assertThat(end).isLessThan(start + 5000); } }
core/tests/coretests/src/android/content/SlowProvider.java 0 → 100644 +65 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.content; import android.database.Cursor; import android.net.Uri; /** * A dummy content provider for tests. This provider runs in a different process from the test and * is intentionally slow. */ public class SlowProvider extends ContentProvider { private static final int ON_CREATE_LATENCY_MILLIS = 3000; @Override public boolean onCreate() { try { Thread.sleep(ON_CREATE_LATENCY_MILLIS); } catch (InterruptedException e) { // Ignore } return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } @Override public String getType(Uri uri) { return "slow"; } @Override public Uri insert(Uri uri, ContentValues values) { return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } }
services/core/java/com/android/server/am/ActivityManagerService.java +13 −16 Original line number Diff line number Diff line Loading @@ -468,18 +468,9 @@ public class ActivityManagerService extends IActivityManager.Stub // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real. static final int PROC_START_TIMEOUT = 10*1000; // How long we wait for an attached process to publish its content providers // before we decide it must be hung. static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000; // How long we wait to kill an application zygote, after the last process using // it has gone away. static final int KILL_APP_ZYGOTE_DELAY_MS = 5 * 1000; /** * How long we wait for an provider to be published. Should be longer than * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT}. */ static final int CONTENT_PROVIDER_WAIT_TIMEOUT = 20 * 1000; // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real, when the process was Loading Loading @@ -4984,7 +4975,8 @@ public class ActivityManagerService extends IActivityManager.Stub if (providers != null && checkAppInLaunchingProvidersLocked(app)) { Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT); mHandler.sendMessageDelayed(msg, ContentResolver.CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS); } checkTime(startTime, "attachApplicationLocked: before bindApplication"); Loading Loading @@ -7273,7 +7265,8 @@ public class ActivityManagerService extends IActivityManager.Stub } // Wait for the provider to be published... final long timeout = SystemClock.uptimeMillis() + CONTENT_PROVIDER_WAIT_TIMEOUT; final long timeout = SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS; boolean timedOut = false; synchronized (cpr) { while (cpr.provider == null) { Loading Loading @@ -7310,14 +7303,16 @@ public class ActivityManagerService extends IActivityManager.Stub } } if (timedOut) { // Note we do it afer releasing the lock. // Note we do it after releasing the lock. String callerName = "unknown"; if (caller != null) { synchronized (this) { final ProcessRecord record = mProcessList.getLRURecordForAppLocked(caller); if (record != null) { callerName = record.processName; } } } Slog.wtf(TAG, "Timeout waiting for provider " + cpi.applicationInfo.packageName + "/" Loading Loading @@ -7949,6 +7944,8 @@ public class ActivityManagerService extends IActivityManager.Stub } resultCallback.sendResult(result); })); } else { resultCallback.sendResult(Bundle.EMPTY); } } catch (RemoteException e) { Log.w(TAG, "Content provider dead retrieving " + uri, e); Loading