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.assertFalse; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertNull; 22 import static org.junit.Assert.assertTrue; 23 24 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; 25 import com.android.ddmlib.Log; 26 import com.android.tradefed.device.DeviceNotAvailableException; 27 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 28 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 29 import com.android.tradefed.util.AbiUtils; 30 31 import org.junit.After; 32 import org.junit.Assume; 33 import org.junit.Before; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 37 import java.io.File; 38 import java.io.FileNotFoundException; 39 import java.util.ArrayList; 40 import java.util.Arrays; 41 import java.util.List; 42 43 /** 44 * Set of tests that verify behavior of external storage devices. 45 */ 46 @RunWith(DeviceJUnit4ClassRunner.class) 47 public class ExternalStorageHostTest extends BaseHostJUnit4Test { 48 private static final String TAG = "ExternalStorageHostTest"; 49 50 private static class Config { 51 public final String apk; 52 public final String pkg; 53 public final String clazz; 54 Config(String apk, String pkg, String clazz)55 public Config(String apk, String pkg, String clazz) { 56 this.apk = apk; 57 this.pkg = pkg; 58 this.clazz = clazz; 59 } 60 } 61 62 private static final String COMMON_CLASS = 63 "com.android.cts.externalstorageapp.CommonExternalStorageTest"; 64 65 private static final String NONE_APK = "CtsExternalStorageApp.apk"; 66 private static final String NONE_PKG = "com.android.cts.externalstorageapp"; 67 private static final String NONE_CLASS = NONE_PKG + ".ExternalStorageTest"; 68 private static final String READ_APK = "CtsReadExternalStorageApp.apk"; 69 private static final String READ_PKG = "com.android.cts.readexternalstorageapp"; 70 private static final String READ_CLASS = READ_PKG + ".ReadExternalStorageTest"; 71 private static final String WRITE_APK = "CtsWriteExternalStorageApp.apk"; 72 private static final String WRITE_PKG = "com.android.cts.writeexternalstorageapp"; 73 private static final String WRITE_CLASS = WRITE_PKG + ".WriteExternalStorageTest"; 74 private static final String WRITE_APK_2 = "CtsWriteExternalStorageApp2.apk"; 75 private static final String WRITE_PKG_2 = "com.android.cts.writeexternalstorageapp2"; 76 private static final String MULTIUSER_APK = "CtsMultiUserStorageApp.apk"; 77 private static final String MULTIUSER_PKG = "com.android.cts.multiuserstorageapp"; 78 private static final String MULTIUSER_CLASS = MULTIUSER_PKG + ".MultiUserStorageTest"; 79 80 private static final String MEDIA_CLAZZ = "com.android.cts.mediastorageapp.MediaStorageTest"; 81 82 private static final Config MEDIA = new Config("CtsMediaStorageApp.apk", 83 "com.android.cts.mediastorageapp", MEDIA_CLAZZ); 84 private static final Config MEDIA_28 = new Config("CtsMediaStorageApp28.apk", 85 "com.android.cts.mediastorageapp28", MEDIA_CLAZZ); 86 private static final Config MEDIA_FULL = new Config("CtsMediaStorageAppFull.apk", 87 "com.android.cts.mediastorageappfull", MEDIA_CLAZZ); 88 89 private static final String PERM_READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE"; 90 private static final String PERM_WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE"; 91 92 private int[] mUsers; 93 getTestAppFile(String fileName)94 private File getTestAppFile(String fileName) throws FileNotFoundException { 95 CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild()); 96 return buildHelper.getTestFile(fileName); 97 } 98 99 @Before setUp()100 public void setUp() throws Exception { 101 mUsers = Utils.prepareMultipleUsers(getDevice()); 102 assertNotNull(getAbi()); 103 assertNotNull(getBuild()); 104 } 105 106 @Before 107 @After cleanUp()108 public void cleanUp() throws DeviceNotAvailableException { 109 getDevice().uninstallPackage(NONE_PKG); 110 getDevice().uninstallPackage(READ_PKG); 111 getDevice().uninstallPackage(WRITE_PKG); 112 getDevice().uninstallPackage(MULTIUSER_PKG); 113 114 wipePrimaryExternalStorage(); 115 } 116 117 @Test testExternalStorageRename()118 public void testExternalStorageRename() throws Exception { 119 try { 120 wipePrimaryExternalStorage(); 121 122 getDevice().uninstallPackage(WRITE_PKG); 123 installPackage(WRITE_APK); 124 125 for (int user : mUsers) { 126 runDeviceTests(WRITE_PKG, WRITE_CLASS, "testExternalStorageRename", user); 127 } 128 } finally { 129 getDevice().uninstallPackage(WRITE_PKG); 130 } 131 } 132 133 /** 134 * Verify that app with no external storage permissions works correctly. 135 */ 136 @Test testExternalStorageNone()137 public void testExternalStorageNone() throws Exception { 138 try { 139 wipePrimaryExternalStorage(); 140 141 getDevice().uninstallPackage(NONE_PKG); 142 String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 143 assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options)); 144 145 for (int user : mUsers) { 146 runDeviceTests(NONE_PKG, COMMON_CLASS, user); 147 runDeviceTests(NONE_PKG, NONE_CLASS, user); 148 } 149 } finally { 150 getDevice().uninstallPackage(NONE_PKG); 151 } 152 } 153 154 /** 155 * Verify that app with 156 * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} works 157 * correctly. 158 */ 159 @Test testExternalStorageRead()160 public void testExternalStorageRead() throws Exception { 161 try { 162 wipePrimaryExternalStorage(); 163 164 getDevice().uninstallPackage(READ_PKG); 165 String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 166 assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options)); 167 168 for (int user : mUsers) { 169 runDeviceTests(READ_PKG, COMMON_CLASS, user); 170 runDeviceTests(READ_PKG, READ_CLASS, user); 171 } 172 } finally { 173 getDevice().uninstallPackage(READ_PKG); 174 } 175 } 176 177 /** 178 * Verify that app with 179 * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} works 180 * correctly. 181 */ 182 @Test testExternalStorageWrite()183 public void testExternalStorageWrite() throws Exception { 184 try { 185 wipePrimaryExternalStorage(); 186 187 getDevice().uninstallPackage(WRITE_PKG); 188 String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 189 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options)); 190 191 for (int user : mUsers) { 192 runDeviceTests(WRITE_PKG, COMMON_CLASS, user); 193 runDeviceTests(WRITE_PKG, WRITE_CLASS, user); 194 } 195 } finally { 196 getDevice().uninstallPackage(WRITE_PKG); 197 } 198 } 199 200 /** 201 * Verify that app with WRITE_EXTERNAL can leave gifts in external storage 202 * directories belonging to other apps, and those apps can read. 203 */ 204 @Test testExternalStorageGifts()205 public void testExternalStorageGifts() throws Exception { 206 try { 207 wipePrimaryExternalStorage(); 208 209 getDevice().uninstallPackage(NONE_PKG); 210 getDevice().uninstallPackage(READ_PKG); 211 getDevice().uninstallPackage(WRITE_PKG); 212 final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 213 214 // We purposefully delay the installation of the reading apps to 215 // verify that the daemon correctly invalidates any caches. 216 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options)); 217 for (int user : mUsers) { 218 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testGifts", user); 219 } 220 221 assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options)); 222 assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options)); 223 for (int user : mUsers) { 224 runDeviceTests(READ_PKG, READ_PKG + ".ReadGiftTest", "testGifts", user); 225 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testGifts", user); 226 } 227 } finally { 228 getDevice().uninstallPackage(NONE_PKG); 229 getDevice().uninstallPackage(READ_PKG); 230 getDevice().uninstallPackage(WRITE_PKG); 231 } 232 } 233 234 @Test testExternalStorageObbGifts()235 public void testExternalStorageObbGifts() throws Exception { 236 try { 237 wipePrimaryExternalStorage(); 238 239 getDevice().uninstallPackage(WRITE_PKG_2); 240 getDevice().uninstallPackage(NONE_PKG); 241 final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 242 243 // We purposefully delay the installation of the reading apps to 244 // verify that the daemon correctly invalidates any caches. 245 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK_2), false, options)); 246 for (int user : mUsers) { 247 updateAppOp(WRITE_PKG_2, user, "android:request_install_packages", true); 248 updatePermissions(WRITE_PKG_2, user, new String[] { 249 PERM_READ_EXTERNAL_STORAGE, 250 PERM_WRITE_EXTERNAL_STORAGE, 251 }, true); 252 } 253 254 for (int user : mUsers) { 255 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest", "testObbGifts", user); 256 } 257 258 assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options)); 259 for (int user : mUsers) { 260 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testObbGifts", user); 261 } 262 263 for (int user : mUsers) { 264 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest", 265 "testAccessObbGifts", user); 266 updateAppOp(WRITE_PKG_2, user, "android:request_install_packages", false); 267 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest", 268 "testCantAccessObbGifts", user); 269 } 270 } finally { 271 getDevice().uninstallPackage(WRITE_PKG_2); 272 getDevice().uninstallPackage(NONE_PKG); 273 } 274 } 275 276 @Test testExternalStorageUnsharedObb()277 public void testExternalStorageUnsharedObb() throws Exception { 278 final int numUsers = mUsers.length; 279 Assume.assumeTrue(numUsers > 1); 280 281 try { 282 wipePrimaryExternalStorage(); 283 284 getDevice().uninstallPackage(NONE_PKG); 285 getDevice().uninstallPackage(WRITE_PKG); 286 final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 287 288 // We purposefully delay the installation of the reading apps to 289 // verify that the daemon correctly invalidates any caches. 290 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options)); 291 updateAppOp(WRITE_PKG, mUsers[0], "android:request_install_packages", true); 292 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testObbGifts", mUsers[0]); 293 294 // Create a file in one user and verify that file is not accessible to other users. 295 assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options)); 296 for (int i = 1; i < numUsers; ++i) { 297 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testNoObbGifts", mUsers[i]); 298 updateAppOp(WRITE_PKG, mUsers[i], "android:request_install_packages", true); 299 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testObbGifts", mUsers[i]); 300 } 301 302 // Delete a file in one user and verify that it doesn't affect files accessible to 303 // other users. 304 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testRemoveObbGifts", mUsers[0]); 305 for (int i = 1; i < numUsers; ++i) { 306 runDeviceTests(NONE_PKG, NONE_PKG + ".GiftTest", "testObbGifts", mUsers[i]); 307 } 308 309 } finally { 310 getDevice().uninstallPackage(NONE_PKG); 311 getDevice().uninstallPackage(WRITE_PKG); 312 } 313 } 314 315 /** 316 * Test multi-user emulated storage environment, ensuring that each user has 317 * isolated storage. 318 */ 319 @Test testMultiUserStorageIsolated()320 public void testMultiUserStorageIsolated() throws Exception { 321 try { 322 if (mUsers.length == 1) { 323 Log.d(TAG, "Single user device; skipping isolated storage tests"); 324 return; 325 } 326 327 final int owner = mUsers[0]; 328 final int secondary = mUsers[1]; 329 330 // Install our test app 331 getDevice().uninstallPackage(MULTIUSER_PKG); 332 String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 333 final String installResult = getDevice() 334 .installPackage(getTestAppFile(MULTIUSER_APK), false, options); 335 assertNull("Failed to install: " + installResult, installResult); 336 337 // Clear data from previous tests 338 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testCleanIsolatedStorage", owner); 339 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testCleanIsolatedStorage", secondary); 340 341 // Have both users try writing into isolated storage 342 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testWriteIsolatedStorage", owner); 343 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testWriteIsolatedStorage", secondary); 344 345 // Verify they both have isolated view of storage 346 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", owner); 347 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testReadIsolatedStorage", secondary); 348 349 // Verify they can't poke at each other 350 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", owner); 351 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testUserIsolation", secondary); 352 353 // Verify they can't access other users' content using media provider 354 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testMediaProviderUserIsolation", owner); 355 runDeviceTests(MULTIUSER_PKG, MULTIUSER_CLASS, "testMediaProviderUserIsolation", secondary); 356 } finally { 357 getDevice().uninstallPackage(MULTIUSER_PKG); 358 } 359 } 360 361 /** 362 * Test that apps with read permissions see the appropriate permissions 363 * when apps with r/w permission levels move around their files. 364 */ 365 @Test testMultiViewMoveConsistency()366 public void testMultiViewMoveConsistency() throws Exception { 367 try { 368 wipePrimaryExternalStorage(); 369 370 getDevice().uninstallPackage(NONE_PKG); 371 getDevice().uninstallPackage(READ_PKG); 372 getDevice().uninstallPackage(WRITE_PKG); 373 final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 374 375 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options)); 376 assertNull(getDevice().installPackage(getTestAppFile(READ_APK), false, options)); 377 378 for (int user : mUsers) { 379 runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testFolderSetup", user); 380 } 381 for (int user : mUsers) { 382 runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testRWAccess", user); 383 } 384 385 for (int user : mUsers) { 386 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteMultiViewTest", "testMoveAway", user); 387 } 388 for (int user : mUsers) { 389 runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testROAccess", user); 390 } 391 392 // for fuse file system 393 Thread.sleep(10000); 394 for (int user : mUsers) { 395 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteMultiViewTest", "testMoveBack", user); 396 } 397 for (int user : mUsers) { 398 runDeviceTests(READ_PKG, READ_PKG + ".ReadMultiViewTest", "testRWAccess", user); 399 } 400 } finally { 401 getDevice().uninstallPackage(NONE_PKG); 402 getDevice().uninstallPackage(READ_PKG); 403 getDevice().uninstallPackage(WRITE_PKG); 404 } 405 } 406 407 /** Verify that app without READ_EXTERNAL can play default URIs in external storage. */ 408 @Test testExternalStorageReadDefaultUris()409 public void testExternalStorageReadDefaultUris() throws Exception { 410 try { 411 wipePrimaryExternalStorage(); 412 413 getDevice().uninstallPackage(NONE_PKG); 414 getDevice().uninstallPackage(WRITE_PKG); 415 final String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 416 417 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options)); 418 assertNull(getDevice().installPackage(getTestAppFile(NONE_APK), false, options)); 419 420 for (int user : mUsers) { 421 updateAppOp(WRITE_PKG, user, "android:write_settings", true); 422 runDeviceTests( 423 WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testChangeDefaultUris", user); 424 425 runDeviceTests( 426 NONE_PKG, NONE_PKG + ".ReadDefaultUris", "testPlayDefaultUris", user); 427 } 428 } finally { 429 // Make sure the provider and uris are reset on failure. 430 for (int user : mUsers) { 431 runDeviceTests( 432 WRITE_PKG, WRITE_PKG + ".ChangeDefaultUris", "testResetDefaultUris", user); 433 } 434 getDevice().uninstallPackage(NONE_PKG); 435 getDevice().uninstallPackage(WRITE_PKG); 436 } 437 } 438 439 /** 440 * For security reasons, the shell user cannot access the shared storage of 441 * secondary users. Instead, developers should use the {@code content} shell 442 * tool to read/write files in those locations. 443 */ 444 @Test testSecondaryUsersInaccessible()445 public void testSecondaryUsersInaccessible() throws Exception { 446 List<String> mounts = new ArrayList<>(); 447 for (String line : getDevice().executeShellCommand("cat /proc/mounts").split("\n")) { 448 String[] split = line.split(" "); 449 if (split[1].startsWith("/storage/") || split[1].startsWith("/mnt/")) { 450 mounts.add(split[1]); 451 } 452 } 453 454 for (int user : mUsers) { 455 String probe = "/sdcard/../" + user; 456 if (user == Utils.USER_SYSTEM) { 457 // Primary user should always be visible. Skip checking raw 458 // mount points, since we'd get false-positives for physical 459 // devices that aren't multi-user aware. 460 assertTrue(probe, access(probe)); 461 } else { 462 // Secondary user should never be visible. 463 assertFalse(probe, access(probe)); 464 for (String mount : mounts) { 465 probe = mount + "/" + user; 466 assertFalse(probe, access(probe)); 467 } 468 } 469 } 470 } 471 472 @Test testMediaSandboxed()473 public void testMediaSandboxed() throws Exception { 474 doMediaSandboxed(MEDIA, true); 475 } 476 @Test testMediaSandboxed28()477 public void testMediaSandboxed28() throws Exception { 478 doMediaSandboxed(MEDIA_28, false); 479 } 480 @Test testMediaSandboxedFull()481 public void testMediaSandboxedFull() throws Exception { 482 doMediaSandboxed(MEDIA_FULL, false); 483 } 484 doMediaSandboxed(Config config, boolean sandboxed)485 private void doMediaSandboxed(Config config, boolean sandboxed) throws Exception { 486 installPackage(config.apk); 487 installPackage(MEDIA_FULL.apk); 488 for (int user : mUsers) { 489 updatePermissions(config.pkg, user, new String[] { 490 PERM_READ_EXTERNAL_STORAGE, 491 PERM_WRITE_EXTERNAL_STORAGE, 492 }, true); 493 updatePermissions(MEDIA_FULL.pkg, user, new String[] { 494 PERM_READ_EXTERNAL_STORAGE, 495 PERM_WRITE_EXTERNAL_STORAGE, 496 }, true); 497 498 // Create the files needed for the test from MEDIA_FULL pkg since shell 499 // can't access secondary user's storage. 500 runDeviceTests(MEDIA_FULL.pkg, MEDIA_FULL.clazz, "testStageFiles", user); 501 502 if (sandboxed) { 503 runDeviceTests(config.pkg, config.clazz, "testSandboxed", user); 504 } else { 505 runDeviceTests(config.pkg, config.clazz, "testNotSandboxed", user); 506 } 507 508 runDeviceTests(MEDIA_FULL.pkg, MEDIA_FULL.clazz, "testClearFiles", user); 509 } 510 } 511 512 @Test testMediaNone()513 public void testMediaNone() throws Exception { 514 doMediaNone(MEDIA); 515 } 516 @Test testMediaNone28()517 public void testMediaNone28() throws Exception { 518 doMediaNone(MEDIA_28); 519 } 520 @Test testMediaNoneFull()521 public void testMediaNoneFull() throws Exception { 522 doMediaNone(MEDIA_FULL); 523 } 524 doMediaNone(Config config)525 private void doMediaNone(Config config) throws Exception { 526 installPackage(config.apk); 527 for (int user : mUsers) { 528 updatePermissions(config.pkg, user, new String[] { 529 PERM_READ_EXTERNAL_STORAGE, 530 PERM_WRITE_EXTERNAL_STORAGE, 531 }, false); 532 533 runDeviceTests(config.pkg, config.clazz, "testMediaNone", user); 534 } 535 } 536 537 @Test testMediaRead()538 public void testMediaRead() throws Exception { 539 doMediaRead(MEDIA); 540 } 541 @Test testMediaRead28()542 public void testMediaRead28() throws Exception { 543 doMediaRead(MEDIA_28); 544 } 545 @Test testMediaReadFull()546 public void testMediaReadFull() throws Exception { 547 doMediaRead(MEDIA_FULL); 548 } 549 doMediaRead(Config config)550 private void doMediaRead(Config config) throws Exception { 551 installPackage(config.apk); 552 for (int user : mUsers) { 553 updatePermissions(config.pkg, user, new String[] { 554 PERM_READ_EXTERNAL_STORAGE, 555 }, true); 556 updatePermissions(config.pkg, user, new String[] { 557 PERM_WRITE_EXTERNAL_STORAGE, 558 }, false); 559 560 runDeviceTests(config.pkg, config.clazz, "testMediaRead", user); 561 } 562 } 563 564 @Test testMediaWrite()565 public void testMediaWrite() throws Exception { 566 doMediaWrite(MEDIA); 567 } 568 @Test testMediaWrite28()569 public void testMediaWrite28() throws Exception { 570 doMediaWrite(MEDIA_28); 571 } 572 @Test testMediaWriteFull()573 public void testMediaWriteFull() throws Exception { 574 doMediaWrite(MEDIA_FULL); 575 } 576 doMediaWrite(Config config)577 private void doMediaWrite(Config config) throws Exception { 578 installPackage(config.apk); 579 for (int user : mUsers) { 580 updatePermissions(config.pkg, user, new String[] { 581 PERM_READ_EXTERNAL_STORAGE, 582 PERM_WRITE_EXTERNAL_STORAGE, 583 }, true); 584 585 runDeviceTests(config.pkg, config.clazz, "testMediaWrite", user); 586 } 587 } 588 589 @Test testMediaEscalation()590 public void testMediaEscalation() throws Exception { 591 doMediaEscalation(MEDIA); 592 } 593 @Test testMediaEscalation28()594 public void testMediaEscalation28() throws Exception { 595 doMediaEscalation(MEDIA_28); 596 } 597 @Test testMediaEscalationFull()598 public void testMediaEscalationFull() throws Exception { 599 doMediaEscalation(MEDIA_FULL); 600 } 601 doMediaEscalation(Config config)602 private void doMediaEscalation(Config config) throws Exception { 603 installPackage(config.apk); 604 605 // TODO: extend test to exercise secondary users 606 for (int user : Arrays.copyOf(mUsers, 1)) { 607 updatePermissions(config.pkg, user, new String[] { 608 PERM_READ_EXTERNAL_STORAGE, 609 }, true); 610 updatePermissions(config.pkg, user, new String[] { 611 PERM_WRITE_EXTERNAL_STORAGE, 612 }, false); 613 614 runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Open", user); 615 runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Update", user); 616 runDeviceTests(config.pkg, config.clazz, "testMediaEscalation_Delete", user); 617 } 618 } 619 620 @Test testExternalStorageClearing()621 public void testExternalStorageClearing() throws Exception { 622 String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 623 624 try { 625 getDevice().uninstallPackage(WRITE_PKG); 626 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options)); 627 for (int user : mUsers) { 628 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testClearingWrite", user); 629 } 630 631 // Uninstall and reinstall means all storage should be cleared 632 getDevice().uninstallPackage(WRITE_PKG); 633 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options)); 634 for (int user : mUsers) { 635 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", "testClearingRead", user); 636 } 637 } finally { 638 getDevice().uninstallPackage(WRITE_PKG); 639 } 640 } 641 642 @Test testIsExternalStorageLegacy()643 public void testIsExternalStorageLegacy() throws Exception { 644 String[] options = {AbiUtils.createAbiFlag(getAbi().getName())}; 645 646 try { 647 getDevice().uninstallPackage(WRITE_PKG); 648 getDevice().uninstallPackage(WRITE_PKG_2); 649 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK), false, options)); 650 assertNull(getDevice().installPackage(getTestAppFile(WRITE_APK_2), false, options)); 651 for (int user : mUsers) { 652 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", 653 "testIsExternalStorageLegacy", user); 654 updatePermissions(WRITE_PKG, user, new String[] { 655 PERM_READ_EXTERNAL_STORAGE, 656 PERM_WRITE_EXTERNAL_STORAGE, 657 }, false); 658 runDeviceTests(WRITE_PKG, WRITE_PKG + ".WriteGiftTest", 659 "testIsExternalStorageLegacy", user); 660 661 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest", 662 "testNotIsExternalStorageLegacy", user); 663 updateAppOp(WRITE_PKG_2, user, "android:request_install_packages", true); 664 runDeviceTests(WRITE_PKG_2, WRITE_PKG + ".WriteGiftTest", 665 "testIsExternalStorageLegacy", user); 666 } 667 } finally { 668 getDevice().uninstallPackage(WRITE_PKG); 669 getDevice().uninstallPackage(WRITE_PKG_2); 670 } 671 } 672 access(String path)673 private boolean access(String path) throws DeviceNotAvailableException { 674 final long nonce = System.nanoTime(); 675 return getDevice().executeShellCommand("ls -la " + path + " && echo " + nonce) 676 .contains(Long.toString(nonce)); 677 } 678 updatePermissions(String packageName, int userId, String[] permissions, boolean grant)679 private void updatePermissions(String packageName, int userId, String[] permissions, 680 boolean grant) throws Exception { 681 final String verb = grant ? "grant" : "revoke"; 682 for (String permission : permissions) { 683 getDevice().executeShellCommand( 684 "cmd package " + verb + " --user " + userId + " --uid " + packageName + " " 685 + permission); 686 } 687 } 688 updateAppOp(String packageName, int userId, String appOp, boolean allow)689 private void updateAppOp(String packageName, int userId, String appOp, boolean allow) 690 throws Exception { 691 updateAppOp(packageName, false, userId, appOp, allow); 692 } 693 updateAppOp(String packageName, boolean targetsUid, int userId, String appOp, boolean allow)694 private void updateAppOp(String packageName, boolean targetsUid, int userId, 695 String appOp, boolean allow) 696 throws Exception { 697 final String verb = allow ? "allow" : "default"; 698 getDevice().executeShellCommand( 699 "cmd appops set --user " + userId + (targetsUid ? " --uid " : " ") + packageName 700 + " " + appOp + " " + verb); 701 } 702 wipePrimaryExternalStorage()703 private void wipePrimaryExternalStorage() throws DeviceNotAvailableException { 704 // Can't delete everything under /sdcard as that's going to remove the mounts. 705 getDevice().executeShellCommand("find /sdcard -type f -delete"); 706 getDevice().executeShellCommand("rm -rf /sdcard/DCIM"); 707 getDevice().executeShellCommand("rm -rf /sdcard/MUST_*"); 708 } 709 runDeviceTests(String packageName, String testClassName, int userId)710 private void runDeviceTests(String packageName, String testClassName, int userId) 711 throws DeviceNotAvailableException { 712 runDeviceTests(getDevice(), packageName, testClassName, null, userId, null); 713 } 714 runDeviceTests(String packageName, String testClassName, String testMethodName, int userId)715 private void runDeviceTests(String packageName, String testClassName, String testMethodName, 716 int userId) throws DeviceNotAvailableException { 717 runDeviceTests(getDevice(), packageName, testClassName, testMethodName, userId, null); 718 } 719 } 720