1 /* 2 * Copyright (C) 2020 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 package com.android.cts.host.blob; 17 18 import static com.google.common.truth.Truth.assertWithMessage; 19 20 import com.android.tradefed.device.ITestDevice; 21 import com.android.tradefed.device.TestDeviceOptions; 22 import com.android.tradefed.log.LogUtil.CLog; 23 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 24 import com.android.tradefed.testtype.junit4.DeviceTestRunOptions; 25 import com.android.tradefed.util.Pair; 26 import com.android.tradefed.util.RunUtil; 27 28 import java.util.Arrays; 29 import java.util.HashMap; 30 import java.util.Map; 31 import java.util.regex.Matcher; 32 import java.util.regex.Pattern; 33 import java.util.stream.Collectors; 34 35 abstract class BaseBlobStoreHostTest extends BaseHostJUnit4Test { 36 protected static final String TARGET_APK = "CtsBlobStoreHostTestHelper.apk"; 37 protected static final String TARGET_PKG = "com.android.cts.device.blob"; 38 39 protected static final String TARGET_APK_DEV = "CtsBlobStoreHostTestHelperDev.apk"; 40 protected static final String TARGET_PKG_DEV = "com.android.cts.device.blob.dev"; 41 42 protected static final String TARGET_APK_ASSIST = "CtsBlobStoreHostTestHelperAssist.apk"; 43 protected static final String TARGET_PKG_ASSIST = "com.android.cts.device.blob.assist"; 44 45 private static final long DEFAULT_INSTRUMENTATION_TIMEOUT_MS = 900_000; // 15min 46 47 protected static final String KEY_SESSION_ID = "session"; 48 49 protected static final String KEY_DIGEST = "digest"; 50 protected static final String KEY_EXPIRY = "expiry"; 51 protected static final String KEY_LABEL = "label"; 52 protected static final String KEY_TAG = "tag"; 53 54 protected static final String KEY_ALLOW_PUBLIC = "public"; 55 protected static final String KEY_ALLOW_SAME_SIGNATURE = "same_signature"; 56 57 private static final long REBOOT_TIMEOUT_MS = 3 * 60 * 1000; 58 private static final long ONLINE_TIMEOUT_MS = 3 * 60 * 1000; 59 60 private static final String PROPERTY_USERSPACE_REBOOT_IS_SUPPORTED = 61 "init.userspace_reboot.is_supported"; 62 runDeviceTest(String testPkg, String testClass, String testMethod)63 protected void runDeviceTest(String testPkg, String testClass, String testMethod) 64 throws Exception { 65 runDeviceTest(testPkg, testClass, testMethod, null); 66 } 67 runDeviceTestAsUser(String testPkg, String testClass, String testMethod, int userId)68 protected void runDeviceTestAsUser(String testPkg, String testClass, String testMethod, 69 int userId) throws Exception { 70 runDeviceTestAsUser(testPkg, testClass, testMethod, null, userId); 71 } 72 runDeviceTest(String testPkg, String testClass, String testMethod, Map<String, String> instrumentationArgs)73 protected void runDeviceTest(String testPkg, String testClass, String testMethod, 74 Map<String, String> instrumentationArgs) throws Exception { 75 runDeviceTestAsUser(testPkg, testClass, testMethod, instrumentationArgs, -1); 76 } 77 runDeviceTestAsUser(String testPkg, String testClass, String testMethod, Map<String, String> instrumentationArgs, int userId)78 protected void runDeviceTestAsUser(String testPkg, String testClass, String testMethod, 79 Map<String, String> instrumentationArgs, int userId) throws Exception { 80 final DeviceTestRunOptions deviceTestRunOptions = new DeviceTestRunOptions(testPkg) 81 .setTestClassName(testClass) 82 .setTestMethodName(testMethod) 83 .setMaxInstrumentationTimeoutMs(DEFAULT_INSTRUMENTATION_TIMEOUT_MS); 84 if (userId != -1) { 85 deviceTestRunOptions.setUserId(userId); 86 } 87 if (instrumentationArgs != null) { 88 for (Map.Entry<String, String> entry : instrumentationArgs.entrySet()) { 89 deviceTestRunOptions.addInstrumentationArg(entry.getKey(), entry.getValue()); 90 } 91 } 92 assertWithMessage(testMethod + " failed").that( 93 runDeviceTests(deviceTestRunOptions)).isTrue(); 94 } 95 getDeviceTimeMs()96 protected long getDeviceTimeMs() throws Exception { 97 final String timeMs = getDevice().executeShellCommand("date +%s%3N"); 98 return Long.parseLong(timeMs.trim()); 99 } 100 rebootAndWaitUntilReady()101 protected void rebootAndWaitUntilReady() throws Exception { 102 TestDeviceOptions options = getDevice().getOptions(); 103 final long prevRebootTimeoutMs = options.getRebootTimeout(); 104 final long prevOnlineTimeoutMs = options.getOnlineTimeout(); 105 updateDeviceOptions(options, REBOOT_TIMEOUT_MS, ONLINE_TIMEOUT_MS); 106 try { 107 if (getDevice().getBooleanProperty(PROPERTY_USERSPACE_REBOOT_IS_SUPPORTED, false)) { 108 getDevice().rebootUserspace(); 109 } else { 110 getDevice().reboot(); // reboot() waits for device to be available 111 } 112 } finally { 113 updateDeviceOptions(options, prevRebootTimeoutMs, prevOnlineTimeoutMs); 114 } 115 } 116 updateDeviceOptions(TestDeviceOptions options, long rebootTimeoutMs, long onlineTimeoutMs)117 private void updateDeviceOptions(TestDeviceOptions options, 118 long rebootTimeoutMs, long onlineTimeoutMs) throws Exception { 119 options.setRebootTimeout((int) rebootTimeoutMs); 120 options.setOnlineTimeout(onlineTimeoutMs); 121 getDevice().setOptions(options); 122 } 123 isMultiUserSupported(ITestDevice device)124 protected static boolean isMultiUserSupported(ITestDevice device) throws Exception { 125 return device.isMultiUserSupported(); 126 } 127 createArgsFromLastTestRun()128 protected Map<String, String> createArgsFromLastTestRun() { 129 final Map<String, String> args = new HashMap<>(); 130 for (String key : new String[] { 131 KEY_SESSION_ID, 132 KEY_DIGEST, 133 KEY_EXPIRY, 134 KEY_LABEL, 135 KEY_TAG 136 }) { 137 final String value = getLastDeviceRunResults().getRunMetrics().get(key); 138 if (value != null) { 139 args.put(key, value); 140 } 141 } 142 return args; 143 } 144 createArgs(Pair<String, String>.... keyValues)145 protected Map<String, String> createArgs(Pair<String, String>... keyValues) { 146 return Arrays.stream(keyValues).collect(Collectors.toMap(p -> p.first, p -> p.second)); 147 } 148 getAppUid(String pkgName)149 protected int getAppUid(String pkgName) throws Exception { 150 final int currentUser = getDevice().getCurrentUser(); 151 final String uidLine = getDevice().executeShellCommand( 152 "cmd package list packages -U --user " + currentUser + " " + pkgName); 153 final Pattern pattern = Pattern.compile("package:" + pkgName + " uid:(\\d+)"); 154 final Matcher matcher = pattern.matcher(uidLine); 155 assertWithMessage("Pkg not found: " + pkgName).that(matcher.find()).isTrue(); 156 final int appUid = Integer.parseInt(matcher.group(1)); 157 return appUid; 158 } 159 addAssistRoleHolder(String pkgName, int userId)160 protected void addAssistRoleHolder(String pkgName, int userId) throws Exception { 161 final String cmd = String.format("cmd role add-role-holder " 162 + "--user %d android.app.role.ASSISTANT %s", userId, pkgName); 163 runCommand(cmd); 164 // Wait for the role holder to be changed. 165 int checkRoleHolderRetries = 20; 166 while (checkRoleHolderRetries-- > 0) { 167 if (Arrays.stream(getAssistRoleHolders(userId)).anyMatch(pkgName::equals)) { 168 break; 169 } 170 // Wait and try again. 171 RunUtil.getDefault().sleep(5000); 172 } 173 } 174 getAssistRoleHolders(int userId)175 private String[] getAssistRoleHolders(int userId) throws Exception { 176 final String cmd = String.format("cmd role get-role-holders " 177 + "--user %d android.app.role.ASSISTANT", userId); 178 final String output = runCommand(cmd).trim(); 179 return output.split(";"); 180 } 181 removeAssistRoleHolder(String pkgName, int userId)182 protected void removeAssistRoleHolder(String pkgName, int userId) throws Exception { 183 final String cmd = String.format("cmd role remove-role-holder " 184 + "--user %d android.app.role.ASSISTANT %s", userId, pkgName); 185 runCommand(cmd); 186 } 187 revokePermission(String pkgName, String permissionName, int userId)188 protected void revokePermission(String pkgName, String permissionName, int userId) 189 throws Exception { 190 final String cmd = String.format("cmd package revoke --user %d %s %s", 191 userId, pkgName, permissionName); 192 runCommand(cmd); 193 } 194 runCommand(String command)195 protected String runCommand(String command) throws Exception { 196 final String output = getDevice().executeShellCommand(command); 197 CLog.v("Output of cmd '" + command + "': '" + output.trim() + "'"); 198 return output; 199 } 200 } 201