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