Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23132a29 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov Committed by Android (Google) Code Review
Browse files

Merge "Add async version of "canonicalize""

parents 11d8a6ef 7a223fbc
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -579,6 +579,15 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
            }
        }

        @Override
        public void canonicalizeAsync(String callingPkg, @Nullable String featureId, Uri uri,
                RemoteCallback callback) {
            final Bundle result = new Bundle();
            result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
                    canonicalize(callingPkg, featureId, uri));
            callback.sendResult(result);
        }

        @Override
        public Uri uncanonicalize(String callingPkg, String featureId,  Uri uri) {
            uri = validateIncomingUri(uri);
+29 −0
Original line number Diff line number Diff line
@@ -359,6 +359,16 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
                    return true;
                }

                case CANONICALIZE_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);
                    canonicalizeAsync(callingPkg, featureId, uri, callback);
                    return true;
                }

                case UNCANONICALIZE_TRANSACTION:
                {
                    data.enforceInterface(IContentProvider.descriptor);
@@ -822,6 +832,25 @@ final class ContentProviderProxy implements IContentProvider
        }
    }

    @Override
    /* oneway */ public void canonicalizeAsync(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.CANONICALIZE_ASYNC_TRANSACTION, data, null,
                    Binder.FLAG_ONEWAY);
        } finally {
            data.recycle();
        }
    }

    @Override
    public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri url)
            throws RemoteException {
+38 −15
Original line number Diff line number Diff line
@@ -712,14 +712,17 @@ public abstract class ContentResolver implements ContentInterface {
     * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}.
     * @hide
     */
    public static final int CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS =
    public static final int CONTENT_PROVIDER_READY_TIMEOUT_MILLIS =
            CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000;

    // Timeout given a ContentProvider that has already been started and connected to.
    private static final int CONTENT_PROVIDER_TIMEOUT_MILLIS = 3 * 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;
    private static final int REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS =
            CONTENT_PROVIDER_READY_TIMEOUT_MILLIS + CONTENT_PROVIDER_TIMEOUT_MILLIS;

    public ContentResolver(@Nullable Context context) {
        this(context, null);
@@ -833,10 +836,10 @@ public abstract class ContentResolver implements ContentInterface {
        IContentProvider provider = acquireExistingProvider(url);
        if (provider != null) {
            try {
                final GetTypeResultListener resultListener = new GetTypeResultListener();
                final StringResultListener resultListener = new StringResultListener();
                provider.getTypeAsync(url, new RemoteCallback(resultListener));
                resultListener.waitForResult();
                return resultListener.type;
                resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
                return resultListener.result;
            } catch (RemoteException e) {
                // Arbitrary and not worth documenting, as Activity
                // Manager will kill this process shortly anyway.
@@ -854,13 +857,13 @@ public abstract class ContentResolver implements ContentInterface {
        }

        try {
            GetTypeResultListener resultListener = new GetTypeResultListener();
            final StringResultListener resultListener = new StringResultListener();
            ActivityManager.getService().getProviderMimeTypeAsync(
                    ContentProvider.getUriWithoutUserId(url),
                    resolveUserId(url),
                    new RemoteCallback(resultListener));
            resultListener.waitForResult();
            return resultListener.type;
            resultListener.waitForResult(REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS);
            return resultListener.result;
        } catch (RemoteException e) {
            // We just failed to send a oneway request to the System Server. Nothing to do.
            return null;
@@ -870,27 +873,29 @@ public abstract class ContentResolver implements ContentInterface {
        }
    }

    private static class GetTypeResultListener implements RemoteCallback.OnResultListener {
    private abstract static class ResultListener<T> implements RemoteCallback.OnResultListener {
        @GuardedBy("this")
        public boolean done;

        @GuardedBy("this")
        public String type;
        public T result;

        @Override
        public void onResult(Bundle result) {
            synchronized (this) {
                type = result.getString(REMOTE_CALLBACK_RESULT);
                this.result = getResultFromBundle(result);
                done = true;
                notifyAll();
            }
        }

        public void waitForResult() {
        protected abstract T getResultFromBundle(Bundle result);

        public void waitForResult(long timeout) {
            synchronized (this) {
                if (!done) {
                    try {
                        wait(GET_TYPE_TIMEOUT_MILLIS);
                        wait(timeout);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
@@ -899,6 +904,20 @@ public abstract class ContentResolver implements ContentInterface {
        }
    }

    private static class StringResultListener extends ResultListener<String> {
        @Override
        protected String getResultFromBundle(Bundle result) {
            return result.getString(REMOTE_CALLBACK_RESULT);
        }
    }

    private static class UriResultListener extends ResultListener<Uri> {
        @Override
        protected Uri getResultFromBundle(Bundle result) {
            return result.getParcelable(REMOTE_CALLBACK_RESULT);
        }
    }

    /**
     * Query for the possible MIME types for the representations the given
     * content URL can be returned when opened as as stream with
@@ -1192,7 +1211,11 @@ public abstract class ContentResolver implements ContentInterface {
        }

        try {
            return provider.canonicalize(mPackageName, mFeatureId, url);
            final UriResultListener resultListener = new UriResultListener();
            provider.canonicalizeAsync(mPackageName, mFeatureId, url,
                    new RemoteCallback(resultListener));
            resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
            return resultListener.result;
        } catch (RemoteException e) {
            // Arbitrary and not worth documenting, as Activity
            // Manager will kill this process shortly anyway.
+10 −1
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ public interface IContentProvider extends IInterface {
    public String getType(Uri url) throws RemoteException;

    /**
     * An oneway version of getType. The functionality is exactly the same, except that the
     * A oneway version of getType. The functionality is exactly the same, except that the
     * call returns immediately, and the resulting type is returned when available via
     * a binder callback.
     */
@@ -126,6 +126,14 @@ public interface IContentProvider extends IInterface {
    public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
            throws RemoteException;

    /**
     * A oneway version of canonicalize. 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 canonicalizeAsync(String callingPkg, @Nullable String featureId, Uri uri,
            RemoteCallback callback) throws RemoteException;

    public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
            throws RemoteException;

@@ -162,4 +170,5 @@ public interface IContentProvider extends IInterface {
    static final int REFRESH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 26;
    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;
}
+8 −0
Original line number Diff line number Diff line
@@ -234,4 +234,12 @@ public class ContentResolverTest {
        assertThat(type).isNull();
        assertThat(end).isLessThan(start + 5000);
    }

    @Test
    public void testCanonicalize() {
        Uri canonical = mResolver.canonicalize(
                Uri.parse("content://android.content.FakeProviderRemote/something"));
        assertThat(canonical).isEqualTo(
                Uri.parse("content://android.content.FakeProviderRemote/canonical"));
    }
}
Loading