1 /* 2 * Copyright (C) 2023 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.tests.sdksandbox.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.DeviceSupportHostUtils; 25 26 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 27 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 28 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions; 29 30 import org.junit.After; 31 import org.junit.Before; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 35 @RunWith(DeviceJUnit4ClassRunner.class) 36 public final class SdkSandboxSmallModuleHostTest extends BaseHostJUnit4Test { 37 38 private static final String TEST_APP_PACKAGE = "com.android.tests.sdksandbox"; 39 private static final String MODULE_NAME = "com.android.adservices"; 40 private static final String SYSTEM_APEX_PATH = "/system/apex/" + MODULE_NAME + ".capex"; 41 private static final String PRIV_APP_DIR = "/apex/" + MODULE_NAME + "/priv-app"; 42 private static final String ACTIVE_APEX_DIR = "/data/apex/active/"; 43 44 private final DeviceSupportHostUtils mDeviceSupportUtils = new DeviceSupportHostUtils(this); 45 46 /** 47 * Runs the given phase of a test by calling into the device. 48 * 49 * <p>Hidden API checks are disabled. 50 * 51 * <p>For example, <code>runPhase("testExample");</code> 52 * 53 * @throws AssertionException if test phase fails. 54 */ runPhase(String phase)55 private void runPhase(String phase) throws Exception { 56 DeviceTestRunOptions options = 57 new DeviceTestRunOptions(TEST_APP_PACKAGE) 58 .setTestClassName(TEST_APP_PACKAGE + ".SdkSandboxSmallModuleTestApp") 59 .setTestMethodName(phase) 60 .setDisableHiddenApiCheck(true); 61 62 assertThat(runDeviceTests(options)).isTrue(); 63 } 64 65 @Before setUp()66 public void setUp() throws Exception { 67 assumeTrue( 68 "Device needs to support SdkSandbox", mDeviceSupportUtils.isSdkSandboxSupported()); 69 70 // Determine if Small module related test can be run on the device 71 boolean canBeUpdatedWithSmallModule = isSmallModuleUpdatePossible(); 72 boolean alreadyHasSmallModuleInstalled = !isAdServicesApkPresent(); 73 assumeTrue( 74 "Device has com.android.adservices APEX or small module pre-installed", 75 canBeUpdatedWithSmallModule || alreadyHasSmallModuleInstalled); 76 77 removeUpdatedApexIfNecessary(); 78 } 79 80 @After tearDown()81 public void tearDown() throws Exception { 82 removeUpdatedApexIfNecessary(); 83 } 84 85 @Test testSmallModuleCanBeInstalled()86 public void testSmallModuleCanBeInstalled() throws Exception { 87 // This test only makes sense for devices where we can install the small module apex 88 assumeTrue( 89 "Device has com.android.adservices APEX pre-installed", 90 isSmallModuleUpdatePossible()); 91 92 runPhase("installSmallModulePendingReboot"); 93 getDevice().reboot(); 94 95 assertWithMessage("AdServices APK is present").that(isAdServicesApkPresent()).isFalse(); 96 } 97 98 @Test testSmallModuleCanBeInstalled_andThenUpdatedToFullModule()99 public void testSmallModuleCanBeInstalled_andThenUpdatedToFullModule() throws Exception { 100 // This test only makes sense for devices where we can install the small module apex 101 assumeTrue( 102 "Device has com.android.adservices APEX pre-installed", 103 isSmallModuleUpdatePossible()); 104 105 runPhase("installSmallModulePendingReboot"); 106 getDevice().reboot(); 107 108 runPhase("installFullModulePendingReboot"); 109 getDevice().reboot(); 110 111 assertWithMessage("AdServices APK is present").that(isAdServicesApkPresent()).isTrue(); 112 } 113 114 /** Verify services exported from AdServices APK are unavailable on small module. */ 115 @Test testVerifyAdServicesAreUnavailableOnSmallModule()116 public void testVerifyAdServicesAreUnavailableOnSmallModule() throws Exception { 117 if (isAdServicesApkPresent()) { 118 // Device does not have small module pre-installed. Prepare it. 119 runPhase("testVerifyAdServicesAreAvailable_preSmallModuleInstall"); 120 121 installSmallModule(); 122 } 123 runPhase("testVerifyAdServicesAreUnavailable_postSmallModuleInstall"); 124 } 125 126 @Test testLoadSdk()127 public void testLoadSdk() throws Exception { 128 if (isAdServicesApkPresent()) { 129 // Device does not have small module pre-installed and loadSdk should work 130 // Test that loadSdk works 131 runPhase("testLoadSdkWithAdServiceApk"); 132 133 installSmallModule(); 134 } 135 // Test that loadSdk returns error when AdServices apk is not present 136 runPhase("testLoadSdkWithoutAdServiceApk"); 137 } 138 installSmallModule()139 private void installSmallModule() throws Exception { 140 runPhase("installSmallModulePendingReboot"); 141 getDevice().reboot(); 142 } 143 isSmallModuleUpdatePossible()144 private boolean isSmallModuleUpdatePossible() throws Exception { 145 return getDevice().doesFileExist(SYSTEM_APEX_PATH); 146 } 147 isAdServicesApkPresent()148 private boolean isAdServicesApkPresent() throws Exception { 149 // If the mounted module contains AdServices apk, it will get mounted as priv-app 150 // apk at PRIV_APP_DIR 151 return getDevice().isDirectory(PRIV_APP_DIR); 152 } 153 removeUpdatedApexIfNecessary()154 private void removeUpdatedApexIfNecessary() throws Exception { 155 String[] children = getDevice().getChildren(ACTIVE_APEX_DIR); 156 boolean activeApexFound = false; 157 for (int i = 0; i < children.length; i++) { 158 String child = children[i]; 159 if (child.startsWith(MODULE_NAME)) { 160 activeApexFound = true; 161 String childPath = ACTIVE_APEX_DIR + "/" + child; 162 getDevice().deleteFile(childPath); 163 getDevice().reboot(); 164 assertWithMessage("Module update removed").that(isAdServicesApkPresent()).isTrue(); 165 } 166 } 167 } 168 } 169