/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.cts.usespermissiondiffcertapp;

import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_CLEAR_PRIMARY_CLIP;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_GRANT_URI;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_REVOKE_URI;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_SET_PRIMARY_CLIP;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_START_ACTIVITY;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_START_SERVICE;
import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_VERIFY_OUTGOING_PERSISTED;
import static com.android.cts.permissiondeclareapp.UtilsProvider.EXTRA_INTENT;
import static com.android.cts.permissiondeclareapp.UtilsProvider.EXTRA_MODE;
import static com.android.cts.permissiondeclareapp.UtilsProvider.EXTRA_PACKAGE_NAME;
import static com.android.cts.permissiondeclareapp.UtilsProvider.EXTRA_URI;

import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.UriPermission;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
import android.test.AndroidTestCase;
import android.util.Log;

import com.android.cts.permissiondeclareapp.UtilsProvider;

import java.io.IOException;
import java.util.List;

/**
 * Tests that signature-enforced permissions cannot be accessed by apps signed
 * with different certs than app that declares the permission.
 * 
 * Accesses app cts/tests/appsecurity-tests/test-apps/PermissionDeclareApp/...
 */
public class AccessPermissionWithDiffSigTest extends AndroidTestCase {
    private static final Uri PERM_URI = Uri.parse("content://ctspermissionwithsignature");
    private static final Uri PERM_URI_GRANTING = Uri.parse("content://ctspermissionwithsignaturegranting");
    private static final Uri PERM_URI_PATH = Uri.parse("content://ctspermissionwithsignaturepath");
    private static final Uri PERM_URI_PATH_RESTRICTING = Uri.parse(
            "content://ctspermissionwithsignaturepathrestricting");
    private static final Uri PRIV_URI = Uri.parse("content://ctsprivateprovider");
    private static final Uri PRIV_URI_GRANTING = Uri.parse("content://ctsprivateprovidergranting");
    private static final String EXPECTED_MIME_TYPE = "got/theMIME";

    private static final Uri AMBIGUOUS_URI_COMPAT = Uri.parse("content://ctsambiguousprovidercompat");
    private static final String EXPECTED_MIME_TYPE_AMBIGUOUS = "got/theUnspecifiedMIME";
    private static final Uri AMBIGUOUS_URI = Uri.parse("content://ctsambiguousprovider");

    private static final Uri[] GRANTABLE = new Uri[] {
            Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
            Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
            Uri.withAppendedPath(PERM_URI_PATH, "foo"),
    };

    private static final Uri[] NOT_GRANTABLE = new Uri[] {
            Uri.withAppendedPath(PERM_URI, "foo"),
            Uri.withAppendedPath(PRIV_URI, "foo"),
            Uri.withAppendedPath(PERM_URI_PATH_RESTRICTING, "foo"),
            CalendarContract.CONTENT_URI,
            ContactsContract.AUTHORITY_URI,
    };

    @Override
    protected void tearDown() throws Exception {
        super.tearDown();

        // Always dispose, usually to clean up from failed tests
        ReceiveUriActivity.finishCurInstanceSync();
    }

    private void assertReadingContentUriNotAllowed(Uri uri, String msg) {
        try {
            getContext().getContentResolver().query(uri, null, null, null, null);
            fail("expected SecurityException reading " + uri + ": " + msg);
        } catch (SecurityException expected) {
            assertNotNull("security exception's error message.", expected.getMessage());
        }
    }

    private void assertReadingContentUriAllowed(Uri uri) {
        try {
            getContext().getContentResolver().query(uri, null, null, null, null);
        } catch (SecurityException e) {
            fail("unexpected SecurityException reading " + uri + ": " + e.getMessage());
        }
    }

    private void assertReadingClipNotAllowed(ClipData clip) {
        assertReadingClipNotAllowed(clip, null);
    }

    private void assertReadingClipNotAllowed(ClipData clip, String msg) {
        for (int i=0; i<clip.getItemCount(); i++) {
            ClipData.Item item = clip.getItemAt(i);
            Uri uri = item.getUri();
            if (uri != null) {
                assertReadingContentUriNotAllowed(uri, msg);
            } else {
                Intent intent = item.getIntent();
                uri = intent.getData();
                if (uri != null) {
                    assertReadingContentUriNotAllowed(uri, msg);
                }
                ClipData intentClip = intent.getClipData();
                if (intentClip != null) {
                    assertReadingClipNotAllowed(intentClip, msg);
                }
            }
        }
    }

    private void assertOpenFileDescriptorModeNotAllowed(Uri uri, String msg, String mode) {
        try {
            getContext().getContentResolver().openFileDescriptor(uri, mode).close();
            fail("expected SecurityException writing " + uri + ": " + msg);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        } catch (SecurityException expected) {
            assertNotNull("security exception's error message.", expected.getMessage());
        }
    }

    private void assertContentUriAllowed(Uri uri) {
        assertReadingContentUriAllowed(uri);
        assertWritingContentUriAllowed(uri);
    }

    private void assertContentUriNotAllowed(Uri uri, String msg) {
        assertReadingContentUriNotAllowed(uri, msg);
        assertWritingContentUriNotAllowed(uri, msg);
    }

    private void assertWritingContentUriNotAllowed(Uri uri, String msg) {
        final ContentResolver resolver = getContext().getContentResolver();
        try {
            resolver.insert(uri, new ContentValues());
            fail("expected SecurityException inserting " + uri + ": " + msg);
        } catch (SecurityException expected) {
            assertNotNull("security exception's error message.", expected.getMessage());
        }

        try {
            resolver.update(uri, new ContentValues(), null, null);
            fail("expected SecurityException updating " + uri + ": " + msg);
        } catch (SecurityException expected) {
            assertNotNull("security exception's error message.", expected.getMessage());
        }

        try {
            resolver.delete(uri, null, null);
            fail("expected SecurityException deleting " + uri + ": " + msg);
        } catch (SecurityException expected) {
            assertNotNull("security exception's error message.", expected.getMessage());
        }

        try {
            getContext().getContentResolver().openOutputStream(uri).close();
            fail("expected SecurityException writing " + uri + ": " + msg);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        } catch (SecurityException expected) {
            assertNotNull("security exception's error message.", expected.getMessage());
        }

        assertOpenFileDescriptorModeNotAllowed(uri, msg, "w");
        assertOpenFileDescriptorModeNotAllowed(uri, msg, "wt");
        assertOpenFileDescriptorModeNotAllowed(uri, msg, "wa");
        assertOpenFileDescriptorModeNotAllowed(uri, msg, "rw");
        assertOpenFileDescriptorModeNotAllowed(uri, msg, "rwt");
    }

    private void assertWritingContentUriAllowed(Uri uri) {
        final ContentResolver resolver = getContext().getContentResolver();
        try {
            resolver.insert(uri, new ContentValues());
            resolver.update(uri, new ContentValues(), null, null);
            resolver.delete(uri, null, null);

            resolver.openOutputStream(uri).close();
            resolver.openFileDescriptor(uri, "w").close();
            resolver.openFileDescriptor(uri, "wt").close();
            resolver.openFileDescriptor(uri, "wa").close();
            resolver.openFileDescriptor(uri, "rw").close();
            resolver.openFileDescriptor(uri, "rwt").close();
        } catch (IOException e) {
            fail("unexpected IOException writing " + uri + ": " + e.getMessage());
        } catch (SecurityException e) {
            fail("unexpected SecurityException writing " + uri + ": " + e.getMessage());
        }
    }

    private void assertWritingClipNotAllowed(ClipData clip) {
        assertWritingClipNotAllowed(clip, null);
    }

    private void assertWritingClipNotAllowed(ClipData clip, String msg) {
        for (int i=0; i<clip.getItemCount(); i++) {
            ClipData.Item item = clip.getItemAt(i);
            Uri uri = item.getUri();
            if (uri != null) {
                assertWritingContentUriNotAllowed(uri, msg);
            } else {
                Intent intent = item.getIntent();
                uri = intent.getData();
                if (uri != null) {
                    assertWritingContentUriNotAllowed(uri, msg);
                }
                ClipData intentClip = intent.getClipData();
                if (intentClip != null) {
                    assertWritingClipNotAllowed(intentClip, msg);
                }
            }
        }
    }

    /**
     * Test that the ctspermissionwithsignature content provider cannot be read,
     * since this app lacks the required certs
     */
    public void testReadProviderWithDiff() {
        assertReadingContentUriRequiresPermission(PERM_URI,
                "com.android.cts.permissionWithSignature");
    }

    /**
     * Test that the ctspermissionwithsignature content provider cannot be written,
     * since this app lacks the required certs
     */
    public void testWriteProviderWithDiff() {
        assertWritingContentUriRequiresPermission(PERM_URI,
                "com.android.cts.permissionWithSignature");
    }

    /**
     * Test that the ctsprivateprovider content provider cannot be read,
     * since it is not exported from its app.
     */
    public void testReadProviderWhenPrivate() {
        assertReadingContentUriNotAllowed(PRIV_URI, "shouldn't read private provider");
    }

    /**
     * Test that the ctsambiguousprovider content provider cannot be read,
     * since it doesn't have an "exported=" line.
     */
    public void testReadProviderWhenAmbiguous() {
        assertReadingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't read ambiguous provider");
    }

    /**
     * Old App Compatibility Test
     *
     * Test that the ctsambiguousprovidercompat content provider can be read for older
     * API versions, because it didn't specify either exported=true or exported=false.
     */
    public void testReadProviderWhenAmbiguousCompat() {
        assertReadingContentUriAllowed(AMBIGUOUS_URI_COMPAT);
    }

    /**
     * Old App Compatibility Test
     *
     * Test that the ctsambiguousprovidercompat content provider can be written for older
     * API versions, because it didn't specify either exported=true or exported=false.
     */
    public void testWriteProviderWhenAmbiguousCompat() {
        assertWritingContentUriAllowed(AMBIGUOUS_URI_COMPAT);
    }

    /**
     * Test that the ctsprivateprovider content provider cannot be written,
     * since it is not exported from its app.
     */
    public void testWriteProviderWhenPrivate() {
        assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write private provider");
    }

    /**
     * Test that the ctsambiguousprovider content provider cannot be written,
     * since it doesn't have an exported= line.
     */
    public void testWriteProviderWhenAmbiguous() {
        assertWritingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't write ambiguous provider");
    }

    private static ClipData makeSingleClipData(Uri uri) {
        return new ClipData("foo", new String[] { "foo/bar" },
                new ClipData.Item(uri));
    }

    private static ClipData makeMultiClipData(Uri uri) {
        Uri grantClip1Uri = Uri.withAppendedPath(uri, "clip1");
        Uri grantClip2Uri = Uri.withAppendedPath(uri, "clip2");
        Uri grantClip3Uri = Uri.withAppendedPath(uri, "clip3");
        Uri grantClip4Uri = Uri.withAppendedPath(uri, "clip4");
        Uri grantClip5Uri = Uri.withAppendedPath(uri, "clip5");
        ClipData clip = new ClipData("foo", new String[] { "foo/bar" },
                new ClipData.Item(grantClip1Uri));
        clip.addItem(new ClipData.Item(grantClip2Uri));
        // Intents in the ClipData should allow their data: and clip URIs
        // to be granted, but only respect the grant flags of the top-level
        // Intent.
        clip.addItem(new ClipData.Item(new Intent(Intent.ACTION_VIEW, grantClip3Uri)));
        Intent intent = new Intent(Intent.ACTION_VIEW, grantClip4Uri);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        clip.addItem(new ClipData.Item(intent));
        intent = new Intent(Intent.ACTION_VIEW);
        intent.setClipData(new ClipData("foo", new String[] { "foo/bar" },
                new ClipData.Item(grantClip5Uri)));
        clip.addItem(new ClipData.Item(intent));
        return clip;
    }

    private static Intent makeClipIntent(ClipData clip, int flags) {
        Intent intent = new Intent();
        intent.setClipData(clip);
        intent.addFlags(flags);
        return intent;
    }

    private static Intent makeClipIntent(Uri uri, int flags) {
        return makeClipIntent(makeMultiClipData(uri), flags);
    }

    private void doTryGrantUriActivityPermissionToSelf(Uri uri, int mode) {
        Uri grantDataUri = Uri.withAppendedPath(uri, "data");
        Intent grantIntent = new Intent();
        grantIntent.setData(grantDataUri);
        grantIntent.addFlags(mode | Intent.FLAG_ACTIVITY_NEW_TASK);
        grantIntent.setClass(getContext(), ReceiveUriActivity.class);
        try {
            ReceiveUriActivity.clearStarted();
            getContext().startActivity(grantIntent);
            ReceiveUriActivity.waitForStart();
            fail("expected SecurityException granting " + grantDataUri + " to activity");
        } catch (SecurityException e) {
            // This is what we want.
        }

        grantIntent = makeClipIntent(uri, mode | Intent.FLAG_ACTIVITY_NEW_TASK);
        grantIntent.setClass(getContext(), ReceiveUriActivity.class);
        try {
            ReceiveUriActivity.clearStarted();
            getContext().startActivity(grantIntent);
            ReceiveUriActivity.waitForStart();
            fail("expected SecurityException granting " + grantIntent.getClipData() + " to activity");
        } catch (SecurityException e) {
            // This is what we want.
        }
    }

    /**
     * Test that we can't grant a permission to ourself.
     */
    public void testGrantReadUriActivityPermissionToSelf() {
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

    /**
     * Test that we can't grant a permission to ourself.
     */
    public void testGrantWriteUriActivityPermissionToSelf() {
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }

    /**
     * Test that we can't grant a permission to ourself.
     */
    public void testGrantReadUriActivityPrivateToSelf() {
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

    /**
     * Test that we can't grant a permission to ourself.
     */
    public void testGrantWriteUriActivityPrivateToSelf() {
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }

    private void doTryGrantUriServicePermissionToSelf(Uri uri, int mode) {
        Uri grantDataUri = Uri.withAppendedPath(uri, "data");
        Intent grantIntent = new Intent();
        grantIntent.setData(grantDataUri);
        grantIntent.addFlags(mode);
        grantIntent.setClass(getContext(), ReceiveUriService.class);
        try {
            getContext().startService(grantIntent);
            fail("expected SecurityException granting " + grantDataUri + " to service");
        } catch (SecurityException e) {
            // This is what we want.
        }

        grantIntent = makeClipIntent(uri, mode);
        grantIntent.setClass(getContext(), ReceiveUriService.class);
        try {
            getContext().startService(grantIntent);
            fail("expected SecurityException granting " + grantIntent.getClipData() + " to service");
        } catch (SecurityException e) {
            // This is what we want.
        }
    }

    /**
     * Test that we can't grant a permission to ourself.
     */
    public void testGrantReadUriServicePermissionToSelf() {
        doTryGrantUriServicePermissionToSelf(
                Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

    /**
     * Test that we can't grant a permission to ourself.
     */
    public void testGrantWriteUriServicePermissionToSelf() {
        doTryGrantUriServicePermissionToSelf(
                Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }

    /**
     * Test that we can't grant a permission to ourself.
     */
    public void testGrantReadUriServicePrivateToSelf() {
        doTryGrantUriServicePermissionToSelf(
                Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

    /**
     * Test that we can't grant a permission to ourself.
     */
    public void testGrantWriteUriServicePrivateToSelf() {
        doTryGrantUriServicePermissionToSelf(
                Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }

    private void grantUriPermissionFail(Uri uri, int mode, boolean service) {
        Uri grantDataUri = Uri.withAppendedPath(uri, "data");
        Intent grantIntent = new Intent();
        grantIntent.setData(grantDataUri);
        grantIntent.addFlags(mode);
        grantIntent.setClass(getContext(),
                service ? ReceiveUriService.class : ReceiveUriActivity.class);
        Intent intent = new Intent();
        intent.setAction(service ? ACTION_START_SERVICE : ACTION_START_ACTIVITY);
        intent.putExtra(EXTRA_INTENT, grantIntent);
        try {
            call(intent);
            fail("Able to grant URI permission to " + grantDataUri + " when should not");
        } catch (Exception expected) {
        }

        grantIntent = makeClipIntent(uri, mode);
        grantIntent.setClass(getContext(),
                service ? ReceiveUriService.class : ReceiveUriActivity.class);
        intent = new Intent();
        intent.setAction(service ? ACTION_START_SERVICE : ACTION_START_ACTIVITY);
        intent.putExtra(EXTRA_INTENT, grantIntent);
        try {
            call(intent);
            fail("Able to grant URI permission to " + grantIntent.getClipData()
                    + " when should not");
        } catch (Exception expected) {
        }
    }

    private void doTestGrantUriPermissionFail(Uri uri) {
        for (boolean service : new boolean[] { false, true }) {
            for (int flags : new int[] {
                    Intent.FLAG_GRANT_READ_URI_PERMISSION, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
            }) {
                grantUriPermissionFail(uri,
                        flags, service);
                grantUriPermissionFail(uri,
                        flags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, service);
                grantUriPermissionFail(uri,
                        flags | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, service);
            }
        }
    }
    
    /**
     * Test that the ctspermissionwithsignature content provider can not grant
     * URI permissions to others.
     */
    public void testGrantPermissionNonGrantingFail() {
        doTestGrantUriPermissionFail(PERM_URI);
    }

    /**
     * Test that the ctspermissionwithsignaturegranting content provider can not grant
     * URI permissions to paths outside of the grant tree
     */
    public void testGrantPermissionOutsideGrantingFail() {
        doTestGrantUriPermissionFail(PERM_URI_GRANTING);
        doTestGrantUriPermissionFail(Uri.withAppendedPath(PERM_URI_GRANTING, "invalid"));
    }

    /**
     * Test that the ctsprivateprovider content provider can not grant
     * URI permissions to others.
     */
    public void testGrantPrivateNonGrantingFail() {
        doTestGrantUriPermissionFail(PRIV_URI);
    }

    /**
     * Test that the ctsambiguousprovider content provider can not grant
     * URI permissions to others.
     */
    public void testGrantAmbiguousNonGrantingFail() {
        doTestGrantUriPermissionFail(AMBIGUOUS_URI);
    }

    /**
     * Test that the ctsprivateprovidergranting content provider can not grant
     * URI permissions to paths outside of the grant tree
     */
    public void testGrantPrivateOutsideGrantingFail() {
        doTestGrantUriPermissionFail(PRIV_URI_GRANTING);
        doTestGrantUriPermissionFail(Uri.withAppendedPath(PRIV_URI_GRANTING, "invalid"));
    }

    private void call(Intent intent) {
        final Bundle extras = new Bundle();
        extras.putParcelable(Intent.EXTRA_INTENT, intent);
        getContext().getContentResolver().call(UtilsProvider.URI, "", "", extras);
    }

    private void grantClipUriPermission(ClipData clip, int mode, boolean service) {
        Intent grantIntent = new Intent();
        if (clip.getItemCount() == 1) {
            grantIntent.setData(clip.getItemAt(0).getUri());
        } else {
            grantIntent.setClipData(clip);
            // Make this Intent unique from the one that started it.
            for (int i=0; i<clip.getItemCount(); i++) {
                Uri uri = clip.getItemAt(i).getUri();
                if (uri != null) {
                    grantIntent.addCategory(uri.toString());
                }
            }
        }
        grantIntent.addFlags(mode);
        grantIntent.setClass(getContext(),
                service ? ReceiveUriService.class : ReceiveUriActivity.class);
        Intent intent = new Intent();
        intent.setAction(service ? ACTION_START_SERVICE : ACTION_START_ACTIVITY);
        intent.putExtra(EXTRA_INTENT, grantIntent);
        call(intent);
    }

    private void grantClipUriPermissionViaContext(Uri uri, int mode) {
        Intent intent = new Intent();
        intent.setAction(ACTION_GRANT_URI);
        intent.putExtra(EXTRA_PACKAGE_NAME, getContext().getPackageName());
        intent.putExtra(EXTRA_URI, uri);
        intent.putExtra(EXTRA_MODE, mode);
        call(intent);
    }

    private void revokeClipUriPermissionViaContext(Uri uri, int mode) {
        Intent intent = new Intent();
        intent.setAction(ACTION_REVOKE_URI);
        intent.putExtra(EXTRA_URI, uri);
        intent.putExtra(EXTRA_MODE, mode);
        call(intent);
    }

    private void setPrimaryClip(ClipData clip) {
        Intent intent = new Intent();
        intent.setAction(ACTION_SET_PRIMARY_CLIP);
        intent.setClipData(clip);
        call(intent);
    }

    private void clearPrimaryClip() {
        Intent intent = new Intent();
        intent.setAction(ACTION_CLEAR_PRIMARY_CLIP);
        call(intent);
    }

    private void assertReadingClipAllowed(ClipData clip) {
        for (int i=0; i<clip.getItemCount(); i++) {
            ClipData.Item item = clip.getItemAt(i);
            Uri uri = item.getUri();
            if (uri != null) {
                Cursor c = getContext().getContentResolver().query(uri,
                        null, null, null, null);
                if (c != null) {
                    c.close();
                }
            } else {
                Intent intent = item.getIntent();
                uri = intent.getData();
                if (uri != null) {
                    Cursor c = getContext().getContentResolver().query(uri,
                            null, null, null, null);
                    if (c != null) {
                        c.close();
                    }
                }
                ClipData intentClip = intent.getClipData();
                if (intentClip != null) {
                    assertReadingClipAllowed(intentClip);
                }
            }
        }
    }

    private void doTestGrantActivityUriReadPermission(Uri uri, boolean useClip) {
        final Uri subUri = Uri.withAppendedPath(uri, "foo");
        final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
        final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
        final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");

        final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
        final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);

        // Precondition: no current access.
        assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
        assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");

        // --------------------------------

        ReceiveUriActivity.clearStarted();
        grantClipUriPermission(subClip, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
        ReceiveUriActivity.waitForStart();

        // See if we now have access to the provider.
        assertReadingClipAllowed(subClip);

        // But not writing.
        assertWritingClipNotAllowed(subClip, "shouldn't write from granted read");

        // And not to the base path.
        assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");

        // And not to a sub path.
        assertReadingContentUriNotAllowed(subSubUri, "shouldn't read non-granted sub URI");

        // --------------------------------

        ReceiveUriActivity.clearNewIntent();
        grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
        ReceiveUriActivity.waitForNewIntent();

        if (false) {
            synchronized (this) {
                Log.i("**", "******************************* WAITING!!!");
                try {
                    wait(10000);
                } catch (InterruptedException e) {
                }
            }
        }

        // See if we now have access to the provider.
        assertReadingClipAllowed(sub2Clip);

        // And still have access to the original URI.
        assertReadingClipAllowed(subClip);

        // But not writing.
        assertWritingClipNotAllowed(sub2Clip, "shouldn't write from granted read");

        // And not to the base path.
        assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");

        // And not to a sub path.
        assertReadingContentUriNotAllowed(sub2SubUri, "shouldn't read non-granted sub URI");

        // And make sure we can't generate a permission to a running activity.
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(uri, "hah"),
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(uri, "hah"),
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        // --------------------------------

        // Dispose of activity.
        ReceiveUriActivity.finishCurInstanceSync();

        synchronized (this) {
            Log.i("**", "******************************* WAITING!!!");
            try {
                wait(100);
            } catch (InterruptedException e) {
            }
        }

        // Ensure reading no longer allowed.
        assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");
        assertReadingClipNotAllowed(sub2Clip, "shouldn't read after losing granted URI");
    }

    private void assertWritingClipAllowed(ClipData clip) {
        for (int i=0; i<clip.getItemCount(); i++) {
            ClipData.Item item = clip.getItemAt(i);
            Uri uri = item.getUri();
            if (uri != null) {
                getContext().getContentResolver().insert(uri, new ContentValues());
            } else {
                Intent intent = item.getIntent();
                uri = intent.getData();
                if (uri != null) {
                    getContext().getContentResolver().insert(uri, new ContentValues());
                }
                ClipData intentClip = intent.getClipData();
                if (intentClip != null) {
                    assertWritingClipAllowed(intentClip);
                }
            }
        }
    }

    private void doTestGrantActivityUriWritePermission(Uri uri, boolean useClip) {
        final Uri subUri = Uri.withAppendedPath(uri, "foo");
        final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
        final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
        final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");

        final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
        final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);

        // Precondition: no current access.
        assertWritingClipNotAllowed(subClip, "shouldn't write when starting test");
        assertWritingClipNotAllowed(sub2Clip, "shouldn't write when starting test");

        // --------------------------------

        ReceiveUriActivity.clearStarted();
        grantClipUriPermission(subClip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
        ReceiveUriActivity.waitForStart();

        // See if we now have access to the provider.
        assertWritingClipAllowed(subClip);

        // But not reading.
        assertReadingClipNotAllowed(subClip, "shouldn't read from granted write");

        // And not to the base path.
        assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");

        // And not a sub-path.
        assertWritingContentUriNotAllowed(subSubUri, "shouldn't write non-granted sub URI");

        // --------------------------------

        ReceiveUriActivity.clearNewIntent();
        grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
        ReceiveUriActivity.waitForNewIntent();

        if (false) {
            synchronized (this) {
                Log.i("**", "******************************* WAITING!!!");
                try {
                    wait(10000);
                } catch (InterruptedException e) {
                }
            }
        }

        // See if we now have access to the provider.
        assertWritingClipAllowed(sub2Clip);

        // And still have access to the original URI.
        assertWritingClipAllowed(subClip);

        // But not reading.
        assertReadingClipNotAllowed(sub2Clip, "shouldn't read from granted write");

        // And not to the base path.
        assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");

        // And not a sub-path.
        assertWritingContentUriNotAllowed(sub2SubUri, "shouldn't write non-granted sub URI");

        // And make sure we can't generate a permission to a running activity.
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(uri, "hah"),
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(uri, "hah"),
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        // --------------------------------

        // Dispose of activity.
        ReceiveUriActivity.finishCurInstanceSync();

        synchronized (this) {
            Log.i("**", "******************************* WAITING!!!");
            try {
                wait(100);
            } catch (InterruptedException e) {
            }
        }

        // Ensure writing no longer allowed.
        assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");
        assertWritingClipNotAllowed(sub2Clip, "shouldn't write after losing granted URI");
    }

    /**
     * Test that the ctspermissionwithsignaturegranting content provider can grant a read
     * permission.
     */
    public void testGrantReadPermissionFromStartActivity() {
        doTestGrantActivityUriReadPermission(PERM_URI_GRANTING, false);
        doTestGrantActivityUriReadPermission(PERM_URI_GRANTING, true);
    }

    /**
     * Test that the ctspermissionwithsignaturegranting content provider can grant a write
     * permission.
     */
    public void testGrantWritePermissionFromStartActivity() {
        doTestGrantActivityUriWritePermission(PERM_URI_GRANTING, true);
        doTestGrantActivityUriWritePermission(PERM_URI_GRANTING, false);
    }

    /**
     * Test that the ctsprivateprovidergranting content provider can grant a read
     * permission.
     */
    public void testGrantReadPrivateFromStartActivity() {
        doTestGrantActivityUriReadPermission(PRIV_URI_GRANTING, false);
        doTestGrantActivityUriReadPermission(PRIV_URI_GRANTING, true);
    }

    /**
     * Test that the ctsprivateprovidergranting content provider can grant a write
     * permission.
     */
    public void testGrantWritePrivateFromStartActivity() {
        doTestGrantActivityUriWritePermission(PRIV_URI_GRANTING, true);
        doTestGrantActivityUriWritePermission(PRIV_URI_GRANTING, false);
    }

    private void doTestGrantServiceUriReadPermission(Uri uri, boolean useClip) {
        final Uri subUri = Uri.withAppendedPath(uri, "foo");
        final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
        final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
        final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");

        ReceiveUriService.stop(getContext());

        final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
        final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);

        // Precondition: no current access.
        assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
        assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");

        // --------------------------------

        ReceiveUriService.clearStarted();
        grantClipUriPermission(subClip, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
        ReceiveUriService.waitForStart();

        int firstStartId = ReceiveUriService.getCurStartId();

        // See if we now have access to the provider.
        assertReadingClipAllowed(subClip);

        // But not writing.
        assertWritingClipNotAllowed(subClip, "shouldn't write from granted read");

        // And not to the base path.
        assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");

        // And not to a sub path.
        assertReadingContentUriNotAllowed(subSubUri, "shouldn't read non-granted sub URI");

        // --------------------------------

        // Send another Intent to it.
        ReceiveUriService.clearStarted();
        grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
        ReceiveUriService.waitForStart();

        if (false) {
            synchronized (this) {
                Log.i("**", "******************************* WAITING!!!");
                try {
                    wait(10000);
                } catch (InterruptedException e) {
                }
            }
        }

        // See if we now have access to the provider.
        assertReadingClipAllowed(sub2Clip);

        // And still to the previous URI.
        assertReadingClipAllowed(subClip);

        // But not writing.
        assertWritingClipNotAllowed(sub2Clip, "shouldn't write from granted read");

        // And not to the base path.
        assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");

        // And not to a sub path.
        assertReadingContentUriNotAllowed(sub2SubUri, "shouldn't read non-granted sub URI");

        // --------------------------------

        // Stop the first command.
        ReceiveUriService.stopCurWithId(firstStartId);

        // Ensure reading no longer allowed.
        assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");

        // And make sure we can't generate a permission to a running service.
        doTryGrantUriActivityPermissionToSelf(subUri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
        doTryGrantUriActivityPermissionToSelf(subUri,
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        // --------------------------------

        // Dispose of service.
        ReceiveUriService.stopSync(getContext());

        // Ensure reading no longer allowed.
        assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");
        assertReadingClipNotAllowed(sub2Clip, "shouldn't read after losing granted URI");
    }

    private void doTestGrantServiceUriWritePermission(Uri uri, boolean useClip) {
        final Uri subUri = Uri.withAppendedPath(uri, "foo");
        final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
        final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
        final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");

        ReceiveUriService.stop(getContext());

        final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
        final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);

        // Precondition: no current access.
        assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
        assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");

        // --------------------------------

        ReceiveUriService.clearStarted();
        grantClipUriPermission(subClip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
        ReceiveUriService.waitForStart();

        int firstStartId = ReceiveUriService.getCurStartId();

        // See if we now have access to the provider.
        assertWritingClipAllowed(subClip);

        // But not reading.
        assertReadingClipNotAllowed(subClip, "shouldn't read from granted write");

        // And not to the base path.
        assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");

        // And not a sub-path.
        assertWritingContentUriNotAllowed(subSubUri, "shouldn't write non-granted sub URI");

        // --------------------------------

        // Send another Intent to it.
        ReceiveUriService.clearStarted();
        grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
        ReceiveUriService.waitForStart();

        // See if we now have access to the provider.
        assertWritingClipAllowed(sub2Clip);

        // And still to the previous URI.
        assertWritingClipAllowed(subClip);

        // But not reading.
        assertReadingClipNotAllowed(sub2Clip, "shouldn't read from granted write");

        // And not to the base path.
        assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");

        // And not a sub-path.
        assertWritingContentUriNotAllowed(sub2SubUri, "shouldn't write non-granted sub URI");

        if (false) {
            synchronized (this) {
                Log.i("**", "******************************* WAITING!!!");
                try {
                    wait(10000);
                } catch (InterruptedException e) {
                }
            }
        }

        // --------------------------------

        // Stop the first command.
        ReceiveUriService.stopCurWithId(firstStartId);

        // Ensure writing no longer allowed.
        assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");

        // And make sure we can't generate a permission to a running service.
        doTryGrantUriActivityPermissionToSelf(subUri,
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
        doTryGrantUriActivityPermissionToSelf(subUri,
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        // --------------------------------

        // Dispose of service.
        ReceiveUriService.stopSync(getContext());

        // Ensure writing no longer allowed.
        assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");
        assertWritingClipNotAllowed(sub2Clip, "shouldn't write after losing granted URI");
    }

    public void testGrantReadPermissionFromStartService() {
        doTestGrantServiceUriReadPermission(PERM_URI_GRANTING, false);
        doTestGrantServiceUriReadPermission(PERM_URI_GRANTING, true);
    }

    public void testGrantWritePermissionFromStartService() {
        doTestGrantServiceUriWritePermission(PERM_URI_GRANTING, false);
        doTestGrantServiceUriWritePermission(PERM_URI_GRANTING, true);
    }

    public void testGrantReadPrivateFromStartService() {
        doTestGrantServiceUriReadPermission(PRIV_URI_GRANTING, false);
        doTestGrantServiceUriReadPermission(PRIV_URI_GRANTING, true);
    }

    public void testGrantWritePrivateFromStartService() {
        doTestGrantServiceUriWritePermission(PRIV_URI_GRANTING, false);
        doTestGrantServiceUriWritePermission(PRIV_URI_GRANTING, true);
    }

    /**
     * Test that ctspermissionwithsignaturepath can't grant read permissions
     * on paths it doesn't have permission to.
     */
    public void testGrantReadUriActivityPathPermissionToSelf() {
        doTryGrantUriActivityPermissionToSelf(PERM_URI_PATH,
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

    /**
     * Test that ctspermissionwithsignaturepath can't grant write permissions
     * on paths it doesn't have permission to.
     */
    public void testGrantWriteUriActivityPathPermissionToSelf() {
        doTryGrantUriActivityPermissionToSelf(PERM_URI_PATH,
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }

    /**
     * Test that ctspermissionwithsignaturepath can't grant read permissions
     * on paths it doesn't have permission to.
     */
    public void testGrantReadUriActivitySubPathPermissionToSelf() {
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(PERM_URI_PATH, "foo"),
                Intent.FLAG_GRANT_READ_URI_PERMISSION);
    }

    /**
     * Test that ctspermissionwithsignaturepath can't grant write permissions
     * on paths it doesn't have permission to.
     */
    public void testGrantWriteUriActivitySubPathPermissionToSelf() {
        doTryGrantUriActivityPermissionToSelf(
                Uri.withAppendedPath(PERM_URI_PATH, "foo"),
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    }

    /**
     * Test that the ctspermissionwithsignaturepath content provider can grant a read
     * permission.
     */
    public void testGrantReadPathPermissionFromStartActivity() {
        doTestGrantActivityUriReadPermission(PERM_URI_PATH, false);
        doTestGrantActivityUriReadPermission(PERM_URI_PATH, true);
    }

    /**
     * Test that the ctspermissionwithsignaturepath content provider can grant a write
     * permission.
     */
    public void testGrantWritePathPermissionFromStartActivity() {
        doTestGrantActivityUriWritePermission(PERM_URI_PATH, false);
        doTestGrantActivityUriWritePermission(PERM_URI_PATH, true);
    }

    /**
     * Test that the ctspermissionwithsignaturepath content provider can grant a read
     * permission.
     */
    public void testGrantReadPathPermissionFromStartService() {
        doTestGrantServiceUriReadPermission(PERM_URI_PATH, false);
        doTestGrantServiceUriReadPermission(PERM_URI_PATH, true);
    }

    /**
     * Test that the ctspermissionwithsignaturepath content provider can grant a write
     * permission.
     */
    public void testGrantWritePathPermissionFromStartService() {
        doTestGrantServiceUriWritePermission(PERM_URI_PATH, false);
        doTestGrantServiceUriWritePermission(PERM_URI_PATH, true);
    }

    /**
     * Verify that we can access paths outside the {@code path-permission}
     * protections, which should only rely on {@code provider} permissions.
     */
    public void testRestrictingProviderNoMatchingPath() {
        assertReadingContentUriAllowed(PERM_URI_PATH_RESTRICTING);
        assertWritingContentUriAllowed(PERM_URI_PATH_RESTRICTING);

        // allowed by no top-level permission
        final Uri test = PERM_URI_PATH_RESTRICTING.buildUpon().appendPath("fo").build();
        assertReadingContentUriAllowed(test);
        assertWritingContentUriAllowed(test);
    }

    /**
     * Verify that paths under {@code path-permission} restriction aren't
     * allowed, even though the {@code provider} requires no permissions.
     */
    public void testRestrictingProviderMatchingPathDenied() {
        // rejected by "foo" prefix
        final Uri test1 = PERM_URI_PATH_RESTRICTING.buildUpon().appendPath("foo").build();
        assertReadingContentUriNotAllowed(test1, null);
        assertWritingContentUriNotAllowed(test1, null);

        // rejected by "foo" prefix
        final Uri test2 = PERM_URI_PATH_RESTRICTING.buildUpon()
                .appendPath("foo").appendPath("ba").build();
        assertReadingContentUriNotAllowed(test2, null);
        assertWritingContentUriNotAllowed(test2, null);
    }

    /**
     * Test that shady {@link Uri} are blocked by {@code path-permission}.
     */
    public void testRestrictingProviderMatchingShadyPaths() {
        assertContentUriAllowed(
                Uri.parse("content://ctspermissionwithsignaturepathrestricting/"));
        assertContentUriAllowed(
                Uri.parse("content://ctspermissionwithsignaturepathrestricting//"));
        assertContentUriAllowed(
                Uri.parse("content://ctspermissionwithsignaturepathrestricting///"));
        assertContentUriNotAllowed(
                Uri.parse("content://ctspermissionwithsignaturepathrestricting/foo"), null);
        assertContentUriNotAllowed(
                Uri.parse("content://ctspermissionwithsignaturepathrestricting//foo"), null);
        assertContentUriNotAllowed(
                Uri.parse("content://ctspermissionwithsignaturepathrestricting///foo"), null);
        assertContentUriNotAllowed(
                Uri.parse("content://ctspermissionwithsignaturepathrestricting/foo//baz"), null);
    }

    /**
     * Verify that at least one {@code path-permission} rule will grant access,
     * even if the caller doesn't hold another matching {@code path-permission}.
     */
    public void testRestrictingProviderMultipleMatchingPath() {
        // allowed by narrow "foo/bar" prefix
        final Uri test1 = PERM_URI_PATH_RESTRICTING.buildUpon()
                .appendPath("foo").appendPath("bar").build();
        assertReadingContentUriAllowed(test1);
        assertWritingContentUriAllowed(test1);

        // allowed by narrow "foo/bar" prefix
        final Uri test2 = PERM_URI_PATH_RESTRICTING.buildUpon()
                .appendPath("foo").appendPath("bar2").build();
        assertReadingContentUriAllowed(test2);
        assertWritingContentUriAllowed(test2);
    }

    public void testGetMimeTypePermission() {
        // Precondition: no current access.
        assertReadingContentUriNotAllowed(PERM_URI, "shouldn't read when starting test");
        assertWritingContentUriNotAllowed(PERM_URI, "shouldn't write when starting test");
        
        // All apps should be able to get MIME type regardless of permission.
        assertEquals(getContext().getContentResolver().getType(PERM_URI), EXPECTED_MIME_TYPE);
    }

    public void testGetMimeTypePrivate() {
        // Precondition: no current access.
        assertReadingContentUriNotAllowed(PRIV_URI, "shouldn't read when starting test");
        assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write when starting test");
        
        // All apps should be able to get MIME type even if provider is private.
        assertEquals(getContext().getContentResolver().getType(PRIV_URI), EXPECTED_MIME_TYPE);
    }

    public void testGetMimeTypeAmbiguous() {
        // Precondition: no current access.
        assertReadingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't read when starting test");
        assertWritingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't write when starting test");

        // All apps should be able to get MIME type even if provider is private.
        assertEquals(getContext().getContentResolver().getType(AMBIGUOUS_URI), EXPECTED_MIME_TYPE);
    }

    /**
     * Old App Compatibility Test
     *
     * We should be able to access the mime type of a content provider of an older
     * application, even if that application didn't explicitly declare either
     * exported=true or exported=false
     */
    public void testGetMimeTypeAmbiguousCompat() {
        // All apps should be able to get MIME type even if provider is private.
        assertEquals(EXPECTED_MIME_TYPE_AMBIGUOUS,
                getContext().getContentResolver().getType(AMBIGUOUS_URI_COMPAT));
    }

    /**
     * Validate behavior of persistable permission grants.
     */
    public void testGrantPersistableUriPermission() {
        final ContentResolver resolver = getContext().getContentResolver();

        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo");
        final ClipData clip = makeSingleClipData(target);

        // Make sure we can't see the target
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertWritingClipNotAllowed(clip, "writing should have failed");

        // Make sure we can't take a grant we don't have
        try {
            resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
            fail("taking read should have failed");
        } catch (SecurityException expected) {
        }

        // And since we were just installed, no persisted grants yet
        assertNoPersistedUriPermission();

        // Now, let's grant ourselves some access
        ReceiveUriActivity.clearStarted();
        grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
        ReceiveUriActivity.waitForStart();

        // We should now have reading access, even before taking the persistable
        // grant. Persisted grants should still be empty.
        assertReadingClipAllowed(clip);
        assertWritingClipNotAllowed(clip, "writing should have failed");
        assertNoPersistedUriPermission();

        // Take the read grant and verify we have it!
        long before = System.currentTimeMillis();
        resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        long after = System.currentTimeMillis();
        assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);

        // Make sure we can't take a grant we don't have
        try {
            resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            fail("taking write should have failed");
        } catch (SecurityException expected) {
        }

        // Launch again giving ourselves persistable read and write access
        ReceiveUriActivity.clearNewIntent();
        grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
        ReceiveUriActivity.waitForNewIntent();

        // Previous persisted grant should be unchanged
        assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);

        // We should have both read and write; read is persisted, and write
        // isn't persisted yet.
        assertReadingClipAllowed(clip);
        assertWritingClipAllowed(clip);

        // Take again, but still only read; should just update timestamp
        before = System.currentTimeMillis();
        resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        after = System.currentTimeMillis();
        assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);

        // And take yet again, both read and write
        before = System.currentTimeMillis();
        resolver.takePersistableUriPermission(target,
                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        after = System.currentTimeMillis();
        assertPersistedUriPermission(target,
                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
                before, after);

        // Now drop the persisted grant; write first, then read
        resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        assertPersistedUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after);
        resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        assertNoPersistedUriPermission();

        // And even though we dropped the persistable grants, our activity is
        // still running with the global grants (until reboot).
        assertReadingClipAllowed(clip);
        assertWritingClipAllowed(clip);

        ReceiveUriActivity.finishCurInstanceSync();
    }

    private void assertNoPersistedUriPermission() {
        assertPersistedUriPermission(null, 0, -1, -1);
    }

    private void assertPersistedUriPermission(Uri uri, int flags, long before, long after) {
        // Assert local
        final List<UriPermission> perms = getContext()
                .getContentResolver().getPersistedUriPermissions();
        if (uri != null) {
            assertEquals("expected exactly one permission", 1, perms.size());

            final UriPermission perm = perms.get(0);
            assertEquals("unexpected uri", uri, perm.getUri());

            final long actual = perm.getPersistedTime();
            if (before != -1) {
                assertTrue("found " + actual + " before " + before, actual >= before);
            }
            if (after != -1) {
                assertTrue("found " + actual + " after " + after, actual <= after);
            }

            final boolean expectedRead = (flags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0;
            final boolean expectedWrite = (flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0;
            assertEquals("unexpected read status", expectedRead, perm.isReadPermission());
            assertEquals("unexpected write status", expectedWrite, perm.isWritePermission());

        } else {
            assertEquals("expected zero permissions", 0, perms.size());
        }

        // And assert remote
        Intent intent = new Intent();
        intent.setAction(ACTION_VERIFY_OUTGOING_PERSISTED);
        intent.putExtra(EXTRA_URI, uri);
        call(intent);
    }

    /**
     * Validate behavior of prefix permission grants.
     */
    public void testGrantPrefixUriPermission() throws Exception {
        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo1");
        final Uri targetMeow = Uri.withAppendedPath(target, "meow");
        final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");

        final ClipData clip = makeSingleClipData(target);
        final ClipData clipMeow = makeSingleClipData(targetMeow);
        final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);

        // Make sure we can't see the target
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertWritingClipNotAllowed(clip, "writing should have failed");

        // Give ourselves prefix read access
        ReceiveUriActivity.clearStarted();
        grantClipUriPermission(clipMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
        ReceiveUriActivity.waitForStart();

        // Verify prefix read access
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertReadingClipAllowed(clipMeow);
        assertReadingClipAllowed(clipMeowCat);
        assertWritingClipNotAllowed(clip, "writing should have failed");
        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");

        // Now give ourselves exact write access
        ReceiveUriActivity.clearNewIntent();
        grantClipUriPermission(clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
        ReceiveUriActivity.waitForNewIntent();

        // Verify we have exact write access, but not prefix write
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertReadingClipAllowed(clipMeow);
        assertReadingClipAllowed(clipMeowCat);
        assertWritingClipAllowed(clip);
        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");

        ReceiveUriActivity.finishCurInstanceSync();
    }

    public void testGrantPersistablePrefixUriPermission() {
        final ContentResolver resolver = getContext().getContentResolver();

        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo2");
        final Uri targetMeow = Uri.withAppendedPath(target, "meow");

        final ClipData clip = makeSingleClipData(target);
        final ClipData clipMeow = makeSingleClipData(targetMeow);

        // Make sure we can't see the target
        assertReadingClipNotAllowed(clip, "reading should have failed");

        // Give ourselves prefix read access
        ReceiveUriActivity.clearStarted();
        grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
        ReceiveUriActivity.waitForStart();

        // Verify prefix read access
        assertReadingClipAllowed(clip);
        assertReadingClipAllowed(clipMeow);

        // Verify we can persist direct grant
        long before = System.currentTimeMillis();
        resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        long after = System.currentTimeMillis();
        assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);

        // But we can't take anywhere under the prefix
        try {
            resolver.takePersistableUriPermission(targetMeow,
                    Intent.FLAG_GRANT_READ_URI_PERMISSION);
            fail("taking under prefix should have failed");
        } catch (SecurityException expected) {
        }

        // Should still have access regardless of taking
        assertReadingClipAllowed(clip);
        assertReadingClipAllowed(clipMeow);

        // And clean up our grants
        resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        assertNoPersistedUriPermission();

        ReceiveUriActivity.finishCurInstanceSync();
    }

    /**
     * Validate behavior of directly granting/revoking permission grants.
     */
    public void testDirectGrantRevokeUriPermission() throws Exception {
        final ContentResolver resolver = getContext().getContentResolver();

        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo3");
        final Uri targetMeow = Uri.withAppendedPath(target, "meow");
        final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");

        final ClipData clip = makeSingleClipData(target);
        final ClipData clipMeow = makeSingleClipData(targetMeow);
        final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);

        // Make sure we can't see the target
        assertReadingClipNotAllowed(clipMeow, "reading should have failed");
        assertWritingClipNotAllowed(clipMeow, "writing should have failed");

        // Give ourselves some grants:
        // /meow/cat  WRITE|PERSISTABLE
        // /meow      READ|PREFIX
        // /meow      WRITE
        grantClipUriPermissionViaContext(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
        grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
        grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        long before = System.currentTimeMillis();
        resolver.takePersistableUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        long after = System.currentTimeMillis();
        assertPersistedUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after);

        // Verify they look good
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertReadingClipAllowed(clipMeow);
        assertReadingClipAllowed(clipMeowCat);
        assertWritingClipNotAllowed(clip, "writing should have failed");
        assertWritingClipAllowed(clipMeow);
        assertWritingClipAllowed(clipMeowCat);

        // Revoke anyone with write under meow
        revokeClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        // This should have nuked persisted permission at lower level, but it
        // shoulnd't have touched our prefix read.
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertReadingClipAllowed(clipMeow);
        assertReadingClipAllowed(clipMeowCat);
        assertWritingClipNotAllowed(clip, "writing should have failed");
        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
        assertNoPersistedUriPermission();

        // Revoking read at top of tree should nuke everything else
        revokeClipUriPermissionViaContext(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertReadingClipNotAllowed(clipMeow, "reading should have failed");
        assertReadingClipNotAllowed(clipMeowCat, "reading should have failed");
        assertWritingClipNotAllowed(clip, "writing should have failed");
        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
        assertNoPersistedUriPermission();
    }

    /**
     * Validate behavior of a direct permission grant, where the receiver of
     * that permission revokes it.
     */
    public void testDirectGrantReceiverRevokeUriPermission() throws Exception {
        final ContentResolver resolver = getContext().getContentResolver();

        final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo3");
        final Uri targetMeow = Uri.withAppendedPath(target, "meow");
        final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");

        final ClipData clip = makeSingleClipData(target);
        final ClipData clipMeow = makeSingleClipData(targetMeow);
        final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);

        // Make sure we can't see the target
        assertReadingClipNotAllowed(clipMeow, "reading should have failed");
        assertWritingClipNotAllowed(clipMeow, "writing should have failed");

        // Give ourselves some grants:
        // /meow/cat  WRITE|PERSISTABLE
        // /meow      READ|PREFIX
        // /meow      WRITE
        grantClipUriPermissionViaContext(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
        grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
                | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
        grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        long before = System.currentTimeMillis();
        resolver.takePersistableUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        long after = System.currentTimeMillis();
        assertPersistedUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after);

        // Verify they look good
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertReadingClipAllowed(clipMeow);
        assertReadingClipAllowed(clipMeowCat);
        assertWritingClipNotAllowed(clip, "writing should have failed");
        assertWritingClipAllowed(clipMeow);
        assertWritingClipAllowed(clipMeowCat);

        // Revoke anyone with write under meow
        getContext().revokeUriPermission(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        // This should have nuked persisted permission at lower level, but it
        // shoulnd't have touched our prefix read.
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertReadingClipAllowed(clipMeow);
        assertReadingClipAllowed(clipMeowCat);
        assertWritingClipNotAllowed(clip, "writing should have failed");
        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
        assertNoPersistedUriPermission();

        // Revoking read at top of tree should nuke everything else
        getContext().revokeUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        assertReadingClipNotAllowed(clip, "reading should have failed");
        assertReadingClipNotAllowed(clipMeow, "reading should have failed");
        assertReadingClipNotAllowed(clipMeowCat, "reading should have failed");
        assertWritingClipNotAllowed(clip, "writing should have failed");
        assertWritingClipNotAllowed(clipMeow, "writing should have failed");
        assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
        assertNoPersistedUriPermission();
    }

    public void testClipboardWithPermission() throws Exception {
        for (Uri target : GRANTABLE) {
            final ClipData clip = makeSingleClipData(target);

            // Normally we can't see the underlying clip data
            assertReadingClipNotAllowed(clip);
            assertWritingClipNotAllowed(clip);

            // But if someone puts it on the clipboard, we can read it
            setPrimaryClip(clip);
            final ClipData clipFromClipboard = getContext().getSystemService(ClipboardManager.class)
                    .getPrimaryClip();
            assertClipDataEquals(clip, clipFromClipboard);
            assertReadingClipAllowed(clipFromClipboard);
            assertWritingClipNotAllowed(clipFromClipboard);

            // And if clipboard is cleared, we lose access
            clearPrimaryClip();
            assertReadingClipNotAllowed(clipFromClipboard);
            assertWritingClipNotAllowed(clipFromClipboard);
        }
    }

    public void testClipboardWithoutPermission() throws Exception {
        for (Uri target : NOT_GRANTABLE) {
            final ClipData clip = makeSingleClipData(target);

            // Can't see it directly
            assertReadingClipNotAllowed(clip);
            assertWritingClipNotAllowed(clip);

            // Can't put on clipboard if we don't own it
            try {
                setPrimaryClip(clip);
                fail("Unexpected ability to put protected data " + clip + " on clipboard!");
            } catch (Exception expected) {
            }
        }
    }

    private static void assertClipDataEquals(ClipData expected, ClipData actual) {
        assertEquals(expected.getItemCount(), actual.getItemCount());
        for (int i = 0; i < expected.getItemCount(); i++) {
            final ClipData.Item expectedItem = expected.getItemAt(i);
            final ClipData.Item actualItem = actual.getItemAt(i);
            assertEquals(expectedItem.getText(), actualItem.getText());
            assertEquals(expectedItem.getHtmlText(), actualItem.getHtmlText());
            assertEquals(expectedItem.getIntent(), actualItem.getIntent());
            assertEquals(expectedItem.getUri(), actualItem.getUri());
        }
    }
}
