Home | History | Annotate | Download | only in workloads
      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