# 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.RunShellCommand(
                '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.GetPlatformName()
        return output 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.RunShellCommandGetOutput(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()
