1#!/usr/bin/env python 2# 3# Copyright (C) 2017 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import json 19import logging 20 21from vts.runners.host import asserts 22from vts.runners.host import base_test 23from vts.runners.host import const 24from vts.runners.host import test_runner 25from vts.utils.python.controllers import android_device 26from vts.utils.python.cpu import cpu_frequency_scaling 27 28 29class HwBinderLatencyTest(base_test.BaseTestClass): 30 """A test case for the hwbinder latency benchmarking. 31 32 Sample output of libhwbinder_latency 33 { 34 "cfg":{"pair":6,"iterations":166,"deadline_us":2500,"passthrough":1}, 35 "fifo_0_data": [15052, ...], 36 "fifo_1_data": [...], 37 ... 38 "ALL":{"SYNC":"GOOD","S":1992,"I":1992,"R":1, 39 "other_ms":{ "avg":0.0048, "wst":0.32, "bst":0.0022, "miss":0, "meetR":1}, 40 "fifo_ms": { "avg":0.0035, "wst":0.037, "bst":0.0021, "miss":0, "meetR":1}, 41 "otherdis":{ "p50":0.19531, "p90":0.19531, "p95":0.19531, "p99": 0.19531}, 42 "fifodis": { "p50":0.19531, "p90":0.19531, "p95":0.19531, "p99": 0.19531} 43 }, 44 "P0":{... 45 }, 46 ... 47 "inheritance": "PASS" 48 } 49 """ 50 # The order of the columns in the output table 51 _MS_COLUMNS = ["avg", "wst", "bst", "miss", "meetR"] 52 _DIS_COLUMNS = ["p50", "p90", "p95", "p99"] 53 # The keys in the JSON object 54 _CFG = "cfg" 55 _PAIR = "pair" 56 _ALL = "ALL" 57 _OTHER_MS = "other_ms" 58 _FIFO_MS = "fifo_ms" 59 _OTHERDIS = "otherdis" 60 _FIFODIS = "fifodis" 61 _INHERITANCE = "inheritance" 62 63 def setUpClass(self): 64 required_params = ["hidl_hal_mode"] 65 self.getUserParams(required_params) 66 self.dut = self.android_devices[0] 67 self._cpu_freq = cpu_frequency_scaling.CpuFrequencyScalingController(self.dut) 68 self._cpu_freq.DisableCpuScaling() 69 70 def setUp(self): 71 self._cpu_freq.SkipIfThermalThrottling(retry_delay_secs=30) 72 73 def tearDown(self): 74 self._cpu_freq.SkipIfThermalThrottling() 75 76 def tearDownClass(self): 77 self._cpu_freq.EnableCpuScaling() 78 79 def testRunBenchmark32Bit(self): 80 result = self._runBenchmark(32) 81 self._addBenchmarkTableToResult(result, 32) 82 self._uploadResult(result, 32) 83 84 def testRunBenchmark64Bit(self): 85 result = self._runBenchmark(64) 86 self._addBenchmarkTableToResult(result, 64) 87 self._uploadResult(result, 64) 88 89 def _runBenchmark(self, bits): 90 """Runs the native binary and parses its result. 91 92 Args: 93 bits: integer (32 or 64), the bitness of the binary to run. 94 95 Returns: 96 dict, the benchmarking result converted from native binary's JSON 97 output. 98 """ 99 logging.info("Start %d-bit hwbinder latency test with HIDL mode=%s", 100 bits, self.hidl_hal_mode) 101 binary = "/data/local/tmp/%s/libhwbinder_latency%s" % (bits, bits) 102 min_cpu, max_cpu = self._cpu_freq.GetMinAndMaxCpuNo() 103 iterations = 1000 // (max_cpu - min_cpu) 104 results = self.dut.shell.Execute([ 105 "chmod 755 %s" % binary, 106 "VTS_ROOT_PATH=/data/local/tmp " \ 107 "LD_LIBRARY_PATH=/system/lib%s:/data/local/tmp/%s/hw:" 108 "/data/local/tmp/%s:$LD_LIBRARY_PATH " 109 "%s -raw_data -pair %d -i %d -m %s" % (bits, bits, bits, 110 binary, max_cpu - min_cpu, iterations, 111 self.hidl_hal_mode.encode("utf-8"))]) 112 # Parses the result. 113 asserts.assertEqual(len(results[const.STDOUT]), 2) 114 logging.info("stderr: %s", results[const.STDERR][1]) 115 logging.info("stdout: %s", results[const.STDOUT][1]) 116 asserts.assertFalse( 117 any(results[const.EXIT_CODE]), 118 "testRunBenchmark%sBit failed." % (bits)) 119 json_result = json.loads(results[const.STDOUT][1]); 120 asserts.assertTrue(json_result[self._INHERITANCE] == "PASS", 121 "Scheduler does not support priority inheritance."); 122 return json_result 123 124 def _createRow(self, pair_name, ms_result, dis_result): 125 """Creates a row from the JSON output. 126 127 Args: 128 pair_name: string, the pair name in the first column. 129 ms_result: dict, the fifo_ms or other_ms object. 130 dis_result: dict, the fifodis or otherdis object. 131 132 Returns: 133 the list containing pair_name and the values in the objects. 134 """ 135 row = [pair_name] 136 row.extend([ms_result[x] for x in self._MS_COLUMNS]) 137 row.extend([dis_result[x] for x in self._DIS_COLUMNS]) 138 return row 139 140 def _addBenchmarkTableToResult(self, result, bits): 141 pair_cnt = result[self._CFG][self._PAIR] 142 row_names = ["P" + str(i) for i in range(pair_cnt)] + [self._ALL] 143 col_names = ["pair"] + self._MS_COLUMNS + self._DIS_COLUMNS 144 fifo_table = [col_names] 145 other_table = [col_names] 146 for row_name in row_names: 147 pair_result = result[row_name] 148 fifo_table.append(self._createRow(row_name, 149 pair_result[self._FIFO_MS], pair_result[self._FIFODIS])) 150 other_table.append(self._createRow(row_name, 151 pair_result[self._OTHER_MS], pair_result[self._OTHERDIS])) 152 self.addTableToResult( 153 "hwbinder_latency_%sbits_fifo" % bits,fifo_table) 154 self.addTableToResult( 155 "hwbinder_latency_%sbits_other" % bits, other_table) 156 157 def _uploadResult(self, result, bits): 158 """Uploads the output of benchmark program to web DB. 159 160 Args: 161 result: dict which is the benchmarking result. 162 bits: integer (32 or 64). 163 """ 164 opts = ["hidl_hal_mode=%s" % self.hidl_hal_mode.encode("utf-8")]; 165 min_cpu, max_cpu = self._cpu_freq.GetMinAndMaxCpuNo() 166 for i in range(max_cpu - min_cpu): 167 self.web.AddProfilingDataUnlabeledVector( 168 "hwbinder_latency_%sbits" % bits, 169 result["fifo_%d_data" % i], options=opts, 170 x_axis_label="hwbinder latency", 171 y_axis_label="Frequency") 172 173 174if __name__ == "__main__": 175 test_runner.main() 176