普通文本  |  126行  |  4.36 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
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.cros.a11y import a11y_test_base
from autotest_lib.client.cros.audio import cras_utils
from autotest_lib.client.cros.audio import sox_utils


class accessibility_ChromeVoxSound(a11y_test_base.a11y_test_base):
    """Check whether ChromeVox makes noise on real hardware."""
    version = 1

    _audio_chunk_size = 1 # Length of chunk size in seconds.
    _detect_time = 40 # Max length of time to spend detecting audio in seconds.


    def _detect_audio(self, name, min_time):
        """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.

        Finally, check whether the found audio matches the expected length.

        @param name: a string representing which sound is expected.
        @param min_time: the minimum allowed sound length in seconds.

        @raises: error.TestFail if the observed behavior doesn't match
                 expected: either no sound or sound of bad length.

        """
        count = 0
        counting = False
        saw_sound_end = 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)
                if not counting:
                    start_time = time.time()
                    counting = True
                count += 1
            elif counting:
                audio_length = time.time() - start_time
                saw_sound_end = True
                break
        if not counting:
            raise error.TestFail('No audio for %s was found!' % name)
        if not saw_sound_end:
            raise error.TestFail('Audio for %s was more than % seconds!' % (
                    name, self._detect_time))

        logging.info('Time taken - %s: %f', name, audio_length)
        if audio_length < min_time:
            raise error.TestFail(
                    '%s audio was only %f seconds long!' % (name, audio_length))
        return


    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 _check_chromevox_sound(self, cr):
        """Test contents.

        Enable ChromeVox, navigate to a new page, and open a new tab.  Check
        the audio output at each point.

        @param cr: the chrome.Chrome() object

        """
        chromevox_start_time = time.time()
        self._toggle_chromevox()
        self._confirm_chromevox_state(True)

        # TODO: this sound doesn't play for Telemetry user.  crbug.com/590403
        # Welcome ding
        # self._detect_audio('enable ChromeVox ding', 1)

        # "ChromeVox Spoken Feedback is ready!"
        self._detect_audio('welcome message', 2)
        chromevox_open_time = time.time() - chromevox_start_time
        logging.info('ChromeVox took %f seconds to start.')

        # New tab sound.
        tab = cr.browser.tabs.New()
        self._detect_audio('new tab ding', 2)

        # Page navigation sound.
        tab.Navigate('chrome://version')
        self._detect_audio('page navigation sound', 2)


    def run_once(self):
        """Entry point of this test."""
        self._loopback_file = os.path.join(self.bindir, 'cras_loopback.wav')
        extension_path = self._get_extension_path()

        with chrome.Chrome(extension_paths=[extension_path]) as cr:
            self._extension = cr.get_extension(extension_path)
            cr.browser.tabs[0].WaitForDocumentReadyStateToBeComplete()
            self._confirm_chromevox_state(False)
            self._check_chromevox_sound(cr)


    def _child_test_cleanup(self):
        try:
            os.remove(self._loopback_file)
        except OSError:
            pass