• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2020 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
6
7from autotest_lib.client.common_lib import error
8from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
9
10
11class BaseMenuNavigator:
12    """Base class for menu navigator."""
13
14    def __init__(self, test):
15        self.test = test
16        self.faft_config = self.test.faft_config
17        self.servo = self.test.servo
18
19    def menu_up(self):
20        """Navigate up in the menu."""
21        if self.faft_config.is_detachable:
22            self.servo.set_nocheck('volume_up_hold', 100)
23        else:
24            self.servo.arrow_up()
25
26    def menu_down(self):
27        """Navigate down in the menu."""
28        if self.faft_config.is_detachable:
29            self.servo.set_nocheck('volume_down_hold', 100)
30        else:
31            self.servo.arrow_down()
32
33    def menu_select(self, msg=None):
34        """Select a menu item."""
35        if msg:
36            logging.info(msg)
37        if self.faft_config.is_detachable:
38            self.servo.power_short_press()
39        else:
40            self.servo.enter_key()
41
42
43class LegacyMenuNavigator(BaseMenuNavigator):
44    """Menu navigator for legacy menu UI.
45
46    The "legacy menu UI" is an old menu-based UI, which has been replaced
47    by the new one, called "menu UI".
48    """
49
50    def trigger_rec_to_dev(self):
51        """Trigger to-dev transition."""
52        self.test.switcher.trigger_rec_to_dev()
53
54    def dev_boot_from_internal(self):
55        """Boot from internal disk in developer mode.
56
57        Menu items in developer warning screen:
58            0. Developer Options
59            1. Show Debug Info
60            2. Enable OS Verification
61           *3. Power Off
62            4. Language
63
64        (*) is the default selection.
65        """
66        self.test.wait_for('firmware_screen')
67        for _ in range(3, 0, -1):
68            self.menu_up()
69            self.test.wait_for('confirm_screen')
70        self.menu_select('Selecting "Developer Options"...')
71        self.test.wait_for('confirm_screen')
72        self.menu_select('Selecting "Boot From Internal Disk"...')
73
74    def trigger_dev_to_normal(self):
75        """Trigger dev-to-norm transition.
76
77        Menu items in developer warning screen:
78            0. Developer Options
79            1. Show Debug Info
80            2. Enable OS Verification
81           *3. Power Off
82            4. Language
83
84        Menu items in to-norm confirmation screen:
85           *0. Confirm Enabling OS Verification
86            1. Cancel
87            2. Power Off
88            3. Language
89
90        (*) is the default selection.
91        """
92        self.test.wait_for('firmware_screen')
93        for _ in range(3, 2, -1):
94            self.menu_up()
95            self.test.wait_for('confirm_screen')
96        self.menu_select('Selecting "Enable OS Verification"...')
97        self.test.wait_for('confirm_screen')
98        self.menu_select('Selecing "Confirm Enabling OS Verification"...')
99
100
101class MenuNavigator(BaseMenuNavigator):
102    """Menu navigator for menu UI.
103
104    The "menu UI" aims to replace both "legacy clamshell UI" and "legacy
105    menu UI". See chromium:1033815 for the discussion about the naming.
106    """
107
108    def _confirm_to_dev(self):
109        if self.faft_config.rec_button_dev_switch:
110            logging.info('Confirm to-dev by RECOVERY button')
111            self.servo.toggle_recovery_switch()
112        elif self.faft_config.power_button_dev_switch:
113            logging.info('Confirm to-dev by POWER button')
114            self.servo.power_normal_press()
115        else:
116            self.menu_select('Confirm to-dev by menu selection')
117
118    def trigger_rec_to_dev(self):
119        """Trigger to-dev transition.
120
121        Menu items in recovery select screen:
122            0. Language
123            1. Recovery using phone
124            2. Recovery using external disk
125            3. Launch diagnostics
126            4. Advanced options
127            5. Power off
128
129        Menu items in advanced options screen:
130            0. Language
131           *1. Enable developer mode
132            2. Back
133            3. Power off
134
135        Menu items in to-dev screen:
136            0. Language
137           *1. Confirm
138            2. Cancel
139            3. Power off
140
141        (*) is the default selection.
142        """
143        self.test.wait_for('firmware_screen')
144        # Since the default selection is unknown, navigate to item 5 first
145        for _ in range(0, 5):
146            self.menu_down()
147            self.test.wait_for('confirm_screen')
148        # Navigate to "Advanced options"
149        self.menu_up()
150        self.test.wait_for('confirm_screen')
151        self.menu_select('Selecting "Advanced options"...')
152        self.test.wait_for('confirm_screen')
153        self.menu_select('Selecting "Enable developer mode"...')
154        self.test.wait_for('confirm_screen')
155        # Confirm to-dev transition
156        self._confirm_to_dev()
157
158    def dev_boot_from_internal(self):
159        """Boot from internal disk in developer mode.
160
161        Menu items in developer mode screen:
162            0. Language
163            1. Return to secure mode
164            2. Boot from internal disk
165            3. Boot from external disk
166            4. Advanced options
167            5. Power off
168        """
169        self.test.wait_for('firmware_screen')
170        # Since the default selection is unknown, navigate to item 0 first
171        for _ in range(5, 0, -1):
172            self.menu_up()
173            self.test.wait_for('confirm_screen')
174        # Navigate to "Boot from internal disk"
175        for _ in range(0, 2):
176            self.menu_down()
177            self.test.wait_for('confirm_screen')
178        self.menu_select('Selecting "Boot from internal disk"...')
179
180    def trigger_dev_to_normal(self):
181        """Trigger dev-to-norm transition.
182
183        Menu items in developer mode screen:
184            0. Language
185            1. Return to secure mode
186            2. Boot from internal disk
187            3. Boot from external disk
188            4. Advanced options
189            5. Power off
190
191        Menu items in to-norm screen:
192            0. Language
193           *1. Confirm
194            2. Cancel
195            3. Power off
196
197        (*) is the default selection.
198        """
199        self.test.wait_for('firmware_screen')
200        # Since the default selection is unknown, navigate to item 0 first
201        for _ in range(5, 0, -1):
202            self.menu_up()
203            self.test.wait_for('confirm_screen')
204        # Navigate to "Return to secure mode"
205        self.menu_down()
206        self.test.wait_for('confirm_screen')
207        self.menu_select('Selecting "Return to secure mode"...')
208        self.test.wait_for('confirm_screen')
209        self.menu_select('Selecing "Confirm"...')
210
211
212class firmware_MenuModeTransition(FirmwareTest):
213    """
214    Servo based test for manual mode transitions through the UI menu.
215    """
216    version = 1
217
218    def initialize(self, host, cmdline_args, ec_wp=None):
219        super(firmware_MenuModeTransition, self).initialize(
220                host, cmdline_args, ec_wp=ec_wp)
221        self.switcher.setup_mode('normal')
222        self.setup_usbkey(usbkey=False)
223
224    def run_once(self):
225        """Method which actually runs the test."""
226        self.check_state((self.checkers.mode_checker, 'normal'))
227
228        if self.faft_config.mode_switcher_type == 'menu_switcher':
229            navigator = MenuNavigator(self)
230        elif (self.faft_config.mode_switcher_type ==
231              'tablet_detachable_switcher'):
232            navigator = LegacyMenuNavigator(self)
233        else:
234            raise error.TestNAError('Test skipped for menuless UI')
235
236        # Trigger to-dev by menu navigation
237        logging.info('Trigger to-dev by menu navigation.')
238        self.switcher.enable_rec_mode_and_reboot(usb_state='host')
239        self.switcher.wait_for_client_offline()
240        navigator.trigger_rec_to_dev()
241
242        # Now the device should be in dev mode screen
243        navigator.dev_boot_from_internal()
244        self.switcher.wait_for_client()
245
246        logging.info('Expected dev mode boot.')
247        self.check_state((self.checkers.mode_checker, 'dev'))
248
249        # Trigger to-norm by menu navigation
250        logging.info('Trigger to-norm by menu navigation.')
251        self.switcher.disable_rec_mode_and_reboot()
252        self.switcher.wait_for_client_offline()
253        navigator.trigger_dev_to_normal()
254        self.switcher.wait_for_client()
255
256        logging.info('Expected normal mode boot, done.')
257        self.check_state((self.checkers.mode_checker, 'normal'))
258