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

Commit ee2f7df9 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Tighten flags enforcement, API to test Uris.

Check and throw if callers request invalid grant flags.  Add API to
test if a Uri is backend by a DocumentsProvider.

Bug: 10919391, 10935608
Change-Id: Ifa6afefb95983558c8c64dc15ddf650e9fe07080
parent 6e85d242
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20970,6 +20970,7 @@ package android.provider {
    method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
    method public static java.lang.String getRootId(android.net.Uri);
    method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
    method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
    field public static final java.lang.String EXTRA_ERROR = "error";
    field public static final java.lang.String EXTRA_INFO = "info";
    field public static final java.lang.String EXTRA_LOADING = "loading";
+25 −0
Original line number Diff line number Diff line
@@ -21,7 +21,10 @@ import static libcore.io.OsConstants.SEEK_SET;

import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.graphics.Bitmap;
@@ -572,6 +575,28 @@ public final class DocumentsContract {
                .appendQueryParameter(PARAM_QUERY, query).build();
    }

    /**
     * Test if the given Uri represents a {@link Document} backed by a
     * {@link DocumentsProvider}.
     */
    public static boolean isDocumentUri(Context context, Uri uri) {
        final List<String> paths = uri.getPathSegments();
        if (paths.size() < 2) {
            return false;
        }
        if (!PATH_DOCUMENT.equals(paths.get(0))) {
            return false;
        }

        final ProviderInfo info = context.getPackageManager()
                .resolveContentProvider(uri.getAuthority(), PackageManager.GET_META_DATA);
        if (info.metaData != null && info.metaData.containsKey(
                DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
            return true;
        }
        return false;
    }

    /**
     * Extract the {@link Root#COLUMN_ROOT_ID} from the given Uri.
     */
+12 −0
Original line number Diff line number Diff line
@@ -66,4 +66,16 @@ public class Preconditions {
            throw new IllegalStateException();
        }
    }

    /**
     * Check the requested flags, throwing if any requested flags are outside
     * the allowed set.
     */
    public static void checkFlagsArgument(int requestedFlags, int allowedFlags) {
        if ((requestedFlags & allowedFlags) != requestedFlags) {
            throw new IllegalArgumentException("Requested flags 0x"
                    + Integer.toHexString(requestedFlags) + ", but only 0x"
                    + Integer.toHexString(allowedFlags) + " are allowed");
        }
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
@@ -209,6 +210,9 @@ public class TestActivity extends Activity {
        if (requestCode == CODE_READ) {
            final Uri uri = data != null ? data.getData() : null;
            if (uri != null) {
                if (DocumentsContract.isDocumentUri(this, uri)) {
                    result += "; DOC_ID";
                }
                getContentResolver()
                        .takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
                InputStream is = null;
@@ -228,6 +232,9 @@ public class TestActivity extends Activity {
        } else if (requestCode == CODE_WRITE) {
            final Uri uri = data != null ? data.getData() : null;
            if (uri != null) {
                if (DocumentsContract.isDocumentUri(this, uri)) {
                    result += "; DOC_ID";
                }
                getContentResolver()
                        .takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                OutputStream os = null;
+7 −16
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import com.android.internal.os.TransferPipe;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.MemInfoReader;
import com.android.internal.util.Preconditions;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.IntentResolver;
@@ -6062,12 +6063,8 @@ public final class ActivityManagerService extends ActivityManagerNative
            }
            // Persistable only supported through Intents
            modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            if (modeFlags == 0) {
                throw new IllegalArgumentException("Mode flags must be "
                        + "FLAG_GRANT_READ_URI_PERMISSION and/or FLAG_GRANT_WRITE_URI_PERMISSION");
            }
            Preconditions.checkFlagsArgument(modeFlags,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags,
                    null);
@@ -6408,11 +6405,8 @@ public final class ActivityManagerService extends ActivityManagerNative
    public void takePersistableUriPermission(Uri uri, int modeFlags) {
        enforceNotIsolatedCaller("takePersistableUriPermission");
        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        if (modeFlags == 0) {
            return;
        }
        Preconditions.checkFlagsArgument(modeFlags,
                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        synchronized (this) {
            final int callingUid = Binder.getCallingUid();
@@ -6436,11 +6430,8 @@ public final class ActivityManagerService extends ActivityManagerNative
    public void releasePersistableUriPermission(Uri uri, int modeFlags) {
        enforceNotIsolatedCaller("releasePersistableUriPermission");
        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        if (modeFlags == 0) {
            return;
        }
        Preconditions.checkFlagsArgument(modeFlags,
                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        synchronized (this) {
            final int callingUid = Binder.getCallingUid();
Loading