diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 31c3232f4714f..9cf6569a6220c 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -307,19 +307,7 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall try { result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getType(uri)); } catch (Exception e) { - Parcel parcel = Parcel.obtain(); - try { - try { - parcel.writeException(e); - } catch (Exception ex) { - // getType threw an unparcelable exception. Wrap the message into - // a parcelable exception type - parcel.writeException(new IllegalStateException(e.getMessage())); - } - result.putByteArray(ContentResolver.REMOTE_CALLBACK_ERROR, parcel.marshall()); - } finally { - parcel.recycle(); - } + putExceptionInBundle(result, ContentResolver.REMOTE_CALLBACK_ERROR, e); } callback.sendResult(result); } @@ -602,8 +590,12 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall public void canonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri, RemoteCallback callback) { final Bundle result = new Bundle(); - result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, - canonicalize(callingPkg, attributionTag, uri)); + try { + result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, + canonicalize(callingPkg, attributionTag, uri)); + } catch (Exception e) { + putExceptionInBundle(result, ContentResolver.REMOTE_CALLBACK_ERROR, e); + } callback.sendResult(result); } @@ -717,6 +709,22 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall return AppOpsManager.MODE_ALLOWED; } + + private void putExceptionInBundle(Bundle bundle, String key, Exception e) { + Parcel parcel = Parcel.obtain(); + try { + try { + parcel.writeException(e); + } catch (Exception ex) { + // getType threw an unparcelable exception. Wrap the message into + // a parcelable exception type + parcel.writeException(new IllegalStateException(e.getMessage())); + } + bundle.putByteArray(key, parcel.marshall()); + } finally { + parcel.recycle(); + } + } } boolean checkUser(int pid, int uid, Context context) { diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java index 57e5dd8f8f203..f48e66681cc77 100644 --- a/core/tests/coretests/src/android/content/ContentResolverTest.java +++ b/core/tests/coretests/src/android/content/ContentResolverTest.java @@ -238,12 +238,9 @@ public class ContentResolverTest { @Test public void testGetType_providerException() { - try { - mResolver.getType(Uri.parse("content://android.content.FakeProviderRemote/error")); - fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { - // Expected - } + String type = + mResolver.getType(Uri.parse("content://android.content.FakeProviderRemote/error")); + assertThat(type).isNull(); } @Test @@ -253,4 +250,15 @@ public class ContentResolverTest { assertThat(canonical).isEqualTo( Uri.parse("content://android.content.FakeProviderRemote/canonical")); } + + @Test + public void testCanonicalize_providerException() { + try { + mResolver.canonicalize( + Uri.parse("content://android.content.FakeProviderRemote/error")); + fail("Expected IllegalArgumentException"); + } catch (IllegalArgumentException e) { + // Expected + } + } } diff --git a/core/tests/coretests/src/android/content/FakeProviderRemote.java b/core/tests/coretests/src/android/content/FakeProviderRemote.java index a320094930944..8bc56607f5558 100644 --- a/core/tests/coretests/src/android/content/FakeProviderRemote.java +++ b/core/tests/coretests/src/android/content/FakeProviderRemote.java @@ -60,6 +60,9 @@ public class FakeProviderRemote extends ContentProvider { @Override public Uri canonicalize(Uri uri) { + if (uri.getPath() != null && uri.getPath().contains("error")) { + throw new IllegalArgumentException("Expected exception"); + } return new Uri.Builder().scheme(uri.getScheme()).authority(uri.getAuthority()) .appendPath("canonical").build(); }