168 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Python
		
	
	
	
| # Copyright 2016 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 os
 | |
| import re
 | |
| 
 | |
| 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
 | |
| 
 | |
| class audio_AlsaAPI(test.test):
 | |
|     """Checks that simple ALSA API functions correctly."""
 | |
|     version = 2
 | |
|     _SND_DEV_DIR = '/dev/snd/'
 | |
|     _PLAYBACK_DEVICE_NAME = '^pcmC(\d+)D(\d+)p$'
 | |
|     # A list of boards that do not correctly implement snd_pcm_drop, see
 | |
|     # crosbug.com/p/51882
 | |
|     _BOARDS_WITHOUT_DROP_SUPPORT = ['banon', 'elm', 'samus', 'squawks']
 | |
|     # A dict of list of (card name, device) to be skipped on some boards.
 | |
|     _DEVICES_TO_BE_SKIPPED = {
 | |
|         # On the following boards, devices 4,5,6 are HDMI devices.
 | |
|         'asuka': {'sklnau8825max': [4, 5, 6]},
 | |
|         'cave': {'sklnau8825max': [4, 5, 6]},
 | |
|         'snappy': {'bxtda7219max': [4, 5, 6]},
 | |
|         # Chell's HDMI device 4 can not be used without being plugged.
 | |
|         # Also, its HDMI devices 5 and 6 are dummy devices.
 | |
|         'chell': {'sklnau8825adi': [4, 5, 6]},
 | |
|         # Kevin's device 3 is a DisplayPort device.
 | |
|         'kevin': {'rk3399-gru-sound': [3]},
 | |
|     }
 | |
| 
 | |
|     def run_once(self, to_test):
 | |
|         """Run alsa_api_test binary and verify its result.
 | |
| 
 | |
|         Checks the source code of alsa_api_test in audiotest repo for detail.
 | |
| 
 | |
|         @param to_test: support these test items:
 | |
|                         move: Checks snd_pcm_forward API.
 | |
|                         fill: Checks snd_pcm_mmap_begin API.
 | |
|                         drop: Checks snd_pcm_drop API.
 | |
| 
 | |
|         """
 | |
|         # Skip test_drop on boards that do not implement snd_pcm_drop
 | |
|         # correctly, as it cannot pass.
 | |
|         board = utils.get_board().lower()
 | |
|         if to_test == 'drop' and \
 | |
|             board.replace('-kernelnext', '') in \
 | |
|             self._BOARDS_WITHOUT_DROP_SUPPORT:
 | |
|             logging.info('Skipping test_drop for unsupported board: %s', board)
 | |
|             return
 | |
| 
 | |
|         self._cardnames = alsa_utils.get_soundcard_names()
 | |
|         self._devices = []
 | |
|         self._find_sound_devices()
 | |
|         method_name = '_test_' + to_test
 | |
|         method = getattr(self, method_name)
 | |
| 
 | |
|         # Stop CRAS to make sure the audio device won't be occupied.
 | |
|         utils.stop_service('cras', ignore_status=True)
 | |
| 
 | |
|         try:
 | |
|             for card_index, device_index in self._devices:
 | |
|                 device = 'hw:%s,%s' % (card_index, device_index)
 | |
|                 method(device)
 | |
|         finally:
 | |
|             # Restart CRAS.
 | |
|             utils.start_service('cras', ignore_status=True)
 | |
| 
 | |
| 
 | |
|     def _skip_device(self, card_device):
 | |
|         """Skips devices on some boards.
 | |
| 
 | |
|         @param card_device: A tuple of (card index, device index).
 | |
| 
 | |
|         @returns: True if the device should be skipped. False otherwise.
 | |
| 
 | |
|         """
 | |
|         card_name = self._cardnames[card_device[0]]
 | |
| 
 | |
|         return card_device[1] in self._DEVICES_TO_BE_SKIPPED.get(
 | |
|                 utils.get_board().lower(), {}).get(card_name, [])
 | |
| 
 | |
| 
 | |
|     def _find_sound_devices(self):
 | |
|         """Finds playback devices in sound device directory.
 | |
| 
 | |
|         @raises: error.TestError if there is no playback device.
 | |
|         """
 | |
|         filenames = os.listdir(self._SND_DEV_DIR)
 | |
|         for filename in filenames:
 | |
|             search = re.match(self._PLAYBACK_DEVICE_NAME, filename)
 | |
|             if search:
 | |
|                 card_device = (search.group(1), int(search.group(2)))
 | |
|                 if not self._skip_device(card_device):
 | |
|                     self._devices.append(card_device)
 | |
|         if not self._devices:
 | |
|             raise error.TestError('There is no playback device')
 | |
| 
 | |
| 
 | |
|     def _make_alsa_api_test_command(self, option, device):
 | |
|         """Makes command for alsa_api_test.
 | |
| 
 | |
|         @param option: same as to_test in run_once.
 | |
|         @param device: device in hw:<card index>:<device index> format.
 | |
| 
 | |
|         @returns: The command in a list of args.
 | |
| 
 | |
|         """
 | |
|         return ['alsa_api_test', '--device', device, '--%s' % option]
 | |
| 
 | |
| 
 | |
|     def _test_move(self, device):
 | |
|         """Runs alsa_api_test command and checks the return code.
 | |
| 
 | |
|         Test snd_pcm_forward can move appl_ptr to hw_ptr.
 | |
| 
 | |
|         @param device: device in hw:<card index>:<device index> format.
 | |
| 
 | |
|         @raises error.TestError if command fails.
 | |
| 
 | |
|         """
 | |
|         ret = utils.system(
 | |
|                 command=self._make_alsa_api_test_command('move', device),
 | |
|                 ignore_status=True)
 | |
|         if ret:
 | |
|             raise error.TestError(
 | |
|                     'ALSA API failed to move appl_ptr on device %s' % device)
 | |
| 
 | |
| 
 | |
|     def _test_fill(self, device):
 | |
|         """Runs alsa_api_test command and checks the return code.
 | |
| 
 | |
|         Test snd_pcm_mmap_begin can provide the access to the buffer, and memset
 | |
|         can fill it with zeros without using snd_pcm_mmap_commit.
 | |
| 
 | |
|         @param device: device in hw:<card index>:<device index> format.
 | |
| 
 | |
|         @raises error.TestError if command fails.
 | |
| 
 | |
|         """
 | |
|         ret = utils.system(
 | |
|                 command=self._make_alsa_api_test_command('fill', device),
 | |
|                 ignore_status=True)
 | |
|         if ret:
 | |
|             raise error.TestError(
 | |
|                     'ALSA API failed to fill buffer on device %s' % device)
 | |
| 
 | |
| 
 | |
|     def _test_drop(self, device):
 | |
|         """Runs alsa_api_test command and checks the return code.
 | |
| 
 | |
|         Test snd_pcm_drop can stop playback and reset hw_ptr to 0 in hardware.
 | |
| 
 | |
|         @param device: device in hw:<card index>:<device index> format.
 | |
| 
 | |
|         @raises error.TestError if command fails.
 | |
| 
 | |
|         """
 | |
|         ret = utils.system(
 | |
|                 command=self._make_alsa_api_test_command('drop', device),
 | |
|                 ignore_status=True)
 | |
|         if ret:
 | |
|             raise error.TestError(
 | |
|                     'ALSA API failed to drop playback and reset hw_ptr'
 | |
|                     'on device %s' % device)
 |