• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 android.appsecurity.cts;
18 
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
24 
25 import android.platform.test.annotations.Presubmit;
26 
27 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
28 import com.android.ddmlib.Log;
29 import com.android.role.RoleProto;
30 import com.android.role.RoleServiceDumpProto;
31 import com.android.role.RoleUserStateProto;
32 import com.android.tradefed.device.CollectingByteOutputReceiver;
33 import com.android.tradefed.device.DeviceNotAvailableException;
34 import com.android.tradefed.device.ITestDevice;
35 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
36 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
37 import com.android.tradefed.util.AbiUtils;
38 
39 import com.google.protobuf.MessageLite;
40 import com.google.protobuf.Parser;
41 
42 import org.junit.After;
43 import org.junit.Assume;
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 
48 import java.io.File;
49 import java.io.FileNotFoundException;
50 import java.util.ArrayList;
51 import java.util.List;
52 
53 /**
54  * Set of tests that verify behavior of external storage devices.
55  */
56 @Presubmit
57 @RunWith(DeviceJUnit4ClassRunner.class)
58 public class ExternalStorageHostTest extends BaseHostJUnit4Test {
59     private static final String TAG = "ExternalStorageHostTest";
60 
61     private static class Config {
62         public final String apk;
63         public final String pkg;
64         public final String clazz;
65 
Config(String apk, String pkg, String clazz)66         public Config(String apk, String pkg, String clazz) {
67             this.apk = apk;
68             this.pkg = pkg;
69             this.clazz = clazz;
70         }
71     }
72 
73     private static final String COMMON_CLASS =
74             "com.android.cts.externalstorageapp.CommonExternalStorageTest";
75 
76     private static final String NONE_APK = "CtsExternalStorageApp.apk";
77     private static final String NONE_PKG = "com.android.cts.externalstorageapp";
78     private static final String NONE_CLASS = NONE_PKG + ".ExternalStorageTest";
79     private static final String READ_APK = "CtsReadExternalStorageApp.apk";
80     private static final String READ_PKG = "com.android.cts.readexternalstorageapp";
81     private static final String READ_CLASS = READ_PKG + ".ReadExternalStorageTest";
82     private static final String WRITE_APK = "CtsWriteExternalStorageApp.apk";
83     private static final String WRITE_PKG = "com.android.cts.writeexternalstorageapp";
84     private static final String WRITE_CLASS = WRITE_PKG + ".WriteExternalStorageTest";
85     private static final String WRITE_APK_2 = "CtsWriteExternalStorageApp2.apk";
86     private static final String WRITE_PKG_2 = "com.android.cts.writeexternalstorageapp2";
87     private static final String MULTIUSER_APK = "CtsMultiUserStorageApp.apk";
88     private static final String MULTIUSER_PKG = "com.android.cts.multiuserstorageapp";
89     private static final String MULTIUSER_CLASS = MULTIUSER_PKG + ".MultiUserStorageTest";
90 
91     private static final String MEDIA_CLAZZ = "com.android.cts.mediastorageapp.MediaStorageTest";
92 
93     private static final Config MEDIA = new Config("CtsMediaStorageApp.apk",
94             "com.android.cts.mediastorageapp", MEDIA_CLAZZ);
95     private static final Config MEDIA_28 = new Config("CtsMediaStorageApp28.apk",
96             "com.android.cts.mediastorageapp28", MEDIA_CLAZZ);
97     private static final Config MEDIA_29 = new Config("CtsMediaStorageApp29.apk",
98             "com.android.cts.mediastorageapp29", MEDIA_CLAZZ);
99 
100     private static final String PERM_ACCESS_MEDIA_LOCATION =
101             "android.permission.ACCESS_MEDIA_LOCATION";
102     private static final String PERM_READ_EXTERNAL_STORAGE =
103             "android.permission.READ_EXTERNAL_STORAGE";
104     private static final String PERM_READ_MEDIA_IMAGES =
105             "android.permission.READ_MEDIA_IMAGES";
106     private static final String PERM_READ_MEDIA_AUDIO =
107             "android.permission.READ_MEDIA_AUDIO";
108     private static final String PERM_READ_MEDIA_VIDEO =
109             "android.permission.READ_MEDIA_VIDEO";
110     private static final String PERM_WRITE_EXTERNAL_STORAGE =
111             "android.permission.WRITE_EXTERNAL_STORAGE";
112 
113     private static final String APP_OPS_MANAGE_EXTERNAL_STORAGE = "android:manage_external_storage";
114     private static final String APP_OPS_MANAGE_MEDIA = "android:manage_media";
115 
116     /** Copied from PackageManager*/
117     private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
118     private static final String FEATURE_EMBEDDED = "android.hardware.type.embedded";
119     private static final String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
120     private static final String FEATURE_WATCH = "android.hardware.type.watch";
121 
122     private int[] mUsers;
123     private boolean mAdbWasRoot;
124 
getTestAppFile(String fileName)125     private File getTestAppFile(String fileName) throws FileNotFoundException {
126         CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild());
127         return buildHelper.getTestFile(fileName);
128     }
129 
130     @Before
setUp()131     public void setUp() throws Exception {
132         mUsers = Utils.prepareMultipleUsers(getDevice());
133         assertNotNull(getAbi());
134         assertNotNull(getBuild());
135 
136         ITestDevice device = getDevice();
137         mAdbWasRoot = device.isAdbRoot();
138         if (mAdbWasRoot) {
139             // This test assumes that the test is not run with root privileges. But this test runs
140             // as a part of appsecurity test suite which contains a lot of other tests. Some of
141             // which may enable adb root, make sure that this test is run without root access.
142             device.disableAdbRoot();
143             assertFalse("adb root is enabled", device.isAdbRoot());
144         }
145     }
146 
147     @Before
148     @After
cleanUp()149     public void cleanUp() throws DeviceNotAvailableException {
150         getDevice().uninstallPackage(NONE_PKG);
151         getDevice().uninstallPackage(READ_PKG);
152         getDevice().uninstallPackage(WRITE_PKG);
153         getDevice().uninstallPackage(MULTIUSER_PKG);
154 
155         wipePrimaryExternalStorage();
156     }
157 
158     @After
tearDown()159     public void tearDown() throws DeviceNotAvailableException {
160         ITestDevice device = getDevice();
161         if (mAdbWasRoot) {
162             device.enableAdbRoot();
163         } else {
164             device.disableAdbRoot();
165         }
166     }
167 
168     @Test
testExternalStorageRename()169     public void testExternalStorageRename() throws Exception {
170         try {
171             wipePrimaryExternalStorage();
172 
173             getDevice().uninstallPackage(WRITE_PKG);
174             installPackage(WRITE_APK);
175 
176             // Make sure user initialization is complete before testing
177             waitForBroadcastIdle();
178 
179             for (int user : mUsers) {
180                 runDeviceTests(WRITE_PKG, WRITE_CLASS, "testExternalStorageRename", user);
181             }
182         } finally {
183             getDevice().uninstallPackage(WRITE_PKG);
184         }
185     }
186 
187     /**
188      * Verify that app with no external storage permissions works correctly.
189      */
190     @Test
testExternalStorageNone29()191     public void testExternalStorageNone29() throws Exception {
192         try {
193             wipePrimaryExternalStorage();
194 
195             getDevice().uninstallPackage(NONE_PKG);
196             String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
197             assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
198 
199             for (int user : mUsers) {
200                 runDeviceTests(NONE_PKG, COMMON_CLASS, user);
201                 runDeviceTests(NONE_PKG, NONE_CLASS, user);
202             }
203         } finally {
204             getDevice().uninstallPackage(NONE_PKG);
205         }
206     }
207 
208     /**
209      * Verify that app with
210      * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} works
211      * correctly.
212      */
213     @Test
testExternalStorageRead29()214     public void testExternalStorageRead29() throws Exception {
215         try {
216             wipePrimaryExternalStorage();
217 
218             getDevice().uninstallPackage(READ_PKG);
219             String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
220             assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
221 
222             for (int user : mUsers) {
223                 runDeviceTests(READ_PKG, COMMON_CLASS, user);
224                 runDeviceTests(READ_PKG, READ_CLASS, user);
225             }
226         } finally {
227             getDevice().uninstallPackage(READ_PKG);
228         }
229     }
230 
231     /**
232      * Verify that app with
233      * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} works
234      * correctly.
235      */
236     @Test
testExternalStorageWrite()237     public void testExternalStorageWrite() throws Exception {
238         try {
239             wipePrimaryExternalStorage();
240 
241             getDevice().uninstallPackage(WRITE_PKG);
242             String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
243             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
244 
245             for (int user : mUsers) {
246                 runDeviceTests(WRITE_PKG, COMMON_CLASS, user);
247                 runDeviceTests(WRITE_PKG, WRITE_CLASS, user);
248             }
249         } finally {
250             getDevice().uninstallPackage(WRITE_PKG);
251         }
252     }
253 
254     /**
255      * Verify that apps can't leave gifts in package specific external storage
256      * directories belonging to other apps. Apps can only create files in their
257      * external storage directories.
258      */
259     @Test
testExternalStorageNoGifts()260     public void testExternalStorageNoGifts() throws Exception {
261         try {
262             wipePrimaryExternalStorage();
263 
264             getDevice().uninstallPackage(NONE_PKG);
265             getDevice().uninstallPackage(READ_PKG);
266             getDevice().uninstallPackage(WRITE_PKG);
267             final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
268 
269             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
270             assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
271             assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
272             for (int user : mUsers) {
273                 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testStageNonGifts", user);
274                 runDeviceTests(READ_PKG, READ_PKG + ".ReadGiftTest", "testStageNonGifts", user);
275                 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testStageNonGifts", user);
276 
277                 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testNoGifts", user);
278                 runDeviceTests(READ_PKG, READ_PKG + ".ReadGiftTest", "testNoGifts", user);
279                 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testNoGifts", user);
280             }
281         } finally {
282             getDevice().uninstallPackage(NONE_PKG);
283             getDevice().uninstallPackage(READ_PKG);
284             getDevice().uninstallPackage(WRITE_PKG);
285         }
286     }
287 
288     /**
289      * Verify that app with REQUEST_INSTALL_PACKAGES can leave gifts in obb
290      * directories belonging to other apps, and those apps can read.
291      */
292     @Test
testCanAccessOtherObbDirs()293     public void testCanAccessOtherObbDirs() throws Exception {
294         try {
295             wipePrimaryExternalStorage();
296 
297             getDevice().uninstallPackage(WRITE_PKG_2);
298             getDevice().uninstallPackage(NONE_PKG);
299             final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
300 
301             // We purposefully delay the installation of the reading apps to
302             // verify that the daemon correctly invalidates any caches.
303             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK_2), false, options));
304             for (int user : mUsers) {
305                 updateAppOp(WRITE_PKG_2, user, "android:request_install_packages", true);
306                 updatePermissions(WRITE_PKG_2, user, new String[] {
307                         PERM_READ_MEDIA_IMAGES,
308                         PERM_READ_MEDIA_VIDEO,
309                         PERM_READ_MEDIA_AUDIO,
310                         PERM_READ_EXTERNAL_STORAGE,
311                         PERM_WRITE_EXTERNAL_STORAGE,
312                 }, true);
313             }
314 
315             for (int user : mUsers) {
316                 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest", "testObbGifts", user);
317             }
318 
319             assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
320             for (int user : mUsers) {
321                 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testObbGifts", user);
322             }
323 
324             for (int user : mUsers) {
325                 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest",
326                         "testAccessObbGifts", user);
327                 updateAppOp(WRITE_PKG_2, user, "android:request_install_packages", false);
328                 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest",
329                         "testCantAccessObbGifts", user);
330             }
331         } finally {
332             getDevice().uninstallPackage(WRITE_PKG_2);
333             getDevice().uninstallPackage(NONE_PKG);
334         }
335     }
336 
337     @Test
testExternalStorageUnsharedObb()338     public void testExternalStorageUnsharedObb() throws Exception {
339         final int numUsers = mUsers.length;
340         Assume.assumeTrue(numUsers > 1);
341 
342         try {
343             wipePrimaryExternalStorage();
344 
345             getDevice().uninstallPackage(NONE_PKG);
346             getDevice().uninstallPackage(WRITE_PKG);
347             final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
348 
349             // We purposefully delay the installation of the reading apps to
350             // verify that the daemon correctly invalidates any caches.
351             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
352             updateAppOp(WRITE_PKG, mUsers[0], "android:request_install_packages", true);
353             runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testObbGifts", mUsers[0]);
354 
355             // Create a file in one user and verify that file is not accessible to other users.
356             assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
357             for (int i = 1; i < numUsers; ++i) {
358                 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testNoObbGifts", mUsers[i]);
359                 updateAppOp(WRITE_PKG, mUsers[i], "android:request_install_packages", true);
360                 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testObbGifts", mUsers[i]);
361             }
362 
363             // Delete a file in one user and verify that it doesn't affect files accessible to
364             // other users.
365             runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testRemoveObbGifts", mUsers[0]);
366             for (int i = 1; i < numUsers; ++i) {
367                 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testObbGifts", mUsers[i]);
368             }
369 
370         } finally {
371             getDevice().uninstallPackage(NONE_PKG);
372             getDevice().uninstallPackage(WRITE_PKG);
373         }
374     }
375 
376     /**
377      * Test multi-user emulated storage environment, ensuring that each user has
378      * isolated storage.
379      */
380     @Test
testMultiUserStorageIsolated()381     public void testMultiUserStorageIsolated() throws Exception {
382         try {
383             if (mUsers.length == 1) {
384                 Log.d(TAG, "Single user device; skipping isolated storage tests");
385                 return;
386             }
387 
388             final int owner = mUsers[0];
389             final int secondary = mUsers[1];
390 
391             // Install our test app
392             getDevice().uninstallPackage(MULTIUSER_PKG);
393             String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
394             final String installResult = getDevice()
395                     .installPackage(getTestAppFile(MULTIUSER_APK), false, options);
396             assertNull("Failed to install: " + installResult, installResult);
397 
398             // Clear data from previous tests
399             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testCleanIsolatedStorage", owner);
400             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testCleanIsolatedStorage", secondary);
401 
402             // Have both users try writing into isolated storage
403             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testWriteIsolatedStorage", owner);
404             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testWriteIsolatedStorage", secondary);
405 
406             // Verify they both have isolated view of storage
407             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", owner);
408             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", secondary);
409 
410             // Verify they can't poke at each other
411             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", owner);
412             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", secondary);
413 
414             // Verify they can't access other users' content using media provider
415             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testMediaProviderUserIsolation", owner);
416             runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testMediaProviderUserIsolation", secondary);
417         } finally {
418             getDevice().uninstallPackage(MULTIUSER_PKG);
419         }
420     }
421 
422     /**
423      * Test that apps with read permissions see the appropriate permissions.
424      */
425     @Test
testMultiViewMoveConsistency()426     public void testMultiViewMoveConsistency() throws Exception {
427         try {
428             wipePrimaryExternalStorage();
429 
430             getDevice().uninstallPackage(NONE_PKG);
431             getDevice().uninstallPackage(READ_PKG);
432             final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
433 
434             assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options));
435 
436             for (int user : mUsers) {
437                 runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testFolderSetup", user);
438             }
439             for (int user : mUsers) {
440                 runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testRWAccess", user);
441             }
442 
443             // for fuse file system
444             Thread.sleep(10000);
445             for (int user : mUsers) {
446                 runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testRWAccess", user);
447             }
448         } finally {
449             getDevice().uninstallPackage(NONE_PKG);
450             getDevice().uninstallPackage(READ_PKG);
451         }
452     }
453 
454     /** Verify that app without READ_EXTERNAL can play default URIs in external storage. */
455     @Test
testExternalStorageReadDefaultUris()456     public void testExternalStorageReadDefaultUris() throws Exception {
457         Throwable existingException = null;
458         try {
459             wipePrimaryExternalStorage();
460 
461             getDevice().uninstallPackage(NONE_PKG);
462             getDevice().uninstallPackage(WRITE_PKG);
463             final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
464 
465             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
466             assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options));
467 
468             for (int user : mUsers) {
469                 updateAppOp(WRITE_PKG, user, "android:write_settings", true);
470                 runDeviceTests(
471                         WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testChangeDefaultUris", user);
472 
473                 runDeviceTests(
474                         NONE_PKG, NONE_PKG + ".ReadDefaultUris", "testPlayDefaultUris", user);
475             }
476         } catch (Throwable t) {
477             Log.e(TAG, "Test exception: " + t);
478             // Don't rethrow if there is already an exception.
479             if (existingException == null) {
480                 existingException = t;
481                 throw t;
482             }
483         } finally {
484             try {
485                 // Make sure the provider and uris are reset on failure.
486                 for (int user : mUsers) {
487                     runDeviceTests(
488                             WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testResetDefaultUris",
489                             user);
490                 }
491                 getDevice().uninstallPackage(NONE_PKG);
492                 getDevice().uninstallPackage(WRITE_PKG);
493             } catch (Throwable t) {
494                 Log.e(TAG, "Cleanup exception: " + t);
495                 // Don't rethrow if there is already an exception.
496                 if (existingException == null) {
497                     existingException = t;
498                     throw t;
499                 }
500             }
501         }
502     }
503 
504     /**
505      * For security reasons, the shell user cannot access the shared storage of
506      * secondary users. Instead, developers should use the {@code content} shell
507      * tool to read/write files in those locations.
508      */
509     @Test
testSecondaryUsersInaccessible()510     public void testSecondaryUsersInaccessible() throws Exception {
511         List<String> mounts = new ArrayList<>();
512         for (String line : getDevice().executeShellCommand("cat /proc/mounts").split("\n")) {
513             String[] split = line.split(" ");
514             if (split[1].startsWith("/storage/") || split[1].startsWith("/mnt/")) {
515                 mounts.add(split[1]);
516             }
517         }
518 
519         for (int user : mUsers) {
520             String probe = "/sdcard/../" + user;
521             if (user == Utils.USER_SYSTEM) {
522                 // Primary user should always be visible. Skip checking raw
523                 // mount points, since we'd get false-positives for physical
524                 // devices that aren't multi-user aware.
525                 assertTrue(probe, access(probe));
526             } else {
527                 // Secondary user should never be visible.
528                 assertFalse(probe, access(probe));
529                 for (String mount : mounts) {
530                     probe = mount + "/" + user;
531                     assertFalse(probe, access(probe));
532                 }
533             }
534         }
535     }
536 
537     @Test
testMediaLegacy28()538     public void testMediaLegacy28() throws Exception {
539         doMediaLegacy(MEDIA_28);
540     }
541     @Test
testMediaLegacy29()542     public void testMediaLegacy29() throws Exception {
543         doMediaLegacy(MEDIA_29);
544     }
545 
doMediaLegacy(Config config)546     private void doMediaLegacy(Config config) throws Exception {
547         installPackage(config.apk);
548         installPackage(MEDIA_29.apk);
549         // Make sure user initialization is complete before updating permission
550         waitForBroadcastIdle();
551         for (int user : mUsers) {
552             updatePermissions(config.pkg, user, new String[] {
553                     PERM_READ_MEDIA_IMAGES,
554                     PERM_READ_MEDIA_VIDEO,
555                     PERM_READ_MEDIA_AUDIO,
556                     PERM_READ_EXTERNAL_STORAGE,
557                     PERM_WRITE_EXTERNAL_STORAGE,
558             }, true);
559             updatePermissions(MEDIA_29.pkg, user, new String[] {
560                     PERM_READ_EXTERNAL_STORAGE,
561                     PERM_WRITE_EXTERNAL_STORAGE,
562             }, true);
563 
564             // Create the files needed for the test from MEDIA_29 pkg since shell
565             // can't access secondary user's storage.
566             runDeviceTests(MEDIA_29.pkg, MEDIA_29.clazz, "testStageFiles", user);
567             runDeviceTests(config.pkg, config.clazz, "testLegacy", user);
568             runDeviceTests(MEDIA_29.pkg, MEDIA_29.clazz, "testClearFiles", user);
569         }
570     }
571 
572     /**
573      * b/197302116. The apps can't be granted prefix UriPermissions to the uri, when the query
574      * result of the uri is 1.
575      */
576     @Test
testOwningOneFileNotGrantPrefixUriPermission()577     public void testOwningOneFileNotGrantPrefixUriPermission() throws Exception {
578         installPackage(MEDIA.apk);
579 
580         int user = getDevice().getCurrentUser();
581 
582         // revoke permissions
583         updatePermissions(MEDIA.pkg, user, new String[] {
584                 PERM_READ_MEDIA_IMAGES,
585                 PERM_READ_MEDIA_VIDEO,
586                 PERM_READ_MEDIA_AUDIO,
587                 PERM_READ_EXTERNAL_STORAGE,
588                 PERM_WRITE_EXTERNAL_STORAGE,
589         }, false);
590 
591 
592         // revoke the app ops permission
593         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_EXTERNAL_STORAGE, false);
594 
595         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
596                 "testOwningOneFileNotGrantPrefixUriPermission", user);
597     }
598 
599     /**
600      * If the app grants read UriPermission to the uri without id (E.g.
601      * MediaStore.Audio.Media.EXTERNAL_CONTENT_URI), the query result of the uri should be the same
602      * without granting permission.
603      */
604     @Test
testReadUriPermissionOnUriWithoutId_sameQueryResult()605     public void testReadUriPermissionOnUriWithoutId_sameQueryResult() throws Exception {
606         installPackage(MEDIA.apk);
607 
608         int user = getDevice().getCurrentUser();
609 
610         // revoke permissions
611         updatePermissions(MEDIA.pkg, user, new String[] {
612                 PERM_READ_MEDIA_IMAGES,
613                 PERM_READ_MEDIA_VIDEO,
614                 PERM_READ_MEDIA_AUDIO,
615                 PERM_READ_EXTERNAL_STORAGE,
616                 PERM_WRITE_EXTERNAL_STORAGE,
617         }, false);
618 
619 
620         // revoke the app ops permission
621         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_EXTERNAL_STORAGE, false);
622 
623         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
624                 "testReadUriPermissionOnUriWithoutId_sameQueryResult", user);
625     }
626 
627     @Test
testGrantUriPermission()628     public void testGrantUriPermission() throws Exception {
629         doGrantUriPermission(MEDIA, "testGrantUriPermission", new String[]{});
630         doGrantUriPermission(MEDIA, "testGrantUriPermission",
631                 new String[]{PERM_READ_MEDIA_IMAGES, PERM_READ_MEDIA_VIDEO,
632                     PERM_READ_MEDIA_AUDIO, PERM_READ_EXTERNAL_STORAGE});
633         doGrantUriPermission(MEDIA, "testGrantUriPermission",
634                 new String[]{PERM_READ_EXTERNAL_STORAGE, PERM_READ_MEDIA_IMAGES,
635                     PERM_READ_MEDIA_VIDEO, PERM_READ_MEDIA_AUDIO, PERM_WRITE_EXTERNAL_STORAGE});
636     }
637 
638     @Test
testGrantUriPermission29()639     public void testGrantUriPermission29() throws Exception {
640         doGrantUriPermission(MEDIA_29, "testGrantUriPermission", new String[]{});
641         doGrantUriPermission(MEDIA_29, "testGrantUriPermission",
642                 new String[]{PERM_READ_EXTERNAL_STORAGE});
643         doGrantUriPermission(MEDIA_29, "testGrantUriPermission",
644                 new String[]{PERM_READ_EXTERNAL_STORAGE, PERM_WRITE_EXTERNAL_STORAGE});
645     }
646 
doGrantUriPermission(Config config, String method, String[] grantPermissions)647     private void doGrantUriPermission(Config config, String method, String[] grantPermissions)
648             throws Exception {
649         uninstallPackage(config.apk);
650         installPackage(config.apk);
651         for (int user : mUsers) {
652             // Over revoke all permissions and grant necessary permissions later.
653             updatePermissions(config.pkg, user, new String[] {
654                     PERM_READ_MEDIA_IMAGES,
655                     PERM_READ_MEDIA_VIDEO,
656                     PERM_READ_MEDIA_AUDIO,
657                     PERM_READ_EXTERNAL_STORAGE,
658                     PERM_WRITE_EXTERNAL_STORAGE,
659             }, false);
660             updatePermissions(config.pkg, user, grantPermissions, true);
661             runDeviceTests(config.pkg, config.clazz, method, user);
662         }
663     }
664 
665     @Test
testMediaNone()666     public void testMediaNone() throws Exception {
667         doMediaNone(MEDIA);
668     }
669     @Test
testMediaNone28()670     public void testMediaNone28() throws Exception {
671         doMediaNone(MEDIA_28);
672     }
673     @Test
testMediaNone29()674     public void testMediaNone29() throws Exception {
675         doMediaNone(MEDIA_29);
676     }
677 
doMediaNone(Config config)678     private void doMediaNone(Config config) throws Exception {
679         installPackage(config.apk);
680         for (int user : mUsers) {
681             updatePermissions(config.pkg, user, new String[] {
682                     PERM_READ_MEDIA_IMAGES,
683                     PERM_READ_MEDIA_VIDEO,
684                     PERM_READ_MEDIA_AUDIO,
685                     PERM_READ_EXTERNAL_STORAGE,
686                     PERM_WRITE_EXTERNAL_STORAGE,
687             }, false);
688 
689             runDeviceTests(config.pkg, config.clazz, "testMediaNone", user);
690         }
691     }
692 
693     @Test
testMediaRead()694     public void testMediaRead() throws Exception {
695         doMediaRead(MEDIA);
696     }
697     @Test
testMediaRead28()698     public void testMediaRead28() throws Exception {
699         doMediaRead(MEDIA_28);
700     }
701     @Test
testMediaRead29()702     public void testMediaRead29() throws Exception {
703         doMediaRead(MEDIA_29);
704     }
705 
doMediaRead(Config config)706     private void doMediaRead(Config config) throws Exception {
707         installPackage(config.apk);
708         for (int user : mUsers) {
709             updatePermissions(config.pkg, user, new String[] {
710                     PERM_READ_MEDIA_IMAGES,
711                     PERM_READ_MEDIA_VIDEO,
712                     PERM_READ_MEDIA_AUDIO,
713                     PERM_READ_EXTERNAL_STORAGE,
714             }, true);
715             updatePermissions(config.pkg, user, new String[] {
716                     PERM_WRITE_EXTERNAL_STORAGE,
717             }, false);
718 
719             runDeviceTests(config.pkg, config.clazz, "testMediaRead", user);
720         }
721     }
722 
723     @Test
testMediaWrite()724     public void testMediaWrite() throws Exception {
725         doMediaWrite(MEDIA);
726     }
727     @Test
testMediaWrite28()728     public void testMediaWrite28() throws Exception {
729         doMediaWrite(MEDIA_28);
730     }
731     @Test
testMediaWrite29()732     public void testMediaWrite29() throws Exception {
733         doMediaWrite(MEDIA_29);
734     }
735 
doMediaWrite(Config config)736     private void doMediaWrite(Config config) throws Exception {
737         installPackage(config.apk);
738         for (int user : mUsers) {
739             updatePermissions(config.pkg, user, new String[] {
740                     PERM_READ_MEDIA_IMAGES,
741                     PERM_READ_MEDIA_VIDEO,
742                     PERM_READ_MEDIA_AUDIO,
743                     PERM_READ_EXTERNAL_STORAGE,
744                     PERM_WRITE_EXTERNAL_STORAGE,
745             }, true);
746 
747             runDeviceTests(config.pkg, config.clazz, "testMediaWrite", user);
748         }
749     }
750 
751     @Test
testMediaEscalation_RequestWriteFilePathSupport()752     public void testMediaEscalation_RequestWriteFilePathSupport() throws Exception {
753         // Not adding tests for MEDIA_28 and MEDIA_29 as they need W_E_S for write access via file
754         // path for shared files, and will always have access as they have W_E_S.
755         installPackage(MEDIA.apk);
756 
757         int user = getDevice().getCurrentUser();
758         // revoke all permissions
759         updatePermissions(MEDIA.pkg, user, new String[] {
760                 PERM_ACCESS_MEDIA_LOCATION,
761                 PERM_READ_MEDIA_IMAGES,
762                 PERM_READ_MEDIA_VIDEO,
763                 PERM_READ_MEDIA_AUDIO,
764                 PERM_READ_EXTERNAL_STORAGE,
765                 PERM_WRITE_EXTERNAL_STORAGE,
766         }, false);
767 
768         // revoke the app ops permission
769         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_MEDIA, false);
770         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_EXTERNAL_STORAGE, false);
771 
772         runDeviceTests(MEDIA.pkg, MEDIA.clazz, "testMediaEscalation_RequestWriteFilePathSupport",
773                 user);
774     }
775 
776     @Test
testMediaEscalation()777     public void testMediaEscalation() throws Exception {
778         doMediaEscalation(MEDIA);
779     }
780     @Test
testMediaEscalation28()781     public void testMediaEscalation28() throws Exception {
782         doMediaEscalation(MEDIA_28);
783     }
784     @Test
testMediaEscalation29()785     public void testMediaEscalation29() throws Exception {
786         doMediaEscalation(MEDIA_29);
787     }
788 
doMediaEscalation(Config config)789     private void doMediaEscalation(Config config) throws Exception {
790         installPackage(config.apk);
791 
792         // TODO: extend test to exercise secondary users
793         int user = getDevice().getCurrentUser();
794         updatePermissions(config.pkg, user, new String[] {
795                 PERM_READ_MEDIA_IMAGES,
796                 PERM_READ_MEDIA_VIDEO,
797                 PERM_READ_MEDIA_AUDIO,
798                 PERM_READ_EXTERNAL_STORAGE,
799         }, true);
800         updatePermissions(config.pkg, user, new String[] {
801                 PERM_WRITE_EXTERNAL_STORAGE,
802         }, false);
803 
804         runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Open", user);
805         runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Update", user);
806         runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Delete", user);
807 
808         runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_RequestWrite", user);
809         runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_RequestTrash", user);
810         runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_RequestFavorite", user);
811         runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_RequestDelete", user);
812     }
813 
814     @Test
testExternalStorageClearing()815     public void testExternalStorageClearing() throws Exception {
816         String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
817 
818         try {
819             getDevice().uninstallPackage(WRITE_PKG);
820             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
821             for (int user : mUsers) {
822                 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testClearingWrite", user);
823             }
824 
825             // Uninstall and reinstall means all storage should be cleared
826             getDevice().uninstallPackage(WRITE_PKG);
827             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
828             for (int user : mUsers) {
829                 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testClearingRead", user);
830             }
831         } finally {
832             getDevice().uninstallPackage(WRITE_PKG);
833         }
834     }
835 
836     @Test
testIsExternalStorageLegacy()837     public void testIsExternalStorageLegacy() throws Exception {
838         String[] options = {AbiUtils.createAbiFlag(getAbi().getName())};
839 
840         try {
841             getDevice().uninstallPackage(WRITE_PKG);
842             getDevice().uninstallPackage(WRITE_PKG_2);
843             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options));
844             assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK_2), false, options));
845             for (int user : mUsers) {
846                 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest",
847                         "testIsExternalStorageLegacy", user);
848                 updatePermissions(WRITE_PKG, user, new String[] {
849                         PERM_READ_EXTERNAL_STORAGE,
850                         PERM_WRITE_EXTERNAL_STORAGE,
851                 }, false);
852                 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest",
853                         "testIsExternalStorageLegacy", user);
854 
855                 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest",
856                         "testNotIsExternalStorageLegacy", user);
857             }
858         } finally {
859             getDevice().uninstallPackage(WRITE_PKG);
860             getDevice().uninstallPackage(WRITE_PKG_2);
861         }
862     }
863 
864     /**
865      * Check the behavior when the app calls MediaStore#createTrashRequest,
866      * MediaStore#createDeleteRequest or MediaStore#createWriteRequest, the user
867      * click the deny button on confirmation dialog.
868      *
869      * @throws Exception
870      */
871     @Test
testCreateRequest_userDenied()872     public void testCreateRequest_userDenied() throws Exception {
873         installPackage(MEDIA.apk);
874 
875         int user = getDevice().getCurrentUser();
876 
877         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
878                 "testMediaEscalationWithDenied_RequestWrite", user);
879         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
880                 "testMediaEscalationWithDenied_RequestDelete", user);
881         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
882                 "testMediaEscalationWithDenied_RequestTrash", user);
883         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
884                 "testMediaEscalationWithDenied_RequestUnTrash", user);
885     }
886 
887     /**
888      * If the app is NOT granted {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
889      * and {@link android.Manifest.permission#MANAGE_EXTERNAL_STORAGE}
890      * when it calls MediaStore#createTrashRequest,
891      * MediaStore#createDeleteRequest, or MediaStore#createWriteRequest,
892      * the system will show the user confirmation dialog.
893      *
894      * @throws Exception
895      */
896     @Test
testCreateRequest_noRESAndMES_showConfirmDialog()897     public void testCreateRequest_noRESAndMES_showConfirmDialog() throws Exception {
898         installPackage(MEDIA.apk);
899 
900         int user = getDevice().getCurrentUser();
901 
902         // grant permissions
903         updatePermissions(MEDIA.pkg, user, new String[] {
904                 PERM_ACCESS_MEDIA_LOCATION,
905         }, true);
906         // revoke permissions
907         updatePermissions(MEDIA.pkg, user, new String[] {
908                 PERM_READ_MEDIA_IMAGES,
909                 PERM_READ_MEDIA_VIDEO,
910                 PERM_READ_MEDIA_AUDIO,
911                 PERM_READ_EXTERNAL_STORAGE,
912                 PERM_WRITE_EXTERNAL_STORAGE,
913         }, false);
914 
915 
916         // revoke the app ops permission
917         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_EXTERNAL_STORAGE, false);
918 
919         // grant the app ops permission
920         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_MEDIA, true);
921 
922         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
923                 "testMediaEscalation_RequestWrite_showConfirmDialog", user);
924     }
925 
926     /**
927      * If the app is NOT granted {@link android.Manifest.permission#MANAGE_MEDIA},
928      * when it calls MediaStore#createTrashRequest,
929      * MediaStore#createDeleteRequest, or MediaStore#createWriteRequest,
930      * the system will show the user confirmation dialog.
931      *
932      * @throws Exception
933      */
934     @Test
testCreateRequest_noMANAGEMEDIA_showConfirmDialog()935     public void testCreateRequest_noMANAGEMEDIA_showConfirmDialog() throws Exception {
936         installPackage(MEDIA.apk);
937 
938         int user = getDevice().getCurrentUser();
939         // grant permissions
940         updatePermissions(MEDIA.pkg, user, new String[] {
941                 PERM_READ_MEDIA_IMAGES,
942                 PERM_READ_MEDIA_VIDEO,
943                 PERM_READ_MEDIA_AUDIO,
944                 PERM_READ_EXTERNAL_STORAGE,
945                 PERM_ACCESS_MEDIA_LOCATION,
946         }, true);
947 
948         // revoke the app ops permission
949         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_MEDIA, false);
950 
951         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
952                 "testMediaEscalation_RequestWrite_showConfirmDialog", user);
953         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
954                 "testMediaEscalation_RequestTrash_showConfirmDialog", user);
955         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
956                 "testMediaEscalation_RequestDelete_showConfirmDialog", user);
957     }
958 
959     /**
960      * If the app is granted {@link android.Manifest.permission#MANAGE_MEDIA},
961      * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}, without
962      * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION},
963      * when it calls MediaStore#createTrashRequest or
964      * MediaStore#createDeleteRequest, The system will NOT show the user
965      * confirmation dialog. When it calls MediaStore#createWriteRequest, the
966      * system will show the user confirmation dialog.
967      *
968      * @throws Exception
969      */
970     @Test
testCreateRequest_withNoAML_showConfirmDialog()971     public void testCreateRequest_withNoAML_showConfirmDialog() throws Exception {
972         installPackage(MEDIA.apk);
973 
974         int user = getDevice().getCurrentUser();
975         // grant permissions
976         updatePermissions(MEDIA.pkg, user, new String[] {
977                 PERM_READ_MEDIA_IMAGES,
978                 PERM_READ_MEDIA_VIDEO,
979                 PERM_READ_MEDIA_AUDIO,
980                 PERM_READ_EXTERNAL_STORAGE,
981         }, true);
982         // revoke permission
983         updatePermissions(MEDIA.pkg, user, new String[] {
984                 PERM_ACCESS_MEDIA_LOCATION,
985         }, false);
986 
987         // grant the app ops permission
988         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_MEDIA, true);
989 
990         // show confirm dialog in requestWrite
991         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
992                 "testMediaEscalation_RequestWrite_showConfirmDialog", user);
993 
994         // not show confirm dialog in requestTrash and requestDelete
995         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
996                 "testMediaEscalation_RequestTrash_notShowConfirmDialog", user);
997         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
998                 "testMediaEscalation_RequestDelete_notShowConfirmDialog", user);
999     }
1000 
1001     /**
1002      * If the app is granted {@link android.Manifest.permission#MANAGE_MEDIA},
1003      * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}, and
1004      * {@link android.Manifest.permission#ACCESS_MEDIA_LOCATION},
1005      * when it calls MediaStore#createWriteRequest, MediaStore#createTrashRequest or
1006      * MediaStore#createDeleteRequest, the system will NOT show the user confirmation dialog.
1007      *
1008      * @throws Exception
1009      */
1010     @Test
testCreateRequest_withPermission_notShowConfirmDialog()1011     public void testCreateRequest_withPermission_notShowConfirmDialog() throws Exception {
1012         installPackage(MEDIA.apk);
1013 
1014         int user = getDevice().getCurrentUser();
1015         // grant permissions
1016         updatePermissions(MEDIA.pkg, user, new String[] {
1017                 PERM_READ_MEDIA_IMAGES,
1018                 PERM_READ_MEDIA_VIDEO,
1019                 PERM_READ_MEDIA_AUDIO,
1020                 PERM_READ_EXTERNAL_STORAGE,
1021                 PERM_ACCESS_MEDIA_LOCATION,
1022         }, true);
1023 
1024         // revoke the app ops permission
1025         updateAppOp(MEDIA.pkg, user, APP_OPS_MANAGE_MEDIA, true);
1026 
1027         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
1028                 "testMediaEscalation_RequestWrite_notShowConfirmDialog", user);
1029         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
1030                 "testMediaEscalation_RequestTrash_notShowConfirmDialog", user);
1031         runDeviceTests(MEDIA.pkg, MEDIA.clazz,
1032                 "testMediaEscalation_RequestDelete_notShowConfirmDialog", user);
1033     }
1034 
getDump(Parser<T> parser, String command)1035     private <T extends MessageLite> T getDump(Parser<T> parser, String command) throws Exception {
1036         final CollectingByteOutputReceiver receiver = new CollectingByteOutputReceiver();
1037         getDevice().executeShellCommand(command, receiver);
1038         return parser.parseFrom(receiver.getOutput());
1039     }
1040 
getAllUsersRoleStates()1041     private List<RoleUserStateProto> getAllUsersRoleStates() throws Exception {
1042         final RoleServiceDumpProto dumpProto =
1043                 getDump(RoleServiceDumpProto.parser(), "dumpsys role --proto");
1044         final List<RoleUserStateProto> res = new ArrayList<>();
1045         for (RoleUserStateProto userState : dumpProto.getUserStatesList()) {
1046             for (int i : mUsers) {
1047                 if (i == userState.getUserId()) {
1048                     res.add(userState);
1049                     break;
1050                 }
1051             }
1052         }
1053         return res;
1054     }
1055 
1056     /**
1057      * Bypasses the calling test case if ANY of the given features is available in the device.
1058      */
bypassTestForFeatures(String... features)1059     private void bypassTestForFeatures(String... features) throws DeviceNotAvailableException {
1060         final String featureList = getDevice().executeShellCommand("pm list features");
1061         for (String feature : features) {
1062             Assume.assumeFalse(featureList.contains(feature));
1063         }
1064     }
1065 
1066     @Test
testSystemGalleryExists()1067     public void testSystemGalleryExists() throws Exception {
1068         // Watches, TVs and IoT devices are not obligated to have a system gallery
1069         bypassTestForFeatures(FEATURE_AUTOMOTIVE, FEATURE_EMBEDDED, FEATURE_LEANBACK_ONLY,
1070                 FEATURE_WATCH);
1071 
1072         final List<RoleUserStateProto> usersRoleStates = getAllUsersRoleStates();
1073 
1074         assertEquals("Unexpected number of users returned by dumpsys role",
1075                 mUsers.length, usersRoleStates.size());
1076 
1077         for (RoleUserStateProto userState : usersRoleStates) {
1078             final List<RoleProto> roles = userState.getRolesList();
1079             boolean systemGalleryRoleFound = false;
1080 
1081             // Iterate through the roles until we find the System Gallery role
1082             for (RoleProto roleProto : roles) {
1083                 if ("android.app.role.SYSTEM_GALLERY".equals(roleProto.getName())) {
1084                     assertEquals(1, roleProto.getHoldersList().size());
1085                     systemGalleryRoleFound = true;
1086                     break;
1087                 }
1088             }
1089             assertTrue("SYSTEM_GALLERY not defined for user " + userState.getUserId(),
1090                     systemGalleryRoleFound);
1091         }
1092     }
1093 
access(String path)1094     private boolean access(String path) throws DeviceNotAvailableException {
1095         final long nonce = System.nanoTime();
1096         return getDevice().executeShellCommand("ls -la " + path + " && echo " + nonce)
1097                 .contains(Long.toString(nonce));
1098     }
1099 
updatePermissions(String packageName, int userId, String[] permissions, boolean grant)1100     private void updatePermissions(String packageName, int userId, String[] permissions,
1101             boolean grant) throws Exception {
1102         final String verb = grant ? "grant" : "revoke";
1103         for (String permission : permissions) {
1104             getDevice().executeShellCommand(
1105                     "cmd package " + verb + " --user " + userId + " --uid " + packageName + " "
1106                             + permission);
1107         }
1108     }
1109 
1110     /** Wait until all broadcast queues are idle. */
waitForBroadcastIdle()1111     private void waitForBroadcastIdle() throws Exception{
1112         getDevice().executeShellCommand("am wait-for-broadcast-idle");
1113     }
1114 
updateAppOp(String packageName, int userId, String appOp, boolean allow)1115     private void updateAppOp(String packageName, int userId, String appOp, boolean allow)
1116             throws Exception {
1117         updateAppOp(packageName, false, userId, appOp, allow);
1118     }
1119 
updateAppOp(String packageName, boolean targetsUid, int userId, String appOp, boolean allow)1120     private void updateAppOp(String packageName, boolean targetsUid, int userId,
1121             String appOp, boolean allow)
1122             throws Exception {
1123         final String verb = allow ? "allow" : "default";
1124         getDevice().executeShellCommand(
1125                 "cmd appops set --user " + userId + (targetsUid ? " --uid " : " ") + packageName
1126                         + " " + appOp + " " + verb);
1127     }
1128 
wipePrimaryExternalStorage()1129     private void wipePrimaryExternalStorage() throws DeviceNotAvailableException {
1130         // Can't delete everything under /sdcard as that's going to remove the mounts.
1131         getDevice().executeShellCommand("find /sdcard -type f -delete");
1132         getDevice().executeShellCommand("rm -rf /sdcard/DCIM/*");
1133         getDevice().executeShellCommand("rm -rf /sdcard/MUST_*");
1134     }
1135 
runDeviceTests(String packageName, String testClassName, int userId)1136     private void runDeviceTests(String packageName, String testClassName, int userId)
1137             throws DeviceNotAvailableException {
1138         runDeviceTests(getDevice(), packageName, testClassName, null, userId, null);
1139     }
1140 
runDeviceTests(String packageName, String testClassName, String testMethodName, int userId)1141     private void runDeviceTests(String packageName, String testClassName, String testMethodName,
1142             int userId) throws DeviceNotAvailableException {
1143         runDeviceTests(getDevice(), packageName, testClassName, testMethodName, userId, null);
1144     }
1145 }
1146