aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2017-12-18 23:19:23 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2017-12-18 23:19:23 +0000
commite911501cb5d982cd4aee22897dd81c0346753825 (patch)
treefa4920d05779dcecf66c4ed70d804bf60f37ac3e
parentaae7d87c9ff7db824434223d5d9ec0e06f58fe36 (diff)
parentb7f69ad57e5e24fe11eea28f324252b715dec808 (diff)
downloadlisa-e911501cb5d982cd4aee22897dd81c0346753825.tar.gz
Merge "LISA: Add system app jank test workload"
-rw-r--r--libs/utils/android/workloads/sysapp.py198
1 files changed, 198 insertions, 0 deletions
diff --git a/libs/utils/android/workloads/sysapp.py b/libs/utils/android/workloads/sysapp.py
new file mode 100644
index 0000000..9957ef5
--- /dev/null
+++ b/libs/utils/android/workloads/sysapp.py
@@ -0,0 +1,198 @@
+# SPDX-License-Identifier: Apache-2.0
+#
+# Copyright (C) 2017, ARM Limited, Google and contributors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import os
+import re
+
+from subprocess import Popen, PIPE
+from time import sleep
+
+from android import Screen, System, Workload
+
+import pandas as pd
+
+
+class SysApp(Workload):
+ """
+ Android system app jank test workload.
+ """
+
+ packages = [
+ Workload.WorkloadPackage("com.android.sysapp.janktests",
+ "data/app/SystemAppJankTests/SystemAppJankTests.apk",
+ "vendor/google_testing/integration/tests/jank/sysapp"),
+ Workload.WorkloadPackage("com.android.chrome",
+ "system/app/Chrome/Chrome.apk",
+ "vendor/unbundled_google/packages/Chrome"),
+ Workload.WorkloadPackage("com.google.android.youtube",
+ "system/app/Youtube/Youtube.apk",
+ "vendor/unbundled_google/packages/YouTube")
+ ]
+
+ test_package = packages[0].package_name
+
+ test_list = [
+ "ChromeJankTests#testChromeOverflowMenuTap",
+ "YouTubeJankTests#testYouTubeRecomendationWindowFling"
+ ]
+
+ def __init__(self, test_env):
+ super(SysApp, self).__init__(test_env)
+
+ def get_test_list(self):
+ return SysApp.test_list
+
+ def _get_test_package(self, test_name):
+ name_start = test_name.partition('JankTests')[0]
+ name_map = {
+ "Chrome": "com.android.chrome",
+ "YouTube": "com.google.android.youtube",
+ }
+ return name_map[name_start]
+
+ def run(self, out_dir, test_name, iterations, collect=''):
+ """
+ Run single system app jank test workload.
+ Performance statistics are stored in self.results, and can be retrieved
+ after the fact by calling SystemUi.get_results()
+
+ :param out_dir: Path to experiment directory where to store results.
+ :type out_dir: str
+
+ :param test_name: Name of the test to run
+ :type test_name: str
+
+ :param iterations: Run benchmark for this required number of iterations
+ :type iterations: int
+
+ :param collect: Specifies what to collect. Possible values:
+ - 'systrace'
+ - 'ftrace'
+ - 'gfxinfo'
+ - 'surfaceflinger'
+ - any combination of the above
+ :type collect: list(str)
+ """
+ if "energy" in collect:
+ raise ValueError('System app workload does not support energy data collection')
+
+ activity = "." + test_name
+ package = self._get_test_package(test_name)
+
+ # Keep track of mandatory parameters
+ self.out_dir = out_dir
+ self.collect = collect
+
+ # Filter out test overhead
+ filter_prop = System.get_boolean_property(self._target, "debug.hwui.filter_test_overhead")
+ if not filter_prop:
+ System.set_property(self._target, "debug.hwui.filter_test_overhead", "true", restart=True)
+
+ # Unlock device screen (assume no password required)
+ Screen.unlock(self._target)
+
+ # Close and clear application
+ System.force_stop(self._target, package, clear=True)
+
+ # Set min brightness
+ Screen.set_brightness(self._target, auto=False, percent=0)
+
+ # Force screen in PORTRAIT mode
+ Screen.set_orientation(self._target, portrait=True)
+
+ # Delete old test results
+ self._target.remove("/sdcard/results.log")
+
+ # Clear logcat
+ self._target.execute("logcat -c")
+
+ # Regexps for benchmark synchronization
+ start_logline = r"TestRunner: started"
+ SYSAPP_BENCHMARK_START_RE = re.compile(start_logline)
+ self._log.debug("START string [%s]", start_logline)
+
+ finish_logline = r"TestRunner: finished"
+ SYSAPP_BENCHMARK_FINISH_RE = re.compile(finish_logline)
+ self._log.debug("FINISH string [%s]", finish_logline)
+
+ # Parse logcat output lines
+ logcat_cmd = self._adb("logcat TestRunner:* System.out:I *:S BENCH:*")
+ self._log.info("%s", logcat_cmd)
+
+ command = "am instrument -e iterations {} -e class {}{} -w {}".format(
+ iterations, self.test_package, activity, self.test_package)
+
+ logcat = Popen(logcat_cmd, shell=True, stdout=PIPE)
+
+ test_proc = self._target.background(command)
+ while True:
+ # read next logcat line (up to max 1024 chars)
+ message = logcat.stdout.readline(1024)
+
+ # Benchmark start
+ match = SYSAPP_BENCHMARK_START_RE.search(message)
+ if match:
+ self.tracingStart()
+ self._log.debug("Benchmark started!")
+
+ # Benchmark finish
+ match = SYSAPP_BENCHMARK_FINISH_RE.search(message)
+ if match:
+ self.tracingStop()
+ self._log.debug("Benchmark finished!")
+ test_proc.wait()
+ break
+ sleep(5)
+ self._target.pull("/sdcard/results.log", os.path.join(out_dir, "results.log"))
+ self.db_file = os.path.join(out_dir, "results.log")
+ self.results = self.get_results(out_dir)
+
+ # Close and clear application
+ System.force_stop(self._target, package, clear=True)
+
+ # Go back to home screen
+ System.home(self._target)
+
+ # Switch back to original settings
+ Screen.set_orientation(self._target, auto=True)
+ Screen.set_brightness(self._target, auto=True)
+
+
+ @staticmethod
+ def get_results(out_dir):
+ """
+ Parse SysApp test output log and return a pandas dataframe of test results.
+
+ :param out_dir: Output directory for a run of the SysApp workload.
+ :type out_dir: str
+ """
+ path = os.path.join(out_dir, "results.log")
+ with open(path, "r") as f:
+ lines = f.readlines()
+ cols = []
+ vals = []
+ for line in lines:
+ name, val = str.split(line)
+ if name == "Result":
+ cols.append("test-name")
+ vals.append(val)
+ elif name.startswith("gfx-"):
+ cols.append(name[4:])
+ vals.append(float(val))
+ else:
+ raise ValueError("Unrecognized line in results file")
+ return pd.DataFrame([vals], columns=cols)