1# Copyright 2015 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 hashlib, logging, os, time 6 7 8from autotest_lib.client.bin import test 9from autotest_lib.client.common_lib import error, file_utils 10from autotest_lib.client.common_lib.cros import chrome 11from autotest_lib.client.cros import power_status, power_utils, service_stopper 12 13_DOWNLOAD_BASE = ('http://commondatastorage.googleapis.com/' 14 'chromiumos-test-assets-public/audio_power/') 15 16# Minimum battery charge percentage to run the test 17BATTERY_INITIAL_CHARGED_MIN = 10 18 19# Measurement duration in seconds. 20MEASUREMENT_DURATION = 150 21 22POWER_DESCRIPTION = 'avg_energy_rate_' 23 24# Time to exclude from calculation after playing audio [seconds]. 25STABILIZATION_DURATION = 10 26 27 28class audio_PlaybackPower(test.test): 29 """Captures power usage for audio playback.""" 30 31 version = 1 32 33 34 def initialize(self): 35 self._service_stopper = None 36 self._backlight = None 37 38 def run_power_test(self, audio_type): 39 """ 40 Captures power usage and reports it to the perf dashboard. 41 42 @param audio_type: audio format label to attach with perf keyval. 43 """ 44 45 self._backlight = power_utils.Backlight() 46 self._backlight.set_default() 47 48 self._service_stopper = service_stopper.ServiceStopper( 49 service_stopper.ServiceStopper.POWER_DRAW_SERVICES) 50 self._service_stopper.stop_services() 51 52 self._power_status = power_status.get_status() 53 # Verify that we are running on battery and the battery is sufficiently 54 # charged. 55 self._power_status.assert_battery_state(BATTERY_INITIAL_CHARGED_MIN) 56 57 measurements = [power_status.SystemPower( 58 self._power_status.battery_path)] 59 60 def get_power(): 61 power_logger = power_status.PowerLogger(measurements) 62 power_logger.start() 63 time.sleep(STABILIZATION_DURATION) 64 start_time = time.time() 65 time.sleep(MEASUREMENT_DURATION) 66 power_logger.checkpoint('result', start_time) 67 keyval = power_logger.calc() 68 logging.info('Power output %s', keyval) 69 return keyval['result_' + measurements[0].domain + '_pwr'] 70 71 energy_rate = get_power() 72 perf_keyval = {} 73 perf_keyval[POWER_DESCRIPTION + audio_type] = energy_rate 74 self.output_perf_value(description=POWER_DESCRIPTION + audio_type, 75 value=energy_rate, units='W', 76 higher_is_better=False) 77 self.write_perf_keyval(perf_keyval) 78 79 80 def run_once(self, test_file, checksum): 81 local_path = os.path.join(self.bindir, '%s' % test_file) 82 file_utils.download_file(_DOWNLOAD_BASE + test_file, local_path) 83 logging.info('Downloaded file: %s. Expected checksum: %s', 84 local_path, checksum) 85 with open(local_path, 'r') as r: 86 md5sum = hashlib.md5(r.read()).hexdigest() 87 if md5sum != checksum: 88 raise error.TestError('unmatched md5 sum: %s' % md5sum) 89 with chrome.Chrome(init_network_controller=True) as cr: 90 cr.browser.platform.SetHTTPServerDirectories(self.bindir) 91 url = cr.browser.platform.http_server.UrlOf(local_path) 92 self.play_audio(cr.browser.tabs[0], url) 93 self.run_power_test(url.split('.')[-1]) 94 95 96 def play_audio(self, tab, url): 97 """Navigates to an audio file over http and plays it in loop. 98 99 @param tab: tab to open an audio stream. 100 @param url: audio/video test url. 101 """ 102 tab.Navigate(url) 103 tab.ExecuteJavaScript( 104 "document.getElementsByTagName('video')[0].loop=true") 105 tab.ExecuteJavaScript( 106 "document.getElementsByTagName('video')[0].volume=1") 107 108 109 def cleanup(self): 110 # cleanup() is run by common_lib/test.py. 111 if self._backlight: 112 self._backlight.restore() 113 if self._service_stopper: 114 self._service_stopper.restore_services() 115 116 super(audio_PlaybackPower, self).cleanup() 117