# Copyright 2016 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, time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest

# platform_S0ixCycle test timing constants
BEFORE_SUSPEND_WAIT_TIME_SECONDS = 10
BEFORE_RESUME_WAIT_TIME_SECONDS = 2
SUSPEND_WAIT_TIME_SECONDS = 5
LIDOPEN_WAIT_TIME_SECONDS = 2
POWER_STATE_RETRY_COUNT = 10


class platform_S0ixCycle(FirmwareTest):
    '''
    Servo based S0ix cycle test and wake source.
    '''
    version = 1

    def initialize(self, host, cmdline_args):
        dict_args = utils.args_to_dict(cmdline_args)
        self.faft_iterations = int(dict_args.get('faft_iterations', 1))
        super(platform_S0ixCycle, self).initialize(host, cmdline_args)
        self.switcher.setup_mode('normal')

    def perform_s0ix_cycle(self):
        """
        Perform S0ix suspend/resume cycle and check state transition.
        """
        resume_sources = ['powerbtn', 'lid', 'kbpress']
        for resume_source in resume_sources:
            time.sleep(BEFORE_SUSPEND_WAIT_TIME_SECONDS)
            self.perform_suspend()
            self.perform_resume(resume_source)

    def perform_suspend(self):
        """
        Perform suspend to idle and check state transition.
        """
        logging.info('== S0ix suspend and check the state transition ==')
        # check S0ix state transition
        if not self.wait_power_state('S0', POWER_STATE_RETRY_COUNT):
            raise error.TestFail('Platform failed to reach S0 state.')
        cmd = 'echo freeze > /sys/power/state'
        block = False
        self.faft_client.system.run_shell_command(cmd, block)
        time.sleep(SUSPEND_WAIT_TIME_SECONDS)
        # check S0ix state transition
        if not self.wait_power_state('S0ix', POWER_STATE_RETRY_COUNT):
            raise error.TestFail('Platform failed to reach S0ix state.')

    def perform_resume(self, resume_source):
        """
        Perform resume with selected resume source and check state transition.
        @param resume_source(string):resume source option.
        """
        logging.info('== S0ix resume and check the state transition ==')
        time.sleep(BEFORE_RESUME_WAIT_TIME_SECONDS)
        if resume_source == 'powerbtn':
            self.ec.send_command('powerbtn')
        elif resume_source == 'lid':
            self.ec.send_command('lidclose')
            time.sleep(LIDOPEN_WAIT_TIME_SECONDS)
            self.ec.send_command('lidopen')
        elif resume_source == 'kbpress':
            self.ec.key_press('<enter>')
        else:
            raise error.TestFail('Invalid resume source.')
        # check S0 state transition
        if not self.wait_power_state('S0', POWER_STATE_RETRY_COUNT):
            raise error.TestFail('Platform failed to reach S0 state.')

    def is_skl_board(self):
        """
        Check this device is a SKL based ChromeBook.
        """
        skl_boards = ('kunimitsu', 'lars', 'glados', 'chell', 'sentry')
        output = self.faft_client.system.get_platform_name()
        return output.lower() in skl_boards

    def is_s0ix_supported(self):
        """
        Check this device supports suspend to idle.
        """
        cmd = 'cat /var/lib/power_manager/suspend_to_idle'
        output = self.faft_client.system.run_shell_command_get_output(cmd)
        if not output:
            return False
        else:
            return int(output[0]) == 1

    def run_once(self):
        """
        Main test logic
        """
        if not self.faft_config.chrome_ec or not self.check_ec_capability():
            raise error.TestNAError(
                    'Chrome EC is not supported on this device.')

        if not (self.is_skl_board() and self.is_s0ix_supported()):
            raise error.TestNAError(
                    'Suspend to idle is not supported on this device.')

        for i in xrange(self.faft_iterations):
            logging.info('== Running FAFT ITERATION %d/%s ==', i + 1,
                         self.faft_iterations)
            logging.info(
                    'S0ix suspend/resume back and check state transition.')
            # wake the display by key press.
            self.ec.key_press('<enter>')
            self.switcher.mode_aware_reboot('custom', self.perform_s0ix_cycle)

    def cleanup(self):
        """
        Cleanup after test completes
        """
        self.ec.set_uart_regexp('None')
        # Test may failed before resume, wake the system.
        self.ec.send_command('powerbtn')
        # Perform a warm reboot as part of the cleanup.
        self._client.reboot()
        super(platform_S0ixCycle, self).cleanup()
