Loading core/java/android/content/ContentResolver.java +46 −14 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.graphics.Point; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.AndroidTimeoutException; import android.os.Bundle; import android.os.CancellationSignal; import android.os.DeadObjectException; Loading Loading @@ -2188,14 +2189,8 @@ public abstract class ContentResolver implements ContentInterface { return null; } ContentProviderClient provider = acquireContentProviderClient(authority); if (provider == null) { throw new IllegalArgumentException("Unknown authority " + authority); } try { try (ContentProviderClient provider = acquireRequiredContentProviderClient(authority)) { return provider.applyBatch(operations); } finally { provider.release(); } } Loading Loading @@ -2397,10 +2392,7 @@ public abstract class ContentResolver implements ContentInterface { return null; } IContentProvider provider = acquireProvider(authority); if (provider == null) { throw new IllegalArgumentException("Unknown authority " + authority); } IContentProvider provider = acquireRequiredProvider(authority); try { final Bundle res = provider.call(mPackageName, mAttributionTag, authority, method, arg, extras); Loading @@ -2419,7 +2411,9 @@ public abstract class ContentResolver implements ContentInterface { * Returns the content provider for the given content URI. * * @param uri The URI to a content provider * @return The ContentProvider for the given URI, or null if no content provider is found. * @return The ContentProvider for the given URI, or null if the content provider initialization * times out. * * @hide */ @UnsupportedAppUsage Loading @@ -2429,11 +2423,31 @@ public abstract class ContentResolver implements ContentInterface { } final String auth = uri.getAuthority(); if (auth != null) { try { return acquireProvider(mContext, auth); } catch (AndroidTimeoutException ate) { Log.e(TAG, ate.getMessage()); return null; } } return null; } /** * Same as {@link #acquireProvider(String)}, except it throws an exception * if the content provider does not exist or times out on start. * * @hide */ @NonNull private IContentProvider acquireRequiredProvider(@NonNull String name) { IContentProvider provider = acquireProvider(mContext, name); if (provider == null) { throw new IllegalArgumentException("Unknown authority " + name); } return provider; } /** * Returns the content provider for the given content URI if the process * already has a reference on it. Loading Loading @@ -2462,7 +2476,12 @@ public abstract class ContentResolver implements ContentInterface { if (name == null) { return null; } try { return acquireProvider(mContext, name); } catch (AndroidTimeoutException ate) { Log.e(TAG, ate.getMessage()); return null; } } /** Loading Loading @@ -2536,6 +2555,19 @@ public abstract class ContentResolver implements ContentInterface { return null; } /** * Same as {@link #acquireContentProviderClient(String)}, except it throws an exception * if the content provider does not exist or times out on start. * * @hide */ private @NonNull ContentProviderClient acquireRequiredContentProviderClient( @NonNull String name) { Objects.requireNonNull(name, "name"); IContentProvider provider = acquireRequiredProvider(name); return new ContentProviderClient(this, provider, name, true); } /** * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do * not trust the stability of the target content provider. This turns off Loading core/java/android/os/AndroidTimeoutException.java 0 → 100644 +33 −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.os; import android.annotation.NonNull; import android.util.AndroidRuntimeException; /** * An exception that indicates that the request timed out, for example because * the requested content provider took too long to initialize. * * @hide */ public final class AndroidTimeoutException extends AndroidRuntimeException { public AndroidTimeoutException(@NonNull String message) { super(message); } } core/java/android/os/Parcel.java +7 −0 Original line number Diff line number Diff line Loading @@ -269,6 +269,8 @@ public final class Parcel { private static final int EX_UNSUPPORTED_OPERATION = -7; private static final int EX_SERVICE_SPECIFIC = -8; private static final int EX_PARCELABLE = -9; private static final int EX_TIMEOUT = -10; /** @hide */ public static final int EX_HAS_NOTED_APPOPS_REPLY_HEADER = -127; // special; see below private static final int EX_HAS_STRICTMODE_REPLY_HEADER = -128; // special; see below Loading Loading @@ -2156,6 +2158,7 @@ public final class Parcel { * <li>{@link SecurityException} * <li>{@link UnsupportedOperationException} * <li>{@link NetworkOnMainThreadException} * <li>{@link AndroidTimeoutException} * </ul> * * @param e The Exception to be written. Loading Loading @@ -2225,6 +2228,8 @@ public final class Parcel { code = EX_UNSUPPORTED_OPERATION; } else if (e instanceof ServiceSpecificException) { code = EX_SERVICE_SPECIFIC; } else if (e instanceof AndroidTimeoutException) { code = EX_TIMEOUT; } return code; } Loading Loading @@ -2403,6 +2408,8 @@ public final class Parcel { return new UnsupportedOperationException(msg); case EX_SERVICE_SPECIFIC: return new ServiceSpecificException(readInt(), msg); case EX_TIMEOUT: return new AndroidTimeoutException(msg); default: return null; } Loading core/tests/coretests/AndroidManifest.xml +6 −0 Original line number Diff line number Diff line Loading @@ -1511,6 +1511,12 @@ android:process=":SlowProvider"> </provider> <provider android:name="android.content.TimingOutProvider" android:authorities="android.content.TimingOutProvider" android:process=":TimingOutProvider"> </provider> <!-- Application components used for os tests --> <service android:name="android.os.MessengerService" Loading core/tests/coretests/src/android/content/ContentResolverTest.java +15 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.graphics.Color; import android.graphics.ImageDecoder; import android.graphics.Paint; import android.net.Uri; import android.os.AndroidTimeoutException; import android.os.MemoryFile; import android.os.ParcelFileDescriptor; import android.os.SystemClock; Loading Loading @@ -225,6 +226,20 @@ public class ContentResolverTest { assertThat(end).isLessThan(start + 5000); } @Test public void testCall_timingOutProvider() { try { // This provider is running in a different process and is configured to time out // on start. We acquire it as "unstable" to avoid getting killed by the timeout in the // content provider process. mResolver.acquireUnstableContentProviderClient( Uri.parse("content://android.content.TimingOutProvider")); fail("AndroidTimeoutException expected"); } catch (AndroidTimeoutException t) { assertThat(t).hasMessageThat().contains("android.content.TimingOutProvider"); } } @Test public void testGetType_unknownProvider() { // This provider does not exist. Loading Loading
core/java/android/content/ContentResolver.java +46 −14 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.graphics.Point; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.net.Uri; import android.os.AndroidTimeoutException; import android.os.Bundle; import android.os.CancellationSignal; import android.os.DeadObjectException; Loading Loading @@ -2188,14 +2189,8 @@ public abstract class ContentResolver implements ContentInterface { return null; } ContentProviderClient provider = acquireContentProviderClient(authority); if (provider == null) { throw new IllegalArgumentException("Unknown authority " + authority); } try { try (ContentProviderClient provider = acquireRequiredContentProviderClient(authority)) { return provider.applyBatch(operations); } finally { provider.release(); } } Loading Loading @@ -2397,10 +2392,7 @@ public abstract class ContentResolver implements ContentInterface { return null; } IContentProvider provider = acquireProvider(authority); if (provider == null) { throw new IllegalArgumentException("Unknown authority " + authority); } IContentProvider provider = acquireRequiredProvider(authority); try { final Bundle res = provider.call(mPackageName, mAttributionTag, authority, method, arg, extras); Loading @@ -2419,7 +2411,9 @@ public abstract class ContentResolver implements ContentInterface { * Returns the content provider for the given content URI. * * @param uri The URI to a content provider * @return The ContentProvider for the given URI, or null if no content provider is found. * @return The ContentProvider for the given URI, or null if the content provider initialization * times out. * * @hide */ @UnsupportedAppUsage Loading @@ -2429,11 +2423,31 @@ public abstract class ContentResolver implements ContentInterface { } final String auth = uri.getAuthority(); if (auth != null) { try { return acquireProvider(mContext, auth); } catch (AndroidTimeoutException ate) { Log.e(TAG, ate.getMessage()); return null; } } return null; } /** * Same as {@link #acquireProvider(String)}, except it throws an exception * if the content provider does not exist or times out on start. * * @hide */ @NonNull private IContentProvider acquireRequiredProvider(@NonNull String name) { IContentProvider provider = acquireProvider(mContext, name); if (provider == null) { throw new IllegalArgumentException("Unknown authority " + name); } return provider; } /** * Returns the content provider for the given content URI if the process * already has a reference on it. Loading Loading @@ -2462,7 +2476,12 @@ public abstract class ContentResolver implements ContentInterface { if (name == null) { return null; } try { return acquireProvider(mContext, name); } catch (AndroidTimeoutException ate) { Log.e(TAG, ate.getMessage()); return null; } } /** Loading Loading @@ -2536,6 +2555,19 @@ public abstract class ContentResolver implements ContentInterface { return null; } /** * Same as {@link #acquireContentProviderClient(String)}, except it throws an exception * if the content provider does not exist or times out on start. * * @hide */ private @NonNull ContentProviderClient acquireRequiredContentProviderClient( @NonNull String name) { Objects.requireNonNull(name, "name"); IContentProvider provider = acquireRequiredProvider(name); return new ContentProviderClient(this, provider, name, true); } /** * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do * not trust the stability of the target content provider. This turns off Loading
core/java/android/os/AndroidTimeoutException.java 0 → 100644 +33 −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.os; import android.annotation.NonNull; import android.util.AndroidRuntimeException; /** * An exception that indicates that the request timed out, for example because * the requested content provider took too long to initialize. * * @hide */ public final class AndroidTimeoutException extends AndroidRuntimeException { public AndroidTimeoutException(@NonNull String message) { super(message); } }
core/java/android/os/Parcel.java +7 −0 Original line number Diff line number Diff line Loading @@ -269,6 +269,8 @@ public final class Parcel { private static final int EX_UNSUPPORTED_OPERATION = -7; private static final int EX_SERVICE_SPECIFIC = -8; private static final int EX_PARCELABLE = -9; private static final int EX_TIMEOUT = -10; /** @hide */ public static final int EX_HAS_NOTED_APPOPS_REPLY_HEADER = -127; // special; see below private static final int EX_HAS_STRICTMODE_REPLY_HEADER = -128; // special; see below Loading Loading @@ -2156,6 +2158,7 @@ public final class Parcel { * <li>{@link SecurityException} * <li>{@link UnsupportedOperationException} * <li>{@link NetworkOnMainThreadException} * <li>{@link AndroidTimeoutException} * </ul> * * @param e The Exception to be written. Loading Loading @@ -2225,6 +2228,8 @@ public final class Parcel { code = EX_UNSUPPORTED_OPERATION; } else if (e instanceof ServiceSpecificException) { code = EX_SERVICE_SPECIFIC; } else if (e instanceof AndroidTimeoutException) { code = EX_TIMEOUT; } return code; } Loading Loading @@ -2403,6 +2408,8 @@ public final class Parcel { return new UnsupportedOperationException(msg); case EX_SERVICE_SPECIFIC: return new ServiceSpecificException(readInt(), msg); case EX_TIMEOUT: return new AndroidTimeoutException(msg); default: return null; } Loading
core/tests/coretests/AndroidManifest.xml +6 −0 Original line number Diff line number Diff line Loading @@ -1511,6 +1511,12 @@ android:process=":SlowProvider"> </provider> <provider android:name="android.content.TimingOutProvider" android:authorities="android.content.TimingOutProvider" android:process=":TimingOutProvider"> </provider> <!-- Application components used for os tests --> <service android:name="android.os.MessengerService" Loading
core/tests/coretests/src/android/content/ContentResolverTest.java +15 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.graphics.Color; import android.graphics.ImageDecoder; import android.graphics.Paint; import android.net.Uri; import android.os.AndroidTimeoutException; import android.os.MemoryFile; import android.os.ParcelFileDescriptor; import android.os.SystemClock; Loading Loading @@ -225,6 +226,20 @@ public class ContentResolverTest { assertThat(end).isLessThan(start + 5000); } @Test public void testCall_timingOutProvider() { try { // This provider is running in a different process and is configured to time out // on start. We acquire it as "unstable" to avoid getting killed by the timeout in the // content provider process. mResolver.acquireUnstableContentProviderClient( Uri.parse("content://android.content.TimingOutProvider")); fail("AndroidTimeoutException expected"); } catch (AndroidTimeoutException t) { assertThat(t).hasMessageThat().contains("android.content.TimingOutProvider"); } } @Test public void testGetType_unknownProvider() { // This provider does not exist. Loading