| # Copyright 2020 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 |
| |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.server.cros.faft.firmware_test import FirmwareTest |
| |
| |
| class BaseMenuNavigator: |
| """Base class for menu navigator.""" |
| |
| def __init__(self, test): |
| self.test = test |
| self.faft_config = self.test.faft_config |
| self.servo = self.test.servo |
| |
| def menu_up(self): |
| """Navigate up in the menu.""" |
| if self.faft_config.is_detachable: |
| self.servo.set_nocheck('volume_up_hold', 100) |
| else: |
| self.servo.arrow_up() |
| |
| def menu_down(self): |
| """Navigate down in the menu.""" |
| if self.faft_config.is_detachable: |
| self.servo.set_nocheck('volume_down_hold', 100) |
| else: |
| self.servo.arrow_down() |
| |
| def menu_select(self, msg=None): |
| """Select a menu item.""" |
| if msg: |
| logging.info(msg) |
| if self.faft_config.is_detachable: |
| self.servo.power_short_press() |
| else: |
| self.servo.enter_key() |
| |
| |
| class LegacyMenuNavigator(BaseMenuNavigator): |
| """Menu navigator for legacy menu UI. |
| |
| The "legacy menu UI" is an old menu-based UI, which has been replaced |
| by the new one, called "menu UI". |
| """ |
| |
| def trigger_rec_to_dev(self): |
| """Trigger to-dev transition.""" |
| self.test.switcher.trigger_rec_to_dev() |
| |
| def dev_boot_from_internal(self): |
| """Boot from internal disk in developer mode. |
| |
| Menu items in developer warning screen: |
| 0. Developer Options |
| 1. Show Debug Info |
| 2. Enable OS Verification |
| *3. Power Off |
| 4. Language |
| |
| (*) is the default selection. |
| """ |
| self.test.wait_for('firmware_screen') |
| for _ in range(3, 0, -1): |
| self.menu_up() |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecting "Developer Options"...') |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecting "Boot From Internal Disk"...') |
| |
| def trigger_dev_to_normal(self): |
| """Trigger dev-to-norm transition. |
| |
| Menu items in developer warning screen: |
| 0. Developer Options |
| 1. Show Debug Info |
| 2. Enable OS Verification |
| *3. Power Off |
| 4. Language |
| |
| Menu items in to-norm confirmation screen: |
| *0. Confirm Enabling OS Verification |
| 1. Cancel |
| 2. Power Off |
| 3. Language |
| |
| (*) is the default selection. |
| """ |
| self.test.wait_for('firmware_screen') |
| for _ in range(3, 2, -1): |
| self.menu_up() |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecting "Enable OS Verification"...') |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecing "Confirm Enabling OS Verification"...') |
| |
| |
| class MenuNavigator(BaseMenuNavigator): |
| """Menu navigator for menu UI. |
| |
| The "menu UI" aims to replace both "legacy clamshell UI" and "legacy |
| menu UI". See chromium:1033815 for the discussion about the naming. |
| """ |
| |
| def _confirm_to_dev(self): |
| if self.faft_config.rec_button_dev_switch: |
| logging.info('Confirm to-dev by RECOVERY button') |
| self.servo.toggle_recovery_switch() |
| elif self.faft_config.power_button_dev_switch: |
| logging.info('Confirm to-dev by POWER button') |
| self.servo.power_normal_press() |
| else: |
| self.menu_select('Confirm to-dev by menu selection') |
| |
| def trigger_rec_to_dev(self): |
| """Trigger to-dev transition. |
| |
| Menu items in recovery select screen: |
| 0. Language |
| 1. Recovery using phone |
| 2. Recovery using external disk |
| 3. Launch diagnostics |
| 4. Advanced options |
| 5. Power off |
| |
| Menu items in advanced options screen: |
| 0. Language |
| *1. Enable developer mode |
| 2. Back |
| 3. Power off |
| |
| Menu items in to-dev screen: |
| 0. Language |
| *1. Confirm |
| 2. Cancel |
| 3. Power off |
| |
| (*) is the default selection. |
| """ |
| self.test.wait_for('firmware_screen') |
| # Since the default selection is unknown, navigate to item 5 first |
| for _ in range(0, 5): |
| self.menu_down() |
| self.test.wait_for('confirm_screen') |
| # Navigate to "Advanced options" |
| self.menu_up() |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecting "Advanced options"...') |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecting "Enable developer mode"...') |
| self.test.wait_for('confirm_screen') |
| # Confirm to-dev transition |
| self._confirm_to_dev() |
| |
| def dev_boot_from_internal(self): |
| """Boot from internal disk in developer mode. |
| |
| Menu items in developer mode screen: |
| 0. Language |
| 1. Return to secure mode |
| 2. Boot from internal disk |
| 3. Boot from external disk |
| 4. Advanced options |
| 5. Power off |
| """ |
| self.test.wait_for('firmware_screen') |
| # Since the default selection is unknown, navigate to item 0 first |
| for _ in range(5, 0, -1): |
| self.menu_up() |
| self.test.wait_for('confirm_screen') |
| # Navigate to "Boot from internal disk" |
| for _ in range(0, 2): |
| self.menu_down() |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecting "Boot from internal disk"...') |
| |
| def trigger_dev_to_normal(self): |
| """Trigger dev-to-norm transition. |
| |
| Menu items in developer mode screen: |
| 0. Language |
| 1. Return to secure mode |
| 2. Boot from internal disk |
| 3. Boot from external disk |
| 4. Advanced options |
| 5. Power off |
| |
| Menu items in to-norm screen: |
| 0. Language |
| *1. Confirm |
| 2. Cancel |
| 3. Power off |
| |
| (*) is the default selection. |
| """ |
| self.test.wait_for('firmware_screen') |
| # Since the default selection is unknown, navigate to item 0 first |
| for _ in range(5, 0, -1): |
| self.menu_up() |
| self.test.wait_for('confirm_screen') |
| # Navigate to "Return to secure mode" |
| self.menu_down() |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecting "Return to secure mode"...') |
| self.test.wait_for('confirm_screen') |
| self.menu_select('Selecing "Confirm"...') |
| |
| |
| class firmware_MenuModeTransition(FirmwareTest): |
| """ |
| Servo based test for manual mode transitions through the UI menu. |
| """ |
| version = 1 |
| |
| def initialize(self, host, cmdline_args, ec_wp=None): |
| super(firmware_MenuModeTransition, self).initialize( |
| host, cmdline_args, ec_wp=ec_wp) |
| self.switcher.setup_mode('normal') |
| self.setup_usbkey(usbkey=False) |
| |
| def run_once(self): |
| """Method which actually runs the test.""" |
| self.check_state((self.checkers.mode_checker, 'normal')) |
| |
| if self.faft_config.mode_switcher_type == 'menu_switcher': |
| navigator = MenuNavigator(self) |
| elif (self.faft_config.mode_switcher_type == |
| 'tablet_detachable_switcher'): |
| navigator = LegacyMenuNavigator(self) |
| else: |
| raise error.TestNAError('Test skipped for menuless UI') |
| |
| # Trigger to-dev by menu navigation |
| logging.info('Trigger to-dev by menu navigation.') |
| self.switcher.enable_rec_mode_and_reboot(usb_state='host') |
| self.switcher.wait_for_client_offline() |
| navigator.trigger_rec_to_dev() |
| |
| # Now the device should be in dev mode screen |
| navigator.dev_boot_from_internal() |
| self.switcher.wait_for_client() |
| |
| logging.info('Expected dev mode boot.') |
| self.check_state((self.checkers.mode_checker, 'dev')) |
| |
| # Trigger to-norm by menu navigation |
| logging.info('Trigger to-norm by menu navigation.') |
| self.switcher.disable_rec_mode_and_reboot() |
| self.switcher.wait_for_client_offline() |
| navigator.trigger_dev_to_normal() |
| self.switcher.wait_for_client() |
| |
| logging.info('Expected normal mode boot, done.') |
| self.check_state((self.checkers.mode_checker, 'normal')) |