[autotest] Refine audio essential tests
- Extract common setups and checks to AudioTest
- Refine tests to explicitly select the target node
- Refine audio_InternalCardNodes
- Reformat some codes and fix pylint warnings
BUG=b:145369399, b:145368865, b:145369119, b:145368916, b:145367773
TEST=test_that run all tests belong to audio_essential
Change-Id: I67ec547fc65960a7522d08e85ca14f22900986d6
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/1944096
Reviewed-by: Yu-Hsuan Hsu <yuhsuan@chromium.org>
Reviewed-by: Kalin Stoyanov <kalin@chromium.org>
Tested-by: En-Shuo Hsu <enshuo@chromium.org>
Commit-Queue: Kalin Stoyanov <kalin@chromium.org>
diff --git a/client/cros/chameleon/audio_board.py b/client/cros/chameleon/audio_board.py
index 5b2cd1c..a98f5fd 100644
--- a/client/cros/chameleon/audio_board.py
+++ b/client/cros/chameleon/audio_board.py
@@ -1,7 +1,6 @@
# Copyright 2015 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 module provides the audio board interface."""
import logging
@@ -17,27 +16,23 @@
A ChameleonConnection object is passed to the construction.
"""
+
def __init__(self, chameleon_connection):
"""Constructs an AudioBoard.
@param chameleon_connection: A ChameleonConnection object.
+ @returns: An AudioBoard object.
+
"""
self._audio_buses = {
1: AudioBus(1, chameleon_connection),
- 2: AudioBus(2, chameleon_connection)}
-
+ 2: AudioBus(2, chameleon_connection)
+ }
+ self._chameleon_connection = chameleon_connection
self._jack_plugger = None
- try:
- self._jack_plugger = AudioJackPlugger(chameleon_connection)
- except AudioJackPluggerException:
- logging.warning(
- 'There is no jack plugger on this audio board.')
- self._jack_plugger = None
-
self._bluetooth_controller = BluetoothController(chameleon_connection)
-
def get_audio_bus(self, bus_index):
"""Gets an audio bus on this audio board.
@@ -48,17 +43,29 @@
"""
return self._audio_buses[bus_index]
-
def get_jack_plugger(self):
"""Gets an AudioJackPlugger on this audio board.
@returns: An AudioJackPlugger object if there is an audio jack plugger.
None if there is no audio jack plugger.
+ @raises:
+ AudioJackPluggerException if there is no jack plugger on this audio
+ board.
"""
+ if self._jack_plugger is None:
+ try:
+ self._jack_plugger = AudioJackPlugger(
+ self._chameleon_connection)
+ except AudioJackPluggerException as e:
+ logging.error(
+ 'There is no jack plugger on this audio board. Please '
+ 'check the jack plugger if all labels are correctly '
+ 'configured.')
+ self._jack_plugger = None
+ raise e
return self._jack_plugger
-
def get_bluetooth_controller(self):
"""Gets an BluetoothController on this audio board.
@@ -88,14 +95,13 @@
ids.CrosIds.EXTERNAL_MIC: 'Cros device external microphone',
ids.PeripheralIds.SPEAKER: 'Peripheral speaker',
ids.PeripheralIds.MIC: 'Peripheral microphone',
- ids.PeripheralIds.BLUETOOTH_DATA_RX:
- 'Bluetooth module output',
- ids.PeripheralIds.BLUETOOTH_DATA_TX:
- 'Bluetooth module input'}
-
+ ids.PeripheralIds.BLUETOOTH_DATA_RX: 'Bluetooth module output',
+ ids.PeripheralIds.BLUETOOTH_DATA_TX: 'Bluetooth module input'
+ }
class AudioBusSnapshot(object):
"""Abstracts the snapshot of AudioBus for user to restore it later."""
+
def __init__(self, endpoints):
"""Initializes an AudioBusSnapshot.
@@ -104,7 +110,6 @@
"""
self._endpoints = endpoints.copy()
-
def __init__(self, bus_index, chameleon_connection):
"""Constructs an AudioBus.
@@ -116,7 +121,6 @@
self._chameleond_proxy = chameleon_connection.chameleond_proxy
self._connected_endpoints = set()
-
def _get_endpoint_name(self, port_id):
"""Gets the endpoint name used in audio bus API.
@@ -128,33 +132,28 @@
"""
return self._PORT_ID_AUDIO_BUS_ENDPOINT_MAP[port_id]
-
def _connect_endpoint(self, endpoint):
"""Connects an endpoint to audio bus.
@param endpoint: An endpoint name in _PORT_ID_AUDIO_BUS_ENDPOINT_MAP.
"""
- logging.debug(
- 'Audio bus %s is connecting endpoint %s',
- self.bus_index, endpoint)
+ logging.debug('Audio bus %s is connecting endpoint %s', self.bus_index,
+ endpoint)
self._chameleond_proxy.AudioBoardConnect(self.bus_index, endpoint)
self._connected_endpoints.add(endpoint)
-
def _disconnect_endpoint(self, endpoint):
"""Disconnects an endpoint from audio bus.
@param endpoint: An endpoint name in _PORT_ID_AUDIO_BUS_ENDPOINT_MAP.
"""
- logging.debug(
- 'Audio bus %s is disconnecting endpoint %s',
- self.bus_index, endpoint)
+ logging.debug('Audio bus %s is disconnecting endpoint %s',
+ self.bus_index, endpoint)
self._chameleond_proxy.AudioBoardDisconnect(self.bus_index, endpoint)
self._connected_endpoints.remove(endpoint)
-
def connect(self, port_id):
"""Connects an audio port to this audio bus.
@@ -165,7 +164,6 @@
endpoint = self._get_endpoint_name(port_id)
self._connect_endpoint(endpoint)
-
def disconnect(self, port_id):
"""Disconnects an audio port from this audio bus.
@@ -176,18 +174,15 @@
endpoint = self._get_endpoint_name(port_id)
self._disconnect_endpoint(endpoint)
-
def clear(self):
"""Disconnects all audio port from this audio bus."""
self._disconnect_all_endpoints()
-
def _disconnect_all_endpoints(self):
"""Disconnects all endpoints from this audio bus."""
for endpoint in self._connected_endpoints.copy():
self._disconnect_endpoint(endpoint)
-
def get_snapshot(self):
"""Gets the snapshot of AudioBus so user can restore it later.
@@ -196,7 +191,6 @@
"""
return self.AudioBusSnapshot(self._connected_endpoints)
-
def restore_snapshot(self, snapshot):
"""Restore the snapshot.
@@ -224,6 +218,7 @@
A ChameleonConnection object is passed to the construction.
"""
+
def __init__(self, chameleon_connection):
"""Constructs an AudioJackPlugger.
@@ -237,20 +232,18 @@
self._chameleond_proxy = chameleon_connection.chameleond_proxy
if not self._chameleond_proxy.AudioBoardHasJackPlugger():
raise AudioJackPluggerException(
- 'There is no jack plugger on audio board. '
- 'Perhaps the audio board is not connected to audio box.')
-
+ 'There is no jack plugger on audio board. '
+ 'Perhaps the audio board is not connected to audio box.')
def plug(self):
"""Plugs the audio cable into audio jack of Cros device."""
self._chameleond_proxy.AudioBoardAudioJackPlug()
- logging.info('Plugged 3.5mm audio cable to Cros device')
-
+ logging.info('Plugged 3.5mm audio cable to Cros device.')
def unplug(self):
"""Unplugs the audio cable from audio jack of Cros device."""
self._chameleond_proxy.AudioBoardAudioJackUnplug()
- logging.info('Unplugged 3.5mm audio cable from Cros device')
+ logging.info('Unplugged 3.5mm audio cable from Cros device.')
class BluetoothController(object):
@@ -260,6 +253,7 @@
API provided by chameleon proxy.
"""
+
def __init__(self, chameleon_connection):
"""Constructs an BluetoothController.
@@ -268,19 +262,16 @@
"""
self._chameleond_proxy = chameleon_connection.chameleond_proxy
-
def reset(self):
"""Resets the bluetooth module."""
self._chameleond_proxy.AudioBoardResetBluetooth()
logging.info('Resets bluetooth module on audio board.')
-
def disable(self):
"""Disables the bluetooth module."""
self._chameleond_proxy.AudioBoardDisableBluetooth()
logging.info('Disables bluetooth module on audio board.')
-
def is_enabled(self):
"""Checks if the bluetooth module is enabled.
diff --git a/client/cros/chameleon/audio_test_utils.py b/client/cros/chameleon/audio_test_utils.py
index 3687ebb..79f02d9 100644
--- a/client/cros/chameleon/audio_test_utils.py
+++ b/client/cros/chameleon/audio_test_utils.py
@@ -1,7 +1,6 @@
# Copyright 2015 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 module provides the test utilities for audio tests using chameleon."""
# TODO (cychiang) Move test utilities from chameleon_audio_helpers
@@ -24,15 +23,15 @@
from autotest_lib.client.cros.chameleon import chameleon_audio_ids
CHAMELEON_AUDIO_IDS_TO_CRAS_NODE_TYPES = {
- chameleon_audio_ids.CrosIds.HDMI: 'HDMI',
- chameleon_audio_ids.CrosIds.HEADPHONE: 'HEADPHONE',
- chameleon_audio_ids.CrosIds.EXTERNAL_MIC: 'MIC',
- chameleon_audio_ids.CrosIds.SPEAKER: 'INTERNAL_SPEAKER',
- chameleon_audio_ids.CrosIds.INTERNAL_MIC: 'INTERNAL_MIC',
- chameleon_audio_ids.CrosIds.BLUETOOTH_HEADPHONE: 'BLUETOOTH',
- chameleon_audio_ids.CrosIds.BLUETOOTH_MIC: 'BLUETOOTH',
- chameleon_audio_ids.CrosIds.USBIN: 'USB',
- chameleon_audio_ids.CrosIds.USBOUT: 'USB',
+ chameleon_audio_ids.CrosIds.HDMI: 'HDMI',
+ chameleon_audio_ids.CrosIds.HEADPHONE: 'HEADPHONE',
+ chameleon_audio_ids.CrosIds.EXTERNAL_MIC: 'MIC',
+ chameleon_audio_ids.CrosIds.SPEAKER: 'INTERNAL_SPEAKER',
+ chameleon_audio_ids.CrosIds.INTERNAL_MIC: 'INTERNAL_MIC',
+ chameleon_audio_ids.CrosIds.BLUETOOTH_HEADPHONE: 'BLUETOOTH',
+ chameleon_audio_ids.CrosIds.BLUETOOTH_MIC: 'BLUETOOTH',
+ chameleon_audio_ids.CrosIds.USBIN: 'USB',
+ chameleon_audio_ids.CrosIds.USBOUT: 'USB',
}
@@ -81,9 +80,10 @@
"""
curr_out_nodes, curr_in_nodes = audio_facade.get_selected_node_types()
out_audio_nodes, in_audio_nodes = audio_nodes
- if (in_audio_nodes != None and
- sorted(curr_in_nodes) != sorted(in_audio_nodes)):
- raise error.TestFail('Wrong input node(s) selected: %s '
+ if (in_audio_nodes != None
+ and sorted(curr_in_nodes) != sorted(in_audio_nodes)):
+ raise error.TestFail(
+ 'Wrong input node(s) selected: %s '
'expected: %s' % (str(curr_in_nodes), str(in_audio_nodes)))
# Treat line-out node as headphone node in Chameleon test since some
@@ -92,9 +92,10 @@
if (out_audio_nodes == ['HEADPHONE'] and curr_out_nodes == ['LINEOUT']):
return
- if (out_audio_nodes != None and
- sorted(curr_out_nodes) != sorted(out_audio_nodes)):
- raise error.TestFail('Wrong output node(s) selected %s '
+ if (out_audio_nodes != None
+ and sorted(curr_out_nodes) != sorted(out_audio_nodes)):
+ raise error.TestFail(
+ 'Wrong output node(s) selected %s '
'expected: %s' % (str(curr_out_nodes), str(out_audio_nodes)))
@@ -116,12 +117,13 @@
for node in in_audio_nodes:
if node not in curr_in_nodes:
raise error.TestFail('Wrong input node(s) plugged: %s '
- 'expected %s to be plugged!' % (str(curr_in_nodes),
- str(in_audio_nodes)))
+ 'expected %s to be plugged!' %
+ (str(curr_in_nodes), str(in_audio_nodes)))
if out_audio_nodes != None:
for node in out_audio_nodes:
if node not in curr_out_nodes:
- raise error.TestFail('Wrong output node(s) plugged: %s '
+ raise error.TestFail(
+ 'Wrong output node(s) plugged: %s '
'expected %s to be plugged!' % (str(curr_out_nodes),
str(out_audio_nodes)))
@@ -140,14 +142,16 @@
"""
curr_out_nodes, curr_in_nodes = audio_facade.get_plugged_node_types()
out_audio_nodes, in_audio_nodes = audio_nodes
- if (in_audio_nodes != None and
- sorted(curr_in_nodes) != sorted(in_audio_nodes)):
+ if (in_audio_nodes != None
+ and sorted(curr_in_nodes) != sorted(in_audio_nodes)):
raise error.TestFail('Wrong input node(s) plugged: %s '
- 'expected: %s!' % (str(curr_in_nodes), str(in_audio_nodes)))
- if (out_audio_nodes != None and
- sorted(curr_out_nodes) != sorted(out_audio_nodes)):
+ 'expected: %s!' % (str(sorted(curr_in_nodes)),
+ str(sorted(in_audio_nodes))))
+ if (out_audio_nodes != None
+ and sorted(curr_out_nodes) != sorted(out_audio_nodes)):
raise error.TestFail('Wrong output node(s) plugged: %s '
- 'expected: %s!' % (str(curr_out_nodes), str(out_audio_nodes)))
+ 'expected: %s!' % (str(sorted(curr_out_nodes)),
+ str(sorted(out_audio_nodes))))
def bluetooth_nodes_plugged(audio_facade):
@@ -241,6 +245,7 @@
@resume_network_timeout_secs: Time in seconds to let Cros device resume and
obtain network.
"""
+
def action_suspend():
"""Calls the host method suspend."""
host.suspend(suspend_time=suspend_time_secs)
@@ -252,12 +257,15 @@
proc.start()
host.test_wait_for_sleep(suspend_time_secs)
logging.info("DUT suspended! Waiting to resume...")
- host.test_wait_for_resume(
- boot_id, suspend_time_secs + resume_network_timeout_secs)
+ host.test_wait_for_resume(boot_id,
+ suspend_time_secs + resume_network_timeout_secs)
logging.info("DUT resumed!")
-def dump_cros_audio_logs(host, audio_facade, directory, suffix='',
+def dump_cros_audio_logs(host,
+ audio_facade,
+ directory,
+ suffix='',
fail_if_warnings=False):
"""Dumps logs for audio debugging from Cros device.
@@ -267,6 +275,7 @@
@directory: The directory to dump logs.
"""
+
def get_file_path(name):
"""Gets file path to dump logs.
@@ -288,8 +297,8 @@
# Raising error if any warning messages in the audio diagnostics
if fail_if_warnings:
- audio_logs = examine_audio_diagnostics(get_file_path(
- 'audio_diagnostics.txt'))
+ audio_logs = examine_audio_diagnostics(
+ get_file_path('audio_diagnostics.txt'))
if audio_logs != '':
raise error.TestFail(audio_logs)
@@ -315,9 +324,8 @@
if search_result:
num_underruns = int(search_result.group(1))
if num_underruns != 0:
- warning_msgs.append(
- 'Found %d underrun at line %d: %s' % (
- num_underruns, line_number, line))
+ warning_msgs.append('Found %d underrun at line %d: %s' %
+ (num_underruns, line_number, line))
# TODO(cychiang) add other check like maximum client reply delay.
line_number = line_number + 1
@@ -387,6 +395,7 @@
_DC_FREQ_THRESHOLD = 0.001
_DC_COEFF_THRESHOLD = 0.01
+
def get_second_peak_ratio(source_id, recorder_id, is_hsp=False):
"""Gets the second peak ratio suitable for use case.
@@ -410,12 +419,17 @@
# The deviation of estimated dominant frequency from golden frequency.
DEFAULT_FREQUENCY_DIFF_THRESHOLD = 5
+
def check_recorded_frequency(
- golden_file, recorder,
+ golden_file,
+ recorder,
second_peak_ratio=_DEFAULT_SECOND_PEAK_RATIO,
frequency_diff_threshold=DEFAULT_FREQUENCY_DIFF_THRESHOLD,
- ignore_frequencies=None, check_anomaly=False, check_artifacts=False,
- mute_durations=None, volume_changes=None,
+ ignore_frequencies=None,
+ check_anomaly=False,
+ check_artifacts=False,
+ mute_durations=None,
+ volume_changes=None,
tolerant_noise_level=DEFAULT_TOLERANT_NOISE_LEVEL):
"""Checks if the recorded data contains sine tone of golden frequency.
@@ -479,27 +493,27 @@
normalized_signal = audio_analysis.normalize_signal(
signal, saturate_value)
logging.debug('saturate_value: %f', saturate_value)
- logging.debug('max signal after normalized: %f', max(normalized_signal))
- spectral = audio_analysis.spectral_analysis(
- normalized_signal, data_format['rate'])
+ logging.debug('max signal after normalized: %f',
+ max(normalized_signal))
+ spectral = audio_analysis.spectral_analysis(normalized_signal,
+ data_format['rate'])
logging.debug('spectral: %s', spectral)
if not spectral:
- errors.append(
- 'Channel %d: Can not find dominant frequency.' %
- test_channel)
+ errors.append('Channel %d: Can not find dominant frequency.' %
+ test_channel)
golden_frequency = golden_file.frequencies[golden_channel]
logging.debug('Checking channel %s spectral %s against frequency %s',
- test_channel, spectral, golden_frequency)
+ test_channel, spectral, golden_frequency)
dominant_frequency = spectral[0][0]
if (abs(dominant_frequency - golden_frequency) >
- frequency_diff_threshold):
+ frequency_diff_threshold):
errors.append(
- 'Channel %d: Dominant frequency %s is away from golden %s' %
- (test_channel, dominant_frequency, golden_frequency))
+ 'Channel %d: Dominant frequency %s is away from golden %s'
+ % (test_channel, dominant_frequency, golden_frequency))
if check_anomaly:
detected_anomaly = audio_analysis.anomaly_detection(
@@ -507,9 +521,8 @@
rate=data_format['rate'],
freq=golden_frequency)
if detected_anomaly:
- errors.append(
- 'Channel %d: Detect anomaly near these time: %s' %
- (test_channel, detected_anomaly))
+ errors.append('Channel %d: Detect anomaly near these time: %s'
+ % (test_channel, detected_anomaly))
else:
logging.info(
'Channel %d: Quality is good as there is no anomaly',
@@ -517,24 +530,26 @@
if check_artifacts or mute_durations or volume_changes:
result = audio_quality_measurement.quality_measurement(
- normalized_signal,
- data_format['rate'],
- dominant_frequency=dominant_frequency)
- logging.debug('Quality measurement result:\n%s', pprint.pformat(result))
+ normalized_signal,
+ data_format['rate'],
+ dominant_frequency=dominant_frequency)
+ logging.debug('Quality measurement result:\n%s',
+ pprint.pformat(result))
if check_artifacts:
if len(result['artifacts']['noise_before_playback']) > 0:
errors.append(
- 'Channel %d: Detects artifacts before playing near'
- ' these time and duration: %s' %
- (test_channel,
- str(result['artifacts']['noise_before_playback'])))
+ 'Channel %d: Detects artifacts before playing near'
+ ' these time and duration: %s' %
+ (test_channel,
+ str(result['artifacts']['noise_before_playback']))
+ )
if len(result['artifacts']['noise_after_playback']) > 0:
errors.append(
- 'Channel %d: Detects artifacts after playing near'
- ' these time and duration: %s' %
- (test_channel,
- str(result['artifacts']['noise_after_playback'])))
+ 'Channel %d: Detects artifacts after playing near'
+ ' these time and duration: %s' %
+ (test_channel,
+ str(result['artifacts']['noise_after_playback'])))
if mute_durations:
delays = result['artifacts']['delay_during_playback']
@@ -542,45 +557,46 @@
for x in delays:
delay_durations.append(x[1])
mute_matched, delay_matched = longest_common_subsequence(
- mute_durations,
- delay_durations,
+ mute_durations, delay_durations,
DEFAULT_EQUIVALENT_THRESHOLD)
# updated delay list
- new_delays = [delays[i]
- for i in delay_matched if not delay_matched[i]]
+ new_delays = [
+ delays[i] for i in delay_matched
+ if not delay_matched[i]
+ ]
result['artifacts']['delay_during_playback'] = new_delays
- unmatched_mutes = [mute_durations[i]
- for i in mute_matched if not mute_matched[i]]
+ unmatched_mutes = [
+ mute_durations[i] for i in mute_matched
+ if not mute_matched[i]
+ ]
if len(unmatched_mutes) > 0:
- errors.append(
- 'Channel %d: Unmatched mute duration: %s' %
- (test_channel, unmatched_mutes))
+ errors.append('Channel %d: Unmatched mute duration: %s' %
+ (test_channel, unmatched_mutes))
if check_artifacts:
if len(result['artifacts']['delay_during_playback']) > 0:
errors.append(
- 'Channel %d: Detects delay during playing near'
- ' these time and duration: %s' %
- (test_channel,
- result['artifacts']['delay_during_playback']))
+ 'Channel %d: Detects delay during playing near'
+ ' these time and duration: %s' %
+ (test_channel,
+ result['artifacts']['delay_during_playback']))
if len(result['artifacts']['burst_during_playback']) > 0:
errors.append(
- 'Channel %d: Detects burst/pop near these time: %s' %
- (test_channel,
- result['artifacts']['burst_during_playback']))
+ 'Channel %d: Detects burst/pop near these time: %s'
+ % (test_channel,
+ result['artifacts']['burst_during_playback']))
if result['equivalent_noise_level'] > tolerant_noise_level:
errors.append(
- 'Channel %d: noise level is higher than tolerant'
- ' noise level: %f > %f' %
- (test_channel,
- result['equivalent_noise_level'],
- tolerant_noise_level))
+ 'Channel %d: noise level is higher than tolerant'
+ ' noise level: %f > %f' %
+ (test_channel, result['equivalent_noise_level'],
+ tolerant_noise_level))
if volume_changes:
matched = True
@@ -594,12 +610,10 @@
break
if not matched:
errors.append(
- 'Channel %d: volume changing is not as expected, '
- 'found changing time and events are: %s while '
- 'expected changing events are %s'%
- (test_channel,
- volume_changing,
- volume_changes))
+ 'Channel %d: volume changing is not as expected, '
+ 'found changing time and events are: %s while '
+ 'expected changing events are %s' %
+ (test_channel, volume_changing, volume_changes))
# Filter out the harmonics resulted from imperfect sin wave.
# This list is different for different channels.
@@ -617,23 +631,23 @@
@returns: True if the frequency should be ignored. False otherwise.
"""
- for ignore_frequency in (ignore_frequencies_harmonics + harmonics
- + [0.0]):
+ for ignore_frequency in (
+ ignore_frequencies_harmonics + harmonics + [0.0]):
if (abs(frequency - ignore_frequency) <
- frequency_diff_threshold):
+ frequency_diff_threshold):
logging.debug('Ignore frequency: %s', frequency)
return True
# Checks DC is small enough.
for freq, coeff in spectral:
if freq < _DC_FREQ_THRESHOLD and coeff > _DC_COEFF_THRESHOLD:
- errors.append(
- 'Channel %d: Found large DC coefficient: '
- '(%f Hz, %f)' % (test_channel, freq, coeff))
+ errors.append('Channel %d: Found large DC coefficient: '
+ '(%f Hz, %f)' % (test_channel, freq, coeff))
# Filter out the frequencies to be ignored.
spectral_post_ignore = [
- x for x in spectral if not should_be_ignored(x[0])]
+ x for x in spectral if not should_be_ignored(x[0])
+ ]
if len(spectral_post_ignore) > 1:
first_coeff = spectral_post_ignore[0][1]
@@ -647,8 +661,8 @@
errors.append(
'Channel %d: No frequency left after removing unwanted '
'frequencies. Spectral: %s; After removing unwanted '
- 'frequencies: %s' %
- (test_channel, spectral, spectral_post_ignore))
+ 'frequencies: %s' % (test_channel, spectral,
+ spectral_post_ignore))
else:
dominant_spectrals.append(spectral_post_ignore[0])
@@ -724,7 +738,9 @@
audio_facade.set_chrome_active_node_type(None, 'BLUETOOTH')
check_audio_nodes(audio_facade, (None, ['BLUETOOTH']))
audio_facade.start_recording(
- dict(file_type='raw', sample_format='S16_LE', channel=2,
+ dict(file_type='raw',
+ sample_format='S16_LE',
+ channel=2,
rate=48000))
@@ -747,31 +763,30 @@
parameters)
-def check_and_set_chrome_active_node_types(audio_facade, output_type=None,
+def check_and_set_chrome_active_node_types(audio_facade,
+ output_type=None,
input_type=None):
- """Check the target types are available, and set them to be active nodes.
+ """Check the target types are available, and set them to be active nodes.
- @param audio_facade: An AudioFacadeNative or AudioFacadeAdapter object.
- @output_type: An output node type defined in cras_utils.CRAS_NODE_TYPES.
+ @param audio_facade: An AudioFacadeNative or AudioFacadeAdapter object.
+ @output_type: An output node type defined in cras_utils.CRAS_NODE_TYPES.
None to skip.
- @input_type: An input node type defined in cras_utils.CRAS_NODE_TYPES.
+ @input_type: An input node type defined in cras_utils.CRAS_NODE_TYPES.
None to skip.
- @raises: error.TestError if the expected node type is missing. We use
- error.TestError here because usually this step is not the main
- purpose of the test, but a setup step.
+ @raises: error.TestError if the expected node type is missing. We use
+ error.TestError here because usually this step is not the main
+ purpose of the test, but a setup step.
- """
- output_types, input_types = audio_facade.get_plugged_node_types()
- logging.debug('Plugged types: output: %r, input: %r',
- output_types, input_types)
- if output_type and output_type not in output_types:
- raise error.TestError(
- 'Target output type %s not present' % output_type)
- if input_type and input_type not in input_types:
- raise error.TestError(
- 'Target input type %s not present' % input_type)
- audio_facade.set_chrome_active_node_type(output_type, input_type)
+ """
+ output_types, input_types = audio_facade.get_plugged_node_types()
+ if output_type and output_type not in output_types:
+ raise error.TestError('Target output type %s not present in %r' %
+ (output_type, output_types))
+ if input_type and input_type not in input_types:
+ raise error.TestError('Target input type %s not present in %r' %
+ (input_type, input_types))
+ audio_facade.set_chrome_active_node_type(output_type, input_type)
def check_hp_or_lineout_plugged(audio_facade):
@@ -793,7 +808,9 @@
return 'LINEOUT'
if 'HEADPHONE' in output_nodes:
return 'HEADPHONE'
- raise error.TestFail('Can not detect line-out or headphone')
+ raise error.TestFail(
+ 'No line-out or headphone in plugged nodes:%r.'
+ 'Please check the audio cable or jack plugger.' % output_nodes)
def get_internal_mic_node(host):
diff --git a/server/cros/audio/audio_test.py b/server/cros/audio/audio_test.py
index ee21d6b..9d72a58 100644
--- a/server/cros/audio/audio_test.py
+++ b/server/cros/audio/audio_test.py
@@ -6,26 +6,46 @@
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
+from autotest_lib.client.cros.chameleon import chameleon_audio_helper
from autotest_lib.server import site_utils
from autotest_lib.server import test
+from autotest_lib.server.cros.multimedia import remote_facade_factory
from autotest_lib.site_utils import lxc
class AudioTest(test.test):
"""Base class for audio tests.
- AudioTest provides a common warmup() function for the collection
- of audio tests.
- It is not mandatory to use this base class for audio tests, it is for
- convenience only.
-
+ AudioTest provides basic initialization, setup and warmup check for the
+ collection of server side audio tests. It is assumed to be run with a
+ Chameleon audio boards. It is recommended to use this base class for server
+ side Chameleon audio tests to take advantage of the initialize, setup and
+ sanity check.
"""
+ def initialize(self, host):
+ """Initialize audio test needed components and do some sanity checks"""
+ if host.chameleon is None:
+ raise error.TestError("host.chameleon is None."
+ "Please check the chameleon of this DUT.")
+
+ self.host = host
+ self.factory = remote_facade_factory.RemoteFacadeFactory(
+ host, results_dir=self.resultsdir)
+ self.widget_factory = chameleon_audio_helper.AudioWidgetFactory(
+ self.factory, self.host)
+ self.facade = self.factory.create_audio_facade()
+ host.chameleon.setup_and_reset(self.resultsdir)
+
+ def setup(self):
+ """Setup needed audio test requirement before executing main logic."""
+ super(AudioTest, self).setup()
+ audio_test_requirement()
+
def warmup(self):
"""Warmup for the test before executing main logic of the test."""
# test.test is an old-style class.
test.test.warmup(self)
- audio_test_requirement()
def audio_test_requirement():
diff --git a/server/site_tests/audio_AudioBasicExternalMicrophone/audio_AudioBasicExternalMicrophone.py b/server/site_tests/audio_AudioBasicExternalMicrophone/audio_AudioBasicExternalMicrophone.py
index ac2e9d4..98fd3e6 100644
--- a/server/site_tests/audio_AudioBasicExternalMicrophone/audio_AudioBasicExternalMicrophone.py
+++ b/server/site_tests/audio_AudioBasicExternalMicrophone/audio_AudioBasicExternalMicrophone.py
@@ -1,20 +1,17 @@
# Copyright 2015 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 external microphone test using the Chameleon board."""
import logging
import os
import time
-from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.audio import audio_test_data
from autotest_lib.client.cros.chameleon import audio_test_utils
from autotest_lib.client.cros.chameleon import chameleon_audio_ids
from autotest_lib.client.cros.chameleon import chameleon_audio_helper
from autotest_lib.server.cros.audio import audio_test
-from autotest_lib.server.cros.multimedia import remote_facade_factory
class audio_AudioBasicExternalMicrophone(audio_test.AudioTest):
@@ -29,43 +26,30 @@
RECORD_SECONDS = 9
DELAY_AFTER_BINDING = 0.5
- def run_once(self, host, check_quality=False):
+ def run_once(self, check_quality=False):
"""Running basic headphone audio tests.
- @param host: device under test host
@param check_quality: flag to check audio quality.
"""
golden_file = audio_test_data.SIMPLE_FREQUENCY_TEST_1330_FILE
- chameleon_board = host.chameleon
- factory = remote_facade_factory.RemoteFacadeFactory(
- host, results_dir=self.resultsdir)
-
- chameleon_board.setup_and_reset(self.outputdir)
-
- widget_factory = chameleon_audio_helper.AudioWidgetFactory(
- factory, host)
-
- source = widget_factory.create_widget(
- chameleon_audio_ids.ChameleonIds.LINEOUT)
- recorder = widget_factory.create_widget(
- chameleon_audio_ids.CrosIds.EXTERNAL_MIC)
- binder = widget_factory.create_binder(source, recorder)
+ source = self.widget_factory.create_widget(
+ chameleon_audio_ids.ChameleonIds.LINEOUT)
+ recorder = self.widget_factory.create_widget(
+ chameleon_audio_ids.CrosIds.EXTERNAL_MIC)
+ binder = self.widget_factory.create_binder(source, recorder)
with chameleon_audio_helper.bind_widgets(binder):
# Checks the node selected by cras is correct.
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')
+ self.host, self.facade, self.resultsdir, 'after_binding')
- _, input_nodes = audio_facade.get_selected_node_types()
- if input_nodes != ['MIC']:
- raise error.TestFail(
- '%s rather than external mic is selected on Cros '
- 'device' % input_nodes)
+ # Selects and checks the node selected by cras is correct.
+ audio_test_utils.check_and_set_chrome_active_node_types(
+ self.facade, None, 'MIC')
logging.info('Setting playback data on Chameleon')
source.set_playback_data(golden_file)
@@ -73,8 +57,7 @@
# Starts playing, waits for some time, and then starts recording.
# This is to avoid artifact caused by chameleon codec initialization
# in the beginning of playback.
- logging.info('Start playing %s from Chameleon',
- golden_file.path)
+ logging.info('Start playing %s from Chameleon', golden_file.path)
source.start_playback()
time.sleep(self.DELAY_BEFORE_RECORD_SECONDS)
@@ -87,7 +70,7 @@
logging.info('Stopped recording from Cros device.')
audio_test_utils.dump_cros_audio_logs(
- host, audio_facade, self.resultsdir, 'after_recording')
+ self.host, self.facade, self.resultsdir, 'after_recording')
recorder.read_recorded_binary()
logging.info('Read recorded binary from Cros device.')
@@ -112,5 +95,7 @@
# correlation, which is suitable for fully-digital audio path like USB
# and HDMI.
audio_test_utils.check_recorded_frequency(
- golden_file, recorder, check_artifacts=check_quality,
+ golden_file,
+ recorder,
+ check_artifacts=check_quality,
ignore_frequencies=[50, 60])
diff --git a/server/site_tests/audio_AudioBasicHeadphone/audio_AudioBasicHeadphone.py b/server/site_tests/audio_AudioBasicHeadphone/audio_AudioBasicHeadphone.py
index c2ca4b0..ec6f1d5 100644
--- a/server/site_tests/audio_AudioBasicHeadphone/audio_AudioBasicHeadphone.py
+++ b/server/site_tests/audio_AudioBasicHeadphone/audio_AudioBasicHeadphone.py
@@ -1,20 +1,17 @@
# 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.
-
"""This is a server side headphone audio test using the Chameleon board."""
import logging
import os
import time
-from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.audio import audio_test_data
from autotest_lib.client.cros.chameleon import audio_test_utils
from autotest_lib.client.cros.chameleon import chameleon_audio_ids
from autotest_lib.client.cros.chameleon import chameleon_audio_helper
from autotest_lib.server.cros.audio import audio_test
-from autotest_lib.server.cros.multimedia import remote_facade_factory
class audio_AudioBasicHeadphone(audio_test.AudioTest):
@@ -30,50 +27,38 @@
DELAY_AFTER_BINDING = 0.5
SILENCE_WAIT = 5
- def run_once(self, host, check_quality=False):
+ def run_once(self, check_quality=False):
"""Running basic headphone audio tests.
- @param host: device under test host
@param check_quality: flag to check audio quality.
-
"""
- if not audio_test_utils.has_headphone(host):
+ if not audio_test_utils.has_headphone(self.host):
return
golden_file = audio_test_data.FREQUENCY_TEST_FILE
- chameleon_board = host.chameleon
- factory = remote_facade_factory.RemoteFacadeFactory(
- host, results_dir=self.resultsdir)
-
- chameleon_board.setup_and_reset(self.outputdir)
-
- widget_factory = chameleon_audio_helper.AudioWidgetFactory(
- factory, host)
-
- source = widget_factory.create_widget(
- chameleon_audio_ids.CrosIds.HEADPHONE)
- recorder = widget_factory.create_widget(
- chameleon_audio_ids.ChameleonIds.LINEIN)
- binder = widget_factory.create_binder(source, recorder)
+ source = self.widget_factory.create_widget(
+ chameleon_audio_ids.CrosIds.HEADPHONE)
+ recorder = self.widget_factory.create_widget(
+ chameleon_audio_ids.ChameleonIds.LINEIN)
+ binder = self.widget_factory.create_binder(source, recorder)
with chameleon_audio_helper.bind_widgets(binder):
- # Checks the node selected by cras is correct.
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')
+ self.host, self.facade, self.resultsdir, 'after_binding')
- audio_test_utils.check_audio_nodes(audio_facade, (['HEADPHONE'], None))
+ # Selects and checks the node selected by cras is correct.
+ audio_test_utils.check_and_set_chrome_active_node_types(
+ self.facade, 'HEADPHONE', None)
logging.info('Setting playback data on Cros device')
source.set_playback_data(golden_file)
# Starts playing, waits for some time, and then starts recording.
# This is to avoid artifact caused by codec initialization.
- logging.info('Start playing %s on Cros device',
- golden_file.path)
+ logging.info('Start playing %s on Cros device', golden_file.path)
source.start_playback()
time.sleep(self.DELAY_BEFORE_RECORD_SECONDS)
@@ -91,7 +76,7 @@
logging.info('Stopped recording from Chameleon.')
audio_test_utils.dump_cros_audio_logs(
- host, audio_facade, self.resultsdir, 'after_recording')
+ self.host, self.facade, self.resultsdir, 'after_recording')
recorder.read_recorded_binary()
logging.info('Read recorded binary from Chameleon.')
diff --git a/server/site_tests/audio_AudioBasicInternalMicrophone/audio_AudioBasicInternalMicrophone.py b/server/site_tests/audio_AudioBasicInternalMicrophone/audio_AudioBasicInternalMicrophone.py
index 1f1db8b..65627db 100644
--- a/server/site_tests/audio_AudioBasicInternalMicrophone/audio_AudioBasicInternalMicrophone.py
+++ b/server/site_tests/audio_AudioBasicInternalMicrophone/audio_AudioBasicInternalMicrophone.py
@@ -1,7 +1,6 @@
# Copyright 2015 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 internal microphone test using the Chameleon board."""
import logging
@@ -10,10 +9,9 @@
from autotest_lib.client.cros.audio import audio_test_data
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.chameleon import chameleon_audio_helper
from autotest_lib.server.cros.audio import audio_test
-from autotest_lib.server.cros.multimedia import remote_facade_factory
class audio_AudioBasicInternalMicrophone(audio_test.AudioTest):
@@ -28,47 +26,33 @@
RECORD_SECONDS = 9
DELAY_AFTER_BINDING = 0.5
- def run_once(self, host):
- """Runs Basic Audio Microphone test.
-
- @param host: device under test CrosHost
- """
- if not audio_test_utils.has_internal_microphone(host):
+ def run_once(self):
+ """Runs Basic Audio Microphone test."""
+ if not audio_test_utils.has_internal_microphone(self.host):
return
golden_file = audio_test_data.SIMPLE_FREQUENCY_TEST_1330_FILE
- chameleon_board = host.chameleon
- factory = remote_facade_factory.RemoteFacadeFactory(
- host, results_dir=self.resultsdir)
+ source = self.widget_factory.create_widget(
+ chameleon_audio_ids.ChameleonIds.LINEOUT)
+ sink = self.widget_factory.create_widget(
+ chameleon_audio_ids.PeripheralIds.SPEAKER)
+ binder = self.widget_factory.create_binder(source, sink)
- chameleon_board.setup_and_reset(self.outputdir)
-
- widget_factory = chameleon_audio_helper.AudioWidgetFactory(
- factory, host)
-
- source = widget_factory.create_widget(
- chameleon_audio_ids.ChameleonIds.LINEOUT)
- sink = widget_factory.create_widget(
- chameleon_audio_ids.PeripheralIds.SPEAKER)
- binder = widget_factory.create_binder(source, sink)
-
- recorder = widget_factory.create_widget(
- chameleon_audio_ids.CrosIds.INTERNAL_MIC)
+ recorder = self.widget_factory.create_widget(
+ chameleon_audio_ids.CrosIds.INTERNAL_MIC)
with chameleon_audio_helper.bind_widgets(binder):
# Checks the node selected by cras is correct.
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')
+ self.host, self.facade, self.resultsdir, 'after_binding')
- expected_internal_mic_node = audio_test_utils.get_internal_mic_node(
- host)
-
- audio_test_utils.check_audio_nodes(
- audio_facade, (None, [expected_internal_mic_node]))
+ # Selects and checks the node selected by cras is correct.
+ audio_test_utils.check_and_set_chrome_active_node_types(
+ self.facade, None,
+ audio_test_utils.get_internal_mic_node(self.host))
logging.info('Setting playback data on Chameleon')
source.set_playback_data(golden_file)
@@ -76,8 +60,7 @@
# Starts playing, waits for some time, and then starts recording.
# This is to avoid artifact caused by chameleon codec initialization
# in the beginning of playback.
- logging.info('Start playing %s from Chameleon',
- golden_file.path)
+ logging.info('Start playing %s from Chameleon', golden_file.path)
source.start_playback()
time.sleep(self.DELAY_BEFORE_RECORD_SECONDS)
@@ -90,7 +73,7 @@
logging.info('Stopped recording from Cros device.')
audio_test_utils.dump_cros_audio_logs(
- host, audio_facade, self.resultsdir, 'after_recording')
+ self.host, self.facade, self.resultsdir, 'after_recording')
recorder.read_recorded_binary()
logging.info('Read recorded binary from Cros device.')
@@ -123,5 +106,5 @@
# Comparing data by frequency is more robust than comparing them by
# correlation, which is suitable for fully-digital audio path like USB
# and HDMI.
- audio_test_utils.check_recorded_frequency(golden_file, recorder,
- second_peak_ratio=0.2)
+ audio_test_utils.check_recorded_frequency(
+ golden_file, recorder, second_peak_ratio=0.2)
diff --git a/server/site_tests/audio_AudioBasicInternalSpeaker/audio_AudioBasicInternalSpeaker.py b/server/site_tests/audio_AudioBasicInternalSpeaker/audio_AudioBasicInternalSpeaker.py
index ba12cd0..fc460d9 100644
--- a/server/site_tests/audio_AudioBasicInternalSpeaker/audio_AudioBasicInternalSpeaker.py
+++ b/server/site_tests/audio_AudioBasicInternalSpeaker/audio_AudioBasicInternalSpeaker.py
@@ -1,7 +1,6 @@
# Copyright 2015 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 internal speaker test using the Chameleon board."""
import logging
@@ -10,10 +9,8 @@
from autotest_lib.client.cros.audio import audio_test_data
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.server.cros.audio import audio_test
-from autotest_lib.server.cros.multimedia import remote_facade_factory
class audio_AudioBasicInternalSpeaker(audio_test.AudioTest):
@@ -27,49 +24,34 @@
DELAY_BEFORE_RECORD_SECONDS = 0.5
RECORD_SECONDS = 8
- def run_once(self, host):
- """Runs Basic Audio Speaker test.
-
- @param host: device under test CrosHost
- """
- if not audio_test_utils.has_internal_speaker(host):
+ def run_once(self):
+ """Runs Basic Audio Speaker test."""
+ if not audio_test_utils.has_internal_speaker(self.host):
return
golden_file = audio_test_data.SIMPLE_FREQUENCY_SPEAKER_TEST_FILE
- chameleon_board = host.chameleon
- factory = remote_facade_factory.RemoteFacadeFactory(
- host, results_dir=self.resultsdir)
+ source = self.widget_factory.create_widget(
+ chameleon_audio_ids.CrosIds.SPEAKER)
- chameleon_board.setup_and_reset(self.outputdir)
+ recorder = self.widget_factory.create_widget(
+ chameleon_audio_ids.ChameleonIds.MIC)
- widget_factory = chameleon_audio_helper.AudioWidgetFactory(
- factory, host)
+ audio_test_utils.dump_cros_audio_logs(self.host, self.facade,
+ self.resultsdir, 'start')
- source = widget_factory.create_widget(
- chameleon_audio_ids.CrosIds.SPEAKER)
+ # Selects and checks the node selected by cras is correct.
+ audio_test_utils.check_and_set_chrome_active_node_types(
+ self.facade, 'INTERNAL_SPEAKER', None)
- recorder = widget_factory.create_widget(
- chameleon_audio_ids.ChameleonIds.MIC)
-
- audio_facade = factory.create_audio_facade()
-
- audio_test_utils.dump_cros_audio_logs(
- host, audio_facade, self.resultsdir, 'start')
-
- # Checks the node selected by cras is correct.
- audio_test_utils.check_audio_nodes(audio_facade,
- (['INTERNAL_SPEAKER'], None))
-
- audio_facade.set_selected_output_volume(80)
+ self.facade.set_selected_output_volume(80)
logging.info('Setting playback data on Cros device')
source.set_playback_data(golden_file)
# Starts playing, waits for some time, and then starts recording.
# This is to avoid artifact caused by codec initialization.
- logging.info('Start playing %s on Cros device',
- golden_file.path)
+ logging.info('Start playing %s on Cros device', golden_file.path)
source.start_playback()
time.sleep(self.DELAY_BEFORE_RECORD_SECONDS)
@@ -77,12 +59,12 @@
recorder.start_recording()
time.sleep(self.RECORD_SECONDS)
- audio_facade.check_audio_stream_at_selected_device()
+ self.facade.check_audio_stream_at_selected_device()
recorder.stop_recording()
logging.info('Stopped recording from Chameleon.')
audio_test_utils.dump_cros_audio_logs(
- host, audio_facade, self.resultsdir, 'after_recording')
+ self.host, self.facade, self.resultsdir, 'after_recording')
recorder.read_recorded_binary()
logging.info('Read recorded binary from Chameleon.')
@@ -108,6 +90,8 @@
# Comparing data by frequency is more robust than comparing by
# correlation, which is suitable for fully-digital audio path like USB
# and HDMI.
- audio_test_utils.check_recorded_frequency(golden_file, recorder,
- second_peak_ratio=0.1,
- ignore_frequencies=[50, 60])
+ audio_test_utils.check_recorded_frequency(
+ golden_file,
+ recorder,
+ second_peak_ratio=0.1,
+ ignore_frequencies=[50, 60])
diff --git a/server/site_tests/audio_InternalCardNodes/audio_InternalCardNodes.py b/server/site_tests/audio_InternalCardNodes/audio_InternalCardNodes.py
index 591d466..e541ae3 100644
--- a/server/site_tests/audio_InternalCardNodes/audio_InternalCardNodes.py
+++ b/server/site_tests/audio_InternalCardNodes/audio_InternalCardNodes.py
@@ -1,16 +1,10 @@
# Copyright 2015 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 test to check nodes created for internal card."""
-import time
-
-from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.chameleon import audio_test_utils
from autotest_lib.server.cros.audio import audio_test
-from autotest_lib.client.cros.audio import audio_spec
-from autotest_lib.server.cros.multimedia import remote_facade_factory
class audio_InternalCardNodes(audio_test.AudioTest):
@@ -21,96 +15,39 @@
"""
version = 1
- DELAY_AFTER_PLUGGING = 2
- DELAY_AFTER_UNPLUGGING = 2
- def run_once(self, host):
- """Runs InternalCardNodes test.
+ def get_expected_nodes(self, plugged):
+ """Gets expected nodes should should be created for internal cards.
- @param host: device under test CrosHost.
-
+ @param plugged: True for plugged state, false otherwise.
+ @returns:
+ a tuple (output, input) containing lists of expected input and
+ output nodes.
"""
- chameleon_board = host.chameleon
- factory = remote_facade_factory.RemoteFacadeFactory(
- host, results_dir=self.resultsdir)
- audio_facade = factory.create_audio_facade()
-
- chameleon_board.setup_and_reset(self.outputdir)
-
- jack_plugger = chameleon_board.get_audio_board().get_jack_plugger()
-
- expected_plugged_nodes_without_audio_jack = (
- [],
- ['POST_DSP_LOOPBACK',
- 'POST_MIX_LOOPBACK'])
-
- # 'Headphone' or 'LINEOUT' will be added to expected list after jack
- # is plugged.
- expected_plugged_nodes_with_audio_jack = (
- [],
- ['MIC', 'POST_DSP_LOOPBACK',
- 'POST_MIX_LOOPBACK'])
-
- # Modify expected nodes for special boards.
- board_name = host.get_board().split(':')[1]
- model_name = host.get_platform()
-
- if audio_test_utils.has_internal_speaker(host):
- expected_plugged_nodes_without_audio_jack[0].append(
- 'INTERNAL_SPEAKER')
- expected_plugged_nodes_with_audio_jack[0].append(
- 'INTERNAL_SPEAKER')
-
- if audio_test_utils.has_internal_microphone(host):
- expected_internal_mics = audio_test_utils.get_plugged_internal_mics(
- host)
- expected_plugged_nodes_without_audio_jack[1].extend(
- expected_internal_mics)
- expected_plugged_nodes_with_audio_jack[1].extend(
- expected_internal_mics)
-
- if board_name == 'link':
- expected_plugged_nodes_without_audio_jack[1].append('KEYBOARD_MIC')
- expected_plugged_nodes_with_audio_jack[1].append('KEYBOARD_MIC')
-
- if audio_spec.has_hotwording(board_name, model_name):
- expected_plugged_nodes_without_audio_jack[1].append('HOTWORD')
- expected_plugged_nodes_with_audio_jack[1].append('HOTWORD')
-
- # If there is no jack plugger, check the nodes without plugging.
- host_info = host.host_info_store.get()
- if jack_plugger is None:
- if 'audio_box' in host_info.labels:
- raise error.TestError("Failed to detect jack plugger.")
- hp_jack_node_type = audio_test_utils.check_hp_or_lineout_plugged(
- audio_facade)
- expected_plugged_nodes_with_audio_jack[0].append(hp_jack_node_type)
-
- audio_test_utils.check_plugged_nodes(
- audio_facade, expected_plugged_nodes_with_audio_jack)
- return
-
- audio_test_utils.check_plugged_nodes(
- audio_facade, expected_plugged_nodes_without_audio_jack)
-
- try:
- jack_plugger.plug()
- time.sleep(self.DELAY_AFTER_PLUGGING)
-
- audio_test_utils.dump_cros_audio_logs(
- host, audio_facade, self.resultsdir)
-
+ nodes = ([], ['POST_DSP_LOOPBACK', 'POST_MIX_LOOPBACK'])
+ if plugged:
# Checks whether line-out or headphone is detected.
hp_jack_node_type = audio_test_utils.check_hp_or_lineout_plugged(
- audio_facade)
- expected_plugged_nodes_with_audio_jack[0].append(hp_jack_node_type)
+ self.facade)
+ nodes[0].append(hp_jack_node_type)
+ nodes[1].append('MIC')
+ if audio_test_utils.has_internal_speaker(self.host):
+ nodes[0].append('INTERNAL_SPEAKER')
+ if audio_test_utils.has_internal_microphone(self.host):
+ nodes[1].extend(
+ audio_test_utils.get_plugged_internal_mics(self.host))
+ if audio_test_utils.has_hotwording(self.host):
+ nodes[1].append('HOTWORD')
+ return nodes
- audio_test_utils.check_plugged_nodes(
- audio_facade, expected_plugged_nodes_with_audio_jack)
+ def run_once(self):
+ """Runs InternalCardNodes test."""
+ jack_plugger = self.host.chameleon.get_audio_board().get_jack_plugger()
- finally:
- jack_plugger.unplug()
- time.sleep(self.DELAY_AFTER_UNPLUGGING)
+ jack_plugger.plug()
+ audio_test_utils.check_plugged_nodes(self.facade,
+ self.get_expected_nodes(True))
- audio_test_utils.check_plugged_nodes(
- audio_facade, expected_plugged_nodes_without_audio_jack)
+ jack_plugger.unplug()
+ audio_test_utils.check_plugged_nodes(self.facade,
+ self.get_expected_nodes(False))