1 /* 2 * Copyright (C) 2018 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.tradefed.targetprep; 18 19 import com.android.compatibility.common.tradefed.build.VtsCompatibilityInvocationHelper; 20 import com.android.annotations.VisibleForTesting; 21 import com.android.tradefed.build.IBuildInfo; 22 import com.android.tradefed.config.Option; 23 import com.android.tradefed.config.OptionClass; 24 import com.android.tradefed.device.DeviceNotAvailableException; 25 import com.android.tradefed.device.ITestDevice; 26 import com.android.tradefed.invoker.IInvocationContext; 27 import com.android.tradefed.log.LogUtil.CLog; 28 import com.android.tradefed.targetprep.TargetSetupError; 29 import com.android.tradefed.targetprep.multi.IMultiTargetPreparer; 30 import com.android.tradefed.testtype.IAbi; 31 import com.android.tradefed.testtype.IAbiReceiver; 32 import com.android.tradefed.util.CmdUtil; 33 import com.android.tradefed.util.FileUtil; 34 35 import java.io.File; 36 import java.io.IOException; 37 import java.util.NoSuchElementException; 38 import java.util.Vector; 39 import java.util.function.Predicate; 40 41 /** 42 * Starts and stops a HAL (Hardware Abstraction Layer) adapter. 43 * Only used for single-device testing or the primary device in multi-device 44 * testing. 45 */ 46 @OptionClass(alias = "vts-hal-adapter-preparer") 47 public class VtsHalAdapterPreparer implements ITargetCleaner, IAbiReceiver { 48 static final int THREAD_COUNT_DEFAULT = 1; 49 50 static final String HAL_INTERFACE_SEP = "::"; 51 static final String HAL_INSTANCE_SEP = "/"; 52 // Relative path to vts native tests directory. 53 static final String VTS_NATIVE_TEST_DIR = "DATA/nativetest%s/"; 54 // Path of native tests directory on target device. 55 static final String TARGET_NATIVE_TEST_DIR = "/data/nativetest%s/"; 56 // Sysprop to stop HIDL adapaters. Currently, there's one global flag for all adapters. 57 static final String ADAPTER_SYSPROP = "test.hidl.adapters.deactivated"; 58 // The wrapper script to start an adapter binary in the background. 59 static final String SCRIPT_PATH = "/data/local/tmp/vts_adapter.sh"; 60 // Command to list the registered instance for the given hal@version. 61 static final String LIST_HAL_CMD = 62 "lshal -ti --neat 2>/dev/null | grep -e '^hwbinder' | awk '{print $2}' | grep %s"; 63 64 @Option(name = "adapter-binary-name", 65 description = "Adapter binary file name (typically under /data/nativetest*/)") 66 private String mAdapterBinaryName = null; 67 68 @Option(name = "hal-package-name", description = "Target hal to adapter") 69 private String mPackageName = null; 70 71 @Option(name = "thread-count", description = "HAL adapter's thread count") 72 private int mThreadCount = THREAD_COUNT_DEFAULT; 73 74 // Application Binary Interface (ABI) info of the current test run. 75 private IAbi mAbi = null; 76 77 // CmdUtil help to verify the cmd results. 78 private CmdUtil mCmdUtil = null; 79 // Predicates to stop retrying cmd. 80 private Predicate<String> mCheckEmpty = (String str) -> { 81 return str.isEmpty(); 82 }; 83 private Predicate<String> mCheckNonEmpty = (String str) -> { 84 return !str.isEmpty(); 85 }; 86 private Vector<String> mCommands = new Vector<String>(); 87 88 /** 89 * {@inheritDoc} 90 */ 91 @Override setUp(ITestDevice device, IBuildInfo buildInfo)92 public void setUp(ITestDevice device, IBuildInfo buildInfo) 93 throws TargetSetupError, BuildError, DeviceNotAvailableException { 94 // adb root. 95 device.enableAdbRoot(); 96 String bitness = 97 (mAbi != null) ? ((mAbi.getBitness() == "32") ? "" : mAbi.getBitness()) : ""; 98 try { 99 pushAdapter(device, bitness); 100 } catch (IOException | NoSuchElementException e) { 101 CLog.e("Could not push adapter: " + e.toString()); 102 throw new TargetSetupError("Could not push adapter."); 103 } 104 105 mCmdUtil = mCmdUtil != null ? mCmdUtil : new CmdUtil(); 106 mCmdUtil.setSystemProperty(device, ADAPTER_SYSPROP, "false"); 107 108 String out = device.executeShellCommand(String.format(LIST_HAL_CMD, mPackageName)); 109 for (String line : out.split("\n")) { 110 if (!line.isEmpty()) { 111 if (!line.contains(HAL_INTERFACE_SEP)) { 112 throw new TargetSetupError("HAL instance with wrong format."); 113 } 114 String interfaceInstance = line.split(HAL_INTERFACE_SEP, 2)[1]; 115 if (!interfaceInstance.contains(HAL_INSTANCE_SEP)) { 116 throw new TargetSetupError("HAL instance with wrong format."); 117 } 118 String interfaceName = interfaceInstance.split(HAL_INSTANCE_SEP, 2)[0]; 119 String instanceName = interfaceInstance.split(HAL_INSTANCE_SEP, 2)[1]; 120 // starts adapter 121 String command = String.format("chmod a+x %s", SCRIPT_PATH); 122 mCommands.add(command); 123 command = String.format("%s /data/nativetest%s/%s %s %s %d", SCRIPT_PATH, bitness, 124 mAdapterBinaryName, interfaceName, instanceName, mThreadCount); 125 CLog.d("Trying to adapter for %s", 126 mPackageName + "::" + interfaceName + "/" + instanceName); 127 mCommands.add(command); 128 } 129 } 130 if (mCommands.isEmpty()) { 131 CLog.w("The specific HAL service is not running."); 132 return; 133 } 134 if (!mCmdUtil.retry( 135 device, mCommands, String.format(LIST_HAL_CMD, mPackageName), mCheckEmpty)) { 136 throw new TargetSetupError("HAL adapter setup failed."); 137 } 138 139 mCmdUtil.restartFramework(device); 140 if (!mCmdUtil.waitCmdResultWithDelay( 141 device, "service list | grep IPackageManager", mCheckNonEmpty)) { 142 throw new TargetSetupError("Failed to start package service"); 143 } 144 } 145 146 /** 147 * {@inheritDoc} 148 */ 149 @Override tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)150 public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e) 151 throws DeviceNotAvailableException { 152 if (!mCommands.isEmpty()) { 153 // stops adapter(s) 154 String command = String.format("setprop %s %s", ADAPTER_SYSPROP, "true"); 155 mCmdUtil = mCmdUtil != null ? mCmdUtil : new CmdUtil(); 156 if (!mCmdUtil.retry(device, command, String.format(LIST_HAL_CMD, mPackageName), 157 mCheckNonEmpty, mCommands.size() + mCmdUtil.MAX_RETRY_COUNT)) { 158 CLog.e("HAL restore failed."); 159 } 160 // TODO: cleanup the pushed adapter files. 161 mCmdUtil.restartFramework(device); 162 } 163 } 164 165 /** 166 * {@inheritDoc} 167 */ 168 @Override setAbi(IAbi abi)169 public void setAbi(IAbi abi) { 170 mAbi = abi; 171 } 172 173 /** 174 * {@inheritDoc} 175 */ 176 @Override getAbi()177 public IAbi getAbi() { 178 return mAbi; 179 } 180 181 /** 182 * Push the required adapter binary to device. 183 * 184 * @param device device object. 185 * @param bitness ABI bitness. 186 * @throws DeviceNotAvailableException. 187 * @throws IOException. 188 * @throws NoSuchElementException. 189 */ pushAdapter(ITestDevice device, String bitness)190 private void pushAdapter(ITestDevice device, String bitness) 191 throws DeviceNotAvailableException, IOException, NoSuchElementException { 192 VtsCompatibilityInvocationHelper invocationHelper = createVtsHelper(); 193 File adapterDir = new File( 194 invocationHelper.getTestsDir(), String.format(VTS_NATIVE_TEST_DIR, bitness)); 195 File adapter = FileUtil.findFile(adapterDir, mAdapterBinaryName); 196 if (adapter != null) { 197 CLog.d("Pushing %s", mAdapterBinaryName); 198 device.pushFile( 199 adapter, String.format(TARGET_NATIVE_TEST_DIR, bitness) + mAdapterBinaryName); 200 } else { 201 throw new NoSuchElementException("Could not find adapter: " + mAdapterBinaryName); 202 } 203 } 204 205 /** 206 * Create and return a {@link VtsCompatibilityInvocationHelper} to use during the preparer. 207 */ 208 @VisibleForTesting createVtsHelper()209 VtsCompatibilityInvocationHelper createVtsHelper() { 210 return new VtsCompatibilityInvocationHelper(); 211 } 212 213 @VisibleForTesting setCmdUtil(CmdUtil cmdUtil)214 void setCmdUtil(CmdUtil cmdUtil) { 215 mCmdUtil = cmdUtil; 216 } 217 218 @VisibleForTesting addCommand(String command)219 void addCommand(String command) { 220 mCommands.add(command); 221 } 222 } 223