1# Copyright (c) 2013 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.common_lib import error 8from autotest_lib.server import test 9from autotest_lib.server.cros.faft.config.config import Config as FAFTConfig 10 11BOOT_WAIT_SECONDS = 100 12DARK_RESUME_SOURCE_PREF = '/sys/class/rtc/rtc0/device' 13POWER_DIR = '/var/lib/power_manager' 14SHUTDOWN_WAIT_SECONDS = 30 15SUSPEND_DURATION = 20 16SUSPEND_DURATION_PREF = '0.0' 17SUSPEND_WAIT_SECONDS = 10 18TMP_POWER_DIR = '/tmp/power_manager' 19 20 21class power_DarkResumeShutdownServer(test.test): 22 """Test power manager shut down from dark resume action.""" 23 version = 1 24 25 26 def initialize(self, host, power_method=None): 27 self._power_method = power_method 28 # save original boot id 29 self.orig_boot_id = host.get_boot_id() 30 31 host.run('mkdir -p %s' % TMP_POWER_DIR) 32 # override suspend durations preference for dark resume 33 logging.info('setting dark_resume_suspend_durations to %s %d', 34 SUSPEND_DURATION_PREF, SUSPEND_DURATION) 35 host.run('echo %s %d > %s/dark_resume_suspend_durations' % 36 (SUSPEND_DURATION_PREF, SUSPEND_DURATION, TMP_POWER_DIR)) 37 38 # override sources preference for dark resume 39 logging.info('setting dark_resume_sources to %s', 40 DARK_RESUME_SOURCE_PREF) 41 host.run('echo %s > %s/dark_resume_sources' % 42 (DARK_RESUME_SOURCE_PREF, TMP_POWER_DIR)) 43 44 # override disabling of dark resume 45 logging.info('enabling dark resume') 46 host.run('echo 0 > %s/disable_dark_resume' % TMP_POWER_DIR) 47 48 # bind the tmp directory to the power preference directory 49 host.run('mount --bind %s %s' % (TMP_POWER_DIR, POWER_DIR)) 50 51 # restart powerd to pick up new dark resume settings 52 logging.info('restarting powerd') 53 host.run('restart powerd') 54 55 56 def platform_supports_dark_resume(self, platform_name): 57 """Check if the test works on the given platform 58 59 @param platform_name: the name of the given platform 60 """ 61 client_attr = FAFTConfig(platform_name) 62 return client_attr.dark_resume_capable 63 64 65 def run_once(self, host=None): 66 """Run the test. 67 68 Setup preferences so that a dark resume will happen shortly after 69 suspending the machine. 70 71 suspend the machine 72 wait 73 turn off AC power 74 wait for shutdown 75 reboot 76 turn on AC power 77 78 @param host: The machine to run the tests on 79 """ 80 platform = host.run_output('mosys platform name') 81 logging.info('Checking platform %s for compatibility with dark resume', 82 platform) 83 if not self.platform_supports_dark_resume(platform): 84 return 85 86 host.power_on(power_method=self._power_method) 87 # The IO redirection is to make the command return right away. For now, 88 # don't go through sys_power for suspending since those code paths use 89 # the RTC. 90 # TODO(dbasehore): rework sys_power to make the RTC alarm optional 91 host.run('/usr/bin/powerd_dbus_suspend --delay=1 ' 92 '> /dev/null 2>&1 < /dev/null &') 93 time.sleep(SUSPEND_WAIT_SECONDS) 94 host.power_off(power_method=self._power_method) 95 96 # wait for power manager to give up and shut down 97 logging.info('waiting for power off') 98 host.wait_down(timeout=SHUTDOWN_WAIT_SECONDS, 99 old_boot_id=self.orig_boot_id) 100 101 # ensure host is now off 102 if host.is_up(): 103 raise error.TestFail('DUT still up. Machine did not shut down from' 104 ' dark resume') 105 else: 106 logging.info('good, host is now off') 107 108 # restart host 109 host.power_on(power_method=self._power_method) 110 host.servo.power_normal_press() 111 if not host.wait_up(timeout=BOOT_WAIT_SECONDS): 112 raise error.TestFail('DUT did not turn back on after shutting down') 113 114 115 def cleanup(self, host): 116 # make sure that the machine is not suspended and that the power is on 117 # when exiting the test 118 host.power_on(power_method=self._power_method) 119 host.servo.ctrl_key() 120 121 # try to clean up the mess we've made if shutdown failed 122 if host.is_up() and host.get_boot_id() == self.orig_boot_id: 123 # clean up mounts 124 logging.info('cleaning up bind mounts') 125 host.run('umount %s' % POWER_DIR, 126 ignore_status=True) 127 128 # restart powerd to pick up old retry settings 129 host.run('restart powerd') 130