blob: 4c345571abec9ebcd23fd8424022995298781db1 [file] [log] [blame]
# Copyright 2021 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 abc
import logging
from autotest_lib.client.common_lib import error
class _BaseMenuModeSwitcher:
"""Base class for mode switch with menu navigator."""
__metaclass__ = abc.ABCMeta
def __init__(self, faft_framework, menu_navigator):
self.test = faft_framework
self.faft_config = self.test.faft_config
self.servo = self.test.servo
self.menu = menu_navigator
self.minidiag_enabled = self.faft_config.minidiag_enabled
@abc.abstractmethod
def trigger_rec_to_dev(self):
"""Trigger to-dev transition."""
raise NotImplementedError
@abc.abstractmethod
def dev_boot_from_internal(self):
"""Boot from internal disk in developer mode."""
raise NotImplementedError
@abc.abstractmethod
def trigger_dev_to_normal(self):
"""Trigger dev-to-norm transition."""
raise NotImplementedError
class _TabletDetachableMenuModeSwitcher(_BaseMenuModeSwitcher):
"""Mode switcher with 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')
self.menu.move_to(3, 0)
self.menu.select('Selecting "Developer Options"...')
self.test.wait_for('keypress_delay')
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')
self.menu.move_to(3, 2)
self.menu.select('Selecting "Enable OS Verification"...')
self.test.wait_for('keypress_delay')
self.menu.select('Selecing "Confirm Enabling OS Verification"...')
class _MenuModeSwitcher(_BaseMenuModeSwitcher):
"""Mode switcher with 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
self.menu.move_to(0, 5)
# Navigate to "Advanced options"
self.menu.up()
self.test.wait_for('keypress_delay')
self.menu.select('Selecting "Advanced options"...')
self.test.wait_for('keypress_delay')
self.menu.select('Selecting "Enable developer mode"...')
self.test.wait_for('keypress_delay')
# 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
self.menu.move_to(5, 0)
# Navigate to "Boot from internal disk"
self.menu.move_to(0, 2)
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
self.menu.move_to(5, 0)
# Navigate to "Return to secure mode"
self.menu.down()
self.test.wait_for('keypress_delay')
self.menu.select('Selecting "Return to secure mode"...')
self.test.wait_for('keypress_delay')
self.menu.select('Selecing "Confirm"...')
def trigger_rec_to_minidiag(self):
"""
Trigger to-minidiag.
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
"""
# Validity check; this only applicable for minidiag enabled devices.
if not self.minidiag_enabled:
raise error.TestError('Minidiag is not enabled for this board')
self.test.wait_for('firmware_screen')
# Since the default selection is unknown, navigate to item 5 first
self.menu.move_to(0, 5)
# Navigate to "Launch diagnostics"
self.menu.up()
self.test.wait_for('keypress_delay')
self.menu.up()
self.test.wait_for('keypress_delay')
self.menu.select('Selecting "Launch diagnostics"...')
self.test.wait_for('firmware_screen')
def navigate_minidiag_storage(self):
"""
Navigate to storage screen.
Menu items in storage screen:
0. Language
1. Page up (disabled)
2. Page down
3. Back
4. Power off
"""
# Validity check; this only applicable for minidiag enabled devices.
if not self.minidiag_enabled:
raise error.TestError('Minidiag is not enabled for this board')
# From root screen to storage screen
self.menu.select('Selecting "Storage"...')
self.test.wait_for('keypress_delay')
# Since the default selection is unknown, navigate to item 4 first
self.menu.move_to(0, 4)
# Navigate to "Back"
self.menu.up()
self.test.wait_for('keypress_delay')
self.menu.select('Back to minidiag root screen...')
self.test.wait_for('keypress_delay')
def navigate_minidiag_quick_memory_check(self):
"""
Navigate to quick memory test screen.
Menu items in quick memory test screen:
0. Language
1. Page up (disabled)
2. Page down (disabled
3. Back
4. Power off
"""
# Validity check; this only applicable for minidiag enabled devices.
if not self.minidiag_enabled:
raise error.TestError('Minidiag is not enabled for this board')
# From root screen to quick memory test screen
# Since there might be self test items, navigate to the last item first
self.menu.move_to(0, 5)
self.menu.up() # full memory test
self.test.wait_for('keypress_delay')
self.menu.up() # quick memory test
self.test.wait_for('keypress_delay')
self.menu.select('Selecting "Quick memory test"...')
self.test.wait_for('keypress_delay')
# Wait for quick memory test
self.menu.select('Back to minidiag root screen...')
self.test.wait_for('keypress_delay')
def reset_and_leave_minidiag(self):
"""Reset the DUT and normal boot to leave minidiag."""
# Validity check; this only applicable for minidiag enabled devices.
if not self.minidiag_enabled:
raise error.TestError('Minidiag is not enabled for this board')
# Since we want to keep the cbmem log, we need an AP reset and reboot to
# normal mode
if self.test.ec.has_command('apreset'):
logging.info('Trigger apreset')
self.test.ec.send_command('apreset')
else:
raise error.TestError('No apreset support')
self.test.switcher.wait_for_client()
_MENU_MODE_SWITCHER_CLASSES = {
'menu_switcher': _MenuModeSwitcher,
'tablet_detachable_switcher': _TabletDetachableMenuModeSwitcher,
}
def create_menu_mode_switcher(faft_framework, menu_navigator):
"""Create a proper navigator based on its mode switcher type.
@param faft_framework: The main FAFT framework object.
@param menu_navigator: The menu navigator for base logic of navigation.
"""
switcher_type = faft_framework.faft_config.mode_switcher_type
switcher_class = _MENU_MODE_SWITCHER_CLASSES.get(switcher_type, None)
if switcher_class is None:
# Not all devices support menu-based UI, so it is fine to return None.
logging.info('Switcher type %s is menuless, return None',
switcher_type)
return None
return switcher_class(faft_framework, menu_navigator)