# Copyright 2015 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

DEBOUNCE_STATE = 'debouncing'

class ConnectionError(Exception):
    """Raised on an error of connecting DUT."""
    pass


class _BaseFwBypasser(object):
    """Base class that controls bypass logic for firmware screens."""

    # Duration of holding Volume down button to quickly bypass the developer
    # warning screen in tablets/detachables.
    HOLD_VOL_DOWN_BUTTON_BYPASS = 3

    def __init__(self, faft_framework):
        self.faft_framework = faft_framework
        self.servo = faft_framework.servo
        self.faft_config = faft_framework.faft_config
        self.client_host = faft_framework._client
        self.ec = getattr(faft_framework, 'ec', None)


    def bypass_dev_mode(self):
        """Bypass the dev mode firmware logic to boot internal image."""
        raise NotImplementedError


    def bypass_dev_boot_usb(self):
        """Bypass the dev mode firmware logic to boot USB."""
        raise NotImplementedError


    def bypass_rec_mode(self):
        """Bypass the rec mode firmware logic to boot USB."""
        raise NotImplementedError


    def trigger_dev_to_rec(self):
        """Trigger to the rec mode from the dev screen."""
        raise NotImplementedError


    def trigger_rec_to_dev(self):
        """Trigger to the dev mode from the rec screen."""
        raise NotImplementedError


    def trigger_dev_to_normal(self):
        """Trigger to the normal mode from the dev screen."""
        raise NotImplementedError


    # This is used as a workaround of a bug in RO - DUT does not supply
    # Vbus when in SRC_ACCESSORY state (we set servo to snk before booting
    # to recovery due to the assumption of no PD in RO). It causes that DUT can
    # not see USB Stick in recovery mode(RO) despite being DFP(b/159938441).
    # The bug in RO has been fixed in 251212fb.
    # Some boards already have it in RO, so the issue does not appear
    def check_vbus_and_pd_state(self):
        """Perform PD power and data swap, if DUT is SRC and doesn't supply
        Vbus"""
        if self.ec and self.faft_config.ec_ro_vbus_bug:
            time.sleep(self.faft_framework.PD_RESYNC_DELAY)
            servo_pr_role = self.servo.get('servo_v4_role')
            if servo_pr_role == 'snk':
                mv = self.servo.get('vbus_voltage')
                # Despite the faft_config, make sure the issue occurs -
                # servo is snk and vbus is not supplied.
                if mv < self.servo.VBUS_THRESHOLD:
                    # Make servo SRC to supply Vbus correctly
                    self.servo.set_servo_v4_role('src')
                    time.sleep(self.faft_framework.PD_RESYNC_DELAY)
            # After reboot, EC can be UFP so check that
            if not self.ec.is_dfp():
                # EC is UFP, perform PD Data Swap
                self.ec.send_command("pd 0 swap data")
                time.sleep(self.faft_framework.PD_RESYNC_DELAY)
                # Make sure EC is DFP now
                if not self.ec.is_dfp():
                    # EC is still UFP
                    raise error.TestError('DUT is not DFP in recovery mode.')


class _KeyboardBypasser(_BaseFwBypasser):
    """Controls bypass logic via keyboard shortcuts for menu UI."""

    def bypass_dev_mode(self):
        """Bypass the dev mode firmware logic to boot internal image.

        Press Ctrl-D repeatedly. To obtain a low firmware boot time, pressing
        Ctrl+D for every half second until firmware_screen delay has been
        reached.
        """
        logging.info("Pressing Ctrl-D.")
        # At maximum, device waits for twice of firmware_screen delay to
        # bypass the Dev screen.
        timeout = time.time() + (self.faft_config.firmware_screen * 2)
        while time.time() < timeout:
            self.servo.ctrl_d()
            time.sleep(0.5)
            if self.client_host.ping_wait_up(timeout=0.1):
                break


    def bypass_dev_boot_usb(self):
        """Bypass the dev mode firmware logic to boot USB."""
        self.faft_framework.wait_for('firmware_screen', 'Pressing ctrl+u')
        self.servo.ctrl_u()


    def bypass_dev_default_boot(self):
        """Bypass the dev mode firmware logic to boot from default target."""
        self.faft_framework.wait_for('firmware_screen', 'Pressing enter')
        self.servo.enter_key()


    def bypass_rec_mode(self):
        """Bypass the rec mode firmware logic to boot USB."""
        self.servo.switch_usbkey('host')
        self.faft_framework.wait_for('usb_plug', 'Switching usb key to DUT')
        self.check_vbus_and_pd_state()
        self.servo.switch_usbkey('dut')
        logging.info('Enabled dut_sees_usb')
        if not self.client_host.ping_wait_up(
                timeout=self.faft_config.delay_reboot_to_ping):
            logging.info('ping timed out, try REC_ON')
            psc = self.servo.get_power_state_controller()
            psc.power_on(psc.REC_ON)
            # Check Vbus after reboot again
            self.check_vbus_and_pd_state()


    def trigger_dev_to_rec(self):
        """Trigger to the to-norm screen from the dev screen."""
        self.faft_framework.wait_for('firmware_screen', 'Pressing ctrl+s')
        self.servo.ctrl_s()


    def trigger_rec_to_dev(self):
        """Trigger to the dev mode from the rec screen."""
        self.faft_framework.wait_for('firmware_screen', 'Pressing ctrl+d')
        self.servo.ctrl_d()
        self.faft_framework.wait_for('confirm_screen', 'Pressing button to switch to dev mode')
        if self.faft_config.rec_button_dev_switch:
            logging.info('RECOVERY button pressed to switch to dev mode')
            self.servo.toggle_recovery_switch()
        elif self.faft_config.power_button_dev_switch:
            logging.info('POWER button pressed to switch to dev mode')
            self.servo.power_normal_press()
        else:
            logging.info('ENTER pressed to switch to dev mode')
            self.servo.enter_key()


    def trigger_dev_to_normal(self):
        """Trigger to the normal mode from the dev screen."""
        # Navigate to to-norm screen
        self.faft_framework.wait_for('firmware_screen', 'Pressing ctrl+s')
        self.servo.ctrl_s()
        # Select "Confirm"
        self.faft_framework.wait_for('confirm_screen', 'Pressing enter')
        self.servo.enter_key()


class _LegacyKeyboardBypasser(_KeyboardBypasser):
    """Controls bypass logic via keyboard shortcuts for legacy clamshell UI."""

    def trigger_dev_to_rec(self):
        """Trigger to the to-norm screen from the dev screen."""
        self.faft_framework.wait_for('firmware_screen', 'Pressing enter')
        self.servo.enter_key()

    def trigger_dev_to_normal(self):
        """Trigger to the normal mode from the dev screen."""
        self.faft_framework.wait_for('firmware_screen', 'Pressing enter')
        self.servo.enter_key()
        self.faft_framework.wait_for('confirm_screen', 'Pressing enter')
        self.servo.enter_key()


class _JetstreamBypasser(_BaseFwBypasser):
    """Controls bypass logic of Jetstream devices."""

    def bypass_dev_mode(self):
        """Bypass the dev mode firmware logic to boot internal image."""
        # Jetstream does nothing to bypass.
        pass


    def bypass_dev_boot_usb(self):
        """Bypass the dev mode firmware logic to boot USB."""
        self.servo.switch_usbkey('dut')
        self.faft_framework.wait_for('firmware_screen', 'Toggling development switch')
        self.servo.toggle_development_switch()


    def bypass_rec_mode(self):
        """Bypass the rec mode firmware logic to boot USB."""
        self.servo.switch_usbkey('host')
        self.faft_framework.wait_for('usb_plug', 'Switching usb key to DUT')
        self.check_vbus_and_pd_state()
        self.servo.switch_usbkey('dut')
        if not self.client_host.ping_wait_up(
                timeout=self.faft_config.delay_reboot_to_ping):
            psc = self.servo.get_power_state_controller()
            psc.power_on(psc.REC_ON)
            # Check Vbus after reboot again
            self.check_vbus_and_pd_state()


    def trigger_dev_to_rec(self):
        """Trigger to the rec mode from the dev screen."""
        # Jetstream does not have this triggering logic.
        raise NotImplementedError


    def trigger_rec_to_dev(self):
        """Trigger to the dev mode from the rec screen."""
        self.servo.disable_development_mode()
        self.faft_framework.wait_for('firmware_screen', 'Toggling development switch')
        self.servo.toggle_development_switch()


    def trigger_dev_to_normal(self):
        """Trigger to the normal mode from the dev screen."""
        # Jetstream does not have this triggering logic.
        raise NotImplementedError


class _TabletDetachableBypasser(_BaseFwBypasser):
    """Controls bypass logic of tablet/ detachable chromebook devices."""

    def set_button(self, button, duration, info):
        """Helper method that sets the button hold time for UI selections"""
        self.servo.set_nocheck(button, duration)
        self.faft_framework.wait_for('confirm_screen')
        logging.info(info)


    def bypass_dev_boot_usb(self):
        """Bypass the dev mode firmware logic to boot USB.

        On tablets/ detachables, recovery entered by pressing pwr, vol up
        & vol down buttons for 10s.
           Menu options seen in DEVELOPER WARNING screen:
                 Developer Options
                 Show Debug Info
                 Enable Root Verification
                 Power Off*
                 Language
           Menu options seen in DEV screen:
                 Boot legacy BIOS
                 Boot USB image
                 Boot developer image*
                 Cancel
                 Power off
                 Language

        Vol up button selects previous item, vol down button selects
        next item and pwr button selects current activated item.

        Note: if dev_default_boot=usb, the default selection will start on USB,
        and this will move up one to legacy boot instead.
        """
        self.trigger_dev_screen()
        self.faft_framework.wait_for('firmware_screen', 'Pressing volume up')
        self.set_button('volume_up_hold', 100, ('Selecting power as'
                        ' enter key to select Boot USB Image'))
        self.servo.power_short_press()

    def bypass_dev_default_boot(self):
        """Open the Developer Options menu, and accept the default boot device

           Menu options seen in DEVELOPER WARNING screen:
                 Developer Options
                 Show Debug Info
                 Enable Root Verification
                 Power Off*
                 Language
           Menu options seen in DEV screen:
                 Boot legacy BIOS*      (default if dev_default_boot=legacy)
                 Boot USB image*        (default if dev_default_boot=usb)
                 Boot developer image*  (default if dev_default_boot=disk)
                 Cancel
                 Power off
                 Language

        Vol up button selects previous item, vol down button selects
        next item and pwr button selects current activated item.
        """
        self.trigger_dev_screen()
        self.faft_framework.wait_for('firmware_screen', 'Pressing power button')
        logging.info('Selecting power as enter key to accept the default'
                     ' boot option.')
        self.servo.power_short_press()

    def bypass_rec_mode(self):
        """Bypass the rec mode firmware logic to boot USB."""
        self.servo.switch_usbkey('host')
        self.faft_framework.wait_for('usb_plug', 'Switching usb key to DUT')
        self.check_vbus_and_pd_state()
        self.servo.switch_usbkey('dut')
        logging.info('Enabled dut_sees_usb')
        if not self.client_host.ping_wait_up(
                timeout=self.faft_config.delay_reboot_to_ping):
            logging.info('ping timed out, try REC_ON')
            psc = self.servo.get_power_state_controller()
            psc.power_on(psc.REC_ON)
            # Check Vbus after reboot again
            self.check_vbus_and_pd_state()


    def bypass_dev_mode(self):
        """Bypass the developer warning screen immediately to boot into
        internal disk.

        On tablets/detachables, press & holding the Volume down button for
        3-seconds will quickly bypass the developer warning screen.
        """
        # Unit for the "volume_down_hold" console command is msec.
        duration = (self.HOLD_VOL_DOWN_BUTTON_BYPASS + 0.1) * 1000
        logging.info("Press and hold volume down button for %.1f seconds to "
                     "immediately bypass the Developer warning screen.",
                     self.HOLD_VOL_DOWN_BUTTON_BYPASS + 0.1)
        # At maximum, device waits for twice of firmware_screen delay to
        # bypass the Dev screen.
        timeout = time.time() + (self.faft_config.firmware_screen * 2)
        # To obtain a low firmware boot time, volume_down button pressed for
        # every 3.1 seconds until firmware_screen delay has been reached.
        while time.time() < timeout:
            self.servo.set_nocheck('volume_down_hold', duration)
            # After pressing 'volume_down_hold' button, wait for 0.1 seconds
            # before start pressing the button for next iteration.
            time.sleep(0.1)
            if self.client_host.ping_wait_up(timeout=0.1):
                break


    def trigger_dev_screen(self):
        """Helper method that transitions from DEVELOPER WARNING to DEV screen

           Menu options seen in DEVELOPER WARNING screen:
                 Developer Options
                 Show Debug Info
                 Enable Root Verification
                 Power Off*
                 Language
           Menu options seen in DEV screen:
                 Boot legacy BIOS
                 Boot USB image
                 Boot developer image*
                 Cancel
                 Power off
                 Language
        Vol up button selects previous item, vol down button selects
        next item and pwr button selects current activated item.
        """
        self.faft_framework.wait_for('firmware_screen', 'Pressing volume up')
        self.servo.set_nocheck('volume_up_hold', 100)
        self.faft_framework.wait_for('confirm_screen', 'Pressing volume up')
        self.servo.set_nocheck('volume_up_hold', 100)
        self.faft_framework.wait_for('confirm_screen', 'Pressing volume up')
        self.set_button('volume_up_hold', 100, ('Selecting power '
                        'as enter key to select Developer Options'))
        self.servo.power_short_press()


    def trigger_rec_to_dev(self):
        """Trigger to the dev mode from the rec screen using vol up button.

        On tablets/ detachables, recovery entered by pressing pwr, vol up
        & vol down buttons for 10s. TO_DEV screen is entered by pressing
        vol up & vol down buttons together on the INSERT screen.
           Menu options seen in TO_DEV screen:
                 Confirm enabling developer mode
                 Cancel*
                 Power off
                 Language
        Vol up button selects previous item, vol down button selects
        next item and pwr button selects current activated item.
        """
        self.faft_framework.wait_for('firmware_screen', 'Pressing volume up + volume down')
        self.set_button('volume_up_down_hold', 100, ('Enter Recovery Menu.'))
        self.faft_framework.wait_for('confirm_screen', 'Pressing volume up')
        self.set_button('volume_up_hold', 100, ('Selecting power as '
                        'enter key to select Confirm Enabling Developer Mode'))
        self.servo.power_short_press()
        self.faft_framework.wait_for('firmware_screen')


    def trigger_dev_to_normal(self):
        """Trigger to the normal mode from the dev screen.

           Menu options seen in DEVELOPER WARNING screen:
                 Developer Options
                 Show Debug Info
                 Enable Root Verification
                 Power Off*
                 Language
           Menu options seen in TO_NORM screen:
                 Confirm Enabling Verified Boot*
                 Cancel
                 Power off
                 Language
        Vol up button selects previous item, vol down button selects
        next item and pwr button selects current activated item.
        """
        self.faft_framework.wait_for('firmware_screen', 'Pressing volume up')
        self.set_button('volume_up_hold', 100, ('Selecting '
                        'Enable Root Verification using pwr '
                        'button to enter TO_NORM screen'))
        self.servo.power_short_press()
        logging.info('Transitioning from DEV to TO_NORM screen.')
        self.faft_framework.wait_for('firmware_screen', 'Pressing power button')
        logging.info('Selecting Confirm Enabling Verified '
                        'Boot using pwr button in '
                        'TO_NORM screen')
        self.servo.power_short_press()

    def trigger_dev_to_rec(self):
        """Trigger to the TO_NORM screen from the dev screen.
           Menu options seen in DEVELOPER WARNING screen:
                 Developer Options
                 Show Debug Info
                 Enable Root Verification
                 Power Off*
                 Language
           Menu options seen in TO_NORM screen:
                 Confirm Enabling Verified Boot*
                 Cancel
                 Power off
                 Language
        Vol up button selects previous item, vol down button selects
        next item and pwr button selects current activated item.
        """
        self.faft_framework.wait_for('firmware_screen', 'Pressing volume up')
        self.set_button('volume_up_hold', 100, ('Selecting '
                        'Enable Root Verification using pwr '
                        'button to enter TO_NORM screen'))
        self.servo.power_short_press()
        logging.info('Transitioning from DEV to TO_NORM screen.')
        self.faft_framework.wait_for('firmware_screen', 'Pressing volume down')

        # In firmware_FwScreenPressPower, test will power off the DUT using
        # Power button in second screen (TO_NORM screen) so scrolling to
        # Power-off is necessary in this case. Hence scroll to Power-off as
        # a generic action and wait for next action of either Lid close or
        # power button press.
        self.servo.set_nocheck('volume_down_hold', 100)
        self.faft_framework.wait_for('confirm_screen', 'Pressing volume down')
        self.servo.set_nocheck('volume_down_hold', 100)
        self.faft_framework.wait_for('confirm_screen')


class _BaseModeSwitcher(object):
    """Base class that controls firmware mode switching."""

    HOLD_VOL_DOWN_BUTTON_BYPASS = _BaseFwBypasser.HOLD_VOL_DOWN_BUTTON_BYPASS

    FW_BYPASSER_CLASS = _BaseFwBypasser

    def __init__(self, faft_framework):
        self.faft_framework = faft_framework
        self.client_host = faft_framework._client
        self.faft_client = faft_framework.faft_client
        self.servo = faft_framework.servo
        self.faft_config = faft_framework.faft_config
        self.checkers = faft_framework.checkers
        self.bypasser = self._create_fw_bypasser()
        self._backup_mode = None

    def _create_fw_bypasser(self):
        """Creates a proper firmware bypasser.

        @rtype: _BaseFwBypasser
        """
        return self.FW_BYPASSER_CLASS(self.faft_framework)

    def setup_mode(self, mode):
        """Setup for the requested mode.

        It makes sure the system in the requested mode. If not, it tries to
        do so.

        @param mode: A string of mode, one of 'normal', 'dev', or 'rec'.
        @raise TestFail: If the system not switched to expected mode after
                         reboot_to_mode.

        """
        if not self.checkers.mode_checker(mode):
            logging.info('System not in expected %s mode. Reboot into it.',
                         mode)
            if self._backup_mode is None:
                # Only resume to normal/dev mode after test, not recovery.
                self._backup_mode = 'dev' if mode == 'normal' else 'normal'
            self.reboot_to_mode(mode)
            if not self.checkers.mode_checker(mode):
                raise error.TestFail('System not switched to expected %s'
                        ' mode after setup_mode.' % mode)

    def restore_mode(self):
        """Restores original dev mode status if it has changed.

        @raise TestFail: If the system not restored to expected mode.
        """
        if (self._backup_mode is not None and
            not self.checkers.mode_checker(self._backup_mode)):
            self.reboot_to_mode(self._backup_mode)
            if not self.checkers.mode_checker(self._backup_mode):
                raise error.TestFail('System not restored to expected %s'
                        ' mode in cleanup.' % self._backup_mode)



    def reboot_to_mode(self, to_mode, from_mode=None, sync_before_boot=True,
                       wait_for_dut_up=True):
        """Reboot and execute the mode switching sequence.

        This method simulates what a user would do to switch between different
        modes of ChromeOS.  Note that the modes are end-states where the OS is
        booted up to the Welcome screen, so it takes care of navigating through
        intermediate steps such as various boot confirmation screens.

        From the user perspective, these are the states (note that there's also
        a rec_force_mrc mode which is like rec mode but forces MRC retraining):

        normal <-----> dev <------ rec
          ^                         ^
          |                         |
          +-------------------------+

        This is the implementation, note that "from_mode" is only used for
        logging purposes.

        Normal <-----> Dev:
          _enable_dev_mode_and_reboot()

        Rec,normal -----> Dev:
          disable_rec_mode_and_reboot()

        Any -----> normal:
          _enable_normal_mode_and_reboot()

        Normal <-----> rec:
          enable_rec_mode_and_reboot(usb_state='dut')

        Normal <-----> rec_force_mrc:
          _enable_rec_mode_force_mrc_and_reboot(usb_state='dut')

        Note that one shouldn't transition to dev again without going through the
        normal mode.  This is because trying to disable os_verification when it's
        already off is not supported by reboot_to_mode.

        @param to_mode: The target mode, one of 'normal', 'dev', or 'rec'.
        @param from_mode: The original mode, optional, one of 'normal, 'dev',
                          or 'rec'.
        @param sync_before_boot: True to sync to disk before booting.
        @param wait_for_dut_up: True to wait DUT online again. False to do the
                                reboot and mode switching sequence only and may
                                need more operations to pass the firmware
                                screen.
        """
        logging.info('-[ModeSwitcher]-[ start reboot_to_mode(%r, %r, %r) ]-',
                     to_mode, from_mode, wait_for_dut_up)

        if from_mode:
            note = 'reboot_to_mode: to=%s, from=%s' % (from_mode, to_mode)
        else:
            note = 'reboot_to_mode: to=%s' % to_mode
        if sync_before_boot:
            lines = self.faft_client.system.run_shell_command_get_output(
                'crossystem')
            logging.debug('-[ModeSwitcher]- crossystem output:\n%s',
                          '\n'.join(lines))
            devsw_cur = self.faft_client.system.get_crossystem_value(
                'devsw_cur')
            note += ', devsw_cur=%s' % devsw_cur
            self.faft_framework.blocking_sync(freeze_for_reset=True)
        note += '.'

        if to_mode == 'rec':
            self.enable_rec_mode_and_reboot(usb_state='dut')

        elif to_mode == 'rec_force_mrc':
            self._enable_rec_mode_force_mrc_and_reboot(usb_state='dut')

        elif to_mode == 'dev':
            self._enable_dev_mode_and_reboot()
            if wait_for_dut_up:
                self.bypass_dev_mode()

        elif to_mode == 'normal':
            self._enable_normal_mode_and_reboot()

        else:
            raise NotImplementedError(
                    'Not supported mode switching from %s to %s' %
                     (str(from_mode), to_mode))

        if wait_for_dut_up:
            self.wait_for_client(retry_power_on=True, note=note)

        logging.info('-[ModeSwitcher]-[ end reboot_to_mode(%r, %r, %r) ]-',
                     to_mode, from_mode, wait_for_dut_up)

    def simple_reboot(self, reboot_type='warm', sync_before_boot=True):
        """Simple reboot method

        Just reboot the DUT using either cold or warm reset.  Does not wait for
        DUT to come back online.  Will wait for test to handle this.

        @param reboot_type: A string of reboot type, 'warm' or 'cold'.
                            If reboot_type != warm/cold, raise exception.
        @param sync_before_boot: True to sync to disk before booting.
                                 If sync_before_boot=False, DUT offline before
                                 calling mode_aware_reboot.
        """
        if reboot_type == 'warm':
            reboot_method = self.servo.get_power_state_controller().warm_reset
        elif reboot_type == 'cold':
            reboot_method = self.servo.get_power_state_controller().reset
        else:
            raise NotImplementedError('Not supported reboot_type: %s',
                                      reboot_type)
        if sync_before_boot:
            boot_id = self.faft_framework.get_bootid()
            self.faft_framework.blocking_sync(freeze_for_reset=True)
        logging.info("-[ModeSwitcher]-[ start simple_reboot(%r) ]-",
                     reboot_type)
        reboot_method()
        if sync_before_boot:
            self.wait_for_client_offline(orig_boot_id=boot_id)
        logging.info("-[ModeSwitcher]-[ end simple_reboot(%r) ]-",
                     reboot_type)

    def mode_aware_reboot(self, reboot_type=None, reboot_method=None,
                          sync_before_boot=True, wait_for_dut_up=True):
        """Uses a mode-aware way to reboot DUT.

        For example, if DUT is in dev mode, it requires pressing Ctrl-D to
        bypass the developer screen.

        @param reboot_type: A string of reboot type, one of 'warm', 'cold', or
                            'custom'. Default is a warm reboot.
        @param reboot_method: A custom method to do the reboot. Only use it if
                              reboot_type='custom'.
        @param sync_before_boot: True to sync to disk before booting.
                                 If sync_before_boot=False, DUT offline before
                                 calling mode_aware_reboot.
        @param wait_for_dut_up: True to wait DUT online again. False to do the
                                reboot only.
        """
        if reboot_type is None or reboot_type == 'warm':
            reboot_method = self.servo.get_power_state_controller().warm_reset
        elif reboot_type == 'cold':
            reboot_method = self.servo.get_power_state_controller().reset
        elif reboot_type != 'custom':
            raise NotImplementedError('Not supported reboot_type: %s',
                                      reboot_type)

        logging.info("-[ModeSwitcher]-[ start mode_aware_reboot(%r, %s, ..) ]-",
                     reboot_type, reboot_method.__name__)
        is_dev = is_rec = is_devsw_boot = False
        if sync_before_boot:
            is_dev = self.checkers.mode_checker('dev')
            is_rec = self.checkers.mode_checker('rec')
            is_devsw_boot = self.checkers.crossystem_checker(
                                               {'devsw_boot': '1'}, True)
            boot_id = self.faft_framework.get_bootid()

            self.faft_framework.blocking_sync(reboot_type != 'custom')
        if is_rec:
            logging.info("-[mode_aware_reboot]-[ is_rec=%s is_dev_switch=%s ]-",
                         is_rec, is_devsw_boot)
        else:
            logging.info("-[mode_aware_reboot]-[ is_dev=%s ]-", is_dev)
        reboot_method()
        if sync_before_boot:
            self.wait_for_client_offline(orig_boot_id=boot_id)
        # Encapsulating the behavior of skipping dev firmware screen,
        # hitting ctrl-D
        # Note that if booting from recovery mode, we can predict the next
        # boot based on the developer switch position at boot (devsw_boot).
        # If devsw_boot is True, we will call bypass_dev_mode after reboot.
        if is_dev or is_devsw_boot:
            self.bypass_dev_mode()
        if wait_for_dut_up:
            self.wait_for_client()
        logging.info("-[ModeSwitcher]-[ end mode_aware_reboot(%r, %s, ..) ]-",
                     reboot_type, reboot_method.__name__)


    def enable_rec_mode_and_reboot(self, usb_state=None):
        """Switch to rec mode and reboot.

        This method emulates the behavior of the old physical recovery switch,
        i.e. switch ON + reboot + switch OFF, and the new keyboard controlled
        recovery mode, i.e. just press Power + Esc + Refresh.

        @param usb_state: A string, one of 'dut', 'host', or 'off'.
        """
        psc = self.servo.get_power_state_controller()
        psc.power_off()
        if usb_state:
            self.servo.switch_usbkey(usb_state)
        psc.power_on(psc.REC_ON)
        self.bypasser.check_vbus_and_pd_state()


    def _enable_rec_mode_force_mrc_and_reboot(self, usb_state=None):
        """Switch to rec mode, enable force mrc cache retraining, and reboot.

        This method emulates the behavior of the old physical recovery switch,
        i.e. switch ON + reboot + switch OFF, and the new keyboard controlled
        recovery mode, i.e. just press Power + Esc + Refresh.

        @param usb_state: A string, one of 'dut', 'host', or 'off'.
        """
        psc = self.servo.get_power_state_controller()
        psc.power_off()
        if usb_state:
            self.servo.switch_usbkey(usb_state)
        psc.power_on(psc.REC_ON_FORCE_MRC)

    def disable_rec_mode_and_reboot(self, usb_state=None):
        """Disable the rec mode and reboot.

        It is achieved by calling power state controller to do a normal
        power on.
        """
        psc = self.servo.get_power_state_controller()
        psc.power_off()
        self.faft_framework.wait_for('ec_boot_to_pwr_button', 'Powering on')
        psc.power_on(psc.REC_OFF)


    def _enable_dev_mode_and_reboot(self):
        """Switch to developer mode and reboot."""
        raise NotImplementedError


    def _enable_normal_mode_and_reboot(self):
        """Switch to normal mode and reboot."""
        raise NotImplementedError


    # Redirects the following methods to FwBypasser
    def bypass_dev_mode(self):
        """Bypass the dev mode firmware logic to boot internal image."""
        logging.info("-[bypass_dev_mode]-")
        self.bypasser.bypass_dev_mode()


    def bypass_dev_boot_usb(self):
        """Bypass the dev mode firmware logic to boot USB."""
        logging.info("-[bypass_dev_boot_usb]-")
        self.bypasser.bypass_dev_boot_usb()


    def bypass_dev_default_boot(self):
        """Bypass the dev mode firmware logic to boot from default target."""
        logging.info("-[bypass_dev_default_boot]-")
        self.bypasser.bypass_dev_default_boot()


    def bypass_rec_mode(self):
        """Bypass the rec mode firmware logic to boot USB."""
        logging.info("-[bypass_rec_mode]-")
        self.bypasser.bypass_rec_mode()


    def trigger_dev_to_rec(self):
        """Trigger to the rec mode from the dev screen."""
        self.bypasser.trigger_dev_to_rec()


    def trigger_rec_to_dev(self):
        """Trigger to the dev mode from the rec screen."""
        self.bypasser.trigger_rec_to_dev()


    def trigger_dev_to_normal(self):
        """Trigger to the normal mode from the dev screen."""
        self.bypasser.trigger_dev_to_normal()


    def wait_for_client(self, timeout=180, retry_power_on=False,
                        debounce_power_state=True, note=''):
        """Wait for the client to come back online.

        New remote processes will be launched if their used flags are enabled.

        @param timeout: Time in seconds to wait for the client SSH daemon to
                        come up.
        @param retry_power_on: Try to power on the DUT if it isn't in S0.
        @param debounce_power_state: Wait until power_state is the same two
                                     times in a row to determine the actual
                                     power_state.
        @param note: Extra note to add to the end of the error text
        @raise ConnectionError: Failed to connect DUT.
        """
        logging.info("-[FAFT]-[ start wait_for_client(%ds) ]---",
                     timeout if retry_power_on else 0)
        # Wait for the system to be powered on before trying the network
        # Skip "None" result because that indicates lack of EC or problem
        # querying the power state.
        current_timer = 0
        self.faft_framework.wait_for('delay_powerinfo_stable',
                                     'checking power state')
        power_state = self.faft_framework.get_power_state()

        # The device may transition between states. Wait until the power state
        # is stable for two seconds before determining the state.
        if debounce_power_state:
            last_state = power_state
            power_state = DEBOUNCE_STATE

        while (timeout > current_timer and
               power_state not in (self.faft_framework.POWER_STATE_S0, None)):
                time.sleep(2)
                current_timer += 2
                power_state = self.faft_framework.get_power_state()

                # If the state changed, debounce it.
                if debounce_power_state and power_state != last_state:
                    last_state = power_state
                    power_state = DEBOUNCE_STATE

                logging.info('power state: %s', power_state)

                # Only power-on the device if it has been consistently out of
                # S0.
                if (retry_power_on and
                    power_state not in (self.faft_framework.POWER_STATE_S0,
                                        None, DEBOUNCE_STATE)):
                    logging.info("-[FAFT]-[ retry powering on the DUT ]---")
                    psc = self.servo.get_power_state_controller()
                    psc.retry_power_on()

        # Use the last state if the device didn't reach a stable state in
        # timeout seconds.
        if power_state == DEBOUNCE_STATE:
            power_state = last_state
        if power_state not in (self.faft_framework.POWER_STATE_S0, None):
            msg = 'DUT unexpectedly down, power state is %s.' % power_state
            if note:
                msg += ' %s' % note
            raise ConnectionError(msg)

        # Wait for the system to respond to ping before attempting ssh
        if not self.client_host.ping_wait_up(timeout):
            logging.warning("-[FAFT]-[ system did not respond to ping ]")
        if self.client_host.wait_up(timeout):
            # Check the FAFT client is avaiable.
            self.faft_client.system.is_available()
            # Stop update-engine as it may change firmware/kernel.
            self.faft_framework.faft_client.updater.stop_daemon()
        else:
            logging.error('wait_for_client() timed out.')
            power_state = self.faft_framework.get_power_state()
            msg = 'DUT is still down unexpectedly.'
            if power_state:
                msg += ' Power state: %s.' % power_state
            if note:
                msg += ' %s' % note
            raise ConnectionError(msg)
        logging.info("-[FAFT]-[ end wait_for_client ]-----")


    def wait_for_client_offline(self, timeout=60, orig_boot_id=None):
        """Wait for the client to come offline.

        @param timeout: Time in seconds to wait the client to come offline.
        @param orig_boot_id: A string containing the original boot id.
        @raise ConnectionError: Failed to wait DUT offline.
        """
        # When running against panther, we see that sometimes
        # ping_wait_down() does not work correctly. There needs to
        # be some investigation to the root cause.
        # If we sleep for 120s before running get_boot_id(), it
        # does succeed. But if we change this to ping_wait_down()
        # there are implications on the wait time when running
        # commands at the fw screens.
        if not self.client_host.ping_wait_down(timeout):
            if orig_boot_id and self.client_host.get_boot_id() != orig_boot_id:
                logging.warn('Reboot done very quickly.')
                return
            raise ConnectionError('DUT is still up unexpectedly')


class _MenuSwitcher(_BaseModeSwitcher):
    """Mode switcher via keyboard shortcuts for menu UI."""

    FW_BYPASSER_CLASS = _KeyboardBypasser

    def _enable_dev_mode_and_reboot(self):
        """Switch to developer mode and reboot."""
        logging.info("Enabling keyboard controlled developer mode")
        # Rebooting EC with rec mode on. Should power on AP.
        # Plug out USB disk for preventing recovery boot without warning
        self.enable_rec_mode_and_reboot(usb_state='host')
        self.wait_for_client_offline()
        self.bypasser.trigger_rec_to_dev()

    def _enable_normal_mode_and_reboot(self):
        """Switch to normal mode and reboot."""
        logging.info("Disabling keyboard controlled developer mode")
        self.disable_rec_mode_and_reboot()
        self.wait_for_client_offline()
        self.bypasser.trigger_dev_to_normal()


class _KeyboardDevSwitcher(_MenuSwitcher):
    """Mode switcher via keyboard shortcuts for legacy clamshell UI."""

    FW_BYPASSER_CLASS = _LegacyKeyboardBypasser


class _JetstreamSwitcher(_BaseModeSwitcher):
    """Mode switcher for Jetstream devices."""

    FW_BYPASSER_CLASS = _JetstreamBypasser

    def _enable_dev_mode_and_reboot(self):
        """Switch to developer mode and reboot."""
        logging.info("Enabling Jetstream developer mode")
        self.enable_rec_mode_and_reboot(usb_state='host')
        self.wait_for_client_offline()
        self.bypasser.trigger_rec_to_dev()

    def _enable_normal_mode_and_reboot(self):
        """Switch to normal mode and reboot."""
        logging.info("Disabling Jetstream developer mode")
        self.servo.disable_development_mode()
        self.enable_rec_mode_and_reboot(usb_state='host')
        self.faft_framework.wait_for('firmware_screen', 'Disabling rec and rebooting')
        self.disable_rec_mode_and_reboot(usb_state='host')


class _TabletDetachableSwitcher(_BaseModeSwitcher):
    """Mode switcher for legacy menu UI."""

    FW_BYPASSER_CLASS = _TabletDetachableBypasser

    def _enable_dev_mode_and_reboot(self):
        """Switch to developer mode and reboot.

        On tablets/ detachables, recovery entered by pressing pwr, vol up
        & vol down buttons for 10s.
           Menu options seen in RECOVERY screen:
                 Enable Developer Mode
                 Show Debug Info
                 Power off*
                 Language
        """
        logging.info('Enabling tablets/detachable recovery mode')
        self.enable_rec_mode_and_reboot(usb_state='host')
        self.wait_for_client_offline()
        self.bypasser.trigger_rec_to_dev()

    def _enable_normal_mode_and_reboot(self):
        """Switch to normal mode and reboot.

           Menu options seen in DEVELOPER WARNING screen:
                 Developer Options
                 Show Debug Info
                 Enable Root Verification
                 Power Off*
                 Language
           Menu options seen in TO_NORM screen:
                 Confirm Enabling Verified Boot
                 Cancel
                 Power off*
                 Language
        Vol up button selects previous item, vol down button selects
        next item and pwr button selects current activated item.
        """
        self.disable_rec_mode_and_reboot()
        self.wait_for_client_offline()
        self.bypasser.trigger_dev_to_normal()


_SWITCHER_CLASSES = {
    'menu_switcher': _MenuSwitcher,
    'keyboard_dev_switcher': _KeyboardDevSwitcher,
    'jetstream_switcher': _JetstreamSwitcher,
    'tablet_detachable_switcher': _TabletDetachableSwitcher,
}


def create_mode_switcher(faft_framework):
    """Creates a proper mode switcher.

    @param faft_framework: The main FAFT framework object.
    """
    switcher_type = faft_framework.faft_config.mode_switcher_type
    switcher_class = _SWITCHER_CLASSES.get(switcher_type, None)
    if switcher_class is None:
        raise NotImplementedError('Not supported mode_switcher_type: %s',
                                  switcher_type)
    else:
        return switcher_class(faft_framework)
