summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitri Plotnikov <dplotnikov@google.com>2020-10-23 15:47:19 -0700
committerDmitri Plotnikov <dplotnikov@google.com>2020-10-28 17:27:27 -0700
commitec2bc8d99fe9fad5f6e829b259b78a2bd58c4a76 (patch)
treec62d2ca580f76a001e6340ac2c4fe10a09b5cccf
parentb2f811d3c8b536452f191bf6aa4ad7c14b0af077 (diff)
Add async version of "uncanonicalize"
This CL is basically identical to http://ag/10353234, which did the same with the sister method, "canonicalize". Fixes: b/147705670 Test: atest FrameworksCoreTests:android.content.ContentResolverTest Change-Id: Ide93850f225cdd61779a62fc2c4666efe438b536
-rw-r--r--core/java/android/content/ContentProvider.java14
-rw-r--r--core/java/android/content/ContentProviderNative.java29
-rw-r--r--core/java/android/content/ContentResolver.java9
-rw-r--r--core/java/android/content/IContentProvider.java9
-rw-r--r--core/tests/coretests/src/android/content/ContentResolverTest.java8
-rw-r--r--core/tests/coretests/src/android/content/FakeProviderRemote.java9
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java16
-rw-r--r--test-mock/src/android/test/mock/MockContentProvider.java18
-rw-r--r--test-mock/src/android/test/mock/MockIContentProvider.java15
9 files changed, 124 insertions, 3 deletions
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 03adbc782eef..49248b51a5c7 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -624,6 +624,20 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
@Override
+ public void uncanonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+ RemoteCallback callback) {
+ final Bundle result = new Bundle();
+ try {
+ result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
+ uncanonicalize(callingPkg, attributionTag, uri));
+ } catch (Exception e) {
+ result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR,
+ new ParcelableException(e));
+ }
+ callback.sendResult(result);
+ }
+
+ @Override
public boolean refresh(String callingPkg, String attributionTag, Uri uri, Bundle extras,
ICancellationSignal cancellationSignal) throws RemoteException {
uri = validateIncomingUri(uri);
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 7bc59013bcfe..7d121d56c86d 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -382,6 +382,16 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
return true;
}
+ case UNCANONICALIZE_ASYNC_TRANSACTION: {
+ data.enforceInterface(IContentProvider.descriptor);
+ String callingPkg = data.readString();
+ String featureId = data.readString();
+ Uri uri = Uri.CREATOR.createFromParcel(data);
+ RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
+ uncanonicalizeAsync(callingPkg, featureId, uri, callback);
+ return true;
+ }
+
case REFRESH_TRANSACTION: {
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
@@ -875,6 +885,25 @@ final class ContentProviderProxy implements IContentProvider
}
@Override
+ /* oneway */ public void uncanonicalizeAsync(String callingPkg, @Nullable String featureId,
+ Uri uri, RemoteCallback callback) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ try {
+ data.writeInterfaceToken(IContentProvider.descriptor);
+
+ data.writeString(callingPkg);
+ data.writeString(featureId);
+ uri.writeToParcel(data, 0);
+ callback.writeToParcel(data, 0);
+
+ mRemote.transact(IContentProvider.UNCANONICALIZE_ASYNC_TRANSACTION, data, null,
+ Binder.FLAG_ONEWAY);
+ } finally {
+ data.recycle();
+ }
+ }
+
+ @Override
public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle extras,
ICancellationSignal signal) throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 50092d17c692..422d3f7c6784 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1338,7 +1338,14 @@ public abstract class ContentResolver implements ContentInterface {
}
try {
- return provider.uncanonicalize(mPackageName, mAttributionTag, url);
+ final UriResultListener resultListener = new UriResultListener();
+ provider.uncanonicalizeAsync(mPackageName, mAttributionTag, url,
+ new RemoteCallback(resultListener));
+ resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
+ if (resultListener.exception != null) {
+ throw resultListener.exception;
+ }
+ return resultListener.result;
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
// Manager will kill this process shortly anyway.
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index becba67a0198..9210b132c75a 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -137,6 +137,14 @@ public interface IContentProvider extends IInterface {
public Uri uncanonicalize(String callingPkg, @Nullable String attributionTag, Uri uri)
throws RemoteException;
+ /**
+ * A oneway version of uncanonicalize. The functionality is exactly the same, except that the
+ * call returns immediately, and the resulting type is returned when available via
+ * a binder callback.
+ */
+ void uncanonicalizeAsync(String callingPkg, @Nullable String attributionTag, Uri uri,
+ RemoteCallback callback) throws RemoteException;
+
public boolean refresh(String callingPkg, @Nullable String attributionTag, Uri url,
@Nullable Bundle extras, ICancellationSignal cancellationSignal) throws RemoteException;
@@ -172,4 +180,5 @@ public interface IContentProvider extends IInterface {
static final int CHECK_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 27;
int GET_TYPE_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 28;
int CANONICALIZE_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 29;
+ int UNCANONICALIZE_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 30;
}
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
index f48e66681cc7..b517428f5b59 100644
--- a/core/tests/coretests/src/android/content/ContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -261,4 +261,12 @@ public class ContentResolverTest {
// Expected
}
}
+
+ @Test
+ public void testUncanonicalize() {
+ Uri uncanonical = mResolver.uncanonicalize(
+ Uri.parse("content://android.content.FakeProviderRemote/something"));
+ assertThat(uncanonical).isEqualTo(
+ Uri.parse("content://android.content.FakeProviderRemote/uncanonical"));
+ }
}
diff --git a/core/tests/coretests/src/android/content/FakeProviderRemote.java b/core/tests/coretests/src/android/content/FakeProviderRemote.java
index 2c92da34d9a4..d0bb78101ee4 100644
--- a/core/tests/coretests/src/android/content/FakeProviderRemote.java
+++ b/core/tests/coretests/src/android/content/FakeProviderRemote.java
@@ -66,4 +66,13 @@ public class FakeProviderRemote extends ContentProvider {
return new Uri.Builder().scheme(uri.getScheme()).authority(uri.getAuthority())
.appendPath("canonical").build();
}
+
+ @Override
+ public Uri uncanonicalize(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("uncanonical").build();
+ }
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 3e779a9b2435..bf742b7f96dc 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -218,6 +218,22 @@ public class PreferencesHelperTest extends UiServiceTestCase {
return null;
}).when(mTestIContentProvider).canonicalizeAsync(any(), any(), any(), any());
doAnswer(invocation -> {
+ String callingPkg = invocation.getArgument(0);
+ String featureId = invocation.getArgument(1);
+ Uri uri = invocation.getArgument(2);
+ RemoteCallback cb = invocation.getArgument(3);
+ IContentProvider mock = (IContentProvider) (invocation.getMock());
+ AsyncTask.SERIAL_EXECUTOR.execute(() -> {
+ final Bundle bundle = new Bundle();
+ try {
+ bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
+ mock.uncanonicalize(callingPkg, featureId, uri));
+ } catch (RemoteException e) { /* consume */ }
+ cb.sendResult(bundle);
+ });
+ return null;
+ }).when(mTestIContentProvider).uncanonicalizeAsync(any(), any(), any(), any());
+ doAnswer(invocation -> {
Uri uri = invocation.getArgument(0);
RemoteCallback cb = invocation.getArgument(1);
IContentProvider mock = (IContentProvider) (invocation.getMock());
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index a5c254f1aca2..5b9f67efd95d 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -169,6 +169,12 @@ public class MockContentProvider extends ContentProvider {
}
@Override
+ public void uncanonicalizeAsync(String callingPkg, String featureId, Uri uri,
+ RemoteCallback callback) {
+ MockContentProvider.this.uncanonicalizeAsync(uri, callback);
+ }
+
+ @Override
public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
Bundle args, ICancellationSignal cancellationSignal) throws RemoteException {
return MockContentProvider.this.refresh(url, args);
@@ -311,6 +317,18 @@ public class MockContentProvider extends ContentProvider {
/**
* @hide
*/
+ @SuppressWarnings("deprecation")
+ public void uncanonicalizeAsync(Uri uri, RemoteCallback callback) {
+ AsyncTask.SERIAL_EXECUTOR.execute(() -> {
+ final Bundle bundle = new Bundle();
+ bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, uncanonicalize(uri));
+ callback.sendResult(bundle);
+ });
+ }
+
+ /**
+ * @hide
+ */
public boolean refresh(Uri url, Bundle args) {
throw new UnsupportedOperationException("unimplemented mock method call");
}
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index 223bcc59039d..82a1cf7d1796 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -162,12 +162,23 @@ public class MockIContentProvider implements IContentProvider {
}
@Override
- public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
- throws RemoteException {
+ public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
+ @SuppressWarnings("deprecation")
+ public void uncanonicalizeAsync(String callingPkg, String featureId, Uri uri,
+ RemoteCallback remoteCallback) {
+ AsyncTask.SERIAL_EXECUTOR.execute(() -> {
+ final Bundle bundle = new Bundle();
+ bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
+ uncanonicalize(callingPkg, featureId, uri));
+ remoteCallback.sendResult(bundle);
+ });
+ }
+
+ @Override
public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args,
ICancellationSignal cancellationSignal) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");