| # Copyright 2018 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, time |
| |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib.cros import chrome |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.cros import service_stopper |
| from autotest_lib.client.cros.graphics import graphics_utils |
| from autotest_lib.client.cros.power import power_rapl |
| from autotest_lib.client.cros.power import power_status |
| from autotest_lib.client.cros.power import power_utils |
| |
| TEST_NAME_AND_FLAGS = [ |
| ['hw_overlays_hw_decode', ['']], |
| ['no_overlays_hw_decode', ['--enable-hardware-overlays=']], |
| ['hw_overlays_sw_decode', ['--disable-accelerated-video-decode']], |
| [ |
| 'no_overlays_sw_decode', |
| ['--disable-accelerated-video-decode', '--enable-hardware-overlays='] |
| ] |
| ] |
| # Amount of time to wait for the URL to load and the video to start playing. |
| PREAMBLE_DURATION_SECONDS = 8 |
| # Amount of time to let the video play while measuring power consumption. |
| MEASUREMENT_DURATION_SECONDS = 12 |
| |
| # Time in seconds to wait for cpu idle until giveup. |
| IDLE_CPU_WAIT_TIMEOUT_SECONDS = 60.0 |
| # Maximum percent of cpu usage considered as idle. |
| IDLE_CPU_LOAD_PERCENTAGE = 0.1 |
| |
| GRAPH_NAME = 'power_consumption' |
| |
| |
| class graphics_VideoRenderingPower(graphics_utils.GraphicsTest): |
| """This test renders on screen for a short while a video from a given |
| |
| (controlled) URL while measuring the power consumption of the different SoC |
| domains. |
| """ |
| version = 1 |
| _backlight = None |
| _service_stopper = None |
| _power_status = None |
| |
| def initialize(self): |
| super(graphics_VideoRenderingPower, self).initialize() |
| |
| self._backlight = power_utils.Backlight() |
| self._backlight.set_default() |
| |
| self._service_stopper = service_stopper.ServiceStopper( |
| service_stopper.ServiceStopper.POWER_DRAW_SERVICES) |
| self._service_stopper.stop_services() |
| |
| self._power_status = power_status.get_status() |
| |
| def cleanup(self): |
| if self._backlight: |
| self._backlight.restore() |
| if self._service_stopper: |
| self._service_stopper.restore_services() |
| super(graphics_VideoRenderingPower, self).cleanup() |
| |
| @graphics_utils.GraphicsTest.failure_report_decorator( |
| 'graphics_VideoRenderingPower') |
| def run_once(self, video_url, video_short_name): |
| """Runs the graphics_VideoRenderingPower test. |
| |
| @param video_url: URL with autoplay video inside. It's assumed that |
| there's just one <video> in the HTML, and that it fits in the |
| viewport. |
| @param video_short_name: short string describing the video; itt will be |
| presented as part of the dashboard entry name. |
| """ |
| |
| # TODO(mcasas): Extend this test to non-Intel platforms. |
| if not power_utils.has_rapl_support(): |
| logging.warning('This board has no RAPL power measurement support, ' |
| 'skipping test.') |
| return |
| |
| rapl = [] |
| if power_utils.has_battery(): |
| rapl.append( |
| power_status.SystemPower(self._power_status.battery_path)) |
| else: |
| logging.warning('This board has no battery.') |
| rapl += power_rapl.create_rapl() |
| |
| for test_name_and_flags in TEST_NAME_AND_FLAGS: |
| logging.info('Test case: %s', test_name_and_flags[0]) |
| # Launch Chrome with the appropriate flag combination. |
| with chrome.Chrome( |
| extra_browser_args=test_name_and_flags[1], |
| init_network_controller=True) as cr: |
| |
| if not utils.wait_for_idle_cpu(IDLE_CPU_WAIT_TIMEOUT_SECONDS, |
| IDLE_CPU_LOAD_PERCENTAGE): |
| raise error.TestFail('Failed: Could not get idle CPU.') |
| if not utils.wait_for_cool_machine(): |
| raise error.TestFail('Failed: Could not get cold machine.') |
| |
| tab = cr.browser.tabs[0] |
| tab.Navigate(video_url) |
| tab.WaitForDocumentReadyStateToBeComplete() |
| tab.EvaluateJavaScript( |
| 'document.' |
| 'getElementsByTagName(\'video\')[0].scrollIntoView(true)') |
| |
| # Disabling hardware overlays is difficult because the flag is |
| # already in the browser. Instead, scroll a bit down to make the |
| # video bleed out of the viewport. |
| if '--enable-hardware-overlays=' in test_name_and_flags[1]: |
| tab.EvaluateJavaScript('window.scrollBy(0, 1)') |
| |
| power_logger = power_status.PowerLogger(rapl) |
| power_logger.start() |
| time.sleep(PREAMBLE_DURATION_SECONDS) |
| |
| start_time = time.time() |
| time.sleep(MEASUREMENT_DURATION_SECONDS) |
| power_logger.checkpoint('result', start_time) |
| |
| measurements = power_logger.calc() |
| logging.debug(measurements) |
| |
| for category in sorted(measurements): |
| if category.endswith('_pwr_avg'): |
| description = '%s_%s_%s' % ( |
| video_short_name, test_name_and_flags[0], category) |
| self.output_perf_value( |
| description=description, |
| value=measurements[category], |
| units='W', |
| higher_is_better=False, |
| graph=GRAPH_NAME) |
| |
| if category.endswith('_pwr_avg'): |
| # write_perf_keyval() wants units (W) first in lowercase. |
| description = '%s_%s_%s' % ( |
| video_short_name, test_name_and_flags[0], category) |
| self.write_perf_keyval({ |
| 'w_' + description: measurements[category] |
| }) |