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
18import re
19import os
20import collections
21import copy
22import logging
23from time import sleep
24
25from subprocess import Popen, PIPE
26
27from android import Screen, System, Workload
28
29# screen density of the device with which this workload has been tested
30DEFAULT_DENSITY = '420'
31
32VELLAMO_DB_PATH = '/data/data/com.quicinc.vellamo/files'
33VELLAMO_SCORE_NAME = 'chapterscores.json'
34VELLAMO_TESTS = ['BROWSER', 'METAL', 'MULTI']
35
36class Vellamo(Workload):
37    """
38    Android Vellamo workload
39    """
40
41    # Package required by this workload
42    package = 'com.quicinc.vellamo'
43    activity = 'com.quicinc.vellamo.main.MainActivity'
44
45    def __init__(self, test_env):
46        super(Vellamo, self).__init__(test_env)
47        self._log = logging.getLogger('Vellamo')
48        self._log.debug('Workload created')
49
50    def run(self, out_dir, test_name, collect=''):
51        """
52        Run single Vellamo workload. Returns a collection of results.
53
54        :param out_dir: Path to experiment directory where to store results.
55        :type out_dir: str
56
57        :param test_name: Name of the test to run
58        :type test_name: str
59
60        :param collect: Specifies what to collect. Possible values:
61            - 'energy'
62            - 'systrace'
63            - 'ftrace'
64            - any combination of the above
65        :type collect: list(str)
66        """
67
68        self.out_dir = out_dir
69        self.collect = collect
70
71        # Check if the density of the target device screen is different from
72        # the one used to get the values below
73        density = Screen.get_screen_density(self._target)
74        if DEFAULT_DENSITY not in density:
75            msg = 'Screen density of target device differs from {}.\n'\
76                  'Please set it to {}'
77            raise RuntimeError(msg.format(DEFAULT_DENSITY, DEFAULT_DENSITY))
78
79        if test_name.upper() not in VELLAMO_TESTS:
80            raise ValueError('Vellamo workload [%s] not supported', test_name)
81
82        # Set parameter depending on test
83        self._log.debug('Start Vellamo Benchmark [%s]', test_name)
84        test_x, test_y = (0, 0)
85        sleep_time = 0
86        if test_name.upper() == 'BROWSER':
87            test_x, test_y = (91, 33)
88            sleep_time = 3.5
89        elif test_name.upper() == 'METAL':
90            test_x, test_y  = (91, 59)
91            sleep_time = 1
92        elif test_name.upper() == 'MULTI':
93            test_x, test_y = (91, 71)
94            sleep_time = 3.5
95
96        # Unlock device screen (assume no password required)
97        Screen.unlock(self._target)
98
99        System.force_stop(self._target, self.package, clear=True)
100
101        # Set min brightness
102        Screen.set_brightness(self._target, auto=False, percent=0)
103
104        # Clear logcat
105        os.system(self._adb('logcat -c'));
106
107        # Regexps for benchmark synchronization
108        start_logline = r'ActivityManager: Start.*'\
109                         ':com.quicinc.vellamo:benchmarking'
110        VELLAMO_BENCHMARK_START_RE = re.compile(start_logline)
111        self._log.debug("START string [%s]", start_logline)
112
113        # End of benchmark is marked by displaying results
114        end_logline = r'ActivityManager: START.*'\
115                       'act=com.quicinc.vellamo.*_RESULTS'
116        VELLAMO_BENCHMARK_END_RE = re.compile(end_logline)
117        self._log.debug("END string [%s]", end_logline)
118
119        # Parse logcat output lines
120        logcat_cmd = self._adb(
121                'logcat ActivityManager:* System.out:I *:S BENCH:*'\
122                .format(self._target.adb_name))
123        self._log.info("%s", logcat_cmd)
124
125        # Start the activity
126        System.start_activity(self._target, self.package, self.activity)
127        logcat = Popen(logcat_cmd, shell=True, stdout=PIPE)
128        sleep(2)
129        # Accept EULA
130        System.tap(self._target, 80, 86)
131        sleep(1)
132        # Click Let's Roll
133        System.tap(self._target, 50, 67)
134        sleep(1)
135        # Skip Arrow
136        System.tap(self._target, 46, 78)
137        # Run Workload
138        System.tap(self._target, test_x, test_y)
139        # Skip instructions
140        System.hswipe(self._target, 10, 80, duration=100, swipe_right=False)
141        System.hswipe(self._target, 10, 80, duration=100, swipe_right=False)
142        System.hswipe(self._target, 10, 80, duration=100, swipe_right=False)
143        self._log.info("Vellamo - {} started!".format(test_name.upper()))
144
145        while True:
146
147            # read next logcat line (up to max 1024 chars)
148            message = logcat.stdout.readline(1024)
149
150            # Benchmark start trigger
151            if VELLAMO_BENCHMARK_START_RE.search(message):
152                # Start tracing
153                self.tracingStart()
154                self._log.debug("Benchmark started!")
155
156            elif VELLAMO_BENCHMARK_END_RE.search(message):
157                # Stop tracing
158                self.tracingStop()
159                break
160
161            else:
162                continue
163
164        # Gather scores file from the device
165        db_file = os.path.join(out_dir, VELLAMO_SCORE_NAME)
166        self._target.pull('{}/{}'.format(VELLAMO_DB_PATH, VELLAMO_SCORE_NAME),
167                         db_file)
168
169        System.force_stop(self._target, self.package, clear=True)
170
171        # Go back to home screen
172        System.home(self._target)
173
174        # Set brightness back to auto
175        Screen.set_brightness(self._target, auto=True)
176
177# vim :set tabstop=4 shiftwidth=4 expandtab
178