142 lines
5.0 KiB
Python
142 lines
5.0 KiB
Python
# Copyright (c) 2013 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 time
|
|
|
|
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
|
|
from autotest_lib.client.cros.audio import audio_spec
|
|
from autotest_lib.client.cros.audio import cras_utils
|
|
|
|
APLAY_FILE = '/dev/zero' # raw data
|
|
|
|
# Expected results of 'aplay -v' commands.
|
|
APLAY_EXPECTED = set([
|
|
('stream', 'PLAYBACK')])
|
|
|
|
|
|
def _play_audio(device_name, duration=1):
|
|
"""Play a tone and try to ensure it played properly.
|
|
|
|
Sample output from aplay -v:
|
|
|
|
Playing raw data '/dev/zero' : Signed 16 bit Little Endian, Rate 44100 Hz,
|
|
Stereo
|
|
Hardware PCM card 0 'HDA Intel PCH' device 0 subdevice 0
|
|
Its setup is:
|
|
stream : PLAYBACK
|
|
access : RW_INTERLEAVED format : S16_LE
|
|
subformat : STD
|
|
channels : 2
|
|
rate : 44100
|
|
exact rate : 44100 (44100/1)
|
|
msbits : 16
|
|
buffer_size : 16384
|
|
period_size : 4096
|
|
period_time : 92879
|
|
tstamp_mode : NONE
|
|
period_step : 1
|
|
avail_min : 4096
|
|
period_event : 0
|
|
start_threshold : 16384
|
|
stop_threshold : 16384
|
|
silence_threshold: 0
|
|
silence_size : 0
|
|
boundary : 4611686018427387904
|
|
appl_ptr : 0
|
|
hw_ptr : 0
|
|
|
|
@param device_name: The output device for aplay.
|
|
@param duration: Duration supplied to aplay.
|
|
@return String output from the command (may be empty).
|
|
@raises CmdError when cmd returns <> 0.
|
|
"""
|
|
cmd = ['aplay',
|
|
'-v', # show verbose details
|
|
'-D %s' % device_name,
|
|
'-d %d' % duration,
|
|
'-f cd', # format
|
|
APLAY_FILE,
|
|
'2>&1'] # verbose details
|
|
return utils.system_output(' '.join(cmd)).strip()
|
|
|
|
|
|
def _check_play(device_name, duration, expected):
|
|
"""Runs aplay command and checks the output against an expected result.
|
|
|
|
The expected results are compared as sets of tuples.
|
|
|
|
@param device_name: The output device for aplay.
|
|
@param duration: Duration supplied to aplay.
|
|
@param expected: The set of expected tuples.
|
|
@raises error.TestError for invalid output or invalidly matching expected.
|
|
"""
|
|
error_msg = 'invalid response from aplay'
|
|
results = _play_audio(device_name, duration)
|
|
if not results.startswith("Playing raw data '%s' :" % APLAY_FILE):
|
|
raise error.TestError('%s: %s' % (error_msg, results))
|
|
result_set = utils.set_from_keyval_output(results, '[\s]*:[\s]*')
|
|
if set(expected) <= result_set:
|
|
return
|
|
raise error.TestError('%s: expected=%s.' %
|
|
(error_msg, sorted(set(expected) - result_set)))
|
|
|
|
|
|
class audio_Aplay(test.test):
|
|
"""Checks that simple aplay functions correctly."""
|
|
version = 1
|
|
|
|
def run_once(self, duration=1, test_headphone=False):
|
|
"""Run aplay and verify its output is as expected.
|
|
|
|
@param duration: The duration to run aplay in seconds.
|
|
@param test_headphone: If the value is true, test a headphone. If false,
|
|
test an internal speaker.
|
|
"""
|
|
|
|
# Check CRAS server is alive. If not, restart it and wait a second to
|
|
# get server ready.
|
|
if utils.get_service_pid('cras') == 0:
|
|
logging.debug("CRAS server is down. Restart it.")
|
|
utils.start_service('cras', ignore_status=True)
|
|
time.sleep(1)
|
|
|
|
# Skip test if there is no internal speaker on the board.
|
|
if not test_headphone:
|
|
board_type = utils.get_board_type()
|
|
board_name = utils.get_board()
|
|
if not audio_spec.has_internal_speaker(board_type, board_name):
|
|
logging.debug("No internal speaker. Skipping the test.")
|
|
return
|
|
|
|
if test_headphone:
|
|
output_node = audio_spec.get_headphone_node(utils.get_board())
|
|
else:
|
|
output_node = "INTERNAL_SPEAKER"
|
|
logging.debug("Test output device %s", output_node)
|
|
|
|
cras_utils.set_single_selected_output_node(output_node)
|
|
|
|
cras_device_type = cras_utils.get_selected_output_device_type()
|
|
logging.debug("Selected output device type=%s", cras_device_type)
|
|
if cras_device_type != output_node:
|
|
raise error.TestFail("Fail to select output device.")
|
|
|
|
cras_device_name = cras_utils.get_selected_output_device_name()
|
|
logging.debug("Selected output device name=%s", cras_device_name)
|
|
if cras_device_name is None:
|
|
raise error.TestFail("Fail to get selected output device.")
|
|
|
|
alsa_device_name = alsa_utils.convert_device_name(cras_device_name)
|
|
|
|
# Stop CRAS to make sure the audio device won't be occupied.
|
|
utils.stop_service('cras', ignore_status=True)
|
|
try:
|
|
_check_play(alsa_device_name, duration, APLAY_EXPECTED)
|
|
finally:
|
|
#Restart CRAS
|
|
utils.start_service('cras', ignore_status=True)
|