189 lines
8.2 KiB
Python
189 lines
8.2 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 time
|
|
import logging
|
|
from threading import Timer
|
|
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
|
|
|
|
|
|
class firmware_ECPowerButton(FirmwareTest):
|
|
"""
|
|
Servo based EC power button test.
|
|
"""
|
|
version = 1
|
|
|
|
# Delay between shutdown and wake by power button
|
|
LONG_WAKE_DELAY = 13
|
|
SHORT_WAKE_DELAY = 7
|
|
|
|
# Delay between recovery screen and shutdown by power button
|
|
RECOVERY_SCREEN_SHUTDOWN_DELAY = 3
|
|
|
|
# Duration of holding down power button to shut down with powerd
|
|
POWER_BUTTON_POWERD_DURATION = 6
|
|
|
|
# Duration of holding down power button to test ignoring power button press
|
|
POWER_BUTTON_IGNORE_PRESS_DURATION = 0.2
|
|
|
|
# Delay after pressing power button to check power state
|
|
POWER_BUTTON_IGNORE_PRESS_DELAY = 10
|
|
|
|
def initialize(self, host, cmdline_args):
|
|
super(firmware_ECPowerButton, self).initialize(host, cmdline_args)
|
|
|
|
# Duration of holding down power button to shut down without powerd
|
|
self.POWER_BUTTON_NO_POWERD_DURATION = max(
|
|
self.faft_config.hold_pwr_button_nopowerd_shutdown, 11)
|
|
# Short duration of holding down power button to power on
|
|
self.POWER_BUTTON_SHORT_POWER_ON_DURATION = max(
|
|
self.faft_config.hold_pwr_button_poweron, 0.05)
|
|
# Long duration of holding down power button to power on
|
|
self.POWER_BUTTON_LONG_POWER_ON_DURATION = max(
|
|
self.faft_config.hold_pwr_button_poweron, 1)
|
|
# Only run in normal mode
|
|
self.switcher.setup_mode('normal')
|
|
self.has_internal_display = host.has_internal_display()
|
|
|
|
def kill_powerd(self):
|
|
"""Stop powerd on client."""
|
|
self.faft_client.system.run_shell_command("stop powerd")
|
|
|
|
def debounce_power_button(self):
|
|
"""Check if power button debouncing works.
|
|
|
|
Press power button for a very short period and checks for power
|
|
button keycode.
|
|
"""
|
|
# Delay 3 seconds to ensure client machine is waiting for key press.
|
|
# Press power button for only 10ms. Should be debounced.
|
|
logging.info('ECPowerButton: debounce_power_button')
|
|
Timer(3, self.servo.power_key, [0.001]).start()
|
|
return self.faft_client.system.check_keys([116])
|
|
|
|
def shutdown_and_wake(self,
|
|
shutdown_powerkey_duration,
|
|
wake_delay,
|
|
wake_powerkey_duration):
|
|
"""
|
|
Shutdown the system by power button, delay, and then power on
|
|
by power button again.
|
|
"""
|
|
self.servo.power_key(shutdown_powerkey_duration)
|
|
|
|
# Send a new line to wakeup EC from deepsleep,
|
|
# it can happen if the EC console is not used for some time.
|
|
# Offset the wake_delay time by the delay (if any) waiting for the AP
|
|
# to start, so that the wake_delay time is the time to wait after the
|
|
# AP is actually up and running.
|
|
wake_delay += self.faft_config.delay_powerinfo_stable
|
|
if wake_delay > 2:
|
|
Timer(wake_delay - 1, self.ec.send_command, [""]).start()
|
|
|
|
Timer(wake_delay,
|
|
self.servo.power_key,
|
|
[wake_powerkey_duration]).start()
|
|
|
|
def run_once(self):
|
|
"""Runs a single iteration of the test."""
|
|
if not self.check_ec_capability():
|
|
raise error.TestNAError("Nothing needs to be tested on this device")
|
|
|
|
logging.info("Boot to recovery screen.")
|
|
self.switcher.enable_rec_mode_and_reboot(usb_state='host')
|
|
time.sleep(self.faft_config.firmware_screen)
|
|
if self.get_power_state() != self.POWER_STATE_S0:
|
|
raise error.TestFail("DUT didn't boot to recovery screen")
|
|
|
|
logging.info("Shutdown by short power button press.")
|
|
self.servo.power_key(self.faft_config.hold_pwr_button_poweron)
|
|
time.sleep(self.RECOVERY_SCREEN_SHUTDOWN_DELAY)
|
|
power_state = self.get_power_state()
|
|
if (power_state != self.POWER_STATE_S5 and
|
|
power_state != self.POWER_STATE_G3):
|
|
raise error.TestFail("DUT didn't shutdown by "
|
|
"short power button press")
|
|
if self.ec.check_feature('EC_FEATURE_EFS2'):
|
|
logging.info("Check if EC jumped to RW.")
|
|
if not self.ec.check_ro_rw('RW'):
|
|
raise error.TestFail("EC didn't jump to RW")
|
|
|
|
logging.info("Boot by short power button press.")
|
|
self.servo.power_key(self.faft_config.hold_pwr_button_poweron)
|
|
self.switcher.wait_for_client()
|
|
if self.get_power_state() != self.POWER_STATE_S0:
|
|
raise error.TestFail("DUT didn't boot by short power button press")
|
|
|
|
if self.has_internal_display:
|
|
logging.info("Display connected, check system ignores short 200ms "
|
|
"power button press.")
|
|
old_boot_id = self.get_bootid(retry=1)
|
|
self.servo.power_key(self.POWER_BUTTON_IGNORE_PRESS_DURATION)
|
|
time.sleep(self.POWER_BUTTON_IGNORE_PRESS_DELAY)
|
|
power_state = self.get_power_state()
|
|
new_boot_id = self.get_bootid(retry=1)
|
|
if power_state != self.POWER_STATE_S0 or new_boot_id != old_boot_id:
|
|
self._reset_client()
|
|
raise error.TestFail("DUT shutdown from short 200ms power "
|
|
"button press")
|
|
else:
|
|
logging.info("No display connected, check system shuts down from "
|
|
"short 200ms power button check.")
|
|
self.servo.power_key(self.POWER_BUTTON_IGNORE_PRESS_DURATION)
|
|
time.sleep(self.POWER_BUTTON_IGNORE_PRESS_DELAY)
|
|
power_state = self.get_power_state()
|
|
logging.info("Power state = %s", power_state)
|
|
if (power_state != self.POWER_STATE_S5 and
|
|
power_state != self.POWER_STATE_G3):
|
|
self._reset_client()
|
|
raise error.TestFail("DUT didn't shutdown by "
|
|
"short power button press")
|
|
self.servo.power_key(self.faft_config.hold_pwr_button_poweron)
|
|
self.switcher.wait_for_client()
|
|
if self.get_power_state() != self.POWER_STATE_S0:
|
|
self._reset_client()
|
|
raise error.TestFail("DUT didn't boot by short power button press")
|
|
|
|
logging.info("Shutdown when powerd is still running and wake from S5 "
|
|
"with short power button press.")
|
|
if self.servo.is_localhost() and self.has_internal_display:
|
|
self.check_state(self.debounce_power_button)
|
|
self.switcher.mode_aware_reboot(
|
|
'custom',
|
|
lambda:self.shutdown_and_wake(
|
|
self.POWER_BUTTON_POWERD_DURATION,
|
|
self.SHORT_WAKE_DELAY,
|
|
self.POWER_BUTTON_SHORT_POWER_ON_DURATION))
|
|
|
|
logging.info("Shutdown when powerd is stopped and wake from G3 "
|
|
"with short power button press.")
|
|
self.kill_powerd()
|
|
self.switcher.mode_aware_reboot(
|
|
'custom',
|
|
lambda:self.shutdown_and_wake(
|
|
self.POWER_BUTTON_NO_POWERD_DURATION,
|
|
self.LONG_WAKE_DELAY,
|
|
self.POWER_BUTTON_SHORT_POWER_ON_DURATION))
|
|
|
|
logging.info("Shutdown when powerd is still running and wake from G3 "
|
|
"with long power button press.")
|
|
self.switcher.mode_aware_reboot(
|
|
'custom',
|
|
lambda:self.shutdown_and_wake(
|
|
self.POWER_BUTTON_POWERD_DURATION,
|
|
self.LONG_WAKE_DELAY,
|
|
self.POWER_BUTTON_LONG_POWER_ON_DURATION))
|
|
|
|
logging.info("Shutdown when powerd is stopped and wake from S5 "
|
|
"with long power button press.")
|
|
self.kill_powerd()
|
|
self.switcher.mode_aware_reboot(
|
|
'custom',
|
|
lambda:self.shutdown_and_wake(
|
|
self.POWER_BUTTON_NO_POWERD_DURATION,
|
|
self.SHORT_WAKE_DELAY,
|
|
self.POWER_BUTTON_LONG_POWER_ON_DURATION))
|