1 # SPDX-License-Identifier: Apache-2.0 2 # 3 # Copyright (C) 2017, ARM Limited, Google and contributors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); you may 6 # 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, WITHOUT 13 # 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 re 19 import os 20 import logging 21 22 from subprocess import Popen, PIPE 23 from time import sleep 24 25 from android import Screen, System, Workload 26 27 import pandas as pd 28 29 class SystemUi(Workload): 30 """ 31 Android SystemUi jank test workload 32 """ 33 34 # Packages required by this workload 35 packages = [ 36 Workload.WorkloadPackage("android.platform.systemui.tests.jank", 37 "data/app/UbSystemUiJankTests/UbSystemUiJankTests.apk", 38 "platform_testing/tests/jank/UbSystemUiJankTests") 39 ] 40 41 # Instrumentation required to run tests 42 test_package = packages[0].package_name 43 44 test_list = \ 45 ["LauncherJankTests#testOpenAllAppsContainer", 46 "LauncherJankTests#testAllAppsContainerSwipe", 47 "LauncherJankTests#testHomeScreenSwipe", 48 "LauncherJankTests#testWidgetsContainerFling", 49 "SettingsJankTests#testSettingsFling", 50 "SystemUiJankTests#testRecentAppsFling", 51 "SystemUiJankTests#testRecentAppsDismiss", 52 "SystemUiJankTests#testNotificationListPull", 53 "SystemUiJankTests#testNotificationListPull_manyNotifications", 54 "SystemUiJankTests#testNotificationListScroll", 55 "SystemUiJankTests#testQuickSettingsPull", 56 "SystemUiJankTests#testUnlock", 57 "SystemUiJankTests#testExpandGroup", 58 "SystemUiJankTests#testClearAll", 59 "SystemUiJankTests#testChangeBrightness", 60 "SystemUiJankTests#testNotificationAppear", 61 "SystemUiJankTests#testCameraFromLockscreen", 62 "SystemUiJankTests#testAmbientWakeUp", 63 "SystemUiJankTests#testGoToFullShade", 64 "SystemUiJankTests#testInlineReply", 65 "SystemUiJankTests#testPinAppearance", 66 "SystemUiJankTests#testLaunchSettings"] 67 68 def __init__(self, test_env): 69 super(SystemUi, self).__init__(test_env) 70 self._log = logging.getLogger('SystemUi') 71 self._log.debug('Workload created') 72 73 # Set of output data reported by SystemUi 74 self.db_file = None 75 76 def get_test_list(self): 77 return SystemUi.test_list 78 79 def run(self, out_dir, test_name, iterations, collect=''): 80 """ 81 Run single SystemUi jank test workload. 82 Performance statistics are stored in self.results, and can be retrieved after 83 the fact by calling SystemUi.get_results() 84 85 :param out_dir: Path to experiment directory where to store results. 86 :type out_dir: str 87 88 :param test_name: Name of the test to run 89 :type test_name: str 90 91 :param iterations: Run benchmark for this required number of iterations 92 :type iterations: int 93 94 :param collect: Specifies what to collect. Possible values: 95 - 'systrace' 96 - 'ftrace' 97 - 'gfxinfo' 98 - 'surfaceflinger' 99 - any combination of the above 100 :type collect: list(str) 101 """ 102 if 'energy' in collect: 103 raise ValueError('SystemUi workload does not support energy data collection') 104 105 activity = '.' + test_name 106 107 # Keep track of mandatory parameters 108 self.out_dir = out_dir 109 self.collect = collect 110 111 # Filter out test overhead 112 filter_prop = System.get_boolean_property(self._target, 'debug.hwui.filter_test_overhead') 113 if not filter_prop: 114 System.set_property(self._target, 'debug.hwui.filter_test_overhead', 'true', restart=True) 115 116 # Unlock device screen (assume no password required) 117 Screen.unlock(self._target) 118 119 # Set airplane mode 120 System.set_airplane_mode(self._target, on=True) 121 122 # Set min brightness 123 Screen.set_brightness(self._target, auto=False, percent=0) 124 125 # Force screen in PORTRAIT mode 126 Screen.set_orientation(self._target, portrait=True) 127 128 # Delete old test results 129 self._target.remove('/sdcard/results.log') 130 131 # Clear logcat 132 os.system(self._adb('logcat -c')); 133 134 # Regexps for benchmark synchronization 135 start_logline = r'TestRunner: started' 136 SYSTEMUI_BENCHMARK_START_RE = re.compile(start_logline) 137 self._log.debug("START string [%s]", start_logline) 138 139 finish_logline = r'TestRunner: finished' 140 SYSTEMUI_BENCHMARK_FINISH_RE = re.compile(finish_logline) 141 self._log.debug("FINISH string [%s]", finish_logline) 142 143 # Parse logcat output lines 144 logcat_cmd = self._adb( 145 'logcat TestRunner:* System.out:I *:S BENCH:*'\ 146 .format(self._target.adb_name)) 147 self._log.info("%s", logcat_cmd) 148 149 command = "nohup am instrument -e iterations {} -e class {}{} -w {}".format( 150 iterations, self.test_package, activity, self.test_package) 151 152 print "command: {}".format(command) 153 154 self._target.background(command) 155 156 logcat = Popen(logcat_cmd, shell=True, stdout=PIPE) 157 while True: 158 # read next logcat line (up to max 1024 chars) 159 message = logcat.stdout.readline(1024) 160 161 # Benchmark start trigger 162 match = SYSTEMUI_BENCHMARK_START_RE.search(message) 163 if match: 164 self.tracingStart() 165 self._log.debug("Benchmark started!") 166 167 match = SYSTEMUI_BENCHMARK_FINISH_RE.search(message) 168 if match: 169 self.tracingStop() 170 self._log.debug("Benchmark finished!") 171 break 172 173 sleep(5) 174 self._target.pull('/sdcard/results.log', os.path.join(out_dir, 'results.log')) 175 self._target.remove('/sdcard/results.log') 176 self.results = self.get_results(out_dir) 177 178 # Go back to home screen 179 System.home(self._target) 180 181 # Switch back to original settings 182 Screen.set_orientation(self._target, auto=True) 183 System.set_airplane_mode(self._target, on=False) 184 Screen.set_brightness(self._target, auto=True) 185 186 187 @staticmethod 188 def get_results(out_dir): 189 """ 190 Parse SystemUi test output log and return a pandas dataframe of test results. 191 192 :param out_dir: Output directory for a run of the SystemUi workload. 193 :type out_dir: str 194 """ 195 path = os.path.join(out_dir, 'results.log') 196 with open(path, "r") as f: 197 lines = f.readlines() 198 data = {} 199 for line in lines: 200 key, val = str.split(line) 201 if key == 'Result': 202 key = 'test-name' 203 elif key.startswith('gfx-'): 204 key = key[4:] 205 val = float(val) 206 else: 207 raise ValueError('Unrecognized line in results file') 208 data[key] = val 209 columns, values = zip(*((k,v) for k,v in data.iteritems())) 210 return pd.DataFrame([values], columns=columns) 211