1# Lint as: python2, python3 2# Copyright 2018 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. 5 6import logging, time 7 8from autotest_lib.client.bin import utils 9from autotest_lib.client.common_lib.cros import chrome 10from autotest_lib.client.common_lib import error 11from autotest_lib.client.cros import service_stopper 12from autotest_lib.client.cros.graphics import graphics_utils 13from autotest_lib.client.cros.power import power_rapl 14from autotest_lib.client.cros.power import power_status 15from autotest_lib.client.cros.power import power_utils 16 17TEST_NAME_AND_FLAGS = [ 18 ['hw_overlays_hw_decode', ['']], 19 ['no_overlays_hw_decode', ['--enable-hardware-overlays=']], 20 ['hw_overlays_sw_decode', ['--disable-accelerated-video-decode']], 21 [ 22 'no_overlays_sw_decode', 23 ['--disable-accelerated-video-decode', '--enable-hardware-overlays='] 24 ] 25] 26# Amount of time to wait for the URL to load and the video to start playing. 27PREAMBLE_DURATION_SECONDS = 8 28# Amount of time to let the video play while measuring power consumption. 29MEASUREMENT_DURATION_SECONDS = 12 30 31# Time in seconds to wait for cpu idle until giveup. 32IDLE_CPU_WAIT_TIMEOUT_SECONDS = 60.0 33# Maximum percent of cpu usage considered as idle. 34IDLE_CPU_LOAD_PERCENTAGE = 2.5 35 36GRAPH_NAME = 'power_consumption' 37 38 39class graphics_VideoRenderingPower(graphics_utils.GraphicsTest): 40 """This test renders on screen for a short while a video from a given 41 42 (controlled) URL while measuring the power consumption of the different SoC 43 domains. 44 """ 45 version = 1 46 _backlight = None 47 _service_stopper = None 48 _power_status = None 49 50 def initialize(self): 51 super(graphics_VideoRenderingPower, self).initialize() 52 53 self._backlight = power_utils.Backlight() 54 self._backlight.set_default() 55 56 self._service_stopper = service_stopper.ServiceStopper( 57 service_stopper.ServiceStopper.POWER_DRAW_SERVICES) 58 self._service_stopper.stop_services() 59 60 self._power_status = power_status.get_status() 61 62 def cleanup(self): 63 if self._backlight: 64 self._backlight.restore() 65 if self._service_stopper: 66 self._service_stopper.restore_services() 67 super(graphics_VideoRenderingPower, self).cleanup() 68 69 @graphics_utils.GraphicsTest.failure_report_decorator( 70 'graphics_VideoRenderingPower') 71 def run_once(self, video_url, video_short_name): 72 """Runs the graphics_VideoRenderingPower test. 73 74 @param video_url: URL with autoplay video inside. It's assumed that 75 there's just one <video> in the HTML, and that it fits in the 76 viewport. 77 @param video_short_name: short string describing the video; itt will be 78 presented as part of the dashboard entry name. 79 """ 80 81 # TODO(mcasas): Extend this test to non-Intel platforms. 82 if not power_utils.has_rapl_support(): 83 logging.warning('This board has no RAPL power measurement support, ' 84 'skipping test.') 85 return 86 87 rapl = [] 88 if power_utils.has_battery(): 89 # Sometimes, the DUT is supposed to have a battery but we may not 90 # detect one. This is a symptom of a bad battery (b/145144707). 91 if self._power_status.battery_path is None: 92 raise error.TestFail('No battery found in this DUT (this is a ' 93 'symptom of a bad battery).') 94 rapl.append( 95 power_status.SystemPower(self._power_status.battery_path)) 96 else: 97 logging.warning('This board has no battery.') 98 rapl += power_rapl.create_rapl() 99 100 for test_name_and_flags in TEST_NAME_AND_FLAGS: 101 logging.info('Test case: %s', test_name_and_flags[0]) 102 # Launch Chrome with the appropriate flag combination. 103 with chrome.Chrome( 104 extra_browser_args=test_name_and_flags[1], 105 init_network_controller=True) as cr: 106 107 if not utils.wait_for_idle_cpu(IDLE_CPU_WAIT_TIMEOUT_SECONDS, 108 IDLE_CPU_LOAD_PERCENTAGE): 109 raise error.TestFail('Failed: Could not get idle CPU.') 110 if not utils.wait_for_cool_machine(): 111 raise error.TestFail('Failed: Could not get cold machine.') 112 113 tab = cr.browser.tabs[0] 114 tab.Navigate(video_url) 115 tab.WaitForDocumentReadyStateToBeComplete() 116 tab.EvaluateJavaScript( 117 'document.' 118 'getElementsByTagName(\'video\')[0].scrollIntoView(true)') 119 120 # Disabling hardware overlays is difficult because the flag is 121 # already in the browser. Instead, scroll a bit down to make the 122 # video bleed out of the viewport. 123 if '--enable-hardware-overlays=' in test_name_and_flags[1]: 124 tab.EvaluateJavaScript('window.scrollBy(0, 1)') 125 126 power_logger = power_status.PowerLogger(rapl) 127 power_logger.start() 128 time.sleep(PREAMBLE_DURATION_SECONDS) 129 130 start_time = time.time() 131 time.sleep(MEASUREMENT_DURATION_SECONDS) 132 power_logger.checkpoint('result', start_time) 133 134 measurements = power_logger.calc() 135 logging.debug(measurements) 136 137 for category in sorted(measurements): 138 if category.endswith('_pwr_avg'): 139 description = '%s_%s_%s' % ( 140 video_short_name, test_name_and_flags[0], category) 141 self.output_perf_value( 142 description=description, 143 value=measurements[category], 144 units='W', 145 higher_is_better=False, 146 graph=GRAPH_NAME) 147 148 if category.endswith('_pwr_avg'): 149 # write_perf_keyval() wants units (W) first in lowercase. 150 description = '%s_%s_%s' % ( 151 video_short_name, test_name_and_flags[0], category) 152 self.write_perf_keyval({ 153 'w_' + description: measurements[category] 154 }) 155