• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import glob
6import os
7import re
8import stat
9import subprocess
10
11from autotest_lib.client.common_lib import error
12from autotest_lib.client.bin import test
13from autotest_lib.client.bin import utils
14
15_SND_DEV_DIR = '/dev/snd/'
16_SND_DEFAULT_MASK = 'controlC*'
17
18class 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