| # Lint as: python2, python3 |
| # Copyright 2019 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| import logging |
| import re |
| import time |
| |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib.cros import chrome |
| from autotest_lib.client.cros.input_playback import keyboard |
| from autotest_lib.client.cros.power import power_status |
| from autotest_lib.client.cros.power import power_test |
| |
| class power_VideoCall(power_test.power_Test): |
| """class for power_VideoCall test.""" |
| version = 1 |
| |
| video_url = 'https://storage.googleapis.com/chromiumos-test-assets-public/power_VideoCall/power_VideoCall.html' |
| doc_url = 'http://crospower.page.link/power_VideoCall_doc' |
| |
| def initialize(self, seconds_period=20., pdash_note='', |
| force_discharge=False): |
| """initialize method.""" |
| super(power_VideoCall, self).initialize(seconds_period=seconds_period, |
| pdash_note=pdash_note, |
| force_discharge=force_discharge) |
| |
| |
| def run_once(self, |
| duration=7200, |
| preset='', |
| video_url='', |
| num_video=5, |
| multitask=True, |
| min_run_time_percent=100): |
| """run_once method. |
| |
| @param duration: time in seconds to display url and measure power. |
| @param preset: preset of the camera record. Possible values are |
| 'ultra' : 1080p30_vp9, |
| 'high' : 720p30_vp9, |
| 'medium' : 720p24_vp8, |
| 'low' : 360p24_vp8 |
| If not supplied, preset will be determined automatically. |
| @param video_url: url of video call simulator. |
| @param num_video: number of video including camera preview. |
| @param multitask: boolean indicate Google Docs multitask enablement. |
| @param min_run_time_percent: int between 0 and 100; |
| run time must be longer than |
| min_run_time_percent / 100.0 * duration. |
| """ |
| |
| if not preset and not video_url: |
| preset = self._get_camera_preset() |
| if not video_url: |
| video_url = self.video_url |
| |
| # Append preset to self.video_url for camera preset. |
| if preset: |
| video_url = '%s?preset=%s' % (video_url, preset) |
| |
| extra_browser_args = self.get_extra_browser_args_for_camera_test() |
| with keyboard.Keyboard() as keys,\ |
| chrome.Chrome(init_network_controller=True, |
| gaia_login=False, |
| extra_browser_args=extra_browser_args, |
| autotest_ext=True) as cr: |
| |
| # Move existing window to left half and open video page |
| tab_left = cr.browser.tabs[0] |
| tab_left.Activate() |
| if multitask: |
| keys.press_key('alt+[') |
| elif not tab_left.EvaluateJavaScript( |
| 'document.webkitIsFullScreen'): |
| # Run in fullscreen when not multitask. |
| keys.press_key('f4') |
| |
| logging.info('Navigating left window to %s', video_url) |
| tab_left.Navigate(video_url) |
| tab_left.WaitForDocumentReadyStateToBeComplete() |
| video_init_time = power_status.VideoFpsLogger.time_until_ready( |
| tab_left, num_video=num_video) |
| self.keyvals['video_init_time'] = video_init_time |
| |
| tab_right = None |
| if multitask: |
| # Open Google Doc on right half |
| logging.info('Navigating right window to %s', self.doc_url) |
| cmd = 'chrome.windows.create({ url : "%s" });' % self.doc_url |
| cr.autotest_ext.EvaluateJavaScript(cmd) |
| tab_right = cr.browser.tabs[-1] |
| tab_right.Activate() |
| keys.press_key('alt+]') |
| tab_right.WaitForDocumentReadyStateToBeComplete() |
| time.sleep(5) |
| |
| self._vlog = power_status.VideoFpsLogger(tab_left, |
| seconds_period=self._seconds_period, |
| checkpoint_logger=self._checkpoint_logger) |
| self._meas_logs.append(self._vlog) |
| |
| # Start typing number block |
| self.start_measurements() |
| # TODO(b/226960942): Revert crrev.com/c/3556798 once root cause is |
| # found for why test fails before 2 hrs. |
| min_run_time = min_run_time_percent / 100.0 * duration |
| type_count = 0 |
| while time.time() - self._start_time < duration: |
| if multitask: |
| keys.press_key('number_block') |
| type_count += 1 |
| if type_count == 10: |
| keys.press_key('ctrl+a_backspace') |
| type_count = 0 |
| else: |
| time.sleep(60) |
| |
| if not tab_left.IsAlive(): |
| msg = 'Video tab crashed' |
| logging.error(msg) |
| if time.time() - self._start_time < min_run_time: |
| self._failure_messages.append(msg) |
| break |
| |
| if tab_right and not tab_right.IsAlive(): |
| msg = 'Doc tab crashed' |
| logging.error(msg) |
| if time.time() - self._start_time < min_run_time: |
| self._failure_messages.append(msg) |
| break |
| |
| self.status.refresh() |
| if self.status.is_low_battery(): |
| logging.info( |
| 'Low battery, stop test early after %.0f minutes', |
| (time.time() - self._start_time) / 60) |
| break |
| |
| if multitask: |
| self.collect_keypress_latency(cr) |
| |
| def _get_camera_preset(self): |
| """Return camera preset appropriate to hw spec. |
| |
| Preset will be determined using this logic. |
| - Newer Intel Core U/P-series CPU with fan -> 'high' |
| - Above without fan -> 'medium' |
| - AMD Ryzen CPU -> 'medium' |
| - High performance ARM -> 'medium' |
| - Other Intel Core CPU -> 'medium' |
| - AMD APU -> 'low' |
| - Intel N-series CPU -> 'low' |
| - Older ARM CPU -> 'low' |
| - Other CPU -> 'low' |
| """ |
| HIGH_IF_HAS_FAN_REGEX = r''' |
| Intel[ ]Core[ ]i[357]-[6-9][0-9]{3}U| # Intel Core i7-8650U |
| Intel[ ]Core[ ]i[357]-1[0-9]{3,4}[UPHG]| # 10510U, 1135G7, 1250P |
| Genuine[ ]Intel[ ]0000| # Unreleased Intel CPU |
| AMD[ ]Eng[ ]Sample # Unreleased AMD CPU |
| ''' |
| MEDIUM_REGEX = r''' |
| AMD[ ]Ryzen[ ][357][ ][3-9][0-9]{3}| # AMD Ryzen 7 3700 |
| Intel[ ]Core[ ][im][357]-[0-9]{4,5}[UY]| # Intel Core i5-8200Y |
| Intel[ ]Core[ ][im][357]-[67]Y[0-9]{2}| # Intel Core m7-6Y75 |
| Intel[ ]Pentium[ ][0-9]{4,5}[UY]| # Intel Pentium 6405U |
| Intel[ ]Celeron[ ][0-9]{4,5}[UY]| # Intel Celeron 5205U |
| qcom[ ]sc[0-9]{4}| # qcom sc7180 |
| mediatek[ ]mt819[0-9] # mediatek mt8192 |
| ''' |
| cpu_name = utils.get_cpu_name() |
| |
| if re.search(HIGH_IF_HAS_FAN_REGEX, cpu_name, re.VERBOSE): |
| if power_status.has_fan(): |
| return 'high' |
| return 'medium' |
| |
| if re.search(MEDIUM_REGEX, cpu_name, re.VERBOSE): |
| return 'medium' |
| |
| return 'low' |