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

from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import constants
from autotest_lib.server import autotest

POWER_DIR = '/var/lib/power_manager'
TMP_POWER_DIR = '/tmp/power_manager'
POWER_DEFAULTS = '/usr/share/power_manager/board_specific'

RESUME_CTRL_RETRIES = 3
RESUME_GRACE_PERIOD = 10
XMLRPC_BRINGUP_TIMEOUT_SECONDS = 60
DARK_SUSPEND_MAX_DELAY_TIMEOUT_MILLISECONDS = 60000


class DarkResumeSuspend(object):
    """Context manager which exposes the dark resume-specific suspend
    functionality.

    This is required because using the RTC for a dark resume test will
    cause the system to wake up in dark resume and resuspend, which is
    not what we want. Instead, we suspend indefinitely, but make sure we
    don't leave the DUT asleep by always running code to wake it up via
    servo.
    """


    def __init__(self, proxy, host, suspend_for):
        """Set up for a dark-resume-ready suspend to be carried out using
        |proxy| and for the subsequent wakeup to be carried out using
        |host|.

        @param proxy: a dark resume xmlrpc server proxy object for the DUT
        @param host: a servo host connected to the DUT
        @param suspend_for : If not 0, sets a rtc alarm to wake the system after
            |suspend_for| secs.
        """
        self._client_proxy = proxy
        self._host = host
        self._suspend_for = suspend_for


    def __enter__(self):
        """Suspend the DUT."""
        logging.info('Suspending DUT (in background)...')
        self._client_proxy.suspend_bg_for_dark_resume(self._suspend_for)


    def __exit__(self, exception, value, traceback):
        """Wake up the DUT."""
        logging.info('Waking DUT from server.')
        _wake_dut(self._host)


class DarkResumeUtils(object):
    """Class containing common functionality for tests which exercise dark
    resume pathways. We set up powerd to allow dark resume and also configure
    the suspended devices so that the backchannel can stay up. We can also
    check for the number of dark resumes that have happened in a particular
    suspend request.
    """


    def __init__(self, host, duration=0):
        """Set up powerd preferences so we will properly go into dark resume,
        and still be able to communicate with the DUT.

        @param host: the DUT to set up dark resume for

        """
        self._host = host
        logging.info('Setting up dark resume preferences')

        # Make temporary directory, which will be used to hold
        # temporary preferences. We want to avoid writing into
        # /var/lib so we don't have to save any state.
        logging.debug('Creating temporary powerd prefs at %s', TMP_POWER_DIR)
        host.run('mkdir -p %s' % TMP_POWER_DIR)

        logging.debug('Enabling dark resume')
        host.run('echo 0 > %s/disable_dark_resume' % TMP_POWER_DIR)
        logging.debug('setting max dark suspend delay timeout to %d msecs',
                  DARK_SUSPEND_MAX_DELAY_TIMEOUT_MILLISECONDS)
        host.run('echo %d > %s/max_dark_suspend_delay_timeout_ms',
                 DARK_SUSPEND_MAX_DELAY_TIMEOUT_MILLISECONDS, TMP_POWER_DIR)

        # bind the tmp directory to the power preference directory
        host.run('mount --bind %s %s' % (TMP_POWER_DIR, POWER_DIR))

        logging.debug('Restarting powerd with new settings')
        host.run('stop powerd; start powerd')

        logging.debug('Starting XMLRPC session to watch for dark resumes')
        self._client_proxy = self._get_xmlrpc_proxy()


    def teardown(self):
        """Clean up changes made by DarkResumeUtils."""

        logging.info('Tearing down dark resume preferences')

        logging.debug('Cleaning up temporary powerd bind mounts')
        self._host.run('umount %s' % POWER_DIR)

        logging.debug('Restarting powerd to revert to old settings')
        self._host.run('stop powerd; start powerd')


    def suspend(self, suspend_for=0):
        """
        Returns a DarkResumeSuspend context manager that allows safe
        suspending of the DUT.
        @param suspend_for : If not 0, sets a rtc alarm to wake the system after
            |suspend_for| secs.
        """
        return DarkResumeSuspend(self._client_proxy, self._host, suspend_for)


    def stop_resuspend_on_dark_resume(self, stop_resuspend=True):
        """
        If |stop_resuspend| is True, stops re-suspend on seeing a dark resume.
        """
        self._client_proxy.set_stop_resuspend(stop_resuspend)


    def count_dark_resumes(self):
        """Return the number of dark resumes that have occurred since the beginning
        of the test. This will wake up the DUT, so make sure to put it back to
        sleep if you need to keep it suspended for some reason.

        This method will raise an error if the DUT does not wake up.

        @return the number of dark resumes counted by this DarkResumeUtils

        """
        _wake_dut(self._host)

        return self._client_proxy.get_dark_resume_count()



    def host_has_lid(self):
        """Returns True if the DUT has a lid."""
        return self._client_proxy.has_lid()


    def _get_xmlrpc_proxy(self):
        """Get a dark resume XMLRPC proxy for the host this DarkResumeUtils is
        attached to.

        The returned object has no particular type.  Instead, when you call
        a method on the object, it marshalls the objects passed as arguments
        and uses them to make RPCs on the remote server.  Thus, you should
        read dark_resume_xmlrpc_server.py to find out what methods are supported.

        @return proxy object for remote XMLRPC server.

        """
        # Make sure the client library is on the device so that the proxy
        # code is there when we try to call it.
        client_at = autotest.Autotest(self._host)
        client_at.install()
        # Start up the XMLRPC proxy on the client
        proxy = self._host.rpc_server_tracker.xmlrpc_connect(
                constants.DARK_RESUME_XMLRPC_SERVER_COMMAND,
                constants.DARK_RESUME_XMLRPC_SERVER_PORT,
                command_name=
                    constants.DARK_RESUME_XMLRPC_SERVER_CLEANUP_PATTERN,
                ready_test_name=
                    constants.DARK_RESUME_XMLRPC_SERVER_READY_METHOD,
                timeout_seconds=XMLRPC_BRINGUP_TIMEOUT_SECONDS)
        return proxy


def _wake_dut(host):
    """
    Make sure |host| is up by pressing power button.

    @raises error.TestFail: If we cannot wake the |host| up. This means the
            DUT has to be woken up manually. Should not happen mostly.
    """
    woken = False
    for i in range(RESUME_CTRL_RETRIES):
        # Check before pressing the power button. Or you might suspend/shutdown
        # the system if already in S0.
        if host.wait_up(timeout=RESUME_GRACE_PERIOD):
            woken = True
            break
        logging.debug('Wake attempt #%d ', i+1)
        host.servo.power_short_press()

    if not woken:
        logging.warning('DUT did not wake -- trouble ahead')
        raise error.TestFail('DUT did not wake')
