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

Commit d55a387f authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Add async version of getProviderMimeType

Fixes: b/147646960
Test: atest FrameworksCoreTests:android.content.ContentResolverTest

Change-Id: I04c15ac008fe14b215f954af150226dc94f22232
parent 17f6ed8b
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -303,8 +303,13 @@ interface IActivityManager {
    boolean isTopActivityImmersive();
    void crashApplication(int uid, int initialPid, in String packageName, int userId,
            in String message, boolean force);
    @UnsupportedAppUsage
    /** @deprecated -- use getProviderMimeTypeAsync */
    @UnsupportedAppUsage(maxTargetSdk = 29, publicAlternatives =
            "Use {@link android.content.ContentResolver#getType} public API instead.")
    String getProviderMimeType(in Uri uri, int userId);

    oneway void getProviderMimeTypeAsync(in Uri uri, int userId, in RemoteCallback resultCallback);

    // Cause the specified process to dump the specified heap.
    boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
            boolean runGc, in String path, in ParcelFileDescriptor fd,
+8 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
@@ -299,6 +300,13 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
            }
        }

        @Override
        public void getTypeAsync(Uri uri, RemoteCallback callback) {
            final Bundle result = new Bundle();
            result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getType(uri));
            callback.sendResult(result);
        }

        @Override
        public Uri insert(String callingPkg, @Nullable String featureId, Uri uri,
                ContentValues initialValues, Bundle extras) {
+25 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.os.ICancellationSignal;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.RemoteCallback;
import android.os.RemoteException;

import java.io.FileNotFoundException;
@@ -146,6 +147,14 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
                    return true;
                }

                case GET_TYPE_ASYNC_TRANSACTION: {
                    data.enforceInterface(IContentProvider.descriptor);
                    Uri url = Uri.CREATOR.createFromParcel(data);
                    RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
                    getTypeAsync(url, callback);
                    return true;
                }

                case INSERT_TRANSACTION:
                {
                    data.enforceInterface(IContentProvider.descriptor);
@@ -494,6 +503,22 @@ final class ContentProviderProxy implements IContentProvider
        }
    }

    @Override
    /* oneway */ public void getTypeAsync(Uri uri, RemoteCallback callback) throws RemoteException {
        Parcel data = Parcel.obtain();
        try {
            data.writeInterfaceToken(IContentProvider.descriptor);

            uri.writeToParcel(data, 0);
            callback.writeToParcel(data, 0);

            mRemote.transact(IContentProvider.GET_TYPE_ASYNC_TRANSACTION, data, null,
                    IBinder.FLAG_ONEWAY);
        } finally {
            data.recycle();
        }
    }

    @Override
    public Uri insert(String callingPkg, @Nullable String featureId, Uri url,
            ContentValues values, Bundle extras) throws RemoteException
+49 −5
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -67,6 +68,7 @@ import android.util.Log;
import android.util.Size;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.MimeIconUtils;

import dalvik.system.CloseGuard;
@@ -695,6 +697,9 @@ public abstract class ContentResolver implements ContentInterface {
    private static final int SLOW_THRESHOLD_MILLIS = 500;
    private final Random mRandom = new Random();  // guarded by itself

    /** @hide */
    public static final String REMOTE_CALLBACK_RESULT = "result";

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

        try {
            String type = ActivityManager.getService().getProviderMimeType(
                    ContentProvider.getUriWithoutUserId(url), resolveUserId(url));
            return type;
            GetTypeResultListener resultListener = new GetTypeResultListener();
            ActivityManager.getService().getProviderMimeTypeAsync(
                    ContentProvider.getUriWithoutUserId(url),
                    resolveUserId(url),
                    new RemoteCallback(resultListener));
            resultListener.waitForResult();
            return resultListener.type;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            // We just failed to send a oneway request to the System Server. Nothing to do.
            return null;
        } catch (java.lang.Exception e) {
            Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
            return null;
        }
    }

    private static final int GET_TYPE_TIMEOUT_MILLIS = 3000;

    private static class GetTypeResultListener implements RemoteCallback.OnResultListener {
        @GuardedBy("this")
        public boolean done;

        @GuardedBy("this")
        public String type;

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

        public void waitForResult() {
            synchronized (this) {
                if (!done) {
                    try {
                        wait(GET_TYPE_TIMEOUT_MILLIS);
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }
            }
        }
    }

    /**
     * Query for the possible MIME types for the representations the given
     * content URL can be returned when opened as as stream with
+10 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.IBinder;
import android.os.ICancellationSignal;
import android.os.IInterface;
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallback;
import android.os.RemoteException;

import java.io.FileNotFoundException;
@@ -42,6 +43,14 @@ public interface IContentProvider extends IInterface {
            @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
            throws RemoteException;
    public String getType(Uri url) throws RemoteException;

    /**
     * An 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.
     */
    void getTypeAsync(Uri uri, RemoteCallback callback) throws RemoteException;

    @Deprecated
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
            + "ContentProviderClient#insert(android.net.Uri, android.content.ContentValues)} "
@@ -152,4 +161,5 @@ public interface IContentProvider extends IInterface {
    static final int UNCANONICALIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 25;
    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;
}
Loading