# Copyright 2018 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 autotest_enum, error
from autotest_lib.server import test
from autotest_lib.server.cros import servo_keyboard_utils
from autotest_lib.server.cros.dark_resume_utils import DarkResumeUtils
from autotest_lib.server.cros.faft.utils.config import Config as FAFTConfig
from autotest_lib.server.cros.power import servo_charger
from autotest_lib.server.cros.servo import chrome_ec


# Possible states base can be forced into.
BASE_STATE = autotest_enum.AutotestEnum('ATTACH', 'DETACH', 'RESET')

# Possible states for tablet mode as defined in common/tablet_mode.c via
# crrev.com/c/1797370.
TABLET_MODE = autotest_enum.AutotestEnum('ON', 'OFF', 'RESET')

# List of wake sources expected to cause a full resume.
FULL_WAKE_SOURCES = [
    'PWR_BTN', 'LID_OPEN', 'BASE_ATTACH', 'BASE_DETACH', 'INTERNAL_KB',
    'USB_KB', 'TABLET_MODE_ON', 'TABLET_MODE_OFF'
]

# List of wake sources expected to cause a dark resume.
DARK_RESUME_SOURCES = ['RTC', 'AC_CONNECTED', 'AC_DISCONNECTED']

# Max time taken by the device to resume. This gives enough time for the device
# to establish network connection with the autotest server
SECS_FOR_RESUMING = 15

# Time in future after which RTC goes off when testing wake due to RTC alarm.
RTC_WAKE_SECS = 20

# Max time taken by the device to suspend. This includes the time powerd takes
# trigger the suspend after receiving the suspend request from autotest script.
SECS_FOR_SUSPENDING = 20

# Time to allow lid transition to take effect.
WAIT_TIME_LID_TRANSITION_SECS = 5

# Time to wait for the DUT to see USB keyboard after restting the Atmega USB
# emulator on Servo.
USB_PRESENT_DELAY = 1


class power_WakeSources(test.test):
    """
    Verify that wakes from input devices can trigger a full
    resume. Currently tests :
        1. power button
        2. lid open
        3. base attach
        4. base detach

    Also tests that dark resume wake sources work as expected, such as:
        1. RTC
        2. AC_CONNECTED
        3. AC_DISCONNECTED

    """
    version = 1

    def _after_resume(self, wake_source):
        """Cleanup to perform after resuming the device.

        @param wake_source: Wake source that has been tested.
        """
        if wake_source in ['BASE_ATTACH', 'BASE_DETACH']:
            self._force_base_state(BASE_STATE.RESET)
        elif wake_source in ['TABLET_MODE_ON', 'TABLET_MODE_OFF']:
            self._force_tablet_mode(TABLET_MODE.RESET)
        elif wake_source in ['AC_CONNECTED', 'AC_DISCONNECTED']:
            self._chg_manager.start_charging()

    def _before_suspend(self, wake_source):
        """Prep before suspend.

        @param wake_source: Wake source that is going to be tested.

        @return: Boolean, whether _before_suspend action is successful.
        """
        if wake_source == 'BASE_ATTACH':
            # Force detach before suspend so that attach won't be ignored.
            self._force_base_state(BASE_STATE.DETACH)
        elif wake_source == 'BASE_DETACH':
            # Force attach before suspend so that detach won't be ignored.
            self._force_base_state(BASE_STATE.ATTACH)
        elif wake_source == 'LID_OPEN':
            # Set the power policy for lid closed action to suspend.
            return self._host.run(
                'set_power_policy --lid_closed_action suspend',
                ignore_status=True).exit_status == 0
        elif wake_source == 'USB_KB':
            # Initialize USB keyboard.
            self._host.servo.set_nocheck('init_usb_keyboard', 'on')
        elif wake_source == 'TABLET_MODE_ON':
            self._force_tablet_mode(TABLET_MODE.OFF)
        elif wake_source == 'TABLET_MODE_OFF':
            self._force_tablet_mode(TABLET_MODE.ON)
        elif wake_source == 'AC_CONNECTED':
            self._chg_manager.stop_charging()
        elif wake_source == 'AC_DISCONNECTED':
            self._chg_manager.start_charging()
        return True

    def _force_tablet_mode(self, mode):
        """Send EC command to force the tablet mode.

        @param mode: mode to force. One of the |TABLET_MODE| enum.
        """
        ec_cmd = 'tabletmode '
        ec_arg = {
            TABLET_MODE.ON: 'on',
            TABLET_MODE.OFF: 'off',
            TABLET_MODE.RESET: 'r'
        }

        ec_cmd += ec_arg[mode]
        self._ec.send_command(ec_cmd)

    def _force_base_state(self, base_state):
        """Send EC command to force the |base_state|.

        @param base_state: State to force base to. One of |BASE_STATE| enum.
        """
        ec_cmd = 'basestate '
        ec_arg = {
            BASE_STATE.ATTACH: 'a',
            BASE_STATE.DETACH: 'd',
            BASE_STATE.RESET: 'r'
        }

        ec_cmd += ec_arg[base_state]
        self._ec.send_command(ec_cmd)

    def _is_valid_wake_source(self, wake_source):
        """Check if |wake_source| is valid for DUT.

        @param wake_source: wake source to verify.
        @return: False if |wake_source| is not valid for DUT, True otherwise
        """
        if wake_source in ['BASE_ATTACH', 'BASE_DETACH']:
            return self._ec.has_command('basestate')
        if wake_source in ['TABLET_MODE_ON', 'TABLET_MODE_OFF']:
            return self._ec.has_command('tabletmode')
        if wake_source == 'LID_OPEN':
            return self._dr_utils.host_has_lid()
        if wake_source == 'INTERNAL_KB':
            return self._faft_config.has_keyboard
        if wake_source == 'USB_KB':
            # Initialize USB keyboard.
            self._host.servo.set_nocheck('init_usb_keyboard', 'on')
            time.sleep(USB_PRESENT_DELAY)
            # Check if DUT can see a wake capable Atmel USB keyboard.
            if servo_keyboard_utils.is_servo_usb_keyboard_present(
                    self._host):
                if servo_keyboard_utils.is_servo_usb_wake_capable(
                        self._host):
                    return True
                else:
                    logging.warning(
                        'Atmel USB keyboard does not have wake capability.'
                        ' Please run firmware_FlashServoKeyboardMap Autotest '
                        'to update the Atmel firmware.')
                    return False
            else:
                logging.warning(
                    'DUT cannot see a Atmel USB keyboard. '
                    ' Please plug in USB C charger into Servo if using V4.')

                return False
        if wake_source in ['AC_CONNECTED', 'AC_DISCONNECTED']:
            if not self._chg_manager:
                logging.warning(
                    'Unable to test AC connect/disconnect with this '
                    'servo setup')
                return False
            # Check both the S0ix and S3 wake masks.
            s0ix_wake_mask = int(self._host.run(
                    'ectool hostevent get %d' %
                    chrome_ec.EC_HOST_EVENT_LAZY_WAKE_MASK_S0IX).stdout,
                                 base=16)
            s3_wake_mask = int(self._host.run(
                    'ectool hostevent get %d' %
                    chrome_ec.EC_HOST_EVENT_LAZY_WAKE_MASK_S3).stdout,
                               base=16)
            wake_mask = s0ix_wake_mask | s3_wake_mask
            if wake_source == 'AC_CONNECTED':
                return wake_mask & chrome_ec.HOSTEVENT_AC_CONNECTED
            if wake_source == 'AC_DISCONNECTED':
                return wake_mask & chrome_ec.HOSTEVENT_AC_DISCONNECTED

        return True

    def _test_wake(self, wake_source, full_wake):
        """Test if |wake_source| triggers a full resume.

        @param wake_source: wake source to test. One of |FULL_WAKE_SOURCES|.
        @return: True, if we are able to successfully test the |wake source|
            triggers a full wake.
        """
        is_success = True
        logging.info(
            'Testing wake by %s triggers a '
            'full wake when dark resume is enabled.', wake_source)
        if not self._before_suspend(wake_source):
            logging.error('Before suspend action failed for %s', wake_source)
            # Still run the _after_resume callback since we can do things like
            # stop charging.
            self._after_resume(wake_source)
            return False

        count_before = self._dr_utils.count_dark_resumes()
        self._dr_utils.suspend(SECS_FOR_SUSPENDING + RTC_WAKE_SECS)
        logging.info('DUT suspended! Waiting to resume...')
        # Wait at least |SECS_FOR_SUSPENDING| secs for the kernel to
        # fully suspend.
        time.sleep(SECS_FOR_SUSPENDING)
        self._trigger_wake(wake_source)
        # Wait at least |SECS_FOR_RESUMING| secs for the device to
        # resume.
        time.sleep(SECS_FOR_RESUMING)

        if not self._host.is_up_fast():
            logging.error(
                    'Device did not resume from suspend for %s.'
                    ' Waking system with power button then RTC.', wake_source)
            self._trigger_wake('PWR_BTN')
            self._after_resume(wake_source)
            if not self._host.is_up():
                raise error.TestFail(
                        'Device failed to wakeup from backup wake sources'
                        ' (power button and RTC).')

            return False

        count_after = self._dr_utils.count_dark_resumes()
        if full_wake:
            if count_before != count_after:
                logging.error('%s incorrectly caused a dark resume.',
                              wake_source)
                is_success = False
            elif is_success:
                logging.info('%s caused a full resume.', wake_source)
        else:
            if count_before == count_after:
                logging.error('%s incorrectly caused a full resume.',
                              wake_source)
                is_success = False
            elif is_success:
                logging.info('%s caused a dark resume.', wake_source)

        self._after_resume(wake_source)
        return is_success

    def _trigger_wake(self, wake_source):
        """Trigger wake using the given |wake_source|.

        @param wake_source : wake_source that is being tested.
            One of |FULL_WAKE_SOURCES|.
        """
        if wake_source == 'PWR_BTN':
            self._host.servo.power_short_press()
        elif wake_source == 'LID_OPEN':
            self._host.servo.lid_close()
            time.sleep(WAIT_TIME_LID_TRANSITION_SECS)
            self._host.servo.lid_open()
        elif wake_source == 'BASE_ATTACH':
            self._force_base_state(BASE_STATE.ATTACH)
        elif wake_source == 'BASE_DETACH':
            self._force_base_state(BASE_STATE.DETACH)
        elif wake_source == 'TABLET_MODE_ON':
            self._force_tablet_mode(TABLET_MODE.ON)
        elif wake_source == 'TABLET_MODE_OFF':
            self._force_tablet_mode(TABLET_MODE.OFF)
        elif wake_source == 'INTERNAL_KB':
            self._host.servo.ctrl_key()
        elif wake_source == 'USB_KB':
            self._host.servo.set_nocheck('usb_keyboard_enter_key', '10')
        elif wake_source == 'RTC':
            # The RTC will wake on its own. We just need to wait
            time.sleep(RTC_WAKE_SECS)
        elif wake_source == 'AC_CONNECTED':
            self._chg_manager.start_charging()
        elif wake_source == 'AC_DISCONNECTED':
            self._chg_manager.stop_charging()

    def cleanup(self):
        """cleanup."""
        self._dr_utils.stop_resuspend_on_dark_resume(False)
        self._dr_utils.teardown()

    def initialize(self, host):
        """Initialize wake sources tests.

        @param host: Host on which the test will be run.
        """
        self._host = host
        self._dr_utils = DarkResumeUtils(host)
        self._dr_utils.stop_resuspend_on_dark_resume()
        self._ec = chrome_ec.ChromeEC(self._host.servo)
        self._faft_config = FAFTConfig(self._host.get_platform())
        self._kstr = host.get_kernel_version()
        # TODO(b/168939843) : Look at implementing AC plug/unplug w/ non-PD RPMs
        # in the lab.
        try:
            self._chg_manager = servo_charger.ServoV4ChargeManager(
                host, host.servo)
        except error.TestNAError:
            logging.warning('Servo does not support AC switching.')
            self._chg_manager = None

    def run_once(self):
        """Body of the test."""

        test_ws = set(
            ws for ws in FULL_WAKE_SOURCES if self._is_valid_wake_source(ws))
        passed_ws = set(ws for ws in test_ws if self._test_wake(ws, True))
        failed_ws = test_ws.difference(passed_ws)
        skipped_ws = set(FULL_WAKE_SOURCES).difference(test_ws)

        test_dark_ws = set(ws for ws in DARK_RESUME_SOURCES
                           if self._is_valid_wake_source(ws))
        skipped_ws.update(set(DARK_RESUME_SOURCES).difference(test_dark_ws))
        for ws in test_dark_ws:
            if self._test_wake(ws, False):
                passed_ws.add(ws)
            else:
                failed_ws.add(ws)

        test_keyval = {}

        for ws in passed_ws:
            test_keyval.update({ws: 'PASS'})
        for ws in failed_ws:
            test_keyval.update({ws: 'FAIL'})
        for ws in skipped_ws:
            test_keyval.update({ws: 'SKIPPED'})
        self.write_test_keyval(test_keyval)

        if passed_ws:
            logging.info('[%s] woke the device as expected.',
                         ''.join(str(elem) + ', ' for elem in passed_ws))

        if skipped_ws:
            logging.info(
                '[%s] are not wake sources on this platform. '
                'Please test manually if not the case.',
                ''.join(str(elem) + ', ' for elem in skipped_ws))

        if failed_ws:
            raise error.TestFail(
                '[%s] wake sources did not behave as expected.' %
                (''.join(str(elem) + ', ' for elem in failed_ws)))
