# 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.')
        self.faft_client.system.run_shell_command(
                'echo freeze > /sys/power/state &')
        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()
