# 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, threading, time

from autotest_lib.client.bin import utils
from autotest_lib.client.cros import service_stopper


# List of thermal throttling services that should be disabled.
# - temp_metrics for link.
# - thermal for daisy, snow, pit etc.
# TODO(ihf): cpu_quiet on nyan isn't a service. We still need to disable it
#            on nyan. See crbug.com/357457.
_THERMAL_SERVICES = ['temp_metrics', 'thermal']


class PerfControl(object):
    """
    Provides methods for setting the performance mode of a device.

    In particular it verifies the machine is idle and cold and tries to set
    it into a consistent, high performance state during initialization.

    Furthermore it monitors the state of the machine (in particular
    temperature) and verifies that nothing bad happened along the way.

    Example usage:

    with PerfControl() as pc:
        if not pc.verify_is_valid():
            raise error.TestError(pc.get_error_reason())
        # Do all performance testing.
        ...
        if not pc.verify_is_valid():
            raise error.TestError(pc.get_error_reason())
    """
    def __init__(self):
        # Keep a copy of the current state for cleanup.
        self._temperature_init = self._get_current_temperature_max()
        self._temperature_critical = utils.get_temperature_critical()
        self._original_governors = utils.set_high_performance_mode()
        self._error_reason = None
        if not utils.wait_for_idle_cpu(60.0, 0.1):
            self._error_reason = 'Could not get idle CPU.'
            return
        if not utils.wait_for_cool_machine():
            self._error_reason = 'Could not get cold machine.'
            return
        self._temperature_cold = self._get_current_temperature_max()
        self._temperature_max = self._temperature_cold
        threading.Thread(target=self._monitor_performance_state).start()
        # Should be last just in case we had a runaway process.
        self._service_stopper = None
        self._stop_thermal_throttling()


    def __enter__(self):
        return self


    def __exit__(self, _type, value, traceback):
        # First thing restart thermal management.
        self._restore_thermal_throttling()
        utils.restore_scaling_governor_states(self._original_governors)


    def get_error_reason(self):
        """
        Returns an error reason string if we encountered problems to pass
        on to harness/wmatrix.
        """
        return self._error_reason


    def verify_is_valid(self):
        """
        For now we declare performance results as valid if
        - we did not have an error before.
        - the monitoring thread never saw temperatures too close to critical.

        TODO(ihf): search log files for thermal throttling messages like in
                   src/build/android/pylib/perf/thermal_throttle.py
        """
        if self._error_reason:
            return False
        temperature_bad = (1.0/3.0 * self._temperature_cold +
                           2.0/3.0 * self._temperature_critical)
        logging.info("Max observed temperature = %.1f'C (bad limit = %.1f'C)",
                     self._temperature_max, temperature_bad)
        if (self._temperature_max > temperature_bad):
            _error_reason = 'Machine got hot during testing.'
            return False
        return True


    def _monitor_performance_state(self):
        """
        Checks machine temperature once per second.
        TODO(ihf): make this more intelligent with regards to governor,
                   CPU, GPU and maybe zram as needed.
        """
        while True:
            time.sleep(1)
            current_temperature = self._get_current_temperature_max()
            self._temperature_max = max(self._temperature_max,
                                        current_temperature)
            # TODO(ihf): Remove this spew once PerfControl is stable.
            logging.info('PerfControl CPU temperature = %.1f',
                          current_temperature)

    def _get_current_temperature_max(self):
        """
        Returns the highest reported board temperature (all sensors) in Celsius.
        """
        temperature = utils.get_temperature_input_max()
        ec_temperatures = utils.get_ec_temperatures()
        if ec_temperatures:
            temperature = max(max(ec_temperatures), temperature)
        return temperature


    def _stop_thermal_throttling(self):
        """
        If exist on the platform/machine it stops the different thermal
        throttling scripts from running.
        Warning: this risks abnormal behavior if machine runs in high load.
        """
        self._service_stopper = service_stopper.ServiceStopper(
                                                    _THERMAL_SERVICES)


    def _restore_thermal_throttling(self):
        """
        Restores the original thermal throttling state.
        """
        self._service_stopper.restore_services()
