# 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
import random
import time

from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.faft.firmware_test import FirmwareTest
from autotest_lib.server.cros.servo import pd_device


class firmware_PDTrySrc(FirmwareTest):
    """
    Servo based USB PD Try.SRC protocol test.

    When a PD device supports Try.SRC mode and it's enabled, it will attempt
    to always connect as a SRC device. This test is therefore only applicable
    if both devices support dualrole and at least one device supports Try.SRC.

    Pass criteria is that when Try.SRC is enabled the device connects > 95% of
    the time in SRC mode. When it is disabled, there must be at least 25%
    variation in connecting as SRC and SNK.
    """
    version = 1

    CONNECT_ITERATIONS = 20
    PD_DISCONNECT_TIME = 1
    PD_CONNECT_DELAY = 4
    SNK = 0
    SRC = 1
    TRYSRC_OFF_THRESHOLD = 15.0
    TRYSRC_ON_THRESHOLD = 96.0

    def _execute_connect_sequence(self, usbpd_dev, pdtester_dev, trysrc):
        """Execute mulitple connections and track power role

        This method will disconnect/connect a TypeC PD port and
        collect the power role statistics of each connection. The time
        delay for reconnect adds a random delay so that test to increase
        randomness for dualrole swaps.

        @param usbpd_dev: PD device object of DUT
        @param pdtester_dev: PD device object of PDTester
        @param trysrc: Enable TrySrc or not

        @returns list with number of SNK and SRC connections
        """
        stats = [0, 0]
        random.seed()
        # Try N disconnect/connects
        for attempt in xrange(self.CONNECT_ITERATIONS):
            try:
                # Disconnect time from 1 to 2 seconds
                disc_time = self.PD_DISCONNECT_TIME + random.random()
                logging.info('Disconnect time = %.2f seconds', disc_time)
                # Set the TrySrc value on DUT
                usbpd_dev.try_src(trysrc)
                # Force disconnect/connect
                pdtester_dev.cc_disconnect_connect(disc_time)
                # Wait for connection to be reestablished
                time.sleep(self.PD_DISCONNECT_TIME + self.PD_CONNECT_DELAY)
                # Check power role and update connection stats
                if pdtester_dev.is_snk():
                    stats[self.SNK] += 1;
                    logging.info('Power Role = SNK')
                elif pdtester_dev.is_src():
                    stats[self.SRC] += 1;
                    logging.info('Power Role = SRC')
            except NotImplementedError:
                raise error.TestFail('TrySRC disconnect requires PDTester')
        logging.info('SNK = %d: SRC = %d: Total = %d',
                     stats[0], stats[1], self.CONNECT_ITERATIONS)
        return stats

    def initialize(self, host, cmdline_args, flip_cc=False):
        super(firmware_PDTrySrc, self).initialize(host, cmdline_args)
        self.setup_pdtester(flip_cc)
        # Only run in normal mode
        self.switcher.setup_mode('normal')
        # Turn off console prints, except for USBPD.
        self.usbpd.enable_console_channel('usbpd')

    def cleanup(self):
        self.usbpd.send_command('chan 0xffffffff')
        super(firmware_PDTrySrc, self).cleanup()

    def run_once(self):
        """Execute Try.SRC PD protocol test

        1. Verify that DUT <-> PDTester device pair exists
        2. Verify that DUT supports dualrole
        3. Verify that DUT supports Try.SRC mode
        4. Enable Try.SRC mode, execute disc/connect sequences
        5. Disable Try.SRC mode, execute disc/connect sequences
        6. Compute DUT SRC/SNK connect ratios for both modes
        7. Compare SRC connect ratio to threholds to determine pass/fail
        """

        # Create list of available UART consoles
        consoles = [self.usbpd, self.pdtester]
        # Backup the original dualrole settings
        original_drp = [None, None]
        port_partner = pd_device.PDPortPartner(consoles)
        # Identify PDTester <-> DUT PD device pair
        port_pair = port_partner.identify_pd_devices()
        if not port_pair:
            raise error.TestFail('No DUT to PDTester connection found!')

        # TODO Device pair must have PDTester so that the disconnect/connect
        # sequence does not affect the SRC/SNK connection. PDTester provides
        # a 'fakedisconnect' feature which more closely resembles unplugging
        # and replugging a Type C cable.
        for side in xrange(len(port_pair)):
            original_drp[side] = port_pair[side].drp_get()
            if port_pair[side].is_pdtester:
                # Identify PDTester and DUT device
                p_idx = side
                d_idx = side ^ 1

        try:
            # Both devices must support dualrole mode for this test. In addtion,
            # DUT must support Try.SRC mode.
            for port in port_pair:
                try:
                    if not port.drp_set('on'):
                        raise error.TestFail('Could not enable DRP')
                except NotImplementedError:
                    raise error.TestFail('Both devices must support DRP')

            # Make sure that DUT supports Try.SRC mode
            if not port_pair[d_idx].try_src(True):
                raise error.TestFail('DUT does not support Try.SRC feature')

            # Run disconnect/connect sequence with Try.SRC enabled
            stats_on = self._execute_connect_sequence(
                    usbpd_dev=port_pair[d_idx],
                    pdtester_dev=port_pair[p_idx],
                    trysrc=True)
            # Run disconnect/connect sequence with Try.SRC disabled
            stats_off = self._execute_connect_sequence(
                    usbpd_dev=port_pair[d_idx],
                    pdtester_dev=port_pair[p_idx],
                    trysrc=False)
        finally:
            # Reenable Try.SRC mode
            port_pair[d_idx].try_src(True)
            # Restore the original dualrole settings
            for side in xrange(len(port_pair)):
                port_pair[side].drp_set(original_drp[side])

        # Compute SRC connect ratio/percent for Try.SRC on and off cases
        total_on = float(stats_on[self.SNK] + stats_on[self.SRC])
        total_off = float(stats_off[self.SNK] + stats_off[self.SRC])
        trysrc_on = float(stats_on[self.SNK]) / total_on * 100.0
        trysrc_off = float(stats_off[self.SNK]) / total_off * 100.0
        logging.info('DUT Try.SRC on = %.1f%%: off = %.1f%%',
                      trysrc_on, trysrc_off)

        # When Try.SRC is off, ideally the SNK/SRC ratio will be close to
        # 50%. However, in practice there is a wide range related to the
        # dualrole swap timers in firmware.
        if (trysrc_off < self.TRYSRC_OFF_THRESHOLD or
            trysrc_off > 100 - self.TRYSRC_OFF_THRESHOLD):
            raise error.TestFail('SRC %% = %.1f: Must be > %.1f & < %.1f' %
                                 (trysrc_off, self.TRYSRC_OFF_THRESHOLD,
                                  100 - self.TRYSRC_OFF_THRESHOLD))
        # When Try.SRC is on, the SRC/SNK, the DUT should connect in SRC
        # mode nearly 100% of the time.
        if trysrc_on < self.TRYSRC_ON_THRESHOLD:
            raise error.TestFail('SRC %% = %.1f: Must be >  %.1f' %
                                 (trysrc_on, self.TRYSRC_ON_THRESHOLD))
