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