1 /* 2 * Copyright (C) 2022 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 com.android.sdksandbox.cts.host; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import static org.junit.Assume.assumeTrue; 23 24 import android.app.sdksandbox.hosttestutils.AdoptableStorageUtils; 25 import android.app.sdksandbox.hosttestutils.SdkSandboxDeviceSupportedHostRule; 26 import android.app.sdksandbox.hosttestutils.SecondaryUserUtils; 27 import android.platform.test.annotations.LargeTest; 28 29 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 30 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 31 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions; 32 33 import org.junit.After; 34 import org.junit.Before; 35 import org.junit.Rule; 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 39 @RunWith(DeviceJUnit4ClassRunner.class) 40 public class SdkSandboxDataIsolationHostTest extends BaseHostJUnit4Test { 41 42 @Rule(order = 0) 43 public final SdkSandboxDeviceSupportedHostRule deviceSupportRule = 44 new SdkSandboxDeviceSupportedHostRule(this); 45 46 private static final String APP_PACKAGE = "com.android.sdksandbox.cts.app"; 47 private static final String APP_APK = "CtsSdkSandboxHostTestApp.apk"; 48 private static final String APP_TEST_CLASS = APP_PACKAGE + ".SdkSandboxDataIsolationTestApp"; 49 50 private static final String APP_2_PACKAGE = "com.android.sdksandbox.cts.app2"; 51 private static final String APP_2_APK = "CtsSdkSandboxHostTestApp2.apk"; 52 53 private final SecondaryUserUtils mUserUtils = new SecondaryUserUtils(this); 54 private final AdoptableStorageUtils mAdoptableUtils = new AdoptableStorageUtils(this); 55 56 /** 57 * Runs the given phase of a test by calling into the device. Throws an exception if the test 58 * phase fails. 59 * 60 * <p>For example, <code>runPhase("testExample");</code> 61 */ runPhase(String phase)62 private void runPhase(String phase) throws Exception { 63 assertThat(runDeviceTests(APP_PACKAGE, APP_TEST_CLASS, phase)).isTrue(); 64 } 65 runPhase( String phase, String instrumentationArgKey, String instrumentationArgValue)66 private void runPhase( 67 String phase, String instrumentationArgKey, String instrumentationArgValue) 68 throws Exception { 69 runDeviceTests( 70 new DeviceTestRunOptions(APP_PACKAGE) 71 .setDevice(getDevice()) 72 .setTestClassName(APP_TEST_CLASS) 73 .setTestMethodName(phase) 74 .addInstrumentationArg(instrumentationArgKey, instrumentationArgValue)); 75 } 76 77 @Before setUp()78 public void setUp() throws Exception { 79 // These tests run on system user 80 uninstallPackage(APP_PACKAGE); 81 uninstallPackage(APP_2_PACKAGE); 82 } 83 84 @After tearDown()85 public void tearDown() throws Exception { 86 mUserUtils.removeSecondaryUserIfNecessary(); 87 uninstallPackage(APP_PACKAGE); 88 uninstallPackage(APP_2_PACKAGE); 89 } 90 91 @Test testAppCannotAccessAnySandboxDirectories()92 public void testAppCannotAccessAnySandboxDirectories() throws Exception { 93 installPackage(APP_APK); 94 installPackage(APP_2_APK); 95 96 runPhase("testAppCannotAccessAnySandboxDirectories"); 97 } 98 99 /** Test whether an SDK can access its provided data directories after data isolation. */ 100 @Test testSdkSandboxDataIsolation_SandboxCanAccessItsDirectory()101 public void testSdkSandboxDataIsolation_SandboxCanAccessItsDirectory() throws Exception { 102 installPackage(APP_APK); 103 runPhase("testSdkSandboxDataIsolation_SandboxCanAccessItsDirectory"); 104 } 105 106 /** 107 * Test whether an SDK can detect if an app is installed by the error obtained from accessing 108 * other sandbox app directories. ENOENT error should occur regardless of whether the app exists 109 * or not. 110 */ 111 @Test testSdkSandboxDataIsolation_CannotVerifyAppExistence()112 public void testSdkSandboxDataIsolation_CannotVerifyAppExistence() throws Exception { 113 installPackage(APP_APK); 114 installPackage(APP_2_APK); 115 116 runPhase("testSdkSandboxDataIsolation_CannotVerifyAppExistence"); 117 } 118 119 /** 120 * Test whether an SDK can detect if an app is installed by the error obtained from accessing 121 * other sandbox user directories. Permission errors should show up regardless of whether the 122 * app exists, when trying to access other user data. 123 */ 124 @Test 125 @LargeTest // Creates user testSdkSandboxDataIsolation_CannotVerifyOtherUserAppExistence()126 public void testSdkSandboxDataIsolation_CannotVerifyOtherUserAppExistence() throws Exception { 127 assumeTrue(getDevice().isMultiUserSupported()); 128 129 installPackage(APP_APK); 130 131 int userId = mUserUtils.createAndStartSecondaryUser(); 132 installPackageAsUser(APP_2_APK, true, userId); 133 134 runPhase( 135 "testSdkSandboxDataIsolation_CannotVerifyOtherUserAppExistence", 136 "sandbox_isolation_user_id", 137 Integer.toString(userId)); 138 } 139 140 /** 141 * Test whether an SDK can verify an app's existence by checking other volumes, after data 142 * isolation has occurred. 143 */ 144 @Test 145 @LargeTest // Creates volume testSdkSandboxDataIsolation_CannotVerifyAcrossVolumes()146 public void testSdkSandboxDataIsolation_CannotVerifyAcrossVolumes() throws Exception { 147 assumeTrue(mAdoptableUtils.isAdoptableStorageSupported()); 148 mAdoptableUtils.enableVirtualDisk(); 149 installPackage(APP_APK); 150 installPackage(APP_2_APK); 151 152 try { 153 final String uuid = mAdoptableUtils.createNewVolume(); 154 155 // Move second package to the newly created volume 156 String result = 157 getDevice() 158 .executeShellCommand("pm move-package " + APP_2_PACKAGE + " " + uuid); 159 assertWithMessage("Command failed: pm move-package").that(result).startsWith("Success"); 160 161 runPhase( 162 "testSdkSandboxDataIsolation_CannotVerifyAcrossVolumes", 163 "sandbox_isolation_uuid", 164 uuid); 165 } finally { 166 mAdoptableUtils.cleanUpVolume(); 167 } 168 } 169 } 170