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