1 /* 2 * Copyright (C) 2013 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.performance.tests; 18 19 import com.android.ddmlib.CollectingOutputReceiver; 20 import com.android.tradefed.device.DeviceNotAvailableException; 21 import com.android.tradefed.device.ITestDevice; 22 import com.android.tradefed.log.LogUtil.CLog; 23 import com.android.tradefed.result.ITestInvocationListener; 24 import com.android.tradefed.result.TestDescription; 25 import com.android.tradefed.testtype.IDeviceTest; 26 import com.android.tradefed.testtype.IRemoteTest; 27 import com.android.tradefed.util.proto.TfMetricProtoUtil; 28 29 import org.json.JSONArray; 30 import org.json.JSONException; 31 import org.json.JSONObject; 32 import org.json.JSONTokener; 33 import org.junit.Assert; 34 35 import java.io.BufferedReader; 36 import java.io.File; 37 import java.io.FileReader; 38 import java.io.IOException; 39 import java.util.Collections; 40 import java.util.HashMap; 41 import java.util.Map; 42 import java.util.concurrent.TimeUnit; 43 44 /** 45 * A harness that launches Geekbench and reports result. 46 * Requires Geekbench binary and plar file in device temporary directory. 47 */ 48 public class GeekbenchTest implements IDeviceTest, IRemoteTest { 49 50 private static final String RUN_KEY = "geekbench3"; 51 private static final int MAX_ATTEMPTS = 3; 52 private static final int TIMEOUT_MS = 10 * 60 * 1000; 53 54 private static final String DEVICE_TEMPORARY_DIR_PATH = "/data/local/tmp/"; 55 private static final String GEEKBENCH_BINARY_FILENAME = "geekbench_armeabi-v7a_32"; 56 private static final String GEEKBENCH_BINARY_DEVICE_PATH = 57 DEVICE_TEMPORARY_DIR_PATH + GEEKBENCH_BINARY_FILENAME; 58 private static final String GEEKBENCH_PLAR_DEVICE_PATH = 59 DEVICE_TEMPORARY_DIR_PATH + "geekbench.plar"; 60 private static final String GEEKBENCH_RESULT_DEVICE_PATH = 61 DEVICE_TEMPORARY_DIR_PATH + "result.txt"; 62 63 private static final String OVERALL_SCORE_NAME = "Overall Score"; 64 private static final Map<String, String> METRICS_KEY_MAP = createMetricsKeyMap(); 65 66 private ITestDevice mDevice; 67 68 private static Map<String, String> createMetricsKeyMap() { 69 Map<String, String> result = new HashMap<String, String>(); 70 result.put(OVERALL_SCORE_NAME, "overall"); 71 result.put("Integer", "integer"); 72 result.put("Floating Point", "floating-point"); 73 result.put("Memory", "memory"); 74 return Collections.unmodifiableMap(result); 75 } 76 77 /** 78 * {@inheritDoc} 79 */ 80 @Override 81 public void setDevice(ITestDevice device) { 82 mDevice = device; 83 } 84 85 /** 86 * {@inheritDoc} 87 */ 88 @Override 89 public ITestDevice getDevice() { 90 return mDevice; 91 } 92 93 /** 94 * {@inheritDoc} 95 */ 96 @Override 97 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 98 TestDescription testId = new TestDescription(getClass().getCanonicalName(), RUN_KEY); 99 ITestDevice device = getDevice(); 100 101 // delete old results 102 device.executeShellCommand(String.format("rm %s", GEEKBENCH_RESULT_DEVICE_PATH)); 103 104 Assert.assertTrue(String.format("Geekbench binary not found on device: %s", 105 GEEKBENCH_BINARY_DEVICE_PATH), device.doesFileExist(GEEKBENCH_BINARY_DEVICE_PATH)); 106 Assert.assertTrue(String.format("Geekbench binary not found on device: %s", 107 GEEKBENCH_PLAR_DEVICE_PATH), device.doesFileExist(GEEKBENCH_PLAR_DEVICE_PATH)); 108 109 listener.testRunStarted(RUN_KEY, 0); 110 listener.testStarted(testId); 111 112 long testStartTime = System.currentTimeMillis(); 113 Map<String, String> metrics = new HashMap<String, String>(); 114 String errMsg = null; 115 116 // start geekbench and wait for test to complete 117 CollectingOutputReceiver receiver = new CollectingOutputReceiver(); 118 device.executeShellCommand(String.format("%s --no-upload --export-json %s", 119 GEEKBENCH_BINARY_DEVICE_PATH, GEEKBENCH_RESULT_DEVICE_PATH), receiver, 120 TIMEOUT_MS, TimeUnit.MILLISECONDS, MAX_ATTEMPTS); 121 CLog.v(receiver.getOutput()); 122 123 // pull result from device 124 File benchmarkReport = device.pullFile(GEEKBENCH_RESULT_DEVICE_PATH); 125 if (benchmarkReport != null) { 126 // parse result 127 CLog.i("== Geekbench 3 result =="); 128 Map<String, String> benchmarkResult = parseResultJSON(benchmarkReport); 129 if (benchmarkResult == null) { 130 errMsg = "Failed to parse Geekbench result JSON."; 131 } else { 132 metrics = benchmarkResult; 133 } 134 135 // delete results from device and host 136 benchmarkReport.delete(); 137 device.executeShellCommand("rm " + GEEKBENCH_RESULT_DEVICE_PATH); 138 } else { 139 errMsg = "Geekbench report not found."; 140 } 141 142 if (errMsg != null) { 143 CLog.e(errMsg); 144 listener.testFailed(testId, errMsg); 145 listener.testEnded(testId, TfMetricProtoUtil.upgradeConvert(metrics)); 146 listener.testRunFailed(errMsg); 147 } else { 148 long durationMs = System.currentTimeMillis() - testStartTime; 149 listener.testEnded(testId, TfMetricProtoUtil.upgradeConvert(metrics)); 150 listener.testRunEnded(durationMs, TfMetricProtoUtil.upgradeConvert(metrics)); 151 } 152 } 153 154 private Map<String, String> parseResultJSON(File resultJson) { 155 Map<String, String> benchmarkResult = new HashMap<String, String>(); 156 try { 157 BufferedReader bufferedReader = new BufferedReader(new FileReader(resultJson)); 158 String line = bufferedReader.readLine(); 159 bufferedReader.close(); 160 if (line != null) { 161 JSONTokener tokener = new JSONTokener(line); 162 JSONObject root = new JSONObject(tokener); 163 String overallScore = root.getString("score"); 164 benchmarkResult.put(METRICS_KEY_MAP.get(OVERALL_SCORE_NAME), overallScore); 165 CLog.i(String.format("Overall: %s", overallScore)); 166 String overallScoreMulticore = root.getString("multicore_score"); 167 benchmarkResult.put(METRICS_KEY_MAP.get(OVERALL_SCORE_NAME) + "-multi", 168 overallScoreMulticore); 169 CLog.i(String.format("Overall-multicore: %s", overallScore)); 170 JSONArray arr = root.getJSONArray("sections"); 171 for (int i = 0; i < arr.length(); i++) { 172 JSONObject section = arr.getJSONObject(i); 173 String sectionName = section.getString("name"); 174 String sectionScore = section.getString("score"); 175 String sectionScoreMulticore = section.getString("multicore_score"); 176 if (METRICS_KEY_MAP.containsKey(sectionName)) { 177 CLog.i(String.format("%s: %s", sectionName, sectionScore)); 178 CLog.i(String.format("%s-multicore: %s", sectionName, 179 sectionScoreMulticore)); 180 benchmarkResult.put(METRICS_KEY_MAP.get(sectionName), sectionScore); 181 CLog.i(String.format("%s-multicore: %s", sectionName, 182 sectionScoreMulticore)); 183 benchmarkResult.put(METRICS_KEY_MAP.get(sectionName) + "-multi", 184 sectionScoreMulticore); 185 } 186 } 187 } 188 } catch (IOException e) { 189 CLog.e("Geekbench3 result file not found."); 190 return null; 191 } catch (JSONException e) { 192 CLog.e("Error parsing Geekbench3 JSON result."); 193 return null; 194 } 195 return benchmarkResult; 196 } 197 } 198