普通文本  |  121行  |  4.33 KB

# 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