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 18 import json 19 import logging 20 21 from vts.runners.host import asserts 22 from vts.runners.host import base_test 23 from vts.runners.host import const 24 from vts.runners.host import test_runner 25 from vts.utils.python.controllers import android_device 26 from vts.utils.python.cpu import cpu_frequency_scaling 27 28 29 class 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.registerController(android_device)[0] 67 self.dut.shell.InvokeTerminal("one") 68 self._cpu_freq = cpu_frequency_scaling.CpuFrequencyScalingController(self.dut) 69 self._cpu_freq.DisableCpuScaling() 70 71 def setUp(self): 72 self._cpu_freq.SkipIfThermalThrottling(retry_delay_secs=30) 73 74 def tearDown(self): 75 self._cpu_freq.SkipIfThermalThrottling() 76 77 def tearDownClass(self): 78 self._cpu_freq.EnableCpuScaling() 79 80 def testRunBenchmark32Bit(self): 81 result = self._runBenchmark(32) 82 self._addBenchmarkTableToResult(result, 32) 83 self._uploadResult(result, 32) 84 85 def testRunBenchmark64Bit(self): 86 result = self._runBenchmark(64) 87 self._addBenchmarkTableToResult(result, 64) 88 self._uploadResult(result, 64) 89 90 def _runBenchmark(self, bits): 91 """Runs the native binary and parses its result. 92 93 Args: 94 bits: integer (32 or 64), the bitness of the binary to run. 95 96 Returns: 97 dict, the benchmarking result converted from native binary's JSON 98 output. 99 """ 100 logging.info("Start %d-bit hwbinder latency test with HIDL mode=%s", 101 bits, self.hidl_hal_mode) 102 binary = "/data/local/tmp/%s/libhwbinder_latency%s" % (bits, bits) 103 min_cpu, max_cpu = self._cpu_freq.GetMinAndMaxCpuNo() 104 iterations = 1000 // (max_cpu - min_cpu) 105 results = self.dut.shell.one.Execute([ 106 "chmod 755 %s" % binary, 107 "VTS_ROOT_PATH=/data/local/tmp " \ 108 "LD_LIBRARY_PATH=/system/lib%s:/data/local/tmp/%s/hw:" 109 "/data/local/tmp/%s:$LD_LIBRARY_PATH " 110 "%s -raw_data -pair %d -i %d -m %s" % (bits, bits, bits, 111 binary, max_cpu - min_cpu, iterations, 112 self.hidl_hal_mode.encode("utf-8"))]) 113 # Parses the result. 114 asserts.assertEqual(len(results[const.STDOUT]), 2) 115 logging.info("stderr: %s", results[const.STDERR][1]) 116 logging.info("stdout: %s", results[const.STDOUT][1]) 117 asserts.assertFalse( 118 any(results[const.EXIT_CODE]), 119 "testRunBenchmark%sBit failed." % (bits)) 120 json_result = json.loads(results[const.STDOUT][1]); 121 asserts.assertTrue(json_result[self._INHERITANCE] == "PASS", 122 "Scheduler does not support priority inheritance."); 123 return json_result 124 125 def _createRow(self, pair_name, ms_result, dis_result): 126 """Creates a row from the JSON output. 127 128 Args: 129 pair_name: string, the pair name in the first column. 130 ms_result: dict, the fifo_ms or other_ms object. 131 dis_result: dict, the fifodis or otherdis object. 132 133 Returns: 134 the list containing pair_name and the values in the objects. 135 """ 136 row = [pair_name] 137 row.extend([ms_result[x] for x in self._MS_COLUMNS]) 138 row.extend([dis_result[x] for x in self._DIS_COLUMNS]) 139 return row 140 141 def _addBenchmarkTableToResult(self, result, bits): 142 pair_cnt = result[self._CFG][self._PAIR] 143 row_names = ["P" + str(i) for i in range(pair_cnt)] + [self._ALL] 144 col_names = ["pair"] + self._MS_COLUMNS + self._DIS_COLUMNS 145 fifo_table = [col_names] 146 other_table = [col_names] 147 for row_name in row_names: 148 pair_result = result[row_name] 149 fifo_table.append(self._createRow(row_name, 150 pair_result[self._FIFO_MS], pair_result[self._FIFODIS])) 151 other_table.append(self._createRow(row_name, 152 pair_result[self._OTHER_MS], pair_result[self._OTHERDIS])) 153 self.addTableToResult( 154 "hwbinder_latency_%sbits_fifo" % bits,fifo_table) 155 self.addTableToResult( 156 "hwbinder_latency_%sbits_other" % bits, other_table) 157 158 def _uploadResult(self, result, bits): 159 """Uploads the output of benchmark program to web DB. 160 161 Args: 162 result: dict which is the benchmarking result. 163 bits: integer (32 or 64). 164 """ 165 opts = ["hidl_hal_mode=%s" % self.hidl_hal_mode.encode("utf-8")]; 166 min_cpu, max_cpu = self._cpu_freq.GetMinAndMaxCpuNo() 167 for i in range(max_cpu - min_cpu): 168 self.web.AddProfilingDataUnlabeledVector( 169 "hwbinder_latency_%sbits" % bits, 170 result["fifo_%d_data" % i], options=opts, 171 x_axis_label="hwbinder latency", 172 y_axis_label="Frequency") 173 174 175 if __name__ == "__main__": 176 test_runner.main() 177