blob: 83885c947ef2c7367062e4ba8fb6897e80f54d10 [file] [log] [blame]
# Copyright (c) 2011 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.
from autotest_lib.client.common_lib import error
from autotest_lib.client.bin import test, utils
import os
class sound_infrastructure(test.test):
"""
Tests that the expected sound infrastructure is present.
If a control or file is found to be missing, that would imply that
the driver has changed, and this will have an impact on the entire
sound system.
o Missing control
Regenerate '/etc/asound.state' for each board which is missing
the control.
- Log in to console on device.
- Set all controls to desired levels.
- Execute 'alsactl --file /tmp/asound.state store'.
- Copy new '/tmp/asound.state' from device to correct place
in source tree. The correct place should normally
correspond to the 'audioconfig-board' ebuild file for that
specific board.
Search the Chromium OS & Chromium sources for that missing
control name. If there are references to that control name,
adjust the sources as necessary.
o Added control (TODO(thutt): added controls not yet checked)
Regenerate '/etc/asound.state' for each affected board.
Validate that sound controls still work on each affected target
device:
Volume Up, Volume Down, Mute
Any UI for controlling AV output
Notify Chrome developers, if necessary, of new control.
Notify GTalk developers, if necessary, of new control.
o Missing file, added file
I don't know what implications this might have, so use caution
here and update these instructions in the case that this
occurs.
At the very least, verify that everything still functions.
Before submitting the fixes, test & verify:
o Sound controls still work on each affected target device
Volume Up, Volume Down, Mute
Any UI for controlling AV output
o I/O devices continue to work
Headphone,
Internal Speakers
HDMI
Internal Mic
o Notify Chrome developers, if necessary, of removed control.
o Notify GTalk developers, if necessary, of removed control.
o Notify Flash player developers, if necessary, of removed control.
o To create 'controls' data file:
Execute the following on the DUT:
amixer controls >{codec-name}.controls
{codec-name} should be replaced with the name of the codec.
Replace spaces in the codec name with '_'.
See get_codec() to help determine the name of the codec.
o To create 'files' data file:
Execute the following on the DUT:
tar --absolute-names -c /dev/snd /proc/asound 2>/dev/null| \
tar -t 2>/dev/null|sed -e 's./$..g' >{codec-name}.files
{codec-name} should be replaced with the name of the codec.
Replace spaces in the codec name with '_'.
See get_codec() to help determine the name of the codec.
"""
version = 1
codec_info = {
'ALL': { # Things common to all sound codecs
'controls': [ ],
'files': [
'/etc/init/adhd.conf', # Upstart script, from ADHD package
'/etc/asound.state', # Factory defaults. From ADHD.
'/usr/bin/alsamixer',
'/usr/bin/amixer',
'/usr/sbin/alsactl',
'/usr/share/alsa/init/00main',
'/usr/share/alsa/init/default',
'/usr/share/alsa/init/hda',
'/usr/share/alsa/init/help',
'/usr/share/alsa/init/info',
'/usr/share/alsa/init/test',
]
},
'WM8903': {
'controls': [ ], # See above for creating 'controls' and 'files'.
'files' : [ ],
},
'ALC271X': {
'controls': [ ],
'files' : [ ],
},
'Cirrus Analog': {
'controls': [ ],
'files' : [ ],
},
'ALC272': {
'controls': [ ],
'files' : [ ],
}
}
def exec_cmd(self, cmd):
return utils.system(cmd, ignore_status = True)
def pathname_must_exist(self, pathname):
if not os.path.exists(pathname):
raise error.TestError("File missing: '%s'" % (pathname))
def control_must_exist(self, control):
if self.exec_cmd("amixer controls|grep -e \"%s\"" % (control)) != 0:
raise error.TestError("Control missing: '%s'" % (control))
def get_codec(self):
# When the codec cannot be determined, the whole test cannot
# proceed. The unknown codec name must be added to 'codecs'
# below, and the associated attributes must be put into
# 'codec_info' above.
codecs = [ 'ALC272', # Mario, Alex
'WM8903', # Seaboard, Aebl, Kaen, Asymptote
'ALC271X', # ZGB
'Cirrus Analog' # Stumpy
]
for c in codecs:
if self.exec_cmd("aplay -l|grep -e '%s'" % (c)) == 0:
return c
raise error.TestError('Unable to determine sound codec.')
def get_codec_basename(self, codec):
return codec.replace(' ', '_')
def get_data_pathname(self, filename):
return os.path.join(self.bindir, filename)
def validate_files(self, files_list):
for f in files_list:
self.pathname_must_exist(f)
def validate_controls(self, controls_list):
for c in controls_list:
self.control_must_exist(c)
def validate_codec(self, codec):
self.validate_files(codec['files'])
self.validate_controls(codec['controls'])
def read_codec_data(self, codec):
codec_basename = self.get_codec_basename(codec)
# Read controls which must be present.
pathname = self.get_data_pathname(codec_basename + ".controls")
self.codec_info[codec]['controls'] = [line.strip() for line in
open(pathname)]
# Read files which must be present.
pathname = self.get_data_pathname(codec_basename + ".files")
self.codec_info[codec]['files'] = [line.strip() for line in
open(pathname)]
def load_asound_state(self):
if self.exec_cmd("alsactl --file /etc/asound.state restore") != 0:
raise error.TestError("Unable to load /etc/asound.state")
def run_once(self):
codec = self.get_codec()
self.read_codec_data(codec)
if codec in self.codec_info:
self.validate_codec(self.codec_info['ALL'])
self.validate_codec(self.codec_info[codec])
else:
raise error.TestError("No test info for codec '%s'." % (codec))
self.load_asound_state()