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.appsecurity.cts; 18 19 import static android.appsecurity.cts.Utils.waitForBootCompleted; 20 21 import static org.hamcrest.CoreMatchers.is; 22 import static org.junit.Assert.assertEquals; 23 import static org.junit.Assert.fail; 24 import static org.junit.Assume.assumeThat; 25 import static org.junit.Assume.assumeTrue; 26 27 import com.android.tradefed.device.DeviceNotAvailableException; 28 import com.android.tradefed.device.ITestDevice; 29 import com.android.tradefed.log.LogUtil; 30 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 31 32 import org.junit.After; 33 import org.junit.Before; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 37 import java.util.HashMap; 38 import java.util.Map; 39 40 /** 41 * Set of tests that verify app data isolation works. 42 */ 43 @RunWith(DeviceJUnit4ClassRunner.class) 44 public class AppDataIsolationTests extends BaseAppSecurityTest { 45 46 private static final String APPA_APK = "CtsAppDataIsolationAppA.apk"; 47 private static final String APP_SHARED_A_APK = "CtsAppDataIsolationAppSharedA.apk"; 48 private static final String APP_DIRECT_BOOT_A_APK = "CtsAppDataIsolationAppDirectBootA.apk"; 49 private static final String APP_API29_A_APK = "CtsAppDataIsolationAppApi29A.apk"; 50 private static final String APPA_PKG = "com.android.cts.appdataisolation.appa"; 51 private static final String APPA_CLASS = 52 "com.android.cts.appdataisolation.appa.AppATests"; 53 private static final String APPA_METHOD_CREATE_CE_DE_DATA = "testCreateCeDeAppData"; 54 private static final String APPA_METHOD_CHECK_CE_DATA_EXISTS = "testAppACeDataExists"; 55 private static final String APPA_METHOD_CHECK_CE_DATA_DOES_NOT_EXIST = 56 "testAppACeDataDoesNotExist"; 57 private static final String APPA_METHOD_CHECK_DE_DATA_EXISTS = "testAppADeDataExists"; 58 private static final String APPA_METHOD_CHECK_DE_DATA_DOES_NOT_EXIST = 59 "testAppADeDataDoesNotExist"; 60 private static final String APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE = 61 "testAppACurProfileDataAccessible"; 62 private static final String APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE = 63 "testAppARefProfileDataAccessible"; 64 private static final String APPA_METHOD_UNLOCK_DEVICE_AND_VERIFY_CE_DE_EXTERNAL_EXIST = 65 "testAppAUnlockDeviceAndVerifyCeDeExternalDataExist"; 66 private static final String APPA_METHOD_CANNOT_ACCESS_APPB_DIR = "testCannotAccessAppBDataDir"; 67 68 private static final String APPA_METHOD_TEST_UNLOCK_DEVICE = 69 "testUnlockDevice"; 70 71 private static final String APPB_APK = "CtsAppDataIsolationAppB.apk"; 72 private static final String APP_SHARED_B_APK = "CtsAppDataIsolationAppSharedB.apk"; 73 private static final String APPB_PKG = "com.android.cts.appdataisolation.appb"; 74 private static final String APPB_CLASS = 75 "com.android.cts.appdataisolation.appb.AppBTests"; 76 private static final String APPB_METHOD_CAN_NOT_ACCESS_APPA_DIR = "testCanNotAccessAppADataDir"; 77 private static final String APPB_METHOD_CAN_ACCESS_APPA_DIR = "testCanAccessAppADataDir"; 78 79 private static final String FBE_MODE_NATIVE = "native"; 80 private static final String FBE_MODE_EMULATED = "emulated"; 81 82 private static final String APPA_METHOD_CREATE_EXTERNAL_DIRS = "testCreateExternalDirs"; 83 private static final String APPA_METHOD_TEST_ISOLATED_PROCESS = "testIsolatedProcess"; 84 private static final String APPA_METHOD_TEST_APP_ZYGOTE_ISOLATED_PROCESS = 85 "testAppZygoteIsolatedProcess"; 86 private static final String APPB_METHOD_CAN_NOT_ACCESS_APPA_EXTERNAL_DIRS = 87 "testCanNotAccessAppAExternalDirs"; 88 private static final String APPB_METHOD_CAN_ACCESS_APPA_EXTERNAL_DIRS = 89 "testCanAccessAppAExternalDirs"; 90 private static final String APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_NOT_EXIST = 91 "testAppAExternalDirsDoNotExist"; 92 private static final String APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST = 93 "testAppAExternalDirsDoExist"; 94 private static final String APPA_METHOD_CHECK_EXTERNAL_DIRS_UNAVAILABLE = 95 "testAppAExternalDirsUnavailable"; 96 private static final String APPA_METHOD_TEST_OTHER_USER_DIRS_NOT_PRESENT = 97 "testOtherUserDirsNotPresent"; 98 private static final String APPA_METHOD_TEST_OTHER_USER_DIRS_NOT_ACCESSIBLE = 99 "testOtherUserDirsNotAccessible"; 100 101 private int mOtherUser = -1; 102 103 @Before setUp()104 public void setUp() throws Exception { 105 Utils.prepareSingleUser(getDevice()); 106 getDevice().uninstallPackage(APPA_PKG); 107 getDevice().uninstallPackage(APPB_PKG); 108 } 109 110 @After tearDown()111 public void tearDown() throws Exception { 112 if (mOtherUser != -1) { 113 getDevice().removeUser(mOtherUser); 114 } 115 getDevice().uninstallPackage(APPA_PKG); 116 getDevice().uninstallPackage(APPB_PKG); 117 } 118 119 @Test testAppAbleToAccessItsDataAfterForceStop()120 public void testAppAbleToAccessItsDataAfterForceStop() throws Exception { 121 // Install AppA and verify no data stored 122 new InstallMultiple().addFile(APPA_APK).run(); 123 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_DOES_NOT_EXIST); 124 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_DOES_NOT_EXIST); 125 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_NOT_EXIST); 126 127 // Create data in CE, DE and external storage 128 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_CE_DE_DATA); 129 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_EXTERNAL_DIRS); 130 131 // Verify CE, DE and external storage contains data, cur profile is accessible and ref 132 // profile is not accessible 133 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_EXISTS); 134 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS); 135 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST); 136 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE); 137 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE); 138 139 // Force stop and verify CE, DE and external storage contains data, cur profile is 140 // accessible and ref profile is not accessible, to confirm it's binding back the same data 141 // directory, not binding to a wrong one / create a new one. 142 forceStopPackage(APPA_PKG); 143 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_EXISTS); 144 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS); 145 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST); 146 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE); 147 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE); 148 } 149 150 @Test testAppAbleToAccessItsDataAfterReboot()151 public void testAppAbleToAccessItsDataAfterReboot() throws Exception { 152 // Install AppA and verify no data stored 153 new InstallMultiple().addFile(APPA_APK).run(); 154 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_DOES_NOT_EXIST); 155 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_DOES_NOT_EXIST); 156 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_NOT_EXIST); 157 158 // Create data in CE, DE and external storage 159 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_CE_DE_DATA); 160 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_EXTERNAL_DIRS); 161 162 // Verify CE, DE and external storage contains data, cur profile is accessible and ref 163 // profile is not accessible 164 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_EXISTS); 165 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS); 166 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST); 167 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE); 168 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE); 169 170 // Reboot and verify CE, DE and external storage contains data, cur profile is accessible 171 // and ref profile is not accessible 172 reboot(); 173 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_EXISTS); 174 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS); 175 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST); 176 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE); 177 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE); 178 } 179 180 @Test testDirectBootModeWorks()181 public void testDirectBootModeWorks() throws Exception { 182 if (!"file".equals(getDevice().getProperty("ro.crypto.type"))) { 183 LogUtil.CLog.d("Device is NOT encrypted with file-based encryption. skipping test"); 184 return; 185 } 186 assumeTrue("Screen lock is not supported so skip direct boot test", 187 hasDeviceFeature("android.software.secure_lock_screen")); 188 // Install AppA and verify no data stored 189 new InstallMultiple().addFile(APP_DIRECT_BOOT_A_APK).run(); 190 new InstallMultiple().addFile(APPB_APK).run(); 191 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_DOES_NOT_EXIST); 192 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_DOES_NOT_EXIST); 193 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_NOT_EXIST); 194 195 // Create data in CE, DE and external storage 196 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_CE_DE_DATA); 197 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_EXTERNAL_DIRS); 198 199 // Verify CE, DE and external storage contains data, cur profile is accessible and ref 200 // profile is not accessible 201 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_EXISTS); 202 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS); 203 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST); 204 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE); 205 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE); 206 207 try { 208 // Setup screenlock 209 getDevice().executeShellCommand("settings put global require_password_to_decrypt 0"); 210 getDevice().executeShellCommand("locksettings set-disabled false"); 211 String response = getDevice().executeShellCommand("locksettings set-pin 1234"); 212 if (!response.contains("1234")) { 213 // This seems to fail occasionally. Try again once, then give up. 214 Thread.sleep(500); 215 response = getDevice().executeShellCommand("locksettings set-pin 1234"); 216 assumeTrue("Test requires setting a pin, which failed: " + response, 217 response.contains("1234")); 218 } 219 220 // Give enough time for vold to update keys 221 Thread.sleep(15000); 222 223 // Follow DirectBootHostTest, reboot system into known state with keys ejected 224 if (isFbeModeEmulated()) { 225 final String res = getDevice().executeShellCommand("sm set-emulate-fbe true"); 226 if (res != null && res.contains("Emulation not supported")) { 227 LogUtil.CLog.i("FBE emulation is not supported, skipping test"); 228 return; 229 } 230 getDevice().waitForDeviceNotAvailable(30000); 231 getDevice().waitForDeviceOnline(120000); 232 } else { 233 getDevice().rebootUntilOnline(); 234 } 235 waitForBootCompleted(getDevice()); 236 237 // Verify DE data is still readable and writeable, while CE and external data are not 238 // accessible 239 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS); 240 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_DOES_NOT_EXIST); 241 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_UNAVAILABLE); 242 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE); 243 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE); 244 // Verify cannot access other apps data 245 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CANNOT_ACCESS_APPB_DIR); 246 247 // Unlock device and verify CE, DE and external data still exist, without killing the 248 // process, as test process usually will be killed after the test 249 runDeviceTests(APPA_PKG, APPA_CLASS, 250 APPA_METHOD_UNLOCK_DEVICE_AND_VERIFY_CE_DE_EXTERNAL_EXIST); 251 252 // Restart test app and verify CE, DE and external storage contains data, cur profile is 253 // accessible and ref profile is not accessible 254 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_EXISTS); 255 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_EXISTS); 256 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_EXIST); 257 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CUR_PROFILE_ACCESSIBLE); 258 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_REF_PROFILE_ACCESSIBLE); 259 } finally { 260 try { 261 // Always try to unlock first, then clear screenlock setting 262 try { 263 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_TEST_UNLOCK_DEVICE); 264 } catch (Exception e) {} 265 getDevice().executeShellCommand("locksettings clear --old 1234"); 266 getDevice().executeShellCommand("locksettings set-disabled true"); 267 getDevice().executeShellCommand( 268 "settings delete global require_password_to_decrypt"); 269 } finally { 270 // Get ourselves back into a known-good state 271 if (isFbeModeEmulated()) { 272 getDevice().executeShellCommand("sm set-emulate-fbe false"); 273 getDevice().waitForDeviceNotAvailable(30000); 274 getDevice().waitForDeviceOnline(); 275 } else { 276 getDevice().rebootUntilOnline(); 277 } 278 getDevice().waitForDeviceAvailable(); 279 } 280 } 281 } 282 283 @Test testAppNotAbleToAccessItsDataAfterReinstall()284 public void testAppNotAbleToAccessItsDataAfterReinstall() throws Exception { 285 // Install AppA create CE DE data 286 new InstallMultiple().addFile(APPA_APK).run(); 287 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_CE_DE_DATA); 288 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_EXTERNAL_DIRS); 289 290 // Reinstall AppA 291 getDevice().uninstallPackage(APPA_PKG); 292 new InstallMultiple().addFile(APPA_APK).run(); 293 294 // Verify CE, DE and external data are removed 295 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_CE_DATA_DOES_NOT_EXIST); 296 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_DE_DATA_DOES_NOT_EXIST); 297 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CHECK_EXTERNAL_DIRS_DO_NOT_EXIST); 298 } 299 300 @Test testNormalProcessCannotAccessOtherAppDataDir()301 public void testNormalProcessCannotAccessOtherAppDataDir() throws Exception { 302 new InstallMultiple().addFile(APPA_APK).run(); 303 new InstallMultiple().addFile(APPB_APK).run(); 304 305 runDeviceTests(APPB_PKG, APPB_CLASS, APPB_METHOD_CAN_NOT_ACCESS_APPA_DIR); 306 } 307 308 @Test testSharedAppAbleToAccessOtherAppDataDir()309 public void testSharedAppAbleToAccessOtherAppDataDir() throws Exception { 310 new InstallMultiple().addFile(APP_SHARED_A_APK).run(); 311 new InstallMultiple().addFile(APP_SHARED_B_APK).run(); 312 313 runDeviceTests(APPB_PKG, APPB_CLASS, APPB_METHOD_CAN_ACCESS_APPA_DIR); 314 } 315 316 @Test testNormalProcessCannotAccessOtherAppExternalDataDir()317 public void testNormalProcessCannotAccessOtherAppExternalDataDir() throws Exception { 318 assumeThatFuseDataIsolationIsEnabled(getDevice()); 319 320 new InstallMultiple().addFile(APPA_APK).run(); 321 new InstallMultiple().addFile(APPB_APK).run(); 322 323 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_EXTERNAL_DIRS); 324 runDeviceTests(APPB_PKG, APPB_CLASS, APPB_METHOD_CAN_NOT_ACCESS_APPA_EXTERNAL_DIRS); 325 } 326 327 @Test testSharedAppAbleToAccessOtherAppExternalDataDir()328 public void testSharedAppAbleToAccessOtherAppExternalDataDir() throws Exception { 329 new InstallMultiple().addFile(APP_SHARED_A_APK).run(); 330 new InstallMultiple().addFile(APP_SHARED_B_APK).run(); 331 332 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_CREATE_EXTERNAL_DIRS); 333 runDeviceTests(APPB_PKG, APPB_CLASS, APPB_METHOD_CAN_ACCESS_APPA_EXTERNAL_DIRS); 334 } 335 336 @Test testIsolatedProcess()337 public void testIsolatedProcess() throws Exception { 338 new InstallMultiple().addFile(APPA_APK).run(); 339 new InstallMultiple().addFile(APPB_APK).run(); 340 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_TEST_ISOLATED_PROCESS); 341 } 342 343 @Test testAppZygoteIsolatedProcess()344 public void testAppZygoteIsolatedProcess() throws Exception { 345 new InstallMultiple().addFile(APPA_APK).run(); 346 new InstallMultiple().addFile(APPB_APK).run(); 347 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_TEST_APP_ZYGOTE_ISOLATED_PROCESS); 348 } 349 350 @Test testAppUnableToAccessOtherUserAppDataDir()351 public void testAppUnableToAccessOtherUserAppDataDir() throws Exception { 352 assumeCanCreateUser(); 353 mOtherUser = getDevice().createUser("other_user"); 354 355 // For targetSdk > 29, directories related to other users are not visible at all. 356 new InstallMultiple().addFile(APPA_APK).run(); 357 new InstallMultiple().addFile(APPB_APK).run(); 358 getDevice().startUser(mOtherUser, true /* wait */); 359 installExistingAppAsUser(APPB_PKG, mOtherUser); 360 361 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_TEST_OTHER_USER_DIRS_NOT_PRESENT, 362 makeOtherUserIdArgs(mOtherUser)); 363 } 364 365 @Test testAppUnableToAccessOtherUserAppDataDirApi29()366 public void testAppUnableToAccessOtherUserAppDataDirApi29() throws Exception { 367 assumeCanCreateUser(); 368 mOtherUser = getDevice().createUser("other_user"); 369 370 // For targetSdk <= 29, directories related to other users are visible but we cannot 371 // access anything within them. 372 new InstallMultiple().addFile(APP_API29_A_APK).run(); 373 new InstallMultiple().addFile(APPB_APK).run(); 374 getDevice().startUser(mOtherUser, true /* wait */); 375 installExistingAppAsUser(APPB_PKG, mOtherUser); 376 377 runDeviceTests(APPA_PKG, APPA_CLASS, APPA_METHOD_TEST_OTHER_USER_DIRS_NOT_ACCESSIBLE, 378 makeOtherUserIdArgs(mOtherUser)); 379 } 380 assumeCanCreateUser()381 private void assumeCanCreateUser() throws DeviceNotAvailableException { 382 assumeTrue("Test requires multi-user support", mSupportsMultiUser); 383 // If we're already at the user limit, e.g. when running the test in a secondary user, 384 // then we can't create another one. 385 int currentUserCount = getDevice().listUsers().size(); 386 assumeTrue("Test requires creating another user", 387 getDevice().getMaxNumberOfUsersSupported() > currentUserCount); 388 } 389 runDeviceTests(String pkgName, String testClassName, String testMethodName, Map<String, String> instrumentationArgs)390 private void runDeviceTests(String pkgName, String testClassName, String testMethodName, 391 Map<String, String> instrumentationArgs) throws DeviceNotAvailableException { 392 runDeviceTests(getDevice(), null, pkgName, testClassName, testMethodName, null, 393 10 * 60 * 1000L, 10 * 60 * 1000L, 0L, true, false, instrumentationArgs); 394 } 395 makeOtherUserIdArgs(int otherUser)396 private Map<String, String> makeOtherUserIdArgs(int otherUser) { 397 Map<String, String> args = new HashMap<>(); 398 args.put("other_user_id", Integer.toString(otherUser)); 399 return args; 400 } 401 forceStopPackage(String packageName)402 private void forceStopPackage(String packageName) throws Exception { 403 getDevice().executeShellCommand("am force-stop " + packageName); 404 } 405 reboot()406 private void reboot() throws Exception { 407 getDevice().reboot(); 408 waitForBootCompleted(getDevice()); 409 } 410 installExistingAppAsUser(String packageName, int userId)411 private void installExistingAppAsUser(String packageName, int userId) throws Exception { 412 final String installString = 413 "Package " + packageName + " installed for user: " + userId + "\n"; 414 assertEquals(installString, getDevice().executeShellCommand( 415 "cmd package install-existing --full" 416 + " --user " + Integer.toString(userId) 417 + " " + packageName)); 418 } 419 assumeThatFuseDataIsolationIsEnabled(ITestDevice device)420 private static void assumeThatFuseDataIsolationIsEnabled(ITestDevice device) 421 throws DeviceNotAvailableException { 422 assumeThat(device.executeShellCommand( 423 "getprop persist.sys.vold_app_data_isolation_enabled").trim(), 424 is("true")); 425 } 426 isFbeModeEmulated()427 private boolean isFbeModeEmulated() throws Exception { 428 String mode = getDevice().executeShellCommand("sm get-fbe-mode").trim(); 429 if (mode.equals(FBE_MODE_EMULATED)) { 430 return true; 431 } else if (mode.equals(FBE_MODE_NATIVE)) { 432 return false; 433 } 434 fail("Unknown FBE mode: " + mode); 435 return false; 436 } 437 } 438