# 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, os, re, struct, time

from autotest_lib.client.bin import test
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.cros import cros_logging

# Kernel 3.8 to 3.14 has cur_delay_info, 3.18+ has frequency_info.
CLOCK_PATHS = [
    '/sys/kernel/debug/dri/0/i915_frequency_info',
    '/sys/kernel/debug/dri/0/i915_cur_delayinfo'
]
# Kernel 3.8 has i915_fbc, kernel > 3.8 i915_fbc_status.
FBC_PATHS = [
    '/sys/kernel/debug/dri/0/i915_fbc',
    '/sys/kernel/debug/dri/0/i915_fbc_status'
]
GEM_PATHS = ['/sys/kernel/debug/dri/0/i915_gem_active']
PSR_PATHS = ['/sys/kernel/debug/dri/0/i915_edp_psr_status']
RC6_PATHS = ['/sys/kernel/debug/dri/0/i915_drpc_info']


class graphics_Idle(test.test):
    """Class for graphics_Idle.  See 'control' for details."""
    version = 1
    _gpu_type = None
    _cpu_type = None
    _board = None
    _failures = 0

    def cleanup(self):
        self.output_perf_value(
            description='Failures',
            value=self._failures,
            units='count',
            higher_is_better=False
        )

    def run_once(self, arc_mode=None):
        # We use kiosk mode to make sure Chrome is idle.
        self._failures += 1
        with chrome.Chrome(
                logged_in=False, extra_browser_args=['--kiosk'],
                arc_mode=arc_mode):
            # Try to protect against runaway previous tests.
            if not utils.wait_for_idle_cpu(20.0, 0.1):
                logging.warning('Could not get idle CPU before running tests.')
            self._gpu_type = utils.get_gpu_family()
            self._cpu_type = utils.get_cpu_soc_family()
            self._board = utils.get_board()
            errors = ''
            errors += self.verify_graphics_dvfs()
            errors += self.verify_graphics_fbc()
            errors += self.verify_graphics_psr()
            errors += self.verify_graphics_gem_idle()
            errors += self.verify_graphics_i915_min_clock()
            errors += self.verify_graphics_rc6()
            errors += self.verify_lvds_downclock()
            errors += self.verify_short_blanking()
            if errors:
                raise error.TestFail('Failed: %s' % errors)
        self._failures -= 1

    def get_valid_path(self, paths):
        for path in paths:
            if os.path.exists(path):
                return path
        logging.error('Error: %s not found.', ' '.join(paths))
        return None

    def handle_error(self, message, path=None):
        logging.error('Error: %s', message)
        # For debugging show the content of the file.
        if path is not None:
            with open(path, 'r') as text_file:
                logging.info('Content of %s\n%s', path, text_file.read())
        # Dump the output of 'top'.
        utils.log_process_activity()
        return message

    def verify_lvds_downclock(self):
        """On systems which support LVDS downclock, checks the kernel log for
        a message that an LVDS downclock mode has been added."""
        logging.info('Running verify_lvds_downclock')
        board = utils.get_board()
        if not (board == 'alex' or board == 'lumpy' or board == 'stout'):
            return ''
        # Get the downclock message from the logs.
        reader = cros_logging.LogReader()
        reader.set_start_by_reboot(-1)
        if not reader.can_find('Adding LVDS downclock mode'):
            return self.handle_error('LVDS downclock quirk not applied. ')
        return ''

    def verify_short_blanking(self):
        """On baytrail systems with a known panel, checks the kernel log for a
        message that a short blanking mode has been added."""
        logging.info('Running verify_short_blanking')
        if self._gpu_type != 'baytrail' or utils.has_no_monitor():
            return ''

        # Open the EDID to find the panel model.
        param_path = '/sys/class/drm/card0-eDP-1/edid'
        if not os.path.exists(param_path):
            logging.error('Error: %s not found.', param_path)
            return self.handle_error(
                'Short blanking not added (no EDID found). ')

        with open(param_path, 'r') as edp_edid_file:
            edp_edid_file.seek(8)
            data = edp_edid_file.read(2)
            manufacturer = int(struct.unpack('<H', data)[0])
            data = edp_edid_file.read(2)
            product_code = int(struct.unpack('<H', data)[0])
        # This is not the panel we are looking for (AUO B116XTN02.2)
        if manufacturer != 0xaf06 or product_code != 0x225c:
            return ''
        # Get the downclock message from the logs.
        reader = cros_logging.LogReader()
        reader.set_start_by_reboot(-1)
        if not reader.can_find('Modified preferred into a short blanking mode'):
            return self.handle_error('Short blanking not added. ')
        return ''

    def verify_graphics_rc6(self):
        """ On systems which support RC6 (non atom), check that we are able to
        get into rc6; idle before doing so, and retry every second for 20
        seconds."""
        logging.info('Running verify_graphics_rc6')
        # TODO(ihf): Implement on baytrail/braswell using residency counters.
        # But note the format changed since SNB, so this will be complex.
        if (utils.get_cpu_soc_family() == 'x86_64' and
                self._gpu_type != 'pinetrail' and
                self._gpu_type != 'baytrail' and self._gpu_type != 'braswell'):
            tries = 0
            found = False
            param_path = self.get_valid_path(RC6_PATHS)
            if not param_path:
                return 'RC6_PATHS not found.'
            while found == False and tries < 20:
                time.sleep(1)
                with open(param_path, 'r') as drpc_info_file:
                    for line in drpc_info_file:
                        match = re.search(r'Current RC state: (.*)', line)
                        if match and match.group(1) == 'RC6':
                            found = True
                            break
                tries += 1
            if not found:
                return self.handle_error('Error: did not see the GPU in RC6.',
                                         param_path)
        return ''

    def verify_graphics_i915_min_clock(self):
        """ On i915 systems, check that we get into the lowest clock frequency;
        idle before doing so, and retry every second for 20 seconds."""
        logging.info('Running verify_graphics_i915_min_clock')
        if (utils.get_cpu_soc_family() == 'x86_64' and
                self._gpu_type != 'pinetrail'):
            tries = 0
            found = False
            param_path = self.get_valid_path(CLOCK_PATHS)
            if not param_path:
                return 'CLOCK_PATHS not found.'
            while not found and tries < 80:
                time.sleep(0.25)

                with open(param_path, 'r') as delayinfo_file:
                    for line in delayinfo_file:
                        # This file has a different format depending on the
                        # board, so we parse both. Also, it would be tedious
                        # to add the minimum clock for each board, so instead
                        # we use 650MHz which is the max of the minimum clocks.
                        match = re.search(r'CAGF: (.*)MHz', line)
                        if match and int(match.group(1)) <= 650:
                            found = True
                            break

                        match = re.search(r'current GPU freq: (.*) MHz', line)
                        if match and int(match.group(1)) <= 650:
                            found = True
                            break

                tries += 1

            if not found:
                return self.handle_error('Did not see the min i915 clock. ',
                                         param_path)

        return ''

    def verify_graphics_dvfs(self):
        """ On systems which support DVFS, check that we get into the lowest
        clock frequency; idle before doing so, and retry every second for 20
        seconds."""
        logging.info('Running verify_graphics_dvfs')

        exynos_node = '/sys/devices/11800000.mali/'
        rk3288_node = '/sys/devices/ffa30000.gpu/'
        rk3399_node = '/sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/'
        mt8173_node = ('/sys/devices/soc/13000000.mfgsys-gpu/devfreq/'
                       '13000000.mfgsys-gpu/')

        if self._cpu_type == 'exynos5':
            if os.path.isdir(exynos_node):
                node = exynos_node
                use_devfreq = False
                enable_node = 'dvfs'
                enable_value = 'on'
            else:
                logging.error('Error: unknown exynos SoC.')
                return self.handle_error('Unknown exynos SoC.')
        elif self._cpu_type.startswith('rockchip'):
            if os.path.isdir(rk3288_node):
                node = rk3288_node
                use_devfreq = False
                enable_node = 'dvfs_enable'
                enable_value = '1'
            elif os.path.isdir(rk3399_node):
                node = rk3399_node
                use_devfreq = True
            else:
                logging.error('Error: unknown rockchip SoC.')
                return self.handle_error('Unknown rockchip SoC.')
        elif self._cpu_type == 'mediatek':
            if os.path.isdir(mt8173_node):
                node = mt8173_node
                use_devfreq = True
            else:
                logging.error('Error: unknown mediatek SoC.')
                return self.handle_error('Unknown mediatek SoC.')
        else:
            return ''

        if use_devfreq:
            governor_path = utils.locate_file('governor', node)
            clock_path = utils.locate_file('cur_freq', node)

            governor = utils.read_one_line(governor_path)
            logging.info('DVFS governor = %s', governor)
            if not governor == 'simple_ondemand':
                logging.error('Error: DVFS governor is not simple_ondemand.')
                return self.handle_error('Governor is wrong.')
        else:
            clock_path = utils.locate_file('clock', node)
            enable_path = utils.locate_file(enable_node, node)

            enable = utils.read_one_line(enable_path)
            logging.info('DVFS enable = %s', enable)
            if not enable == enable_value:
                return self.handle_error('DVFS is not enabled. ')

        freqs_path = utils.locate_file('available_frequencies', node)

        # available_frequencies are always sorted in ascending order
        # each line may contain one or multiple integers separated by spaces
        min_freq = int(utils.read_one_line(freqs_path).split()[0])

        # daisy_* (exynos5250) boards set idle frequency to 266000000
        # See: crbug.com/467401 and crosbug.com/p/19710
        if self._board.startswith('daisy'):
            min_freq = 266000000

        logging.info('Expecting idle DVFS clock = %u', min_freq)
        tries = 0
        found = False
        while not found and tries < 80:
            time.sleep(0.25)
            clock = int(utils.read_one_line(clock_path))
            if clock <= min_freq:
                logging.info('Found idle DVFS clock = %u', clock)
                found = True
                break

            tries += 1
        if not found:
            logging.error('Error: DVFS clock (%u) > min (%u)', clock, min_freq)
            return self.handle_error('Did not see the min DVFS clock. ',
                                     clock_path)
        return ''

    def verify_graphics_fbc(self):
        """ On systems which support FBC, check that we can get into FBC;
        idle before doing so, and retry every second for 20 seconds."""
        logging.info('Running verify_graphics_fbc')

        # Link's FBC is disabled (crbug.com/338588).
        # TODO(marcheu): remove this when/if we fix this bug.
        board = utils.get_board()
        if board == 'link':
            return ''

        # Machines which don't have a monitor can't get FBC.
        if utils.has_no_monitor():
            return ''

        if (self._gpu_type == 'haswell' or self._gpu_type == 'ivybridge' or
                self._gpu_type == 'sandybridge'):
            tries = 0
            found = False
            param_path = self.get_valid_path(FBC_PATHS)
            if not param_path:
                return 'FBC_PATHS not found.'
            while not found and tries < 20:
                time.sleep(1)
                with open(param_path, 'r') as fbc_info_file:
                    for line in fbc_info_file:
                        if re.search('FBC enabled', line):
                            found = True
                            break

                tries += 1
            if not found:
                return self.handle_error('Did not see FBC enabled. ',
                                         param_path)
        return ''

    def verify_graphics_psr(self):
        """ On systems which support PSR, check that we can get into PSR;
        idle before doing so, and retry every second for 20 seconds."""
        logging.info('Running verify_graphics_psr')

        board = utils.get_board()
        if board != 'samus':
            return ''
        tries = 0
        found = False
        param_path = self.get_valid_path(PSR_PATHS)
        if not param_path:
            return 'PSR_PATHS not found.'
        while not found and tries < 20:
            time.sleep(1)
            with open(param_path, 'r') as fbc_info_file:
                for line in fbc_info_file:
                    match = re.search(r'Performance_Counter: (.*)', line)
                    if match and int(match.group(1)) > 0:
                        found = True
                        break

            tries += 1
        if not found:
            return self.handle_error('Did not see PSR enabled. ', param_path)
        return ''

    def verify_graphics_gem_idle(self):
        """ On systems which have i915, check that we can get all gem objects
        to become idle (i.e. the i915_gem_active list need to go to 0);
        idle before doing so, and retry every second for 20 seconds."""
        logging.info('Running verify_graphics_gem_idle')
        if (utils.get_cpu_soc_family() == 'x86_64' and
                self._gpu_type != 'pinetrail'):
            tries = 0
            found = False
            gem_path = self.get_valid_path(GEM_PATHS)
            if not gem_path:
                return 'GEM_PATHS not found.'
            while not found and tries < 240:
                time.sleep(0.25)
                with open(gem_path, 'r') as gem_file:
                    for line in gem_file:
                        if re.search('Total 0 objects', line):
                            found = True
                            break

                tries += 1
            if not found:
                return self.handle_error('Did not reach 0 gem actives. ',
                                         gem_path)
        return ''
