1 # Copyright (c) 2012 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 5 import logging, threading, time 6 from autotest_lib.client.bin import test, utils 7 from autotest_lib.client.common_lib import error 8 from autotest_lib.client.common_lib.cros import chrome 9 from autotest_lib.client.cros import power_utils, rtc 10 from autotest_lib.client.cros.audio import audio_helper 11 12 class power_AudioDetector(test.test): 13 """Verifies that audio playback prevents powerd from suspending.""" 14 version = 1 15 16 def run_once(self, run_time_sec=60): 17 if run_time_sec < 10: 18 raise error.TestFail('Must run for at least 10 seconds') 19 20 with chrome.Chrome(): 21 # Audio loop time should be significantly shorter than 22 # |run_time_sec| time, so that the total playback time doesn't 23 # exceed it by much. 24 audio_loop_time_sec = min(10, run_time_sec / 10 + 0.5) 25 26 # Set a low audio volume to avoid annoying people during tests. 27 audio_helper.set_volume_levels(10, 100) 28 29 # Start playing audio file. 30 self._enable_audio_playback = True 31 thread = threading.Thread(target=self._play_audio, 32 args=(audio_loop_time_sec,)) 33 thread.start() 34 35 # Restart powerd with timeouts for quick idle events. 36 gap_ms = run_time_sec * 1000 / 4 37 dim_ms = min(10000, gap_ms) 38 off_ms = min(20000, gap_ms * 2) 39 suspend_ms = min(30000, gap_ms * 3) 40 prefs = { 'disable_idle_suspend' : 0, 41 'ignore_external_policy' : 1, 42 'plugged_dim_ms' : dim_ms, 43 'plugged_off_ms' : off_ms, 44 'plugged_suspend_ms' : suspend_ms, 45 'unplugged_dim_ms' : dim_ms, 46 'unplugged_off_ms' : off_ms, 47 'unplugged_suspend_ms' : suspend_ms } 48 self._pref_change = power_utils.PowerPrefChanger(prefs) 49 50 # Set an alarm to wake up the system in case the audio detector 51 # fails and the system suspends. 52 alarm_time = rtc.get_seconds() + run_time_sec 53 rtc.set_wake_alarm(alarm_time) 54 55 time.sleep(run_time_sec) 56 57 # Stop powerd to avoid suspending when the audio stops. 58 utils.system_output('stop powerd') 59 60 # Stop audio and wait for the audio thread to terminate. 61 self._enable_audio_playback = False 62 thread.join(timeout=(audio_loop_time_sec * 2)) 63 if thread.is_alive(): 64 logging.error('Audio thread did not terminate at end of test.') 65 66 # Check powerd's log to make sure that no suspend took place. 67 powerd_log_path = '/var/log/power_manager/powerd.LATEST' 68 log = open(powerd_log_path, 'r').read() 69 if log.find('Starting suspend') != -1: 70 err_str = 'System suspended while audio was playing.' 71 raise error.TestFail(err_str) 72 73 74 def cleanup(self): 75 utils.restart_job('powerd') 76 77 78 def _play_audio(self, loop_time): 79 """ 80 Repeatedly plays audio until self._audio_playback_enabled == False. 81 """ 82 # TODO(crosbug.com/33988): Allow for pauses in audio playback to 83 # simulate delays in loading the next song. 84 while self._enable_audio_playback: 85 audio_helper.play_sound(duration_seconds=loop_time) 86 logging.info('Done playing audio.') 87