1 /* 2 * Copyright (C) 2020 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.scopedstorage.cts.host; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assume.assumeFalse; 22 23 import android.platform.test.annotations.AppModeFull; 24 25 import com.android.modules.utils.build.testing.DeviceSdkLevel; 26 import com.android.tradefed.device.DeviceNotAvailableException; 27 import com.android.tradefed.device.ITestDevice; 28 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 29 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions; 30 31 import org.junit.After; 32 import org.junit.Before; 33 import org.junit.Ignore; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 37 /** 38 * Runs the ScopedStorageTest tests. 39 */ 40 @RunWith(DeviceJUnit4ClassRunner.class) 41 @AppModeFull 42 public class ScopedStorageHostTest extends BaseHostTestCase { 43 private boolean mIsExternalStorageSetup; 44 45 /** 46 * Runs the given phase of ScopedStorageTest by calling into the device. 47 * Throws an exception if the test phase fails. 48 */ runDeviceTest(String phase)49 void runDeviceTest(String phase) throws Exception { 50 assertThat(runDeviceTests("android.scopedstorage.cts", 51 "android.scopedstorage.cts.ScopedStorageTest", phase)).isTrue(); 52 } 53 54 /** 55 * Runs the given phase of ScopedStorageTest by calling into the device with {@code 56 * --no-isolated-storage} flag. 57 * Throws an exception if the test phase fails. 58 */ runDeviceTestWithDisabledIsolatedStorage(String phase)59 void runDeviceTestWithDisabledIsolatedStorage(String phase) throws Exception { 60 runDeviceTests(new DeviceTestRunOptions("android.scopedstorage.cts") 61 .setDevice(getDevice()) 62 .setTestClassName("android.scopedstorage.cts.ScopedStorageTest") 63 .setTestMethodName(phase) 64 .setDisableIsolatedStorage(true)); 65 } 66 setupExternalStorage()67 private void setupExternalStorage() throws Exception { 68 if (!mIsExternalStorageSetup) { 69 runDeviceTest("setupExternalStorage"); 70 mIsExternalStorageSetup = true; 71 } 72 } 73 74 @Before setup()75 public void setup() throws Exception { 76 // Ignore tests on automotive devices b/319785789 77 assumeFalse(hasDeviceFeature("android.hardware.type.automotive")); 78 79 setupExternalStorage(); 80 executeShellCommand("mkdir /sdcard/Android/data/com.android.shell -m 2770"); 81 executeShellCommand("mkdir /sdcard/Android/data/com.android.shell/files -m 2770"); 82 } 83 84 @Before revokeStoragePermissions()85 public void revokeStoragePermissions() throws Exception { 86 revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE", 87 "android.permission.READ_EXTERNAL_STORAGE"); 88 } 89 90 @After tearDown()91 public void tearDown() throws Exception { 92 executeShellCommand("rm -r /sdcard/Android/data/com.android.shell"); 93 } 94 95 @Test testManageExternalStorageCanDeleteOtherAppsContents()96 public void testManageExternalStorageCanDeleteOtherAppsContents() throws Exception { 97 allowAppOps("android:manage_external_storage"); 98 try { 99 runDeviceTest("testManageExternalStorageCanDeleteOtherAppsContents"); 100 } finally { 101 denyAppOps("android:manage_external_storage"); 102 } 103 } 104 105 @Test testManageExternalStorageCanReadRedactedContents()106 public void testManageExternalStorageCanReadRedactedContents() throws Exception { 107 allowAppOps("android:manage_external_storage"); 108 try { 109 runDeviceTest("testManageExternalStorageCanReadRedactedContents"); 110 } finally { 111 denyAppOps("android:manage_external_storage"); 112 } 113 } 114 115 @Test testManageExternalStorageCanRenameOtherAppsContents()116 public void testManageExternalStorageCanRenameOtherAppsContents() throws Exception { 117 allowAppOps("android:manage_external_storage"); 118 try { 119 runDeviceTest("testManageExternalStorageCanRenameOtherAppsContents"); 120 } finally { 121 denyAppOps("android:manage_external_storage"); 122 } 123 } 124 125 @Test testManageExternalStorageCannotRenameAndroid()126 public void testManageExternalStorageCannotRenameAndroid() throws Exception { 127 allowAppOps("android:manage_external_storage"); 128 try { 129 runDeviceTest("testManageExternalStorageCannotRenameAndroid"); 130 } finally { 131 denyAppOps("android:manage_external_storage"); 132 } 133 } 134 135 @Test testManageExternalStorageCantReadWriteOtherAppExternalDir()136 public void testManageExternalStorageCantReadWriteOtherAppExternalDir() throws Exception { 137 allowAppOps("android:manage_external_storage"); 138 try { 139 runDeviceTest("testManageExternalStorageCantReadWriteOtherAppExternalDir"); 140 } finally { 141 denyAppOps("android:manage_external_storage"); 142 } 143 } 144 145 @Test testManageExternalStorageCantInsertFilesInOtherAppPrivateDir()146 public void testManageExternalStorageCantInsertFilesInOtherAppPrivateDir() throws Exception { 147 allowAppOps("android:manage_external_storage"); 148 try { 149 runDeviceTest("testManageExternalStorageCantInsertFilesInOtherAppPrivateDir"); 150 } finally { 151 denyAppOps("android:manage_external_storage"); 152 } 153 } 154 155 @Test testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir()156 public void testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir() throws Exception { 157 allowAppOps("android:manage_external_storage"); 158 try { 159 runDeviceTest("testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir"); 160 } finally { 161 denyAppOps("android:manage_external_storage"); 162 } 163 } 164 165 @Test testCheckInstallerAppAccessToObbDirs()166 public void testCheckInstallerAppAccessToObbDirs() throws Exception { 167 allowAppOps("android:request_install_packages"); 168 // WRITE_EXTERNAL_STORAGE is no-op for Installers U onwards 169 if (isSdkLevelLessThanU()) { 170 grantPermissions("android.permission.WRITE_EXTERNAL_STORAGE"); 171 } 172 try { 173 runDeviceTest("testCheckInstallerAppAccessToObbDirs"); 174 } finally { 175 denyAppOps("android:request_install_packages"); 176 // WRITE_EXTERNAL_STORAGE is no-op for Installers U onwards 177 if (isSdkLevelLessThanU()) { 178 revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE"); 179 } 180 } 181 } 182 183 @Test testCheckInstallerAppCannotAccessDataDirs()184 public void testCheckInstallerAppCannotAccessDataDirs() throws Exception { 185 allowAppOps("android:request_install_packages"); 186 // WRITE_EXTERNAL_STORAGE is no-op for Installers U onwards 187 if (isSdkLevelLessThanU()) { 188 grantPermissions("android.permission.WRITE_EXTERNAL_STORAGE"); 189 } 190 try { 191 runDeviceTest("testCheckInstallerAppCannotAccessDataDirs"); 192 } finally { 193 denyAppOps("android:request_install_packages"); 194 // WRITE_EXTERNAL_STORAGE is no-op for Installers U onwards 195 if (isSdkLevelLessThanU()) { 196 revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE"); 197 } 198 } 199 } 200 201 @Test testManageExternalStorageQueryOtherAppsFile()202 public void testManageExternalStorageQueryOtherAppsFile() throws Exception { 203 allowAppOps("android:manage_external_storage"); 204 try { 205 runDeviceTest("testManageExternalStorageQueryOtherAppsFile"); 206 } finally { 207 denyAppOps("android:manage_external_storage"); 208 } 209 } 210 211 @Test testManageExternalStorageDoesntSkipScanningDirtyNomediaDir()212 public void testManageExternalStorageDoesntSkipScanningDirtyNomediaDir() throws Exception { 213 allowAppOps("android:manage_external_storage"); 214 try { 215 runDeviceTest("testManageExternalStorageDoesntSkipScanningDirtyNomediaDir"); 216 } finally { 217 denyAppOps("android:manage_external_storage"); 218 } 219 } 220 221 @Test testScanDoesntSkipDirtySubtree()222 public void testScanDoesntSkipDirtySubtree() throws Exception { 223 allowAppOps("android:manage_external_storage"); 224 try { 225 runDeviceTest("testScanDoesntSkipDirtySubtree"); 226 } finally { 227 denyAppOps("android:manage_external_storage"); 228 } 229 } 230 231 @Test testFileManagerCanTrashOtherAndroidMediaFiles()232 public void testFileManagerCanTrashOtherAndroidMediaFiles() throws Exception { 233 allowAppOps("android:manage_external_storage"); 234 try { 235 runDeviceTest("testFileManagerCanTrashOtherAndroidMediaFiles"); 236 } finally { 237 denyAppOps("android:manage_external_storage"); 238 } 239 } 240 241 @Test testFileManagerCanUpdateOtherAndroidMediaFiles()242 public void testFileManagerCanUpdateOtherAndroidMediaFiles() throws Exception { 243 allowAppOps("android:manage_external_storage"); 244 try { 245 runDeviceTest("testFileManagerCanUpdateOtherAndroidMediaFiles"); 246 } finally { 247 denyAppOps("android:manage_external_storage"); 248 } 249 } 250 251 @Test testOpenOtherPendingFilesFromFuse()252 public void testOpenOtherPendingFilesFromFuse() throws Exception { 253 grantPermissions("android.permission.READ_EXTERNAL_STORAGE"); 254 try { 255 runDeviceTest("testOpenOtherPendingFilesFromFuse"); 256 } finally { 257 revokePermissions("android.permission.READ_EXTERNAL_STORAGE"); 258 } 259 } 260 261 @Test testAndroidMedia()262 public void testAndroidMedia() throws Exception { 263 grantPermissions("android.permission.READ_EXTERNAL_STORAGE"); 264 try { 265 runDeviceTest("testAndroidMedia"); 266 } finally { 267 revokePermissions("android.permission.READ_EXTERNAL_STORAGE"); 268 } 269 } 270 271 @Test testNoIsolatedStorageInstrumentationFlag()272 public void testNoIsolatedStorageInstrumentationFlag() throws Exception { 273 grantPermissions("android.permission.READ_EXTERNAL_STORAGE", 274 "android.permission.WRITE_EXTERNAL_STORAGE"); 275 try { 276 runDeviceTestWithDisabledIsolatedStorage("testNoIsolatedStorageCanCreateFilesAnywhere"); 277 runDeviceTestWithDisabledIsolatedStorage( 278 "testNoIsolatedStorageCantReadWriteOtherAppExternalDir"); 279 runDeviceTestWithDisabledIsolatedStorage("testNoIsolatedStorageStorageReaddir"); 280 runDeviceTestWithDisabledIsolatedStorage("testNoIsolatedStorageQueryOtherAppsFile"); 281 } finally { 282 revokePermissions("android.permission.READ_EXTERNAL_STORAGE", 283 "android.permission.WRITE_EXTERNAL_STORAGE"); 284 } 285 } 286 287 @Test testRenameFromShell()288 public void testRenameFromShell() throws Exception { 289 final ITestDevice device = getDevice(); 290 final boolean isAdbRoot = device.isAdbRoot() ? true : false; 291 try { 292 if (isAdbRoot) { 293 device.disableAdbRoot(); 294 } 295 runDeviceTest("testRenameFromShell"); 296 } finally { 297 if (isAdbRoot) { 298 device.enableAdbRoot(); 299 } 300 } 301 } 302 303 @Test 304 @Ignore("b/247099819") testClearPackageData()305 public void testClearPackageData() throws Exception { 306 grantPermissions("android.permission.READ_EXTERNAL_STORAGE"); 307 try { 308 runDeviceTest("testClearPackageData"); 309 } finally { 310 revokePermissions("android.permission.READ_EXTERNAL_STORAGE"); 311 } 312 } 313 314 @Test testInsertExternalFilesViaDataAsFileManager()315 public void testInsertExternalFilesViaDataAsFileManager() throws Exception { 316 allowAppOps("android:manage_external_storage"); 317 try { 318 runDeviceTest("testInsertExternalFilesViaData"); 319 } finally { 320 denyAppOps("android:manage_external_storage"); 321 } 322 } 323 324 /** 325 * Test that File Manager can't update file path to private directories. 326 */ 327 @Test testUpdateExternalFilesViaDataAsFileManager()328 public void testUpdateExternalFilesViaDataAsFileManager() throws Exception { 329 allowAppOps("android:manage_external_storage"); 330 try { 331 runDeviceTest("testUpdateExternalFilesViaData"); 332 } finally { 333 denyAppOps("android:manage_external_storage"); 334 } 335 } 336 337 /** 338 * Test that File Manager can't insert files from private directories. 339 */ 340 @Test testInsertExternalFilesViaRelativePathAsFileManager()341 public void testInsertExternalFilesViaRelativePathAsFileManager() throws Exception { 342 allowAppOps("android:manage_external_storage"); 343 try { 344 runDeviceTest("testInsertExternalFilesViaRelativePath"); 345 } finally { 346 denyAppOps("android:manage_external_storage"); 347 } 348 } 349 350 /** 351 * Test that File Manager can't update file path to private directories. 352 */ 353 @Test testUpdateExternalFilesViaRelativePathAsFileManager()354 public void testUpdateExternalFilesViaRelativePathAsFileManager() throws Exception { 355 allowAppOps("android:manage_external_storage"); 356 try { 357 runDeviceTest("testUpdateExternalFilesViaRelativePath"); 358 } finally { 359 denyAppOps("android:manage_external_storage"); 360 } 361 } 362 grantPermissionsToPackage(String packageName, String... perms)363 private void grantPermissionsToPackage(String packageName, String... perms) throws Exception { 364 int currentUserId = getCurrentUserId(); 365 for (String perm : perms) { 366 executeShellCommand("pm grant --user %d %s %s", 367 currentUserId, packageName, perm); 368 } 369 } 370 grantPermissions(String... perms)371 private void grantPermissions(String... perms) throws Exception { 372 grantPermissionsToPackage("android.scopedstorage.cts", perms); 373 } 374 revokePermissions(String... perms)375 private void revokePermissions(String... perms) throws Exception { 376 int currentUserId = getCurrentUserId(); 377 for (String perm : perms) { 378 executeShellCommand("pm revoke --user %d android.scopedstorage.cts %s", 379 currentUserId, perm); 380 } 381 } 382 allowAppOps(String... ops)383 private void allowAppOps(String... ops) throws Exception { 384 for (String op : ops) { 385 executeShellCommand("cmd appops set --uid android.scopedstorage.cts " + op + " allow"); 386 } 387 } 388 denyAppOps(String... ops)389 private void denyAppOps(String... ops) throws Exception { 390 for (String op : ops) { 391 executeShellCommand("cmd appops set --uid android.scopedstorage.cts " + op + " deny"); 392 } 393 } 394 isSdkLevelLessThanU()395 private boolean isSdkLevelLessThanU() throws DeviceNotAvailableException { 396 DeviceSdkLevel deviceSdkLevel = new DeviceSdkLevel(getDevice()); 397 return !deviceSdkLevel.isDeviceAtLeastU(); 398 } 399 } 400