• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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