1 /* 2 * Copyright (C) 2016 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.compatibility.common.tradefed.targetprep; 18 19 import com.android.ddmlib.IDevice; 20 import com.android.ddmlib.Log; 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.targetprep.ITargetCleaner; 27 import com.android.tradefed.targetprep.TargetSetupError; 28 import com.android.tradefed.targetprep.BuildError; 29 import com.android.tradefed.testtype.IAbi; 30 import com.android.tradefed.testtype.IAbiReceiver; 31 import com.android.tradefed.util.StreamUtil; 32 33 import java.io.File; 34 import java.io.InputStream; 35 import java.io.IOException; 36 import java.nio.file.Paths; 37 import java.util.NoSuchElementException; 38 39 import org.json.JSONException; 40 import org.json.JSONObject; 41 42 /** 43 * A {@link HidlProfilerPreparer} that attempts to enable and disable HIDL profiling on a target device. 44 * <p /> 45 * This is used when one wants to do such setup and cleanup operations in Java instead of the 46 * VTS Python runner, Python test template, or Python test case. 47 */ 48 @OptionClass(alias = "push-file") 49 public class HidlProfilerPreparer implements ITargetCleaner, IAbiReceiver { 50 private static final String LOG_TAG = "HidlProfilerPreparer"; 51 52 private static final String TARGET_PROFILING_TRACE_PATH = "/data/local/tmp/"; 53 private static final String TARGET_PROFILING_LIBRARY_PATH = "/data/local/tmp/<bitness>/hw/"; 54 private static final String HOST_PROFILING_TRACE_PATH = "/tmp/vts-trace/record-replay/"; 55 private static final String HOST_PROFILING_TRACE_PATH_KEY = "profiling_trace_path"; 56 57 private static final String VENDOR_TEST_CONFIG_FILE_PATH = 58 "/config/google-tradefed-vts-config.config"; 59 60 @Option(name="target-profiling-trace-path", description= 61 "The target-side path to store the profiling trace file(s).") 62 private String mTargetProfilingTracePath = TARGET_PROFILING_TRACE_PATH; 63 64 @Option(name="target-profiling-library-path", description= 65 "The target-side path to store the profiling trace file(s). " + 66 "Use <bitness> to auto fill in 32 or 64 depending on the target device bitness.") 67 private String mTargetProfilingLibraryPath = TARGET_PROFILING_LIBRARY_PATH; 68 69 @Option(name="copy-generated-trace-files", description= 70 "Whether to copy the generated trace files to a host-side, " + 71 "designated destination dir") 72 private boolean mCopyGeneratedTraceFiles = false; 73 74 @Option(name="host-profiling-trace-path", description= 75 "The host-side path to store the profiling trace file(s).") 76 private String mHostProfilingTracePath = HOST_PROFILING_TRACE_PATH; 77 78 private IAbi mAbi = null; 79 80 /** 81 * Set mTargetProfilingTracePath. Exposed for testing. 82 */ setTargetProfilingTracePath(String path)83 void setTargetProfilingTracePath(String path) { 84 mTargetProfilingTracePath = path; 85 } 86 87 /** 88 * Set mTargetProfilingLibraryPath. Exposed for testing. 89 */ setTargetProfilingLibraryPath(String path)90 void setTargetProfilingLibraryPath(String path) { 91 mTargetProfilingLibraryPath = path; 92 } 93 94 /** 95 * {@inheritDoc} 96 */ 97 @Override setAbi(IAbi abi)98 public void setAbi(IAbi abi){ 99 mAbi = abi; 100 } 101 102 /** 103 * {@inheritDoc} 104 */ 105 @Override setUp(ITestDevice device, IBuildInfo buildInfo)106 public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError, BuildError, 107 DeviceNotAvailableException, RuntimeException { 108 readVtsTradeFedVendorConfig(); 109 110 // Cleanup any existing traces 111 Log.d(LOG_TAG, String.format("Deleting any existing target-side trace files in %s.", 112 mTargetProfilingTracePath)); 113 device.executeShellCommand( 114 String.format("rm %s/*.vts.trace", mTargetProfilingTracePath)); 115 116 Log.d(LOG_TAG, String.format("Starting the HIDL profiling (bitness: %s).", 117 mAbi.getBitness())); 118 mTargetProfilingLibraryPath = mTargetProfilingLibraryPath.replace( 119 "<bitness>", mAbi.getBitness()); 120 Log.d(LOG_TAG, String.format("Target Profiling Library Path: %s", 121 mTargetProfilingLibraryPath)); 122 123 String result = 124 device.executeShellCommand("setenforce 0"); 125 Log.d(LOG_TAG, String.format("setenforce: %s", result)); 126 127 // profiler runs as a different user and thus 777 is needed. 128 result = 129 device.executeShellCommand("chmod 777 /data"); 130 Log.d(LOG_TAG, String.format("chmod: %s", result)); 131 result = 132 device.executeShellCommand("chmod 777 /data/local"); 133 Log.d(LOG_TAG, String.format("chmod: %s", result)); 134 result = 135 device.executeShellCommand("chmod 777 /data/local/tmp"); 136 Log.d(LOG_TAG, String.format("chmod: %s", result)); 137 138 result = 139 device.executeShellCommand("chmod 755 /data/local/tmp/vts_profiling_configure"); 140 Log.d(LOG_TAG, String.format("chmod: %s", result)); 141 result = device.executeShellCommand( 142 String.format("/data/local/tmp/vts_profiling_configure enable")); 143 Log.d(LOG_TAG, String.format("start profiling: %s", result)); 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 Log.d(LOG_TAG, "Stopping the HIDL Profiling."); 153 // Disables VTS Profiling 154 device.executeShellCommand("chmod 755 /data/local/tmp/vts_profiling_configure"); 155 String result = device.executeShellCommand( 156 "/data/local/tmp/vts_profiling_configure disable clear"); 157 Log.d(LOG_TAG, String.format("stop profiling: %s", result)); 158 159 // Gets trace files from the target. 160 if (!mTargetProfilingTracePath.endsWith("/")) { 161 mTargetProfilingTracePath += "/"; 162 } 163 String traceFileListString = device.executeShellCommand( 164 String.format("ls %s*.vts.trace", mTargetProfilingTracePath)); 165 if (!traceFileListString.contains("No such file or directory")) { 166 Log.d(LOG_TAG, String.format("Generated trace files: %s", 167 traceFileListString)); 168 if (mCopyGeneratedTraceFiles) { 169 File destDir = new File(mHostProfilingTracePath); 170 if (!destDir.exists() && !destDir.mkdirs()) { 171 Log.e(LOG_TAG, String.format("Couldn't create a dir, %s.", 172 mHostProfilingTracePath)); 173 } else { 174 for (String traceFilePath : traceFileListString.split("\\s+")) { 175 File traceFile = new File(traceFilePath); 176 File destFile = new File(destDir, traceFile.getName()); 177 Log.d(LOG_TAG, String.format("Copying a trace file: %s -> %s", 178 traceFilePath, destFile)); 179 if (device.pullFile(traceFilePath, destFile)) { 180 Log.d(LOG_TAG, "Copying a trace file succeeded."); 181 } else { 182 Log.e(LOG_TAG, "Copying a trace file failed."); 183 } 184 } 185 } 186 } 187 } else { 188 Log.d(LOG_TAG, "Generated trace files: none"); 189 } 190 } 191 192 /** 193 * Reads HOST_PROFILING_TRACE_PATH_KEY value from VENDOR_TEST_CONFIG_FILE_PATH. 194 */ readVtsTradeFedVendorConfig()195 private void readVtsTradeFedVendorConfig() throws RuntimeException { 196 Log.d(LOG_TAG, String.format("Load vendor test config %s", 197 VENDOR_TEST_CONFIG_FILE_PATH)); 198 InputStream config = getClass().getResourceAsStream( 199 VENDOR_TEST_CONFIG_FILE_PATH); 200 if (config == null) { 201 Log.d(LOG_TAG, 202 String.format("Vendor test config file %s does not exist.", 203 VENDOR_TEST_CONFIG_FILE_PATH)); 204 return; 205 } 206 207 try { 208 String content = StreamUtil.getStringFromStream(config); 209 Log.d(LOG_TAG, String.format("Loaded vendor test config %s", 210 content)); 211 if (content != null) { 212 JSONObject vendorConfigJson = new JSONObject(content); 213 try { 214 String tracePath = vendorConfigJson.getString( 215 HOST_PROFILING_TRACE_PATH_KEY); 216 if (tracePath.length() > 0) { 217 mHostProfilingTracePath = tracePath; 218 } 219 } catch (NoSuchElementException e) { 220 Log.d(LOG_TAG, 221 String.format( 222 "Vendor config does not define %s", 223 HOST_PROFILING_TRACE_PATH_KEY)); 224 } 225 } 226 } catch (IOException e) { 227 throw new RuntimeException( 228 "Failed to read vendor config json file"); 229 } catch (JSONException e) { 230 throw new RuntimeException( 231 "Failed to build updated vendor config json data"); 232 } 233 } 234 } 235