# 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 os
import re

from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.audio import alsa_utils

class audio_AlsaAPI(test.test):
    """Checks that simple ALSA API functions correctly."""
    version = 2
    _SND_DEV_DIR = '/dev/snd/'
    _PLAYBACK_DEVICE_NAME = '^pcmC(\d+)D(\d+)p$'
    # A list of boards that do not correctly implement snd_pcm_drop, see
    # crosbug.com/p/51882
    _BOARDS_WITHOUT_DROP_SUPPORT  = ['banon', 'elm', 'samus', 'squawks']
    # A dict of list of (card name, device) to be skipped on some boards.
    _DEVICES_TO_BE_SKIPPED = {
        # On the following boards, devices 4,5,6 are HDMI devices.
        'asuka': {'sklnau8825max': [4, 5, 6]},
        'cave': {'sklnau8825max': [4, 5, 6]},
        'snappy': {'bxtda7219max': [4, 5, 6]},
        # Chell's HDMI device 4 can not be used without being plugged.
        # Also, its HDMI devices 5 and 6 are dummy devices.
        'chell': {'sklnau8825adi': [4, 5, 6]},
        # Kevin's device 3 is a DisplayPort device.
        'kevin': {'rk3399-gru-sound': [3]},
    }

    def run_once(self, to_test):
        """Run alsa_api_test binary and verify its result.

        Checks the source code of alsa_api_test in audiotest repo for detail.

        @param to_test: support these test items:
                        move: Checks snd_pcm_forward API.
                        fill: Checks snd_pcm_mmap_begin API.
                        drop: Checks snd_pcm_drop API.

        """
        # Skip test_drop on boards that do not implement snd_pcm_drop
        # correctly, as it cannot pass.
        board = utils.get_board().lower()
        if to_test == 'drop' and board in self._BOARDS_WITHOUT_DROP_SUPPORT:
            logging.info('Skipping test_drop for unsupported board: %s', board)
            return

        self._cardnames = alsa_utils.get_soundcard_names()
        self._devices = []
        self._find_sound_devices()
        method_name = '_test_' + to_test
        method = getattr(self, method_name)

        # Stop CRAS to make sure the audio device won't be occupied.
        utils.stop_service('cras', ignore_status=True)

        try:
            for card_index, device_index in self._devices:
                device = 'hw:%s,%s' % (card_index, device_index)
                method(device)
        finally:
            # Restart CRAS.
            utils.start_service('cras', ignore_status=True)


    def _skip_device(self, card_device):
        """Skips devices on some boards.

        @param card_device: A tuple of (card index, device index).

        @returns: True if the device should be skipped. False otherwise.

        """
        card_name = self._cardnames[card_device[0]]

        return card_device[1] in self._DEVICES_TO_BE_SKIPPED.get(
                utils.get_board().lower(), {}).get(card_name, [])


    def _find_sound_devices(self):
        """Finds playback devices in sound device directory.

        @raises: error.TestError if there is no playback device.
        """
        filenames = os.listdir(self._SND_DEV_DIR)
        for filename in filenames:
            search = re.match(self._PLAYBACK_DEVICE_NAME, filename)
            if search:
                card_device = (search.group(1), int(search.group(2)))
                if not self._skip_device(card_device):
                    self._devices.append(card_device)
        if not self._devices:
            raise error.TestError('There is no playback device')


    def _make_alsa_api_test_command(self, option, device):
        """Makes command for alsa_api_test.

        @param option: same as to_test in run_once.
        @param device: device in hw:<card index>:<device index> format.

        @returns: The command in a list of args.

        """
        return ['alsa_api_test', '--device', device, '--%s' % option]


    def _test_move(self, device):
        """Runs alsa_api_test command and checks the return code.

        Test snd_pcm_forward can move appl_ptr to hw_ptr.

        @param device: device in hw:<card index>:<device index> format.

        @raises error.TestError if command fails.

        """
        ret = utils.system(
                command=self._make_alsa_api_test_command('move', device),
                ignore_status=True)
        if ret:
            raise error.TestError(
                    'ALSA API failed to move appl_ptr on device %s' % device)


    def _test_fill(self, device):
        """Runs alsa_api_test command and checks the return code.

        Test snd_pcm_mmap_begin can provide the access to the buffer, and memset
        can fill it with zeros without using snd_pcm_mmap_commit.

        @param device: device in hw:<card index>:<device index> format.

        @raises error.TestError if command fails.

        """
        ret = utils.system(
                command=self._make_alsa_api_test_command('fill', device),
                ignore_status=True)
        if ret:
            raise error.TestError(
                    'ALSA API failed to fill buffer on device %s' % device)


    def _test_drop(self, device):
        """Runs alsa_api_test command and checks the return code.

        Test snd_pcm_drop can stop playback and reset hw_ptr to 0 in hardware.

        @param device: device in hw:<card index>:<device index> format.

        @raises error.TestError if command fails.

        """
        ret = utils.system(
                command=self._make_alsa_api_test_command('drop', device),
                ignore_status=True)
        if ret:
            raise error.TestError(
                    'ALSA API failed to drop playback and reset hw_ptr'
                    'on device %s' % device)
