• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2014 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 os
6import logging
7import time
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.common_lib.cros import chrome
11from autotest_lib.client.cros.a11y import a11y_test_base
12from autotest_lib.client.cros.audio import cras_utils
13from autotest_lib.client.cros.audio import sox_utils
14
15
16class accessibility_ChromeVoxSound(a11y_test_base.a11y_test_base):
17    """Check whether ChromeVox makes noise on real hardware."""
18    version = 1
19
20    _audio_chunk_size = 1 # Length of chunk size in seconds.
21    _detect_time = 40 # Max length of time to spend detecting audio in seconds.
22
23
24    def _detect_audio(self, name, min_time, max_time):
25        """Detects whether audio was heard and returns the approximate time.
26
27        Runs for at most self._detect_time, checking each chunk for sound.
28        After first detecting a chunk that has audio, counts the subsequent
29        chunks that also do.
30
31        Finally, check whether the found audio matches the expected length.
32
33        @param name: a string representing which sound is expected.
34        @param min_time: the minimum allowed sound length in seconds.
35        @param max_time: the maximum allowed sound length in seconds.
36
37        @raises: error.TestFail if the observed behavior doesn't match
38                 expected: either no sound or sound of bad length.
39
40        """
41        count = 0
42        counting = False
43
44        for i in xrange(self._detect_time / self._audio_chunk_size):
45            rms = self._rms_of_next_audio_chunk()
46            if rms > 0:
47                logging.info('Found passing chunk: %d.', i)
48                if not counting:
49                    start_time = time.time()
50                    counting = True
51                count += 1
52            elif counting:
53                audio_length = time.time() - start_time
54                break
55        if not counting:
56            raise error.TestFail('No audio for %s was found!' % name)
57
58        logging.info('Time taken - %s: %f', name, audio_length)
59        if audio_length < min_time:
60            raise error.TestFail(
61                    '%s audio was only %f seconds long!' % (name, audio_length))
62        elif audio_length > max_time:
63            raise error.TestFail(
64                    '%s audio was too long: %f seconds!' % (name, audio_length))
65        return
66
67
68    def _rms_of_next_audio_chunk(self):
69        """Finds the sox_stats values of the next chunk of audio."""
70        cras_utils.loopback(self._loopback_file, channels=1,
71                            duration=self._audio_chunk_size)
72        stat_output = sox_utils.get_stat(self._loopback_file)
73        logging.info(stat_output)
74        return vars(stat_output)['rms']
75
76
77    def _check_chromevox_sound(self, cr):
78        """Test contents.
79
80        Enable ChromeVox, navigate to a new page, and open a new tab.  Check
81        the audio output at each point.
82
83        @param cr: the chrome.Chrome() object
84
85        """
86        chromevox_start_time = time.time()
87        self._toggle_chromevox()
88        self._confirm_chromevox_state(True)
89
90        # TODO: this sound doesn't play for Telemetry user.  crbug.com/590403
91        # Welcome ding
92        # self._detect_audio('enable ChromeVox ding', 1, 2)
93
94        # "ChromeVox Spoken Feedback is ready!"
95        self._detect_audio('welcome message', 2, 6)
96        chromevox_open_time = time.time() - chromevox_start_time
97        logging.info('ChromeVox took %f seconds to start.')
98
99        # Page navigation sound.
100        cr.browser.tabs[0].Navigate('chrome://version')
101        self._detect_audio('page navigation sound', 2, 6)
102
103        # New tab sound
104        tab = cr.browser.tabs.New()
105        self._detect_audio('new tab ding', 2, 6)
106
107
108    def run_once(self):
109        """Entry point of this test."""
110        self._loopback_file = os.path.join(self.bindir, 'cras_loopback.wav')
111        extension_path = self._get_extension_path()
112
113        with chrome.Chrome(extension_paths=[extension_path]) as cr:
114            self._extension = cr.get_extension(extension_path)
115            cr.browser.tabs[0].WaitForDocumentReadyStateToBeComplete()
116            self._confirm_chromevox_state(False)
117            self._check_chromevox_sound(cr)
118
119
120    def _child_test_cleanup(self):
121        try:
122            os.remove(self._loopback_file)
123        except OSError:
124            pass
125