aboutsummaryrefslogtreecommitdiff
path: root/server/site_tests/firmware_FwScreenPressPower/firmware_FwScreenPressPower.py
blob: 362b7da2c29984630526a26734d4b441b2c2dc3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# Copyright (c) 2011 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
import time

from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest


class firmware_FwScreenPressPower(FirmwareTest):
    """
    Servo based power button triggered shutdown test during firmware screens.

    This test requires a USB disk plugged-in, which contains a ChromeOS test
    image (built by "build_image --test"). On runtime, this test triggers
    firmware screens (developer, remove, insert, yuck, and to_norm screens),
    and then presses the power button in order to power the machine down.
    """
    version = 1
    NEEDS_SERVO_USB = True

    SHORT_SHUTDOWN_CONFIRMATION_PERIOD = 0.1

    def wait_fw_screen_and_press_power(self):
        """Wait for firmware warning screen and press power button."""
        time.sleep(self.faft_config.firmware_screen)
        # While the firmware screen, the power button probing loop sleeps
        # 0.25 second on every scan. Use the normal delay (1.2 second) for
        # power press.

        if self.faft_config.is_detachable and self.faft_config.mode_switcher_type == 'menu_switcher':
            # Since power button has been overridden as a select button in the
            # fw screens for detachables, we can just skip this part of the test
            # and shut down the DUT using the power state controller instead.
            logging.info("Setting Power Off")
            self.servo.get_power_state_controller().power_off()
        else:
            # Otherwise use the power button
            logging.info("Pressing Power Button")
            self.servo.power_normal_press()

    def wait_longer_fw_screen_and_press_power(self):
        """Wait for firmware screen without timeout and press power button."""
        time.sleep(self.faft_config.dev_screen_timeout)
        self.wait_fw_screen_and_press_power()

    def wait_second_screen_and_press_power(self):
        """Wait and trigger a second screen and press power button."""
        self.switcher.trigger_dev_to_rec()
        self.wait_fw_screen_and_press_power()

    def wait_yuck_screen_and_press_power(self):
        """Insert corrupted USB for yuck screen and press power button."""
        # This USB stick will be removed in cleanup phase.
        self.servo.switch_usbkey('dut')
        time.sleep(self.faft_config.usb_plug)
        self.wait_longer_fw_screen_and_press_power()

    def initialize(self, host, cmdline_args):
        """Initialize the test"""
        super(firmware_FwScreenPressPower, self).initialize(host, cmdline_args)
        self.switcher.setup_mode('dev')
        self.setup_usbkey(True, host=True)
        usb_dev = self.servo.probe_host_usb_dev()
        # Corrupt the kernel of USB stick. It is needed for triggering a
        # yuck screen later.
        self.corrupt_usb_kernel(usb_dev)

    def cleanup(self):
        """Cleanup the test"""
        try:
            self.servo.switch_usbkey('host')
            usb_dev = self.servo.probe_host_usb_dev()
            # Restore the kernel of USB stick which is corrupted on setup phase.
            self.restore_usb_kernel(usb_dev)
        except Exception as e:
            logging.error("Caught exception: %s", str(e))
        super(firmware_FwScreenPressPower, self).cleanup()

    def run_once(self):
        """Main test logic"""
        if self.faft_config.mode_switcher_type not in (
                'keyboard_dev_switcher', 'tablet_detachable_switcher',
                'menu_switcher'):
            raise error.TestNAError("This test is only valid on devices with "
                                    "screens.")
        if not self.faft_config.has_powerbutton:
            raise error.TestNAError("This test is only valid on devices with "
                                    "power button.")

        logging.info(
                "Expected dev mode and reboot. "
                "When the next DEVELOPER SCREEN shown, press power button "
                "to make DUT shutdown.")
        self.check_state((self.checkers.crossystem_checker, {
                'devsw_boot': '1',
                'mainfw_type': 'developer',
        }))
        self.switcher.simple_reboot()
        self.run_shutdown_process(
                self.wait_fw_screen_and_press_power,
                post_power_action=self.switcher.bypass_dev_mode)
        self.switcher.wait_for_client()

        if self.faft_config.power_button_dev_switch:
            logging.info("Skipping TO_NORM screen test. The power button is "
                         "used to confirm DEV mode to NORM mode.")
        else:
            logging.info(
                    "Reboot. When the developer screen shown, press "
                    "enter key to trigger either TO_NORM screen (new) or "
                    "RECOVERY INSERT screen (old). Then press power button "
                    "to make DUT shutdown.")
            self.check_state((self.checkers.crossystem_checker, {
                    'devsw_boot': '1',
                    'mainfw_type': 'developer',
            }))
            self.switcher.simple_reboot()
            self.run_shutdown_process(
                    self.wait_second_screen_and_press_power,
                    post_power_action=self.switcher.bypass_dev_mode,
                    shutdown_timeout=self.SHORT_SHUTDOWN_CONFIRMATION_PERIOD)
            self.switcher.wait_for_client()

        logging.info("Request recovery boot. When the RECOVERY INSERT "
                     "screen shows, press power button to make DUT shutdown.")
        self.check_state((self.checkers.crossystem_checker, {
                'devsw_boot': '1',
                'mainfw_type': 'developer',
        }))
        self.servo.set_nocheck('power_state', 'rec')
        self.run_shutdown_process(
                self.wait_longer_fw_screen_and_press_power,
                post_power_action=self.switcher.bypass_dev_mode,
                shutdown_timeout=self.SHORT_SHUTDOWN_CONFIRMATION_PERIOD)
        self.switcher.wait_for_client()

        logging.info("Request recovery boot again. When the recovery "
                     "insert screen shows, insert a corrupted USB and trigger "
                     "a YUCK SCREEN. Then press power button to "
                     "make DUT shutdown.")
        self.check_state((self.checkers.crossystem_checker, {
                'devsw_boot': '1',
                'mainfw_type': 'developer',
        }))
        self.servo.set_nocheck('power_state', 'rec')
        self.run_shutdown_process(
                self.wait_yuck_screen_and_press_power,
                post_power_action=self.switcher.bypass_dev_mode,
                shutdown_timeout=self.SHORT_SHUTDOWN_CONFIRMATION_PERIOD)
        self.switcher.wait_for_client()

        logging.info("Switch back to normal mode.")
        self.check_state((self.checkers.crossystem_checker, {
                'devsw_boot': '1',
                'mainfw_type': 'developer',
        }))
        self.switcher.reboot_to_mode(to_mode='normal')

        logging.info("Expected normal mode and request recovery boot. "
                     "Because an USB stick is inserted, a RECOVERY REMOVE "
                     "screen shows. Press power button to make DUT shutdown.")
        self.check_state((self.checkers.crossystem_checker, {
                'devsw_boot': '0',
                'mainfw_type': 'normal',
        }))
        self.servo.set_nocheck('power_state', 'rec')
        self.run_shutdown_process(
                self.wait_longer_fw_screen_and_press_power,
                shutdown_timeout=self.SHORT_SHUTDOWN_CONFIRMATION_PERIOD)
        self.switcher.wait_for_client()

        logging.info("Check and done.")
        self.check_state((self.checkers.crossystem_checker, {
                'devsw_boot': '0',
                'mainfw_type': 'normal',
        }))