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