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