118 lines
4.1 KiB
Python
118 lines
4.1 KiB
Python
# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
import logging, os, tempfile, threading
|
|
from autotest_lib.client.bin import test, utils
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.client.common_lib.cros import chrome
|
|
|
|
POWER_MANAGER_SETTINGS = {
|
|
'plugged_dim_ms': 1000,
|
|
'plugged_off_ms': 5000,
|
|
'plugged_suspend_ms': 10000,
|
|
'unplugged_dim_ms': 1000,
|
|
'unplugged_off_ms': 5000,
|
|
'unplugged_suspend_ms': 10000,
|
|
'disable_idle_suspend': 0,
|
|
'ignore_external_policy': 1,
|
|
}
|
|
|
|
SUSPEND_TIMEOUT_MS = 30000
|
|
|
|
|
|
class power_IdleSuspend(test.test):
|
|
"""
|
|
Verify power manager tries to suspend while idle.
|
|
|
|
This test does not actually allow the system to suspend. Instead,
|
|
it replaces /sys/power/state with a pipe and waits until "mem" is
|
|
written to it. Such a write would normally cause suspend.
|
|
"""
|
|
version = 1
|
|
mounts = ()
|
|
|
|
def initialize(self):
|
|
super(power_IdleSuspend, self).initialize()
|
|
self.mounts = []
|
|
|
|
|
|
def setup_power_manager(self):
|
|
"""Configures powerd for the test."""
|
|
# create directory for temporary settings
|
|
self.tempdir = tempfile.mkdtemp(prefix='IdleSuspend.')
|
|
logging.info('using temporary directory %s', self.tempdir)
|
|
|
|
# override power manager settings
|
|
for key, val in POWER_MANAGER_SETTINGS.iteritems():
|
|
logging.info('overriding %s to %s', key, val)
|
|
tmp_path = '%s/%s' % (self.tempdir, key)
|
|
mount_path = '/usr/share/power_manager/%s' % key
|
|
utils.write_one_line(tmp_path, str(val))
|
|
utils.run('mount --bind %s %s' % (tmp_path, mount_path))
|
|
self.mounts.append(mount_path)
|
|
|
|
# override /sys/power/state with fifo
|
|
fifo_path = '%s/sys_power_state' % self.tempdir
|
|
os.mkfifo(fifo_path)
|
|
utils.run('mount --bind %s /sys/power/state' % fifo_path)
|
|
self.mounts.append('/sys/power/state')
|
|
|
|
|
|
def wait_for_suspend(self):
|
|
"""Thread callback to watch for powerd to announce idle transition."""
|
|
# block reading new power state from /sys/power/state
|
|
sys_power_state = open('/sys/power/state')
|
|
self.new_power_state = sys_power_state.read()
|
|
logging.info('new power state: %s', self.new_power_state)
|
|
|
|
|
|
def run_once(self):
|
|
with chrome.Chrome():
|
|
# stop power manager before reconfiguring
|
|
logging.info('stopping powerd')
|
|
utils.run('stop powerd')
|
|
|
|
# override power manager settings
|
|
self.setup_power_manager()
|
|
|
|
# start thread to wait for suspend
|
|
self.new_power_state = None
|
|
thread = threading.Thread(target=self.wait_for_suspend)
|
|
thread.start()
|
|
|
|
# touch OOBE completed file so powerd won't ignore idle state.
|
|
utils.run('touch /home/chronos/.oobe_completed')
|
|
|
|
# restart powerd to pick up new settings
|
|
logging.info('restarting powerd')
|
|
utils.run('start powerd')
|
|
|
|
# wait for idle suspend
|
|
thread.join(SUSPEND_TIMEOUT_MS / 1000.)
|
|
|
|
if thread.is_alive():
|
|
# join timed out - powerd didn't write to /sys/power/state
|
|
raise error.TestFail('timed out waiting for suspend')
|
|
|
|
if self.new_power_state is None:
|
|
# probably an exception in the thread, check the log
|
|
raise error.TestError('reader thread crashed')
|
|
|
|
if self.new_power_state.strip() not in ['mem', 'freeze']:
|
|
err_str = 'bad power state written to /sys/power/state'
|
|
raise error.TestFail(err_str)
|
|
|
|
|
|
def cleanup(self):
|
|
# restore original power manager settings
|
|
for mount in self.mounts:
|
|
logging.info('restoring %s', mount)
|
|
utils.run('umount -l %s' % mount)
|
|
|
|
# restart powerd to pick up original settings
|
|
logging.info('restarting powerd')
|
|
utils.run('restart powerd')
|
|
|
|
super(power_IdleSuspend, self).cleanup()
|