xref: /aosp_15_r20/external/autotest/client/site_tests/power_VideoCall/power_VideoCall.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1# Lint as: python2, python3
2# Copyright 2019 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5import logging
6import re
7import time
8
9from autotest_lib.client.bin import utils
10from autotest_lib.client.common_lib.cros import chrome
11from autotest_lib.client.cros.input_playback import keyboard
12from autotest_lib.client.cros.power import power_status
13from autotest_lib.client.cros.power import power_test
14
15class power_VideoCall(power_test.power_Test):
16    """class for power_VideoCall test."""
17    version = 1
18
19    video_url = 'https://storage.googleapis.com/chromiumos-test-assets-public/power_VideoCall/power_VideoCall.html'
20    doc_url = 'http://crospower.page.link/power_VideoCall_doc'
21
22    def initialize(self, seconds_period=20., pdash_note='',
23                   force_discharge=False):
24        """initialize method."""
25        super(power_VideoCall, self).initialize(seconds_period=seconds_period,
26                                                pdash_note=pdash_note,
27                                                force_discharge=force_discharge)
28
29
30    def run_once(self,
31                 duration=7200,
32                 preset='',
33                 video_url='',
34                 num_video=5,
35                 multitask=True,
36                 min_run_time_percent=100):
37        """run_once method.
38
39        @param duration: time in seconds to display url and measure power.
40        @param preset: preset of the camera record. Possible values are
41                       'ultra' :  1080p30_vp9,
42                       'high' :   720p30_vp9,
43                       'medium' : 720p24_vp8,
44                       'low' :    360p24_vp8
45                       If not supplied, preset will be determined automatically.
46        @param video_url: url of video call simulator.
47        @param num_video: number of video including camera preview.
48        @param multitask: boolean indicate Google Docs multitask enablement.
49        @param min_run_time_percent: int between 0 and 100;
50                                     run time must be longer than
51                                     min_run_time_percent / 100.0 * duration.
52        """
53
54        if not preset and not video_url:
55            preset = self._get_camera_preset()
56        if not video_url:
57            video_url = self.video_url
58
59        # Append preset to self.video_url for camera preset.
60        if preset:
61            video_url = '%s?preset=%s' % (video_url, preset)
62
63        extra_browser_args = self.get_extra_browser_args_for_camera_test()
64        with keyboard.Keyboard() as keys,\
65             chrome.Chrome(init_network_controller=True,
66                           gaia_login=False,
67                           extra_browser_args=extra_browser_args,
68                           autotest_ext=True) as cr:
69
70            # Move existing window to left half and open video page
71            tab_left = cr.browser.tabs[0]
72            tab_left.Activate()
73            if multitask:
74                keys.press_key('alt+[')
75            elif not tab_left.EvaluateJavaScript(
76                    'document.webkitIsFullScreen'):
77                # Run in fullscreen when not multitask.
78                keys.press_key('f4')
79
80            logging.info('Navigating left window to %s', video_url)
81            tab_left.Navigate(video_url)
82            tab_left.WaitForDocumentReadyStateToBeComplete()
83            video_init_time = power_status.VideoFpsLogger.time_until_ready(
84                    tab_left, num_video=num_video)
85            self.keyvals['video_init_time'] = video_init_time
86
87            tab_right = None
88            if multitask:
89                # Open Google Doc on right half
90                logging.info('Navigating right window to %s', self.doc_url)
91                cmd = 'chrome.windows.create({ url : "%s" });' % self.doc_url
92                cr.autotest_ext.EvaluateJavaScript(cmd)
93                tab_right = cr.browser.tabs[-1]
94                tab_right.Activate()
95                keys.press_key('alt+]')
96                tab_right.WaitForDocumentReadyStateToBeComplete()
97                time.sleep(5)
98
99            self._vlog = power_status.VideoFpsLogger(tab_left,
100                seconds_period=self._seconds_period,
101                checkpoint_logger=self._checkpoint_logger)
102            self._meas_logs.append(self._vlog)
103
104            # Start typing number block
105            self.start_measurements()
106            # TODO(b/226960942): Revert crrev.com/c/3556798 once root cause is
107            # found for why test fails before 2 hrs.
108            min_run_time = min_run_time_percent / 100.0 * duration
109            type_count = 0
110            while time.time() - self._start_time < duration:
111                if multitask:
112                    keys.press_key('number_block')
113                    type_count += 1
114                    if type_count == 10:
115                        keys.press_key('ctrl+a_backspace')
116                        type_count = 0
117                else:
118                    time.sleep(60)
119
120                if not tab_left.IsAlive():
121                    msg = 'Video tab crashed'
122                    logging.error(msg)
123                    if time.time() - self._start_time < min_run_time:
124                        self._failure_messages.append(msg)
125                    break
126
127                if tab_right and not tab_right.IsAlive():
128                    msg = 'Doc tab crashed'
129                    logging.error(msg)
130                    if time.time() - self._start_time < min_run_time:
131                        self._failure_messages.append(msg)
132                    break
133
134                self.status.refresh()
135                if self.status.is_low_battery():
136                    logging.info(
137                        'Low battery, stop test early after %.0f minutes',
138                        (time.time() - self._start_time) / 60)
139                    break
140
141            if multitask:
142                self.collect_keypress_latency(cr)
143
144    def _get_camera_preset(self):
145        """Return camera preset appropriate to hw spec.
146
147        Preset will be determined using this logic.
148        - Newer Intel Core U/P-series CPU with fan -> 'high'
149        - Above without fan -> 'medium'
150        - AMD Ryzen CPU -> 'medium'
151        - High performance ARM -> 'medium'
152        - Other Intel Core CPU -> 'medium'
153        - AMD APU -> 'low'
154        - Intel N-series CPU -> 'low'
155        - Older ARM CPU -> 'low'
156        - Other CPU -> 'low'
157        """
158        HIGH_IF_HAS_FAN_REGEX = r'''
159            Intel[ ]Core[ ]i[357]-[6-9][0-9]{3}U|     # Intel Core i7-8650U
160            Intel[ ]Core[ ]i[357]-1[0-9]{3,4}[UPHG]|  # 10510U, 1135G7, 1250P
161            Genuine[ ]Intel[ ]0000|                   # Unreleased Intel CPU
162            AMD[ ]Eng[ ]Sample                        # Unreleased AMD CPU
163        '''
164        MEDIUM_REGEX = r'''
165            AMD[ ]Ryzen[ ][357][ ][3-9][0-9]{3}|      # AMD Ryzen 7 3700
166            Intel[ ]Core[ ][im][357]-[0-9]{4,5}[UY]|  # Intel Core i5-8200Y
167            Intel[ ]Core[ ][im][357]-[67]Y[0-9]{2}|   # Intel Core m7-6Y75
168            Intel[ ]Pentium[ ][0-9]{4,5}[UY]|         # Intel Pentium 6405U
169            Intel[ ]Celeron[ ][0-9]{4,5}[UY]|         # Intel Celeron 5205U
170            qcom[ ]sc[0-9]{4}|                        # qcom sc7180
171            mediatek[ ]mt819[0-9]                     # mediatek mt8192
172        '''
173        cpu_name = utils.get_cpu_name()
174
175        if re.search(HIGH_IF_HAS_FAN_REGEX, cpu_name, re.VERBOSE):
176            if power_status.has_fan():
177                return 'high'
178            return 'medium'
179
180        if re.search(MEDIUM_REGEX, cpu_name, re.VERBOSE):
181            return 'medium'
182
183        return 'low'
184