1 /* 2 * Copyright (C) 2014 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.graphics.tests; 18 19 import com.android.tradefed.config.Option; 20 import com.android.tradefed.config.Option.Importance; 21 import com.android.tradefed.device.CollectingOutputReceiver; 22 import com.android.tradefed.device.DeviceNotAvailableException; 23 import com.android.tradefed.device.ITestDevice; 24 import com.android.tradefed.log.LogUtil.CLog; 25 import com.android.tradefed.result.ITestInvocationListener; 26 import com.android.tradefed.testtype.IDeviceTest; 27 import com.android.tradefed.testtype.IRemoteTest; 28 import com.android.tradefed.util.AbiFormatter; 29 import com.android.tradefed.util.RunUtil; 30 import com.android.tradefed.util.proto.TfMetricProtoUtil; 31 32 import org.junit.Assert; 33 34 import java.util.HashMap; 35 import java.util.Map; 36 import java.util.concurrent.TimeUnit; 37 38 /** 39 * Test Runner for graphics Flatland Benchmark test. 40 * <p> 41 * Flatland test is a benchmark for measuring GPU performance in various 2D UI rendering and 42 * window composition scenarios. 43 * <p> 44 * Since it is measuring the hardware performance, the test should be executed in 45 * as consistent and static an environment as possible. 46 * <ul> 47 * <li>The display should be turned off and background service should be stopped before 48 * running the benchmark. Running 'adb shell stop' is probably sufficient for this, 49 * but if there are device specific background services that consume 50 * much CPU cycles, memory bandwidth, or might otherwise interfere with GPU rendering, 51 * those should be stopped as well 52 * <li>All relevant hardware clocks should be locked at particular frequency when running the test. 53 * </ul> 54 * <p> 55 * If running the benchmark with clocks locked causes thermal throttling, set option "--sleep-time" 56 * to 10 to 50 (ms) to insert sleep between each benchmark sample run. 57 * <p> 58 * Output interpretation: 59 * For each test case, the expected time in milliseconds that a single frame of the scenario 60 * takes to complete will be printed out. Four types of values could displayed: 61 * <ul> 62 * <li>fast - frames of the scenarios are completed too fast to be reliably benchmarked. This 63 * corresponds to frame time less than 3 ms. The scenario was skipped. "0" will be posted into 64 * the dashboard. 65 * <li>slow - frame time is too long, normally orver 50 ms. The scenario was skipped. "1000" will 66 * be posted into the dashboard. 67 * <li>varies - frame time was not stable. rerun the test to get a stable results. If that results 68 * show repeatedly, something is wrong with the environment, signal to file a bug. 69 * <li>decimal number - frame time for the scenarios are measured. 70 * </ul> 71 */ 72 public class FlatlandTest implements IDeviceTest, IRemoteTest { 73 74 private static final long SHELL_TIMEOUT = 30*60*1000; 75 private static final String COMMAND = "flatland|#ABI32#|"; 76 private static final String FIRST_LINE = "cmdline:"; 77 private static final String TITLE = "Scenario"; 78 private static final long START_TIMER = 2 * 60 * 1000; // 2 minutes 79 private static final String RESULT_FAST = "fast"; 80 private static final String RESULT_SLOW = "slow"; 81 private static final String RESULT_VARIES = "varies"; 82 83 private ITestDevice mTestDevice = null; 84 // HashMap to store results for 85 public Map<String, String> mResultMap = new HashMap<String, String>(); 86 87 @Option(name = "ru-key", description = "Reporting unit key to use when posting results") 88 private String mRuKey = "flatland"; 89 90 @Option(name = "run-path", 91 description = "path for the binary") 92 private String mRunPath = "/data/local/tmp/"; 93 94 @Option(name = "sleep-time", 95 description = "sleep for N ms between samples, set to 10 - 50 ms if the locked CPU" 96 + " frequency causes thermal throttle.") 97 private int mSleepTime = 50; 98 99 @Option(name = "schema-map", 100 description = "map a test case name to a schema key") 101 private Map<String, String> mSchemaMap = new HashMap<String, String>(); 102 103 @Option(name = AbiFormatter.FORCE_ABI_STRING, 104 description = AbiFormatter.FORCE_ABI_DESCRIPTION, 105 importance = Importance.IF_UNSET) 106 private String mForceAbi = null; 107 108 @Override 109 public void setDevice(ITestDevice testDevice) { 110 mTestDevice = testDevice; 111 } 112 113 @Override 114 public ITestDevice getDevice() { 115 return mTestDevice; 116 } 117 118 @Override 119 public void run(ITestInvocationListener standardListener) throws DeviceNotAvailableException { 120 Assert.assertNotNull(mRunPath); 121 RunUtil.getDefault().sleep(START_TIMER); 122 123 // execute test 124 StringBuilder cmd = new StringBuilder(); 125 cmd.append(mRunPath); 126 cmd.append(COMMAND); 127 if (mSleepTime > 0) { 128 cmd.append(" -s "); 129 cmd.append(mSleepTime); 130 } 131 standardListener.testRunStarted(mRuKey, 1); 132 long start = System.currentTimeMillis(); 133 CollectingOutputReceiver receiver = new CollectingOutputReceiver(); 134 mTestDevice.executeShellCommand(AbiFormatter.formatCmdForAbi(cmd.toString(), mForceAbi), 135 receiver, SHELL_TIMEOUT, TimeUnit.MILLISECONDS, 2); 136 String result = receiver.getOutput(); 137 if (result == null) { 138 CLog.v("no test results returned. Test failed?"); 139 return; 140 } 141 // parse results and report metrics 142 parseResult(result); 143 standardListener.testRunEnded( 144 (System.currentTimeMillis() - start), TfMetricProtoUtil.upgradeConvert(mResultMap)); 145 } 146 147 /** 148 * Parse results returned from running the benchmark 149 */ 150 public void parseResult(String result) { 151 String[] lines = result.split(System.getProperty("line.separator")); 152 if (lines.length <= 0) { 153 return; 154 } 155 for (int i = 0; i < lines.length; i++) { 156 if (!lines[i].contains(FIRST_LINE) && !(lines[i].contains(TITLE))) { 157 // skip the first two lines 158 String[] items = lines[i].trim().split("\\|"); 159 if (items.length == 3) { 160 String schemaKey = String.format("%s %s", items[0].trim(), items[1].trim()); 161 if (mSchemaMap.get(schemaKey) != null) { 162 // get the mapped schema key if there is any 163 schemaKey = mSchemaMap.get(schemaKey); 164 } 165 String renderTime = items[2].trim(); 166 if (renderTime != null) { 167 if (renderTime.equals(RESULT_FAST)) { 168 mResultMap.put(schemaKey, "0"); 169 } else if (renderTime.equals(RESULT_SLOW)) { 170 mResultMap.put(schemaKey, "1000"); 171 } else if (renderTime.equals(RESULT_VARIES)){ 172 mResultMap.put(schemaKey, "-1"); 173 } else { 174 mResultMap.put(schemaKey, renderTime); 175 } 176 } 177 } 178 } 179 } 180 } 181 } 182