1 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import glob 6 import os 7 import re 8 import stat 9 import subprocess 10 11 from autotest_lib.client.common_lib import error 12 from autotest_lib.client.bin import test 13 from autotest_lib.client.bin import utils 14 15 _SND_DEV_DIR = '/dev/snd/' 16 _SND_DEFAULT_MASK = 'controlC*' 17 18 class sound_infrastructure(test.test): 19 """ 20 Tests that the expected sound infrastructure is present. 21 22 Check that at least one playback and capture device exists and that their 23 permissions are configured properly. 24 25 """ 26 version = 2 27 _NO_PLAYBACK_BOARDS_LIST = [] 28 _NO_RECORDER_BOARDS_LIST = ['veyron_mickey'] 29 _NO_AUDIO_DEVICE_LIST = ['veyron_rialto'] 30 31 def check_snd_dev_perms(self, filename): 32 desired_mode = (stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | 33 stat.S_IWGRP | stat.S_IFCHR) 34 st = os.stat(filename) 35 if (st.st_mode != desired_mode): 36 raise error.TestFail("Incorrect permissions for %s" % filename) 37 38 def check_sound_files(self, playback=True, record=True): 39 """Checks sound files present in snd directory. 40 41 @param playback: Checks playback device. 42 @param record: Checks record device. 43 44 @raises: error.TestFail if sound file is missing. 45 46 """ 47 patterns = {'^controlC(\d+)': False} 48 if playback: 49 patterns['^pcmC(\d+)D(\d+)p$'] = False 50 if record: 51 patterns['^pcmC(\d+)D(\d+)c$'] = False 52 53 filenames = os.listdir(_SND_DEV_DIR) 54 55 for filename in filenames: 56 for pattern in patterns: 57 if re.match(pattern, filename): 58 patterns[pattern] = True 59 self.check_snd_dev_perms(_SND_DEV_DIR + filename) 60 61 for pattern in patterns: 62 if not patterns[pattern]: 63 raise error.TestFail("Missing device %s" % pattern) 64 65 def check_device_list(self, playback=True, record=True): 66 """Checks sound card and device list by alsa utils command. 67 68 @param playback: Checks playback sound card and devices. 69 @param record: Checks record sound card and devices. 70 71 @raises: error.TestFail if no playback/record devices found. 72 73 """ 74 no_cards_pattern = '.*no soundcards found.*' 75 if playback: 76 aplay = subprocess.Popen(["aplay", "-l"], stderr=subprocess.PIPE) 77 aplay_list = aplay.communicate()[1] 78 if aplay.returncode or re.match(no_cards_pattern, aplay_list): 79 raise error.TestFail("No playback devices found by aplay") 80 81 if record: 82 no_cards_pattern = '.*no soundcards found.*' 83 arecord = subprocess.Popen( 84 ["arecord", "-l"], stderr=subprocess.PIPE) 85 arecord_list = arecord.communicate()[1] 86 if arecord.returncode or re.match(no_cards_pattern, arecord_list): 87 raise error.TestFail("No record devices found by arecord") 88 89 def run_once(self): 90 board = utils.get_board().lower() 91 snd_control = len(glob.glob(_SND_DEV_DIR + _SND_DEFAULT_MASK)) 92 if board in self._NO_AUDIO_DEVICE_LIST: 93 if snd_control: 94 raise error.TestError('%s is not supposed to have sound control!' % board) 95 else: 96 return 97 record = board not in self._NO_RECORDER_BOARDS_LIST 98 playback = board not in self._NO_PLAYBACK_BOARDS_LIST 99 self.check_sound_files(playback, record) 100 self.check_device_list(playback, record) 101