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