# Copyright (c) 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. import os import logging from autotest_lib.client.bin import test from autotest_lib.client.bin import utils from autotest_lib.client.common_lib import error from autotest_lib.client.common_lib.cros import chrome from autotest_lib.client.cros.audio import cras_utils from autotest_lib.client.cros.audio import sox_utils class accessibility_ChromeVoxSound(test.test): """Check whether ChromeVox makes noise on real hardware.""" version = 1 _audio_chunk_size = 1 # Length of chunk size in seconds. _detect_time = 20 # Max length of time to spend detecting audio in seconds. def _enable_ChromeVox(self): """Enable ChromeVox using a11y API call.""" cmd = ''' window.__result = false; chrome.accessibilityFeatures.spokenFeedback.set({value: true}); chrome.accessibilityFeatures.spokenFeedback.get({}, function(d) {window.__result = d[\'value\'];} ); ''' self._extension.ExecuteJavaScript(cmd) utils.poll_for_condition( lambda: self._extension.EvaluateJavaScript('window.__result'), exception = error.TestError( 'Timeout waiting for ChromeVox to be enabled.')) def _detect_audio(self): """Detects whether audio was heard and returns the approximate time. Runs for at most self._detect_time, checking each chunk for sound. After first detecting a chunk that has audio, counts the subsequent chunks that also do. @return: Approximate length of time in seconds there was audio. """ count = 0 counting = False for i in xrange(self._detect_time / self._audio_chunk_size): rms = self._rms_of_next_audio_chunk() if rms > 0: logging.info('Found passing chunk: %d.', i) count += 1 counting = True elif counting: return count * self._audio_chunk_size logging.warning('Timeout before end of audio!') return count * self._audio_chunk_size def _rms_of_next_audio_chunk(self): """Finds the sox_stats values of the next chunk of audio.""" cras_utils.loopback(self._loopback_file, channels=1, duration=self._audio_chunk_size) stat_output = sox_utils.get_stat(self._loopback_file) logging.info(stat_output) return vars(stat_output)['rms'] def warmup(self): self._loopback_file = os.path.join(self.bindir, 'cras_loopback.wav') def run_once(self): """Entry point of this test.""" extension_path = os.path.join(os.path.dirname(__file__), 'a11y_ext') with chrome.Chrome(extension_paths=[extension_path], is_component=False) as cr: # Setup ChromeVox extension self._extension = cr.get_extension(extension_path) # Begin actual test logging.info('Detecting initial ChromeVox welcome sound.') self._enable_ChromeVox() audio_length = self._detect_audio() if audio_length < 1: raise error.TestError('No sound after enabling Chromevox!') logging.info('Detecting initial ChromeVox welcome speech.') audio_length = self._detect_audio() if audio_length < 2: raise error.TestError('Speech after enabling ChromeVox was <= ' '%f seconds long!' % audio_length) logging.info('Detecting page navigation sound.') cr.browser.tabs[0].Navigate('chrome://version') audio_length = self._detect_audio() if audio_length < 2: raise error.TestError('Speech after loading a page was <= ' '%f seconds long!' % audio_length) logging.info('Detecting new tab sound.') tab = cr.browser.tabs.New() audio_length = self._detect_audio() if audio_length < 1: raise error.TestError('No sound after opening new tab!') def cleanup(self): try: os.remove(self._loopback_file) except OSError: pass