208 lines
7.0 KiB
Python
208 lines
7.0 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.
|
|
|
|
from threading import Timer
|
|
import logging
|
|
import re
|
|
import time
|
|
|
|
from autotest_lib.client.common_lib import error
|
|
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
|
|
|
|
|
|
def delayed(seconds): # pylint:disable=missing-docstring
|
|
def decorator(f): # pylint:disable=missing-docstring
|
|
def wrapper(*args, **kargs): # pylint:disable=missing-docstring
|
|
t = Timer(seconds, f, args, kargs)
|
|
t.start()
|
|
return wrapper
|
|
return decorator
|
|
|
|
|
|
class firmware_ECLidSwitch(FirmwareTest):
|
|
"""
|
|
Servo based EC lid switch test.
|
|
"""
|
|
version = 1
|
|
|
|
# Delay between closing and opening the lid
|
|
LID_DELAY = 1
|
|
|
|
# Delay to allow FAFT client receive command
|
|
RPC_DELAY = 2
|
|
|
|
# Delay between shutdown and wakeup by lid switch
|
|
WAKE_DELAY = 10
|
|
|
|
def initialize(self, host, cmdline_args):
|
|
super(firmware_ECLidSwitch, self).initialize(host, cmdline_args)
|
|
# Only run in normal mode
|
|
self.switcher.setup_mode('normal')
|
|
|
|
def _open_lid(self):
|
|
"""Open lid by servo."""
|
|
self.servo.set('lid_open', 'yes')
|
|
|
|
def _close_lid(self):
|
|
"""Close lid by servo."""
|
|
self.servo.set('lid_open', 'no')
|
|
|
|
@delayed(RPC_DELAY)
|
|
def delayed_open_lid(self):
|
|
"""Delay by RPC_DELAY and then open lid by servo."""
|
|
self._open_lid()
|
|
|
|
@delayed(RPC_DELAY)
|
|
def delayed_close_lid(self):
|
|
"""Delay by RPC_DELAY and then close lid by servo."""
|
|
self._close_lid()
|
|
|
|
def _wake_by_lid_switch(self):
|
|
"""Wake DUT with lid switch."""
|
|
self._close_lid()
|
|
time.sleep(self.LID_DELAY)
|
|
self._open_lid()
|
|
|
|
def delayed_wake(self):
|
|
"""
|
|
Confirm the device is in G3, wait for WAKE_DELAY, and then wake DUT
|
|
with lid switch.
|
|
"""
|
|
self.check_shutdown_power_state(self.POWER_STATE_G3, pwr_retries=10)
|
|
time.sleep(self.WAKE_DELAY)
|
|
self._wake_by_lid_switch()
|
|
|
|
def immediate_wake(self):
|
|
"""Confirm the device is in G3 and then wake DUT with lid switch."""
|
|
self.check_shutdown_power_state(self.POWER_STATE_G3, pwr_retries=10)
|
|
self._wake_by_lid_switch()
|
|
|
|
def shutdown_and_wake(self, shutdown_func, wake_func):
|
|
"""Software shutdown and wake.
|
|
|
|
Args:
|
|
shutdown_func: Function to shut down DUT.
|
|
wake_func: Delayed function to wake DUT.
|
|
"""
|
|
shutdown_func()
|
|
wake_func()
|
|
|
|
def _get_keyboard_backlight(self):
|
|
"""Get keyboard backlight brightness.
|
|
|
|
Returns:
|
|
Backlight brightness percentage 0~100. If it is disabled, 0 is
|
|
returned.
|
|
"""
|
|
cmd = 'ectool pwmgetkblight'
|
|
pattern_percent = re.compile(
|
|
'Current keyboard backlight percent: (\d*)')
|
|
pattern_disable = re.compile('Keyboard backlight disabled.')
|
|
lines = self.faft_client.system.run_shell_command_get_output(cmd)
|
|
for line in lines:
|
|
matched_percent = pattern_percent.match(line)
|
|
if matched_percent is not None:
|
|
return int(matched_percent.group(1))
|
|
matched_disable = pattern_disable.match(line)
|
|
if matched_disable is not None:
|
|
return 0
|
|
raise error.TestError('Cannot get keyboard backlight status.')
|
|
|
|
def _set_keyboard_backlight(self, value):
|
|
"""Set keyboard backlight brightness.
|
|
|
|
Args:
|
|
value: Backlight brightness percentage 0~100.
|
|
"""
|
|
cmd = 'ectool pwmsetkblight %d' % value
|
|
self.faft_client.system.run_shell_command(cmd)
|
|
|
|
def check_keycode(self):
|
|
"""Check that lid open/close do not send power button keycode.
|
|
|
|
Returns:
|
|
True if no power button keycode is captured. Otherwise, False.
|
|
"""
|
|
# Don't check the keycode if we don't have a keyboard.
|
|
if not self.check_ec_capability(['keyboard'], suppress_warning=True):
|
|
return True
|
|
|
|
self._open_lid()
|
|
self.delayed_close_lid()
|
|
if self.faft_client.system.check_keys([]) < 0:
|
|
return False
|
|
self.delayed_open_lid()
|
|
if self.faft_client.system.check_keys([]) < 0:
|
|
return False
|
|
return True
|
|
|
|
def check_backlight(self):
|
|
"""Check if lid open/close controls keyboard backlight as expected.
|
|
|
|
Returns:
|
|
True if keyboard backlight is turned off when lid close and on when
|
|
lid open.
|
|
"""
|
|
if not self.check_ec_capability(['kblight'], suppress_warning=True):
|
|
return True
|
|
ok = True
|
|
original_value = self._get_keyboard_backlight()
|
|
self._set_keyboard_backlight(100)
|
|
|
|
self._close_lid()
|
|
if self._get_keyboard_backlight() != 0:
|
|
logging.error("Keyboard backlight still on when lid close.")
|
|
ok = False
|
|
self._open_lid()
|
|
if self._get_keyboard_backlight() == 0:
|
|
logging.error("Keyboard backlight still off when lid open.")
|
|
ok = False
|
|
|
|
self._set_keyboard_backlight(original_value)
|
|
return ok
|
|
|
|
def check_keycode_and_backlight(self):
|
|
"""
|
|
Disable powerd to prevent DUT shutting down during test. Then check
|
|
if lid switch event controls keycode and backlight as we expected.
|
|
"""
|
|
ok = True
|
|
logging.info("Stopping powerd")
|
|
self.faft_client.system.run_shell_command('stop powerd')
|
|
if not self.check_keycode():
|
|
logging.error("check_keycode failed.")
|
|
ok = False
|
|
if not self.check_backlight():
|
|
logging.error("check_backlight failed.")
|
|
ok = False
|
|
logging.info("Restarting powerd")
|
|
self.faft_client.system.run_shell_command('start powerd')
|
|
return ok
|
|
|
|
def run_once(self):
|
|
"""Runs a single iteration of the test."""
|
|
if not self.check_ec_capability(['lid']):
|
|
raise error.TestNAError("Nothing needs to be tested on this device")
|
|
|
|
logging.info("Shut down and then wake up DUT after a delay.")
|
|
self.switcher.mode_aware_reboot(
|
|
'custom',
|
|
lambda:self.shutdown_and_wake(
|
|
shutdown_func=self.run_shutdown_cmd,
|
|
wake_func=self.delayed_wake))
|
|
logging.info("Shut down and then wake up DUT immediately.")
|
|
self.switcher.mode_aware_reboot(
|
|
'custom',
|
|
lambda:self.shutdown_and_wake(
|
|
shutdown_func=self.run_shutdown_cmd,
|
|
wake_func=self.immediate_wake))
|
|
logging.info("Close and then open the lid when not logged in.")
|
|
self.switcher.mode_aware_reboot(
|
|
'custom',
|
|
lambda:self.shutdown_and_wake(
|
|
shutdown_func=self._close_lid,
|
|
wake_func=self.immediate_wake))
|
|
logging.info("Check keycode and backlight.")
|
|
self.check_state(self.check_keycode_and_backlight)
|