126 lines
4.4 KiB
Python
126 lines
4.4 KiB
Python
# 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
|