1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts.usespermissiondiffcertapp;
18 
19 import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_CLEAR_PRIMARY_CLIP;
20 import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_GRANT_URI;
21 import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_REVOKE_URI;
22 import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_SET_PRIMARY_CLIP;
23 import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_START_ACTIVITY;
24 import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_START_SERVICE;
25 import static com.android.cts.permissiondeclareapp.UtilsProvider.ACTION_VERIFY_OUTGOING_PERSISTED;
26 import static com.android.cts.permissiondeclareapp.UtilsProvider.EXTRA_INTENT;
27 import static com.android.cts.permissiondeclareapp.UtilsProvider.EXTRA_MODE;
28 import static com.android.cts.permissiondeclareapp.UtilsProvider.EXTRA_PACKAGE_NAME;
29 import static com.android.cts.permissiondeclareapp.UtilsProvider.EXTRA_URI;
30 
31 import android.content.ClipData;
32 import android.content.ClipboardManager;
33 import android.content.ContentResolver;
34 import android.content.ContentValues;
35 import android.content.Intent;
36 import android.content.UriPermission;
37 import android.database.Cursor;
38 import android.net.Uri;
39 import android.os.Bundle;
40 import android.provider.CalendarContract;
41 import android.provider.ContactsContract;
42 import android.test.AndroidTestCase;
43 import android.util.Log;
44 
45 import androidx.test.InstrumentationRegistry;
46 
47 import com.android.cts.permissiondeclareapp.UtilsProvider;
48 
49 import java.io.IOException;
50 import java.util.List;
51 
52 /**
53  * Tests that signature-enforced permissions cannot be accessed by apps signed
54  * with different certs than app that declares the permission.
55  *
56  * Accesses app cts/tests/appsecurity-tests/test-apps/PermissionDeclareApp/...
57  */
58 public class AccessPermissionWithDiffSigTest extends AndroidTestCase {
59     private static final Uri PERM_URI = Uri.parse("content://ctspermissionwithsignature");
60     private static final Uri PERM_URI_GRANTING = Uri.parse("content://ctspermissionwithsignaturegranting");
61     private static final Uri PERM_URI_PATH = Uri.parse("content://ctspermissionwithsignaturepath");
62     private static final Uri PERM_URI_PATH_RESTRICTING = Uri.parse(
63             "content://ctspermissionwithsignaturepathrestricting");
64     private static final Uri PRIV_URI = Uri.parse("content://ctsprivateprovider");
65     private static final Uri PRIV_URI_GRANTING = Uri.parse("content://ctsprivateprovidergranting");
66     private static final String EXPECTED_MIME_TYPE = "got/theMIME";
67 
68     private static final Uri AMBIGUOUS_URI_COMPAT = Uri.parse("content://ctsambiguousprovidercompat");
69     private static final String EXPECTED_MIME_TYPE_AMBIGUOUS = "got/theUnspecifiedMIME";
70     private static final Uri AMBIGUOUS_URI = Uri.parse("content://ctsambiguousprovider");
71 
72     private static final Uri[] GRANTABLE = new Uri[] {
73             Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
74             Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
75             Uri.withAppendedPath(PERM_URI_PATH, "foo"),
76     };
77 
78     private static final Uri[] NOT_GRANTABLE = new Uri[] {
79             Uri.withAppendedPath(PERM_URI, "foo"),
80             Uri.withAppendedPath(PRIV_URI, "foo"),
81             Uri.withAppendedPath(PERM_URI_PATH_RESTRICTING, "foo"),
82             CalendarContract.CONTENT_URI,
83             ContactsContract.AUTHORITY_URI,
84     };
85 
86     @Override
tearDown()87     protected void tearDown() throws Exception {
88         super.tearDown();
89 
90         // Always dispose, usually to clean up from failed tests
91         ReceiveUriActivity.finishCurInstanceSync();
92     }
93 
assertReadingContentUriNotAllowed(Uri uri, String msg)94     private void assertReadingContentUriNotAllowed(Uri uri, String msg) {
95         try {
96             getContext().getContentResolver().query(uri, null, null, null, null);
97             fail("expected SecurityException reading " + uri + ": " + msg);
98         } catch (SecurityException expected) {
99             assertNotNull("security exception's error message.", expected.getMessage());
100         }
101     }
102 
assertReadingContentUriAllowed(Uri uri)103     private void assertReadingContentUriAllowed(Uri uri) {
104         try {
105             getContext().getContentResolver().query(uri, null, null, null, null);
106         } catch (SecurityException e) {
107             fail("unexpected SecurityException reading " + uri + ": " + e.getMessage());
108         }
109     }
110 
assertReadingClipNotAllowed(ClipData clip)111     private void assertReadingClipNotAllowed(ClipData clip) {
112         assertReadingClipNotAllowed(clip, null);
113     }
114 
assertReadingClipNotAllowed(ClipData clip, String msg)115     private void assertReadingClipNotAllowed(ClipData clip, String msg) {
116         for (int i=0; i<clip.getItemCount(); i++) {
117             ClipData.Item item = clip.getItemAt(i);
118             Uri uri = item.getUri();
119             if (uri != null) {
120                 assertReadingContentUriNotAllowed(uri, msg);
121             } else {
122                 Intent intent = item.getIntent();
123                 uri = intent.getData();
124                 if (uri != null) {
125                     assertReadingContentUriNotAllowed(uri, msg);
126                 }
127                 ClipData intentClip = intent.getClipData();
128                 if (intentClip != null) {
129                     assertReadingClipNotAllowed(intentClip, msg);
130                 }
131             }
132         }
133     }
134 
assertOpenFileDescriptorModeNotAllowed(Uri uri, String msg, String mode)135     private void assertOpenFileDescriptorModeNotAllowed(Uri uri, String msg, String mode) {
136         try {
137             getContext().getContentResolver().openFileDescriptor(uri, mode).close();
138             fail("expected SecurityException writing " + uri + ": " + msg);
139         } catch (IOException e) {
140             throw new IllegalStateException(e);
141         } catch (SecurityException expected) {
142             assertNotNull("security exception's error message.", expected.getMessage());
143         }
144     }
145 
assertContentUriAllowed(Uri uri)146     private void assertContentUriAllowed(Uri uri) {
147         assertReadingContentUriAllowed(uri);
148         assertWritingContentUriAllowed(uri);
149     }
150 
assertContentUriNotAllowed(Uri uri, String msg)151     private void assertContentUriNotAllowed(Uri uri, String msg) {
152         assertReadingContentUriNotAllowed(uri, msg);
153         assertWritingContentUriNotAllowed(uri, msg);
154     }
155 
assertWritingContentUriNotAllowed(Uri uri, String msg)156     private void assertWritingContentUriNotAllowed(Uri uri, String msg) {
157         final ContentResolver resolver = getContext().getContentResolver();
158         try {
159             resolver.insert(uri, new ContentValues());
160             fail("expected SecurityException inserting " + uri + ": " + msg);
161         } catch (SecurityException expected) {
162             assertNotNull("security exception's error message.", expected.getMessage());
163         }
164 
165         try {
166             resolver.update(uri, new ContentValues(), null, null);
167             fail("expected SecurityException updating " + uri + ": " + msg);
168         } catch (SecurityException expected) {
169             assertNotNull("security exception's error message.", expected.getMessage());
170         }
171 
172         try {
173             resolver.delete(uri, null, null);
174             fail("expected SecurityException deleting " + uri + ": " + msg);
175         } catch (SecurityException expected) {
176             assertNotNull("security exception's error message.", expected.getMessage());
177         }
178 
179         try {
180             getContext().getContentResolver().openOutputStream(uri).close();
181             fail("expected SecurityException writing " + uri + ": " + msg);
182         } catch (IOException e) {
183             throw new IllegalStateException(e);
184         } catch (SecurityException expected) {
185             assertNotNull("security exception's error message.", expected.getMessage());
186         }
187 
188         assertOpenFileDescriptorModeNotAllowed(uri, msg, "w");
189         assertOpenFileDescriptorModeNotAllowed(uri, msg, "wt");
190         assertOpenFileDescriptorModeNotAllowed(uri, msg, "wa");
191         assertOpenFileDescriptorModeNotAllowed(uri, msg, "rw");
192         assertOpenFileDescriptorModeNotAllowed(uri, msg, "rwt");
193     }
194 
assertWritingContentUriAllowed(Uri uri)195     private void assertWritingContentUriAllowed(Uri uri) {
196         final ContentResolver resolver = getContext().getContentResolver();
197         try {
198             resolver.insert(uri, new ContentValues());
199             resolver.update(uri, new ContentValues(), null, null);
200             resolver.delete(uri, null, null);
201 
202             resolver.openOutputStream(uri).close();
203             resolver.openFileDescriptor(uri, "w").close();
204             resolver.openFileDescriptor(uri, "wt").close();
205             resolver.openFileDescriptor(uri, "wa").close();
206             resolver.openFileDescriptor(uri, "rw").close();
207             resolver.openFileDescriptor(uri, "rwt").close();
208         } catch (IOException e) {
209             fail("unexpected IOException writing " + uri + ": " + e.getMessage());
210         } catch (SecurityException e) {
211             fail("unexpected SecurityException writing " + uri + ": " + e.getMessage());
212         }
213     }
214 
assertWritingClipNotAllowed(ClipData clip)215     private void assertWritingClipNotAllowed(ClipData clip) {
216         assertWritingClipNotAllowed(clip, null);
217     }
218 
assertWritingClipNotAllowed(ClipData clip, String msg)219     private void assertWritingClipNotAllowed(ClipData clip, String msg) {
220         for (int i=0; i<clip.getItemCount(); i++) {
221             ClipData.Item item = clip.getItemAt(i);
222             Uri uri = item.getUri();
223             if (uri != null) {
224                 assertWritingContentUriNotAllowed(uri, msg);
225             } else {
226                 Intent intent = item.getIntent();
227                 uri = intent.getData();
228                 if (uri != null) {
229                     assertWritingContentUriNotAllowed(uri, msg);
230                 }
231                 ClipData intentClip = intent.getClipData();
232                 if (intentClip != null) {
233                     assertWritingClipNotAllowed(intentClip, msg);
234                 }
235             }
236         }
237     }
238 
239     /**
240      * Test that the ctspermissionwithsignature content provider cannot be read,
241      * since this app lacks the required certs
242      */
testReadProviderWithDiff()243     public void testReadProviderWithDiff() {
244         assertReadingContentUriRequiresPermission(PERM_URI,
245                 "com.android.cts.permissionWithSignature");
246     }
247 
248     /**
249      * Test that the ctspermissionwithsignature content provider cannot be written,
250      * since this app lacks the required certs
251      */
testWriteProviderWithDiff()252     public void testWriteProviderWithDiff() {
253         assertWritingContentUriRequiresPermission(PERM_URI,
254                 "com.android.cts.permissionWithSignature");
255     }
256 
257     /**
258      * Test that the ctsprivateprovider content provider cannot be read,
259      * since it is not exported from its app.
260      */
testReadProviderWhenPrivate()261     public void testReadProviderWhenPrivate() {
262         assertReadingContentUriNotAllowed(PRIV_URI, "shouldn't read private provider");
263     }
264 
265     /**
266      * Test that the ctsambiguousprovider content provider cannot be read,
267      * since it doesn't have an "exported=" line.
268      */
testReadProviderWhenAmbiguous()269     public void testReadProviderWhenAmbiguous() {
270         assertReadingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't read ambiguous provider");
271     }
272 
273     /**
274      * Old App Compatibility Test
275      *
276      * Test that the ctsambiguousprovidercompat content provider can be read for older
277      * API versions, because it didn't specify either exported=true or exported=false.
278      */
testReadProviderWhenAmbiguousCompat()279     public void testReadProviderWhenAmbiguousCompat() {
280         assertReadingContentUriAllowed(AMBIGUOUS_URI_COMPAT);
281     }
282 
283     /**
284      * Old App Compatibility Test
285      *
286      * Test that the ctsambiguousprovidercompat content provider can be written for older
287      * API versions, because it didn't specify either exported=true or exported=false.
288      */
testWriteProviderWhenAmbiguousCompat()289     public void testWriteProviderWhenAmbiguousCompat() {
290         assertWritingContentUriAllowed(AMBIGUOUS_URI_COMPAT);
291     }
292 
293     /**
294      * Test that the ctsprivateprovider content provider cannot be written,
295      * since it is not exported from its app.
296      */
testWriteProviderWhenPrivate()297     public void testWriteProviderWhenPrivate() {
298         assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write private provider");
299     }
300 
301     /**
302      * Test that the ctsambiguousprovider content provider cannot be written,
303      * since it doesn't have an exported= line.
304      */
testWriteProviderWhenAmbiguous()305     public void testWriteProviderWhenAmbiguous() {
306         assertWritingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't write ambiguous provider");
307     }
308 
makeSingleClipData(Uri uri)309     private static ClipData makeSingleClipData(Uri uri) {
310         return new ClipData("foo", new String[] { "foo/bar" },
311                 new ClipData.Item(uri));
312     }
313 
makeMultiClipData(Uri uri)314     private static ClipData makeMultiClipData(Uri uri) {
315         Uri grantClip1Uri = Uri.withAppendedPath(uri, "clip1");
316         Uri grantClip2Uri = Uri.withAppendedPath(uri, "clip2");
317         Uri grantClip3Uri = Uri.withAppendedPath(uri, "clip3");
318         Uri grantClip4Uri = Uri.withAppendedPath(uri, "clip4");
319         Uri grantClip5Uri = Uri.withAppendedPath(uri, "clip5");
320         ClipData clip = new ClipData("foo", new String[] { "foo/bar" },
321                 new ClipData.Item(grantClip1Uri));
322         clip.addItem(new ClipData.Item(grantClip2Uri));
323         // Intents in the ClipData should allow their data: and clip URIs
324         // to be granted, but only respect the grant flags of the top-level
325         // Intent.
326         clip.addItem(new ClipData.Item(new Intent(Intent.ACTION_VIEW, grantClip3Uri)));
327         Intent intent = new Intent(Intent.ACTION_VIEW, grantClip4Uri);
328         intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
329                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
330         clip.addItem(new ClipData.Item(intent));
331         intent = new Intent(Intent.ACTION_VIEW);
332         intent.setClipData(new ClipData("foo", new String[] { "foo/bar" },
333                 new ClipData.Item(grantClip5Uri)));
334         clip.addItem(new ClipData.Item(intent));
335         return clip;
336     }
337 
makeClipIntent(ClipData clip, int flags)338     private static Intent makeClipIntent(ClipData clip, int flags) {
339         Intent intent = new Intent();
340         intent.setClipData(clip);
341         intent.addFlags(flags);
342         return intent;
343     }
344 
makeClipIntent(Uri uri, int flags)345     private static Intent makeClipIntent(Uri uri, int flags) {
346         return makeClipIntent(makeMultiClipData(uri), flags);
347     }
348 
doTryGrantUriActivityPermissionToSelf(Uri uri, int mode)349     private void doTryGrantUriActivityPermissionToSelf(Uri uri, int mode) {
350         Uri grantDataUri = Uri.withAppendedPath(uri, "data");
351         Intent grantIntent = new Intent();
352         grantIntent.setData(grantDataUri);
353         grantIntent.addFlags(mode | Intent.FLAG_ACTIVITY_NEW_TASK);
354         grantIntent.setClass(getContext(), ReceiveUriActivity.class);
355         try {
356             ReceiveUriActivity.clearStarted();
357             getContext().startActivity(grantIntent);
358             ReceiveUriActivity.waitForStart();
359             fail("expected SecurityException granting " + grantDataUri + " to activity");
360         } catch (SecurityException e) {
361             // This is what we want.
362         }
363 
364         grantIntent = makeClipIntent(uri, mode | Intent.FLAG_ACTIVITY_NEW_TASK);
365         grantIntent.setClass(getContext(), ReceiveUriActivity.class);
366         try {
367             ReceiveUriActivity.clearStarted();
368             getContext().startActivity(grantIntent);
369             ReceiveUriActivity.waitForStart();
370             fail("expected SecurityException granting " + grantIntent.getClipData() + " to activity");
371         } catch (SecurityException e) {
372             // This is what we want.
373         }
374     }
375 
376     /**
377      * Test that we can't grant a permission to ourself.
378      */
testGrantReadUriActivityPermissionToSelf()379     public void testGrantReadUriActivityPermissionToSelf() {
380         doTryGrantUriActivityPermissionToSelf(
381                 Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
382                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
383     }
384 
385     /**
386      * Test that we can't grant a permission to ourself.
387      */
testGrantWriteUriActivityPermissionToSelf()388     public void testGrantWriteUriActivityPermissionToSelf() {
389         doTryGrantUriActivityPermissionToSelf(
390                 Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
391                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
392     }
393 
394     /**
395      * Test that we can't grant a permission to ourself.
396      */
testGrantReadUriActivityPrivateToSelf()397     public void testGrantReadUriActivityPrivateToSelf() {
398         doTryGrantUriActivityPermissionToSelf(
399                 Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
400                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
401     }
402 
403     /**
404      * Test that we can't grant a permission to ourself.
405      */
testGrantWriteUriActivityPrivateToSelf()406     public void testGrantWriteUriActivityPrivateToSelf() {
407         doTryGrantUriActivityPermissionToSelf(
408                 Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
409                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
410     }
411 
doTryGrantUriServicePermissionToSelf(Uri uri, int mode)412     private void doTryGrantUriServicePermissionToSelf(Uri uri, int mode) {
413         Uri grantDataUri = Uri.withAppendedPath(uri, "data");
414         Intent grantIntent = new Intent();
415         grantIntent.setData(grantDataUri);
416         grantIntent.addFlags(mode);
417         grantIntent.setClass(getContext(), ReceiveUriService.class);
418         try {
419             getContext().startService(grantIntent);
420             fail("expected SecurityException granting " + grantDataUri + " to service");
421         } catch (SecurityException e) {
422             // This is what we want.
423         }
424 
425         grantIntent = makeClipIntent(uri, mode);
426         grantIntent.setClass(getContext(), ReceiveUriService.class);
427         try {
428             getContext().startService(grantIntent);
429             fail("expected SecurityException granting " + grantIntent.getClipData() + " to service");
430         } catch (SecurityException e) {
431             // This is what we want.
432         }
433     }
434 
435     /**
436      * Test that we can't grant a permission to ourself.
437      */
testGrantReadUriServicePermissionToSelf()438     public void testGrantReadUriServicePermissionToSelf() {
439         doTryGrantUriServicePermissionToSelf(
440                 Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
441                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
442     }
443 
444     /**
445      * Test that we can't grant a permission to ourself.
446      */
testGrantWriteUriServicePermissionToSelf()447     public void testGrantWriteUriServicePermissionToSelf() {
448         doTryGrantUriServicePermissionToSelf(
449                 Uri.withAppendedPath(PERM_URI_GRANTING, "foo"),
450                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
451     }
452 
453     /**
454      * Test that we can't grant a permission to ourself.
455      */
testGrantReadUriServicePrivateToSelf()456     public void testGrantReadUriServicePrivateToSelf() {
457         doTryGrantUriServicePermissionToSelf(
458                 Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
459                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
460     }
461 
462     /**
463      * Test that we can't grant a permission to ourself.
464      */
testGrantWriteUriServicePrivateToSelf()465     public void testGrantWriteUriServicePrivateToSelf() {
466         doTryGrantUriServicePermissionToSelf(
467                 Uri.withAppendedPath(PRIV_URI_GRANTING, "foo"),
468                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
469     }
470 
grantUriPermissionFail(Uri uri, int mode, boolean service)471     private void grantUriPermissionFail(Uri uri, int mode, boolean service) {
472         Uri grantDataUri = Uri.withAppendedPath(uri, "data");
473         Intent grantIntent = new Intent();
474         grantIntent.setData(grantDataUri);
475         grantIntent.addFlags(mode);
476         grantIntent.setClass(getContext(),
477                 service ? ReceiveUriService.class : ReceiveUriActivity.class);
478         Intent intent = new Intent();
479         intent.setAction(service ? ACTION_START_SERVICE : ACTION_START_ACTIVITY);
480         intent.putExtra(EXTRA_INTENT, grantIntent);
481         try {
482             call(intent);
483             fail("Able to grant URI permission to " + grantDataUri + " when should not");
484         } catch (Exception expected) {
485         }
486 
487         grantIntent = makeClipIntent(uri, mode);
488         grantIntent.setClass(getContext(),
489                 service ? ReceiveUriService.class : ReceiveUriActivity.class);
490         intent = new Intent();
491         intent.setAction(service ? ACTION_START_SERVICE : ACTION_START_ACTIVITY);
492         intent.putExtra(EXTRA_INTENT, grantIntent);
493         try {
494             call(intent);
495             fail("Able to grant URI permission to " + grantIntent.getClipData()
496                     + " when should not");
497         } catch (Exception expected) {
498         }
499     }
500 
doTestGrantUriPermissionFail(Uri uri)501     private void doTestGrantUriPermissionFail(Uri uri) {
502         for (boolean service : new boolean[] { false, true }) {
503             for (int flags : new int[] {
504                     Intent.FLAG_GRANT_READ_URI_PERMISSION, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
505             }) {
506                 grantUriPermissionFail(uri,
507                         flags, service);
508                 grantUriPermissionFail(uri,
509                         flags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, service);
510                 grantUriPermissionFail(uri,
511                         flags | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, service);
512             }
513         }
514     }
515 
516     /**
517      * Test that the ctspermissionwithsignature content provider can not grant
518      * URI permissions to others.
519      */
testGrantPermissionNonGrantingFail()520     public void testGrantPermissionNonGrantingFail() {
521         doTestGrantUriPermissionFail(PERM_URI);
522     }
523 
524     /**
525      * Test that the ctspermissionwithsignaturegranting content provider can not grant
526      * URI permissions to paths outside of the grant tree
527      */
testGrantPermissionOutsideGrantingFail()528     public void testGrantPermissionOutsideGrantingFail() {
529         doTestGrantUriPermissionFail(PERM_URI_GRANTING);
530         doTestGrantUriPermissionFail(Uri.withAppendedPath(PERM_URI_GRANTING, "invalid"));
531     }
532 
533     /**
534      * Test that the ctsprivateprovider content provider can not grant
535      * URI permissions to others.
536      */
testGrantPrivateNonGrantingFail()537     public void testGrantPrivateNonGrantingFail() {
538         doTestGrantUriPermissionFail(PRIV_URI);
539     }
540 
541     /**
542      * Test that the ctsambiguousprovider content provider can not grant
543      * URI permissions to others.
544      */
testGrantAmbiguousNonGrantingFail()545     public void testGrantAmbiguousNonGrantingFail() {
546         doTestGrantUriPermissionFail(AMBIGUOUS_URI);
547     }
548 
549     /**
550      * Test that the ctsprivateprovidergranting content provider can not grant
551      * URI permissions to paths outside of the grant tree
552      */
testGrantPrivateOutsideGrantingFail()553     public void testGrantPrivateOutsideGrantingFail() {
554         doTestGrantUriPermissionFail(PRIV_URI_GRANTING);
555         doTestGrantUriPermissionFail(Uri.withAppendedPath(PRIV_URI_GRANTING, "invalid"));
556     }
557 
call(Intent intent)558     private void call(Intent intent) {
559         final Bundle extras = new Bundle();
560         extras.putParcelable(Intent.EXTRA_INTENT, intent);
561         getContext().getContentResolver().call(UtilsProvider.URI, "", "", extras);
562     }
563 
grantClipUriPermission(ClipData clip, int mode, boolean service)564     private void grantClipUriPermission(ClipData clip, int mode, boolean service) {
565         Intent grantIntent = new Intent();
566         if (clip.getItemCount() == 1) {
567             grantIntent.setData(clip.getItemAt(0).getUri());
568         } else {
569             grantIntent.setClipData(clip);
570             // Make this Intent unique from the one that started it.
571             for (int i=0; i<clip.getItemCount(); i++) {
572                 Uri uri = clip.getItemAt(i).getUri();
573                 if (uri != null) {
574                     grantIntent.addCategory(uri.toString());
575                 }
576             }
577         }
578         grantIntent.addFlags(mode);
579         grantIntent.setClass(getContext(),
580                 service ? ReceiveUriService.class : ReceiveUriActivity.class);
581         Intent intent = new Intent();
582         intent.setAction(service ? ACTION_START_SERVICE : ACTION_START_ACTIVITY);
583         intent.putExtra(EXTRA_INTENT, grantIntent);
584         call(intent);
585     }
586 
grantClipUriPermissionViaContext(Uri uri, int mode)587     private void grantClipUriPermissionViaContext(Uri uri, int mode) {
588         Intent intent = new Intent();
589         intent.setAction(ACTION_GRANT_URI);
590         intent.putExtra(EXTRA_PACKAGE_NAME, getContext().getPackageName());
591         intent.putExtra(EXTRA_URI, uri);
592         intent.putExtra(EXTRA_MODE, mode);
593         call(intent);
594     }
595 
revokeClipUriPermissionViaContext(Uri uri, int mode)596     private void revokeClipUriPermissionViaContext(Uri uri, int mode) {
597         Intent intent = new Intent();
598         intent.setAction(ACTION_REVOKE_URI);
599         intent.putExtra(EXTRA_URI, uri);
600         intent.putExtra(EXTRA_MODE, mode);
601         call(intent);
602     }
603 
setPrimaryClip(ClipData clip)604     private void setPrimaryClip(ClipData clip) {
605         Intent intent = new Intent();
606         intent.setAction(ACTION_SET_PRIMARY_CLIP);
607         intent.setClipData(clip);
608         call(intent);
609     }
610 
clearPrimaryClip()611     private void clearPrimaryClip() {
612         Intent intent = new Intent();
613         intent.setAction(ACTION_CLEAR_PRIMARY_CLIP);
614         call(intent);
615     }
616 
assertReadingClipAllowed(ClipData clip)617     private void assertReadingClipAllowed(ClipData clip) {
618         for (int i=0; i<clip.getItemCount(); i++) {
619             ClipData.Item item = clip.getItemAt(i);
620             Uri uri = item.getUri();
621             if (uri != null) {
622                 Cursor c = getContext().getContentResolver().query(uri,
623                         null, null, null, null);
624                 if (c != null) {
625                     c.close();
626                 }
627             } else {
628                 Intent intent = item.getIntent();
629                 uri = intent.getData();
630                 if (uri != null) {
631                     Cursor c = getContext().getContentResolver().query(uri,
632                             null, null, null, null);
633                     if (c != null) {
634                         c.close();
635                     }
636                 }
637                 ClipData intentClip = intent.getClipData();
638                 if (intentClip != null) {
639                     assertReadingClipAllowed(intentClip);
640                 }
641             }
642         }
643     }
644 
doTestGrantActivityUriReadPermission(Uri uri, boolean useClip)645     private void doTestGrantActivityUriReadPermission(Uri uri, boolean useClip) {
646         final Uri subUri = Uri.withAppendedPath(uri, "foo");
647         final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
648         final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
649         final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
650 
651         final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
652         final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);
653 
654         // Precondition: no current access.
655         assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
656         assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");
657 
658         // --------------------------------
659 
660         ReceiveUriActivity.clearStarted();
661         grantClipUriPermission(subClip, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
662         ReceiveUriActivity.waitForStart();
663 
664         // See if we now have access to the provider.
665         assertReadingClipAllowed(subClip);
666 
667         // But not writing.
668         assertWritingClipNotAllowed(subClip, "shouldn't write from granted read");
669 
670         // And not to the base path.
671         assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
672 
673         // And not to a sub path.
674         assertReadingContentUriNotAllowed(subSubUri, "shouldn't read non-granted sub URI");
675 
676         // --------------------------------
677 
678         ReceiveUriActivity.clearNewIntent();
679         grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
680         ReceiveUriActivity.waitForNewIntent();
681 
682         if (false) {
683             synchronized (this) {
684                 Log.i("**", "******************************* WAITING!!!");
685                 try {
686                     wait(10000);
687                 } catch (InterruptedException e) {
688                 }
689             }
690         }
691 
692         // See if we now have access to the provider.
693         assertReadingClipAllowed(sub2Clip);
694 
695         // And still have access to the original URI.
696         assertReadingClipAllowed(subClip);
697 
698         // But not writing.
699         assertWritingClipNotAllowed(sub2Clip, "shouldn't write from granted read");
700 
701         // And not to the base path.
702         assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
703 
704         // And not to a sub path.
705         assertReadingContentUriNotAllowed(sub2SubUri, "shouldn't read non-granted sub URI");
706 
707         // And make sure we can't generate a permission to a running activity.
708         doTryGrantUriActivityPermissionToSelf(
709                 Uri.withAppendedPath(uri, "hah"),
710                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
711         doTryGrantUriActivityPermissionToSelf(
712                 Uri.withAppendedPath(uri, "hah"),
713                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
714 
715         // --------------------------------
716 
717         // Dispose of activity.
718         ReceiveUriActivity.finishCurInstanceSync();
719 
720         synchronized (this) {
721             Log.i("**", "******************************* WAITING!!!");
722             try {
723                 wait(100);
724             } catch (InterruptedException e) {
725             }
726         }
727 
728         // Ensure reading no longer allowed.
729         assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");
730         assertReadingClipNotAllowed(sub2Clip, "shouldn't read after losing granted URI");
731     }
732 
assertWritingClipAllowed(ClipData clip)733     private void assertWritingClipAllowed(ClipData clip) {
734         for (int i=0; i<clip.getItemCount(); i++) {
735             ClipData.Item item = clip.getItemAt(i);
736             Uri uri = item.getUri();
737             if (uri != null) {
738                 getContext().getContentResolver().insert(uri, new ContentValues());
739             } else {
740                 Intent intent = item.getIntent();
741                 uri = intent.getData();
742                 if (uri != null) {
743                     getContext().getContentResolver().insert(uri, new ContentValues());
744                 }
745                 ClipData intentClip = intent.getClipData();
746                 if (intentClip != null) {
747                     assertWritingClipAllowed(intentClip);
748                 }
749             }
750         }
751     }
752 
doTestGrantActivityUriWritePermission(Uri uri, boolean useClip)753     private void doTestGrantActivityUriWritePermission(Uri uri, boolean useClip) {
754         final Uri subUri = Uri.withAppendedPath(uri, "foo");
755         final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
756         final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
757         final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
758 
759         final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
760         final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);
761 
762         // Precondition: no current access.
763         assertWritingClipNotAllowed(subClip, "shouldn't write when starting test");
764         assertWritingClipNotAllowed(sub2Clip, "shouldn't write when starting test");
765 
766         // --------------------------------
767 
768         ReceiveUriActivity.clearStarted();
769         grantClipUriPermission(subClip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
770         ReceiveUriActivity.waitForStart();
771 
772         // See if we now have access to the provider.
773         assertWritingClipAllowed(subClip);
774 
775         // But not reading.
776         assertReadingClipNotAllowed(subClip, "shouldn't read from granted write");
777 
778         // And not to the base path.
779         assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
780 
781         // And not a sub-path.
782         assertWritingContentUriNotAllowed(subSubUri, "shouldn't write non-granted sub URI");
783 
784         // --------------------------------
785 
786         ReceiveUriActivity.clearNewIntent();
787         grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
788         ReceiveUriActivity.waitForNewIntent();
789 
790         if (false) {
791             synchronized (this) {
792                 Log.i("**", "******************************* WAITING!!!");
793                 try {
794                     wait(10000);
795                 } catch (InterruptedException e) {
796                 }
797             }
798         }
799 
800         // See if we now have access to the provider.
801         assertWritingClipAllowed(sub2Clip);
802 
803         // And still have access to the original URI.
804         assertWritingClipAllowed(subClip);
805 
806         // But not reading.
807         assertReadingClipNotAllowed(sub2Clip, "shouldn't read from granted write");
808 
809         // And not to the base path.
810         assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
811 
812         // And not a sub-path.
813         assertWritingContentUriNotAllowed(sub2SubUri, "shouldn't write non-granted sub URI");
814 
815         // And make sure we can't generate a permission to a running activity.
816         doTryGrantUriActivityPermissionToSelf(
817                 Uri.withAppendedPath(uri, "hah"),
818                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
819         doTryGrantUriActivityPermissionToSelf(
820                 Uri.withAppendedPath(uri, "hah"),
821                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
822 
823         // --------------------------------
824 
825         // Dispose of activity.
826         ReceiveUriActivity.finishCurInstanceSync();
827 
828         synchronized (this) {
829             Log.i("**", "******************************* WAITING!!!");
830             try {
831                 wait(100);
832             } catch (InterruptedException e) {
833             }
834         }
835 
836         // Ensure writing no longer allowed.
837         assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");
838         assertWritingClipNotAllowed(sub2Clip, "shouldn't write after losing granted URI");
839     }
840 
841     /**
842      * Test that the ctspermissionwithsignaturegranting content provider can grant a read
843      * permission.
844      */
testGrantReadPermissionFromStartActivity()845     public void testGrantReadPermissionFromStartActivity() {
846         doTestGrantActivityUriReadPermission(PERM_URI_GRANTING, false);
847         doTestGrantActivityUriReadPermission(PERM_URI_GRANTING, true);
848     }
849 
850     /**
851      * Test that the ctspermissionwithsignaturegranting content provider can grant a write
852      * permission.
853      */
testGrantWritePermissionFromStartActivity()854     public void testGrantWritePermissionFromStartActivity() {
855         doTestGrantActivityUriWritePermission(PERM_URI_GRANTING, true);
856         doTestGrantActivityUriWritePermission(PERM_URI_GRANTING, false);
857     }
858 
859     /**
860      * Test that the ctsprivateprovidergranting content provider can grant a read
861      * permission.
862      */
testGrantReadPrivateFromStartActivity()863     public void testGrantReadPrivateFromStartActivity() {
864         doTestGrantActivityUriReadPermission(PRIV_URI_GRANTING, false);
865         doTestGrantActivityUriReadPermission(PRIV_URI_GRANTING, true);
866     }
867 
868     /**
869      * Test that the ctsprivateprovidergranting content provider can grant a write
870      * permission.
871      */
testGrantWritePrivateFromStartActivity()872     public void testGrantWritePrivateFromStartActivity() {
873         doTestGrantActivityUriWritePermission(PRIV_URI_GRANTING, true);
874         doTestGrantActivityUriWritePermission(PRIV_URI_GRANTING, false);
875     }
876 
doTestGrantServiceUriReadPermission(Uri uri, boolean useClip)877     private void doTestGrantServiceUriReadPermission(Uri uri, boolean useClip) {
878         final Uri subUri = Uri.withAppendedPath(uri, "foo");
879         final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
880         final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
881         final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
882 
883         ReceiveUriService.stop(getContext());
884 
885         final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
886         final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);
887 
888         // Precondition: no current access.
889         assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
890         assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");
891 
892         // --------------------------------
893 
894         ReceiveUriService.clearStarted();
895         grantClipUriPermission(subClip, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
896         ReceiveUriService.waitForStart();
897 
898         int firstStartId = ReceiveUriService.getCurStartId();
899 
900         // See if we now have access to the provider.
901         assertReadingClipAllowed(subClip);
902 
903         // But not writing.
904         assertWritingClipNotAllowed(subClip, "shouldn't write from granted read");
905 
906         // And not to the base path.
907         assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
908 
909         // And not to a sub path.
910         assertReadingContentUriNotAllowed(subSubUri, "shouldn't read non-granted sub URI");
911 
912         // --------------------------------
913 
914         // Send another Intent to it.
915         ReceiveUriService.clearStarted();
916         grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
917         ReceiveUriService.waitForStart();
918 
919         if (false) {
920             synchronized (this) {
921                 Log.i("**", "******************************* WAITING!!!");
922                 try {
923                     wait(10000);
924                 } catch (InterruptedException e) {
925                 }
926             }
927         }
928 
929         // See if we now have access to the provider.
930         assertReadingClipAllowed(sub2Clip);
931 
932         // And still to the previous URI.
933         assertReadingClipAllowed(subClip);
934 
935         // But not writing.
936         assertWritingClipNotAllowed(sub2Clip, "shouldn't write from granted read");
937 
938         // And not to the base path.
939         assertReadingContentUriNotAllowed(uri, "shouldn't read non-granted base URI");
940 
941         // And not to a sub path.
942         assertReadingContentUriNotAllowed(sub2SubUri, "shouldn't read non-granted sub URI");
943 
944         // --------------------------------
945 
946         // Stop the first command.
947         ReceiveUriService.stopCurWithId(firstStartId);
948 
949         // Ensure reading no longer allowed.
950         assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");
951 
952         // And make sure we can't generate a permission to a running service.
953         doTryGrantUriActivityPermissionToSelf(subUri,
954                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
955         doTryGrantUriActivityPermissionToSelf(subUri,
956                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
957 
958         // --------------------------------
959 
960         // Dispose of service.
961         ReceiveUriService.stopSync(getContext());
962 
963         // Ensure reading no longer allowed.
964         assertReadingClipNotAllowed(subClip, "shouldn't read after losing granted URI");
965         assertReadingClipNotAllowed(sub2Clip, "shouldn't read after losing granted URI");
966     }
967 
doTestGrantServiceUriWritePermission(Uri uri, boolean useClip)968     private void doTestGrantServiceUriWritePermission(Uri uri, boolean useClip) {
969         final Uri subUri = Uri.withAppendedPath(uri, "foo");
970         final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
971         final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
972         final Uri sub2SubUri = Uri.withAppendedPath(sub2Uri, "no");
973 
974         ReceiveUriService.stop(getContext());
975 
976         final ClipData subClip = useClip ? makeMultiClipData(subUri) : makeSingleClipData(subUri);
977         final ClipData sub2Clip = useClip ? makeMultiClipData(sub2Uri) : makeSingleClipData(sub2Uri);
978 
979         // Precondition: no current access.
980         assertReadingClipNotAllowed(subClip, "shouldn't read when starting test");
981         assertReadingClipNotAllowed(sub2Clip, "shouldn't read when starting test");
982 
983         // --------------------------------
984 
985         ReceiveUriService.clearStarted();
986         grantClipUriPermission(subClip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
987         ReceiveUriService.waitForStart();
988 
989         int firstStartId = ReceiveUriService.getCurStartId();
990 
991         // See if we now have access to the provider.
992         assertWritingClipAllowed(subClip);
993 
994         // But not reading.
995         assertReadingClipNotAllowed(subClip, "shouldn't read from granted write");
996 
997         // And not to the base path.
998         assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
999 
1000         // And not a sub-path.
1001         assertWritingContentUriNotAllowed(subSubUri, "shouldn't write non-granted sub URI");
1002 
1003         // --------------------------------
1004 
1005         // Send another Intent to it.
1006         ReceiveUriService.clearStarted();
1007         grantClipUriPermission(sub2Clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, true);
1008         ReceiveUriService.waitForStart();
1009 
1010         // See if we now have access to the provider.
1011         assertWritingClipAllowed(sub2Clip);
1012 
1013         // And still to the previous URI.
1014         assertWritingClipAllowed(subClip);
1015 
1016         // But not reading.
1017         assertReadingClipNotAllowed(sub2Clip, "shouldn't read from granted write");
1018 
1019         // And not to the base path.
1020         assertWritingContentUriNotAllowed(uri, "shouldn't write non-granted base URI");
1021 
1022         // And not a sub-path.
1023         assertWritingContentUriNotAllowed(sub2SubUri, "shouldn't write non-granted sub URI");
1024 
1025         if (false) {
1026             synchronized (this) {
1027                 Log.i("**", "******************************* WAITING!!!");
1028                 try {
1029                     wait(10000);
1030                 } catch (InterruptedException e) {
1031                 }
1032             }
1033         }
1034 
1035         // --------------------------------
1036 
1037         // Stop the first command.
1038         ReceiveUriService.stopCurWithId(firstStartId);
1039 
1040         // Ensure writing no longer allowed.
1041         assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");
1042 
1043         // And make sure we can't generate a permission to a running service.
1044         doTryGrantUriActivityPermissionToSelf(subUri,
1045                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
1046         doTryGrantUriActivityPermissionToSelf(subUri,
1047                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1048 
1049         // --------------------------------
1050 
1051         // Dispose of service.
1052         ReceiveUriService.stopSync(getContext());
1053 
1054         // Ensure writing no longer allowed.
1055         assertWritingClipNotAllowed(subClip, "shouldn't write after losing granted URI");
1056         assertWritingClipNotAllowed(sub2Clip, "shouldn't write after losing granted URI");
1057     }
1058 
testGrantReadPermissionFromStartService()1059     public void testGrantReadPermissionFromStartService() {
1060         doTestGrantServiceUriReadPermission(PERM_URI_GRANTING, false);
1061         doTestGrantServiceUriReadPermission(PERM_URI_GRANTING, true);
1062     }
1063 
testGrantWritePermissionFromStartService()1064     public void testGrantWritePermissionFromStartService() {
1065         doTestGrantServiceUriWritePermission(PERM_URI_GRANTING, false);
1066         doTestGrantServiceUriWritePermission(PERM_URI_GRANTING, true);
1067     }
1068 
testGrantReadPrivateFromStartService()1069     public void testGrantReadPrivateFromStartService() {
1070         doTestGrantServiceUriReadPermission(PRIV_URI_GRANTING, false);
1071         doTestGrantServiceUriReadPermission(PRIV_URI_GRANTING, true);
1072     }
1073 
testGrantWritePrivateFromStartService()1074     public void testGrantWritePrivateFromStartService() {
1075         doTestGrantServiceUriWritePermission(PRIV_URI_GRANTING, false);
1076         doTestGrantServiceUriWritePermission(PRIV_URI_GRANTING, true);
1077     }
1078 
1079     /**
1080      * Test that ctspermissionwithsignaturepath can't grant read permissions
1081      * on paths it doesn't have permission to.
1082      */
testGrantReadUriActivityPathPermissionToSelf()1083     public void testGrantReadUriActivityPathPermissionToSelf() {
1084         doTryGrantUriActivityPermissionToSelf(PERM_URI_PATH,
1085                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
1086     }
1087 
1088     /**
1089      * Test that ctspermissionwithsignaturepath can't grant write permissions
1090      * on paths it doesn't have permission to.
1091      */
testGrantWriteUriActivityPathPermissionToSelf()1092     public void testGrantWriteUriActivityPathPermissionToSelf() {
1093         doTryGrantUriActivityPermissionToSelf(PERM_URI_PATH,
1094                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1095     }
1096 
1097     /**
1098      * Test that ctspermissionwithsignaturepath can't grant read permissions
1099      * on paths it doesn't have permission to.
1100      */
testGrantReadUriActivitySubPathPermissionToSelf()1101     public void testGrantReadUriActivitySubPathPermissionToSelf() {
1102         doTryGrantUriActivityPermissionToSelf(
1103                 Uri.withAppendedPath(PERM_URI_PATH, "foo"),
1104                 Intent.FLAG_GRANT_READ_URI_PERMISSION);
1105     }
1106 
1107     /**
1108      * Test that ctspermissionwithsignaturepath can't grant write permissions
1109      * on paths it doesn't have permission to.
1110      */
testGrantWriteUriActivitySubPathPermissionToSelf()1111     public void testGrantWriteUriActivitySubPathPermissionToSelf() {
1112         doTryGrantUriActivityPermissionToSelf(
1113                 Uri.withAppendedPath(PERM_URI_PATH, "foo"),
1114                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1115     }
1116 
1117     /**
1118      * Test that the ctspermissionwithsignaturepath content provider can grant a read
1119      * permission.
1120      */
testGrantReadPathPermissionFromStartActivity()1121     public void testGrantReadPathPermissionFromStartActivity() {
1122         doTestGrantActivityUriReadPermission(PERM_URI_PATH, false);
1123         doTestGrantActivityUriReadPermission(PERM_URI_PATH, true);
1124     }
1125 
1126     /**
1127      * Test that the ctspermissionwithsignaturepath content provider can grant a write
1128      * permission.
1129      */
testGrantWritePathPermissionFromStartActivity()1130     public void testGrantWritePathPermissionFromStartActivity() {
1131         doTestGrantActivityUriWritePermission(PERM_URI_PATH, false);
1132         doTestGrantActivityUriWritePermission(PERM_URI_PATH, true);
1133     }
1134 
1135     /**
1136      * Test that the ctspermissionwithsignaturepath content provider can grant a read
1137      * permission.
1138      */
testGrantReadPathPermissionFromStartService()1139     public void testGrantReadPathPermissionFromStartService() {
1140         doTestGrantServiceUriReadPermission(PERM_URI_PATH, false);
1141         doTestGrantServiceUriReadPermission(PERM_URI_PATH, true);
1142     }
1143 
1144     /**
1145      * Test that the ctspermissionwithsignaturepath content provider can grant a write
1146      * permission.
1147      */
testGrantWritePathPermissionFromStartService()1148     public void testGrantWritePathPermissionFromStartService() {
1149         doTestGrantServiceUriWritePermission(PERM_URI_PATH, false);
1150         doTestGrantServiceUriWritePermission(PERM_URI_PATH, true);
1151     }
1152 
1153     /**
1154      * Verify that we can access paths outside the {@code path-permission}
1155      * protections, which should only rely on {@code provider} permissions.
1156      */
testRestrictingProviderNoMatchingPath()1157     public void testRestrictingProviderNoMatchingPath() {
1158         assertReadingContentUriAllowed(PERM_URI_PATH_RESTRICTING);
1159         assertWritingContentUriAllowed(PERM_URI_PATH_RESTRICTING);
1160 
1161         // allowed by no top-level permission
1162         final Uri test = PERM_URI_PATH_RESTRICTING.buildUpon().appendPath("fo").build();
1163         assertReadingContentUriAllowed(test);
1164         assertWritingContentUriAllowed(test);
1165     }
1166 
1167     /**
1168      * Verify that paths under {@code path-permission} restriction aren't
1169      * allowed, even though the {@code provider} requires no permissions.
1170      */
testRestrictingProviderMatchingPathDenied()1171     public void testRestrictingProviderMatchingPathDenied() {
1172         // rejected by "foo" prefix
1173         final Uri test1 = PERM_URI_PATH_RESTRICTING.buildUpon().appendPath("foo").build();
1174         assertReadingContentUriNotAllowed(test1, null);
1175         assertWritingContentUriNotAllowed(test1, null);
1176 
1177         // rejected by "foo" prefix
1178         final Uri test2 = PERM_URI_PATH_RESTRICTING.buildUpon()
1179                 .appendPath("foo").appendPath("ba").build();
1180         assertReadingContentUriNotAllowed(test2, null);
1181         assertWritingContentUriNotAllowed(test2, null);
1182     }
1183 
1184     /**
1185      * Test that shady {@link Uri} are blocked by {@code path-permission}.
1186      */
testRestrictingProviderMatchingShadyPaths()1187     public void testRestrictingProviderMatchingShadyPaths() {
1188         assertContentUriAllowed(
1189                 Uri.parse("content://ctspermissionwithsignaturepathrestricting/"));
1190         assertContentUriAllowed(
1191                 Uri.parse("content://ctspermissionwithsignaturepathrestricting//"));
1192         assertContentUriAllowed(
1193                 Uri.parse("content://ctspermissionwithsignaturepathrestricting///"));
1194         assertContentUriNotAllowed(
1195                 Uri.parse("content://ctspermissionwithsignaturepathrestricting/foo"), null);
1196         assertContentUriNotAllowed(
1197                 Uri.parse("content://ctspermissionwithsignaturepathrestricting//foo"), null);
1198         assertContentUriNotAllowed(
1199                 Uri.parse("content://ctspermissionwithsignaturepathrestricting///foo"), null);
1200         assertContentUriNotAllowed(
1201                 Uri.parse("content://ctspermissionwithsignaturepathrestricting/foo//baz"), null);
1202     }
1203 
1204     /**
1205      * Verify that at least one {@code path-permission} rule will grant access,
1206      * even if the caller doesn't hold another matching {@code path-permission}.
1207      */
testRestrictingProviderMultipleMatchingPath()1208     public void testRestrictingProviderMultipleMatchingPath() {
1209         // allowed by narrow "foo/bar" prefix
1210         final Uri test1 = PERM_URI_PATH_RESTRICTING.buildUpon()
1211                 .appendPath("foo").appendPath("bar").build();
1212         assertReadingContentUriAllowed(test1);
1213         assertWritingContentUriAllowed(test1);
1214 
1215         // allowed by narrow "foo/bar" prefix
1216         final Uri test2 = PERM_URI_PATH_RESTRICTING.buildUpon()
1217                 .appendPath("foo").appendPath("bar2").build();
1218         assertReadingContentUriAllowed(test2);
1219         assertWritingContentUriAllowed(test2);
1220     }
1221 
testGetMimeTypePermission()1222     public void testGetMimeTypePermission() {
1223         // Precondition: no current access.
1224         assertReadingContentUriNotAllowed(PERM_URI, "shouldn't read when starting test");
1225         assertWritingContentUriNotAllowed(PERM_URI, "shouldn't write when starting test");
1226 
1227         // All apps should be able to get MIME type regardless of permission.
1228         assertEquals(getContext().getContentResolver().getType(PERM_URI), EXPECTED_MIME_TYPE);
1229     }
1230 
testGetMimeTypePrivate()1231     public void testGetMimeTypePrivate() {
1232         // Precondition: no current access.
1233         assertReadingContentUriNotAllowed(PRIV_URI, "shouldn't read when starting test");
1234         assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write when starting test");
1235 
1236         // All apps should be able to get MIME type even if provider is private.
1237         assertEquals(getContext().getContentResolver().getType(PRIV_URI), EXPECTED_MIME_TYPE);
1238     }
1239 
testGetMimeTypeAmbiguous()1240     public void testGetMimeTypeAmbiguous() {
1241         // Precondition: no current access.
1242         assertReadingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't read when starting test");
1243         assertWritingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't write when starting test");
1244 
1245         // All apps should be able to get MIME type even if provider is private.
1246         assertEquals(getContext().getContentResolver().getType(AMBIGUOUS_URI), EXPECTED_MIME_TYPE);
1247     }
1248 
1249     /**
1250      * Old App Compatibility Test
1251      *
1252      * We should be able to access the mime type of a content provider of an older
1253      * application, even if that application didn't explicitly declare either
1254      * exported=true or exported=false
1255      */
testGetMimeTypeAmbiguousCompat()1256     public void testGetMimeTypeAmbiguousCompat() {
1257         // All apps should be able to get MIME type even if provider is private.
1258         assertEquals(EXPECTED_MIME_TYPE_AMBIGUOUS,
1259                 getContext().getContentResolver().getType(AMBIGUOUS_URI_COMPAT));
1260     }
1261 
1262     /**
1263      * Validate behavior of persistable permission grants.
1264      */
testGrantPersistableUriPermission()1265     public void testGrantPersistableUriPermission() {
1266         final ContentResolver resolver = getContext().getContentResolver();
1267 
1268         final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo");
1269         final ClipData clip = makeSingleClipData(target);
1270 
1271         // Make sure we can't see the target
1272         assertReadingClipNotAllowed(clip, "reading should have failed");
1273         assertWritingClipNotAllowed(clip, "writing should have failed");
1274 
1275         // Make sure we can't take a grant we don't have
1276         try {
1277             resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
1278             fail("taking read should have failed");
1279         } catch (SecurityException expected) {
1280         }
1281 
1282         // And since we were just installed, no persisted grants yet
1283         assertNoPersistedUriPermission();
1284 
1285         // Now, let's grant ourselves some access
1286         ReceiveUriActivity.clearStarted();
1287         grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
1288                 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
1289         ReceiveUriActivity.waitForStart();
1290 
1291         // We should now have reading access, even before taking the persistable
1292         // grant. Persisted grants should still be empty.
1293         assertReadingClipAllowed(clip);
1294         assertWritingClipNotAllowed(clip, "writing should have failed");
1295         assertNoPersistedUriPermission();
1296 
1297         // Take the read grant and verify we have it!
1298         long before = System.currentTimeMillis();
1299         resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
1300         long after = System.currentTimeMillis();
1301         assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);
1302 
1303         // Make sure we can't take a grant we don't have
1304         try {
1305             resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1306             fail("taking write should have failed");
1307         } catch (SecurityException expected) {
1308         }
1309 
1310         // Launch again giving ourselves persistable read and write access
1311         ReceiveUriActivity.clearNewIntent();
1312         grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
1313                 | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
1314                 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, false);
1315         ReceiveUriActivity.waitForNewIntent();
1316 
1317         // Previous persisted grant should be unchanged
1318         assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);
1319 
1320         // We should have both read and write; read is persisted, and write
1321         // isn't persisted yet.
1322         assertReadingClipAllowed(clip);
1323         assertWritingClipAllowed(clip);
1324 
1325         // Take again, but still only read; should just update timestamp
1326         before = System.currentTimeMillis();
1327         resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
1328         after = System.currentTimeMillis();
1329         assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);
1330 
1331         // And take yet again, both read and write
1332         before = System.currentTimeMillis();
1333         resolver.takePersistableUriPermission(target,
1334                 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1335         after = System.currentTimeMillis();
1336         assertPersistedUriPermission(target,
1337                 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
1338                 before, after);
1339 
1340         // Now drop the persisted grant; write first, then read
1341         resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
1342         assertPersistedUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after);
1343         resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1344         assertNoPersistedUriPermission();
1345 
1346         // And even though we dropped the persistable grants, our activity is
1347         // still running with the global grants (until reboot).
1348         assertReadingClipAllowed(clip);
1349         assertWritingClipAllowed(clip);
1350 
1351         ReceiveUriActivity.finishCurInstanceSync();
1352     }
1353 
assertNoPersistedUriPermission()1354     private void assertNoPersistedUriPermission() {
1355         assertPersistedUriPermission(null, 0, -1, -1);
1356     }
1357 
assertPersistedUriPermission(Uri uri, int flags, long before, long after)1358     private void assertPersistedUriPermission(Uri uri, int flags, long before, long after) {
1359         // Assert local
1360         final List<UriPermission> perms = getContext()
1361                 .getContentResolver().getPersistedUriPermissions();
1362         if (uri != null) {
1363             assertEquals("expected exactly one permission", 1, perms.size());
1364 
1365             final UriPermission perm = perms.get(0);
1366             assertEquals("unexpected uri", uri, perm.getUri());
1367 
1368             final long actual = perm.getPersistedTime();
1369             if (before != -1) {
1370                 assertTrue("found " + actual + " before " + before, actual >= before);
1371             }
1372             if (after != -1) {
1373                 assertTrue("found " + actual + " after " + after, actual <= after);
1374             }
1375 
1376             final boolean expectedRead = (flags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0;
1377             final boolean expectedWrite = (flags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0;
1378             assertEquals("unexpected read status", expectedRead, perm.isReadPermission());
1379             assertEquals("unexpected write status", expectedWrite, perm.isWritePermission());
1380 
1381         } else {
1382             assertEquals("expected zero permissions", 0, perms.size());
1383         }
1384 
1385         // And assert remote
1386         Intent intent = new Intent();
1387         intent.setAction(ACTION_VERIFY_OUTGOING_PERSISTED);
1388         intent.putExtra(EXTRA_URI, uri);
1389         call(intent);
1390     }
1391 
1392     /**
1393      * Validate behavior of prefix permission grants.
1394      */
testGrantPrefixUriPermission()1395     public void testGrantPrefixUriPermission() throws Exception {
1396         final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo1");
1397         final Uri targetMeow = Uri.withAppendedPath(target, "meow");
1398         final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");
1399 
1400         final ClipData clip = makeSingleClipData(target);
1401         final ClipData clipMeow = makeSingleClipData(targetMeow);
1402         final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);
1403 
1404         // Make sure we can't see the target
1405         assertReadingClipNotAllowed(clip, "reading should have failed");
1406         assertWritingClipNotAllowed(clip, "writing should have failed");
1407 
1408         // Give ourselves prefix read access
1409         ReceiveUriActivity.clearStarted();
1410         grantClipUriPermission(clipMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
1411                 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
1412         ReceiveUriActivity.waitForStart();
1413 
1414         // Verify prefix read access
1415         assertReadingClipNotAllowed(clip, "reading should have failed");
1416         assertReadingClipAllowed(clipMeow);
1417         assertReadingClipAllowed(clipMeowCat);
1418         assertWritingClipNotAllowed(clip, "writing should have failed");
1419         assertWritingClipNotAllowed(clipMeow, "writing should have failed");
1420         assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
1421 
1422         // Now give ourselves exact write access
1423         ReceiveUriActivity.clearNewIntent();
1424         grantClipUriPermission(clip, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
1425         ReceiveUriActivity.waitForNewIntent();
1426 
1427         // Verify we have exact write access, but not prefix write
1428         assertReadingClipNotAllowed(clip, "reading should have failed");
1429         assertReadingClipAllowed(clipMeow);
1430         assertReadingClipAllowed(clipMeowCat);
1431         assertWritingClipAllowed(clip);
1432         assertWritingClipNotAllowed(clipMeow, "writing should have failed");
1433         assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
1434 
1435         ReceiveUriActivity.finishCurInstanceSync();
1436     }
1437 
testGrantPersistablePrefixUriPermission()1438     public void testGrantPersistablePrefixUriPermission() {
1439         final ContentResolver resolver = getContext().getContentResolver();
1440 
1441         final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo2");
1442         final Uri targetMeow = Uri.withAppendedPath(target, "meow");
1443 
1444         final ClipData clip = makeSingleClipData(target);
1445         final ClipData clipMeow = makeSingleClipData(targetMeow);
1446 
1447         // Make sure we can't see the target
1448         assertReadingClipNotAllowed(clip, "reading should have failed");
1449 
1450         // Give ourselves prefix read access
1451         ReceiveUriActivity.clearStarted();
1452         grantClipUriPermission(clip, Intent.FLAG_GRANT_READ_URI_PERMISSION
1453                 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
1454                 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION, false);
1455         ReceiveUriActivity.waitForStart();
1456 
1457         // Verify prefix read access
1458         assertReadingClipAllowed(clip);
1459         assertReadingClipAllowed(clipMeow);
1460 
1461         // Verify we can persist direct grant
1462         long before = System.currentTimeMillis();
1463         resolver.takePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
1464         long after = System.currentTimeMillis();
1465         assertPersistedUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION, before, after);
1466 
1467         // But we can't take anywhere under the prefix
1468         try {
1469             resolver.takePersistableUriPermission(targetMeow,
1470                     Intent.FLAG_GRANT_READ_URI_PERMISSION);
1471             fail("taking under prefix should have failed");
1472         } catch (SecurityException expected) {
1473         }
1474 
1475         // Should still have access regardless of taking
1476         assertReadingClipAllowed(clip);
1477         assertReadingClipAllowed(clipMeow);
1478 
1479         // And clean up our grants
1480         resolver.releasePersistableUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
1481         assertNoPersistedUriPermission();
1482 
1483         ReceiveUriActivity.finishCurInstanceSync();
1484     }
1485 
1486     /**
1487      * Validate behavior of directly granting/revoking permission grants.
1488      */
testDirectGrantRevokeUriPermission()1489     public void testDirectGrantRevokeUriPermission() throws Exception {
1490         final ContentResolver resolver = getContext().getContentResolver();
1491 
1492         final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo3");
1493         final Uri targetMeow = Uri.withAppendedPath(target, "meow");
1494         final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");
1495 
1496         final ClipData clip = makeSingleClipData(target);
1497         final ClipData clipMeow = makeSingleClipData(targetMeow);
1498         final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);
1499 
1500         // Make sure we can't see the target
1501         assertReadingClipNotAllowed(clipMeow, "reading should have failed");
1502         assertWritingClipNotAllowed(clipMeow, "writing should have failed");
1503 
1504         // Give ourselves some grants:
1505         // /meow/cat  WRITE|PERSISTABLE
1506         // /meow      READ|PREFIX
1507         // /meow      WRITE
1508         grantClipUriPermissionViaContext(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
1509                 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
1510         grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
1511                 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
1512         grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1513 
1514         long before = System.currentTimeMillis();
1515         resolver.takePersistableUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1516         long after = System.currentTimeMillis();
1517         assertPersistedUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after);
1518 
1519         // Verify they look good
1520         assertReadingClipNotAllowed(clip, "reading should have failed");
1521         assertReadingClipAllowed(clipMeow);
1522         assertReadingClipAllowed(clipMeowCat);
1523         assertWritingClipNotAllowed(clip, "writing should have failed");
1524         assertWritingClipAllowed(clipMeow);
1525         assertWritingClipAllowed(clipMeowCat);
1526 
1527         // Revoke anyone with write under meow
1528         revokeClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1529 
1530         // This should have nuked persisted permission at lower level, but it
1531         // shoulnd't have touched our prefix read.
1532         assertReadingClipNotAllowed(clip, "reading should have failed");
1533         assertReadingClipAllowed(clipMeow);
1534         assertReadingClipAllowed(clipMeowCat);
1535         assertWritingClipNotAllowed(clip, "writing should have failed");
1536         assertWritingClipNotAllowed(clipMeow, "writing should have failed");
1537         assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
1538         assertNoPersistedUriPermission();
1539 
1540         // Revoking read at top of tree should nuke everything else
1541         revokeClipUriPermissionViaContext(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
1542         assertReadingClipNotAllowed(clip, "reading should have failed");
1543         assertReadingClipNotAllowed(clipMeow, "reading should have failed");
1544         assertReadingClipNotAllowed(clipMeowCat, "reading should have failed");
1545         assertWritingClipNotAllowed(clip, "writing should have failed");
1546         assertWritingClipNotAllowed(clipMeow, "writing should have failed");
1547         assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
1548         assertNoPersistedUriPermission();
1549     }
1550 
1551     /**
1552      * Validate behavior of a direct permission grant, where the receiver of
1553      * that permission revokes it.
1554      */
testDirectGrantReceiverRevokeUriPermission()1555     public void testDirectGrantReceiverRevokeUriPermission() throws Exception {
1556         final ContentResolver resolver = getContext().getContentResolver();
1557 
1558         final Uri target = Uri.withAppendedPath(PERM_URI_GRANTING, "foo3");
1559         final Uri targetMeow = Uri.withAppendedPath(target, "meow");
1560         final Uri targetMeowCat = Uri.withAppendedPath(targetMeow, "cat");
1561 
1562         final ClipData clip = makeSingleClipData(target);
1563         final ClipData clipMeow = makeSingleClipData(targetMeow);
1564         final ClipData clipMeowCat = makeSingleClipData(targetMeowCat);
1565 
1566         // Make sure we can't see the target
1567         assertReadingClipNotAllowed(clipMeow, "reading should have failed");
1568         assertWritingClipNotAllowed(clipMeow, "writing should have failed");
1569 
1570         // Give ourselves some grants:
1571         // /meow/cat  WRITE|PERSISTABLE
1572         // /meow      READ|PREFIX
1573         // /meow      WRITE
1574         grantClipUriPermissionViaContext(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION
1575                 | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
1576         grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_READ_URI_PERMISSION
1577                 | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
1578         grantClipUriPermissionViaContext(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1579 
1580         long before = System.currentTimeMillis();
1581         resolver.takePersistableUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1582         long after = System.currentTimeMillis();
1583         assertPersistedUriPermission(targetMeowCat, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, before, after);
1584 
1585         // Verify they look good
1586         assertReadingClipNotAllowed(clip, "reading should have failed");
1587         assertReadingClipAllowed(clipMeow);
1588         assertReadingClipAllowed(clipMeowCat);
1589         assertWritingClipNotAllowed(clip, "writing should have failed");
1590         assertWritingClipAllowed(clipMeow);
1591         assertWritingClipAllowed(clipMeowCat);
1592 
1593         // Revoke anyone with write under meow
1594         getContext().revokeUriPermission(targetMeow, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
1595 
1596         // This should have nuked persisted permission at lower level, but it
1597         // shoulnd't have touched our prefix read.
1598         assertReadingClipNotAllowed(clip, "reading should have failed");
1599         assertReadingClipAllowed(clipMeow);
1600         assertReadingClipAllowed(clipMeowCat);
1601         assertWritingClipNotAllowed(clip, "writing should have failed");
1602         assertWritingClipNotAllowed(clipMeow, "writing should have failed");
1603         assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
1604         assertNoPersistedUriPermission();
1605 
1606         // Revoking read at top of tree should nuke everything else
1607         getContext().revokeUriPermission(target, Intent.FLAG_GRANT_READ_URI_PERMISSION);
1608         assertReadingClipNotAllowed(clip, "reading should have failed");
1609         assertReadingClipNotAllowed(clipMeow, "reading should have failed");
1610         assertReadingClipNotAllowed(clipMeowCat, "reading should have failed");
1611         assertWritingClipNotAllowed(clip, "writing should have failed");
1612         assertWritingClipNotAllowed(clipMeow, "writing should have failed");
1613         assertWritingClipNotAllowed(clipMeowCat, "writing should have failed");
1614         assertNoPersistedUriPermission();
1615     }
1616 
testClipboardWithPermission()1617     public void testClipboardWithPermission() throws Exception {
1618         for (Uri target : GRANTABLE) {
1619             final ClipData clip = makeSingleClipData(target);
1620 
1621             // Normally we can't see the underlying clip data
1622             assertReadingClipNotAllowed(clip);
1623             assertWritingClipNotAllowed(clip);
1624 
1625             // Use shell's permissions to ensure we can access the clipboard
1626             InstrumentationRegistry.getInstrumentation().getUiAutomation()
1627                     .adoptShellPermissionIdentity();
1628             ClipData clipFromClipboard;
1629             try {
1630                 // But if someone puts it on the clipboard, we can read it
1631                 setPrimaryClip(clip);
1632                 clipFromClipboard = getContext()
1633                         .getSystemService(ClipboardManager.class).getPrimaryClip();
1634             } finally {
1635                 InstrumentationRegistry.getInstrumentation().getUiAutomation()
1636                         .dropShellPermissionIdentity();
1637             }
1638             assertClipDataEquals(clip, clipFromClipboard);
1639             assertReadingClipAllowed(clipFromClipboard);
1640             assertWritingClipNotAllowed(clipFromClipboard);
1641 
1642             // And if clipboard is cleared, we lose access
1643             clearPrimaryClip();
1644             assertReadingClipNotAllowed(clipFromClipboard);
1645             assertWritingClipNotAllowed(clipFromClipboard);
1646         }
1647     }
1648 
testClipboardWithoutPermission()1649     public void testClipboardWithoutPermission() throws Exception {
1650         for (Uri target : NOT_GRANTABLE) {
1651             final ClipData clip = makeSingleClipData(target);
1652 
1653             // Can't see it directly
1654             assertReadingClipNotAllowed(clip);
1655             assertWritingClipNotAllowed(clip);
1656 
1657             // Can't put on clipboard if we don't own it
1658             try {
1659                 setPrimaryClip(clip);
1660                 fail("Unexpected ability to put protected data " + clip + " on clipboard!");
1661             } catch (Exception expected) {
1662             }
1663         }
1664     }
1665 
assertClipDataEquals(ClipData expected, ClipData actual)1666     private static void assertClipDataEquals(ClipData expected, ClipData actual) {
1667         assertEquals(expected.getItemCount(), actual.getItemCount());
1668         for (int i = 0; i < expected.getItemCount(); i++) {
1669             final ClipData.Item expectedItem = expected.getItemAt(i);
1670             final ClipData.Item actualItem = actual.getItemAt(i);
1671             assertEquals(expectedItem.getText(), actualItem.getText());
1672             assertEquals(expectedItem.getHtmlText(), actualItem.getHtmlText());
1673             assertEquals(expectedItem.getIntent(), actualItem.getIntent());
1674             assertEquals(expectedItem.getUri(), actualItem.getUri());
1675         }
1676     }
1677 }
1678