Home | History | Annotate | Download | only in workloads
      1 # SPDX-License-Identifier: Apache-2.0
      2 #
      3 # Copyright (C) 2015, ARM Limited 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 import pandas as pd
     27 
     28 
     29 class UiBench(Workload):
     30     """
     31     Android UiBench workload
     32     """
     33     # Packages required by this workload
     34     packages = [
     35         Workload.WorkloadPackage("com.android.test.uibench",
     36             "data/app/UiBench/UiBench.apk",
     37             "frameworks/base/tests/UiBench"),
     38         Workload.WorkloadPackage("com.android.uibench.janktests",
     39             "data/app/UiBenchJankTests/UiBenchJankTests.apk",
     40             "platform_testing/tests/jank/uibench"),
     41     ]
     42 
     43     # Package required by this workload
     44     package = packages[0].package_name
     45 
     46     # Instrumentation required to run tests
     47     test_package = packages[1].package_name
     48 
     49     # Supported tests list
     50     test_list = \
     51     ['UiBenchJankTests#testClippedListView',
     52     'UiBenchJankTests#testDialogListFling',
     53     'UiBenchJankTests#testFadingEdgeListViewFling',
     54     'UiBenchJankTests#testFullscreenOverdraw',
     55     'UiBenchJankTests#testGLTextureView',
     56     'UiBenchJankTests#testInflatingListViewFling',
     57     'UiBenchJankTests#testInvalidate',
     58     'UiBenchJankTests#testInvalidateTree',
     59     'UiBenchJankTests#testOpenNavigationDrawer',
     60     'UiBenchJankTests#testOpenNotificationShade',
     61     'UiBenchJankTests#testResizeHWLayer',
     62     'UiBenchJankTests#testSaveLayerAnimation',
     63     'UiBenchJankTests#testSlowBindRecyclerViewFling',
     64     'UiBenchJankTests#testSlowNestedRecyclerViewFling',
     65     'UiBenchJankTests#testSlowNestedRecyclerViewInitialFling',
     66     'UiBenchJankTests#testTrivialAnimation',
     67     'UiBenchJankTests#testTrivialListViewFling',
     68     'UiBenchJankTests#testTrivialRecyclerListViewFling',
     69     'UiBenchRenderingJankTests#testBitmapUploadJank',
     70     'UiBenchRenderingJankTests#testShadowGridListFling',
     71     'UiBenchTextJankTests#testEditTextTyping',
     72     'UiBenchTextJankTests#testLayoutCacheHighHitrateFling',
     73     'UiBenchTextJankTests#testLayoutCacheLowHitrateFling',
     74     'UiBenchTransitionsJankTests#testActivityTransitionsAnimation',
     75     'UiBenchWebView#testWebViewFling']
     76 
     77     def __init__(self, test_env):
     78         super(UiBench, self).__init__(test_env)
     79         self._log = logging.getLogger('UiBench')
     80         self._log.debug('Workload created')
     81 
     82         # Set of output data reported by UiBench
     83         self.db_file = None
     84 
     85     def get_test_list(self):
     86 	return UiBench.test_list
     87 
     88     def run(self, out_dir, test_name, iterations=10, collect=''):
     89         """
     90         Run single UiBench workload.
     91 
     92         :param out_dir: Path to experiment directory where to store results.
     93         :type out_dir: str
     94 
     95         :param test_name: Name of the test to run
     96         :type test_name: str
     97 
     98         :param iterations: Run benchmak for this required number of iterations
     99         :type iterations: int
    100 
    101         :param collect: Specifies what to collect. Possible values:
    102             - 'systrace'
    103             - 'ftrace'
    104         :type collect: list(str)
    105         """
    106 
    107         if 'energy' in collect:
    108             raise ValueError('UiBench workload does not support energy data collection')
    109 
    110         activity = '.' + test_name
    111 
    112         # Keep track of mandatory parameters
    113         self.out_dir = out_dir
    114         self.collect = collect
    115 
    116         # Filter out test overhead
    117         filter_prop = System.get_boolean_property(self._target, 'debug.hwui.filter_test_overhead')
    118         if not filter_prop:
    119             System.set_property(
    120                 self._target, 'debug.hwui.filter_test_overhead', 'true', restart=True)
    121 
    122         # Unlock device screen (assume no password required)
    123         Screen.unlock(self._target)
    124 
    125         # Close and clear application
    126         System.force_stop(self._target, self.package, clear=True)
    127 
    128         # Set airplane mode
    129         System.set_airplane_mode(self._target, on=True)
    130 
    131         # Set min brightness
    132         Screen.set_brightness(self._target, auto=False, percent=0)
    133 
    134         # Force screen in PORTRAIT mode
    135         Screen.set_orientation(self._target, portrait=True)
    136 
    137         # Clear logcat
    138         os.system(self._adb('logcat -c'));
    139 
    140         # Regexps for benchmark synchronization
    141         start_logline = r'TestRunner: started'
    142         UIBENCH_BENCHMARK_START_RE = re.compile(start_logline)
    143         self._log.debug("START string [%s]", start_logline)
    144 
    145         finish_logline = r'TestRunner: finished'
    146         UIBENCH_BENCHMARK_FINISH_RE = re.compile(finish_logline)
    147         self._log.debug("FINISH string [%s]", start_logline)
    148 
    149         # Parse logcat output lines
    150         logcat_cmd = self._adb(
    151                 'logcat TestRunner:* System.out:I *:S BENCH:*'\
    152                 .format(self._target.adb_name))
    153         self._log.info("%s", logcat_cmd)
    154 
    155         command = "am instrument -e iterations {} -e class {}{} -w {}".format(
    156             iterations, self.test_package, activity, self.test_package)
    157         test_proc = self._target.background(command)
    158 
    159         logcat = Popen(logcat_cmd, shell=True, stdout=PIPE)
    160         while True:
    161 
    162             # read next logcat line (up to max 1024 chars)
    163             message = logcat.stdout.readline(1024)
    164 
    165             # Benchmark start trigger
    166             match = UIBENCH_BENCHMARK_START_RE.search(message)
    167             if match:
    168                 self.tracingStart()
    169                 self._log.debug("Benchmark started!")
    170 
    171             match = UIBENCH_BENCHMARK_FINISH_RE.search(message)
    172             if match:
    173                 self.tracingStop()
    174                 self._log.debug("Benchmark finished!")
    175                 test_proc.wait()
    176                 break
    177 
    178         # Get frame stats
    179         self.db_file = os.path.join(out_dir, "framestats.txt")
    180         with open(self.db_file, 'w') as f:
    181             f.writelines(test_proc.stdout.readlines())
    182         self.results = self.get_results(out_dir)
    183 
    184         # Close and clear application
    185         System.force_stop(self._target, self.package, clear=True)
    186 
    187         # Go back to home screen
    188         System.home(self._target)
    189 
    190         # Switch back to original settings
    191         Screen.set_orientation(self._target, auto=True)
    192         System.set_airplane_mode(self._target, on=False)
    193         Screen.set_brightness(self._target, auto=True)
    194 
    195     @staticmethod
    196     def get_results(res_dir):
    197         path = os.path.join(res_dir, 'framestats.txt')
    198         with open(path, "r") as f:
    199             lines = f.readlines()
    200 
    201         values = []
    202         columns = []
    203         RESULTS_PARSE_RE = re.compile(r'gfx-([^=]+)=([0-9.]+)')
    204         for line in lines:
    205             matches = RESULTS_PARSE_RE.search(line)
    206             if matches:
    207                 columns.append(matches.group(1))
    208                 values.append(float(matches.group(2)))
    209         return pd.DataFrame([values], columns=columns)
    210 # vim :set tabstop=4 shiftwidth=4 expandtab
    211