# 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.

"""This is a server side ARC audio playback test using the Chameleon board."""

import logging
import os
import time

from autotest_lib.client.bin import utils
from autotest_lib.client.cros.chameleon import audio_test_utils
from autotest_lib.client.cros.chameleon import chameleon_audio_helper
from autotest_lib.client.cros.chameleon import chameleon_audio_ids
from autotest_lib.client.cros.multimedia import arc_resource_common
from autotest_lib.server import autotest
from autotest_lib.server.cros.audio import audio_test
from autotest_lib.server.cros.multimedia import remote_facade_factory


class audio_AudioARCPlayback(audio_test.AudioTest):
    """Server side ARC audio playback test.

    This test talks to a Chameleon board and a Cros device to verify
    audio playback function of the Cros device with ARC.

    """
    version = 1
    DELAY_AFTER_BINDING = 0.5
    WAIT_CLIENT_READY_TIMEOUT_SECS = 120
    WAIT_PLAYBACK_SECS = 10

    def run_once(self, host, source_id, sink_id, recorder_id,
                 golden_file, switch_hsp=False):
        """Runs record test through ARC on Cros device.

        @param host: device under test, a CrosHost.
        @param source_id: An ID defined in chameleon_audio_ids for source.
        @param sink_id: An ID defined in chameleon_audio_ids for sink if needed.
                        Currently this is only used on bluetooth.
        @param recorder_id: An ID defined in chameleon_audio_ids for recording.
        @param golden_file: A test file defined in audio_test_data.
        @param switch_hsp: Run a recording process on Cros device. This is
                           to trigger Cros switching from A2DP to HSP.

        """
        self.host = host

        if (source_id == chameleon_audio_ids.CrosIds.SPEAKER and
            not audio_test_utils.has_internal_speaker(host)):
            return

        self.client_at = None

        # Runs a client side test to start Chrome and install Play Music app.
        self.setup_playmusic_app()

        # Do not start Chrome because client side test had started it.
        # Do not install autotest because client side test had installed it.
        factory = remote_facade_factory.RemoteFacadeFactory(
                host, no_chrome=True, install_autotest=False,
                results_dir=self.resultsdir)

        # Setup Chameleon and create widgets.
        host.chameleon.setup_and_reset(self.outputdir)

        widget_factory = chameleon_audio_helper.AudioWidgetFactory(
                factory, host)

        source = widget_factory.create_widget(source_id, use_arc=True)
        recorder = widget_factory.create_widget(recorder_id)

        # Chameleon Mic does not need binding.
        binding = (recorder_id != chameleon_audio_ids.ChameleonIds.MIC)

        binder = None

        if binding:
            if sink_id:
                sink = widget_factory.create_widget(sink_id)
                binder = widget_factory.create_binder(source, sink, recorder)
            else:
                binder = widget_factory.create_binder(source, recorder)

        # Second peak ratio is determined by quality of audio path.
        second_peak_ratio = audio_test_utils.get_second_peak_ratio(
                source_id=source_id,
                recorder_id=recorder_id,
                is_hsp=switch_hsp)

        with chameleon_audio_helper.bind_widgets(binder):
            time.sleep(self.DELAY_AFTER_BINDING)

            audio_facade = factory.create_audio_facade()

            audio_test_utils.dump_cros_audio_logs(
                    host, audio_facade, self.resultsdir, 'after_binding')

            # Checks the node selected by CRAS is correct.
            audio_test_utils.check_output_port(audio_facade, source.port_id)

            if switch_hsp:
                audio_test_utils.switch_to_hsp(audio_facade)

            logging.info('Setting playback file on Cros device')
            source.set_playback_data(golden_file)

            logging.info('Start recording from Chameleon')
            recorder.start_recording()

            logging.info('Start playing %s on Cros device',
                         golden_file.path)
            source.start_playback()

            time.sleep(self.WAIT_PLAYBACK_SECS)

            recorder.stop_recording()
            logging.info('Stopped recording from Chameleon.')

            audio_test_utils.dump_cros_audio_logs(
                    host, audio_facade, self.resultsdir,
                    'after_recording')

            recorder.read_recorded_binary()
            logging.info('Read recorded binary from Chameleon.')

            recorded_file = os.path.join(self.resultsdir, "recorded.raw")
            logging.info('Saving recorded data to %s', recorded_file)
            recorder.save_file(recorded_file)

            audio_test_utils.check_recorded_frequency(
                    golden_file, recorder,
                    second_peak_ratio=second_peak_ratio)


    def run_client_side_test(self):
        """Runs a client side test on Cros device in background."""
        self.client_at = autotest.Autotest(self.host)
        logging.info('Start running client side test %s',
                     arc_resource_common.PlayMusicProps.TEST_NAME)
        self.client_at.run_test(
                arc_resource_common.PlayMusicProps.TEST_NAME,
                background=True)


    def setup_playmusic_app(self):
        """Setups Play Music app on Cros device.

        Runs a client side test on Cros device to start Chrome and ARC and
        install Play Music app.
        Wait for it to be ready.

        """
        # Removes ready tag that server side test should wait for later.
        self.remove_ready_tag()

        # Runs the client side test.
        self.run_client_side_test()

        logging.info('Waiting for client side Play Music app to be ready')

        # Waits for ready tag to be posted by client side test.
        utils.poll_for_condition(condition=self.ready_tag_exists,
                                 timeout=self.WAIT_CLIENT_READY_TIMEOUT_SECS,
                                 desc='Wait for client side test being ready',
                                 sleep_interval=1)

        logging.info('Client side Play Music app is ready')


    def cleanup(self):
        """Cleanup of the test."""
        self.touch_exit_tag()
        super(audio_AudioARCPlayback, self).cleanup()


    def remove_ready_tag(self):
        """Removes ready tag on Cros device."""
        if self.ready_tag_exists():
            self.host.run(command='rm %s' % (
                    arc_resource_common.PlayMusicProps.READY_TAG_FILE))


    def touch_exit_tag(self):
        """Touches exit tag on Cros device to stop client side test."""
        self.host.run(command='touch %s' % (
                arc_resource_common.PlayMusicProps.EXIT_TAG_FILE))


    def ready_tag_exists(self):
        """Checks if ready tag exists.

        @returns: True if the tag file exists. False otherwise.

        """
        return self.host.path_exists(
                arc_resource_common.PlayMusicProps.READY_TAG_FILE)
