• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2016 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
5"""This is a server side audio volume test using the Chameleon board."""
6
7import logging
8import os
9import time
10
11from autotest_lib.client.cros.chameleon import audio_test_utils
12from autotest_lib.client.cros.chameleon import chameleon_audio_ids
13from autotest_lib.client.cros.chameleon import chameleon_audio_helper
14from autotest_lib.server.cros.audio import audio_test
15from autotest_lib.server.cros.multimedia import remote_facade_factory
16
17
18class audio_AudioArtifacts(audio_test.AudioTest):
19    """Server side audio artifacts test.
20
21    This test talks to a Chameleon board and a Cros device to detect
22    audio artifacts from the Cros device.
23
24    """
25    version = 1
26    RECORD_SECONDS = 20
27    DELAY_AFTER_BINDING = 0.5
28    KEEP_VOLUME_SECONDS = 0.5
29    START_PLAYBACK_SECONDS = 0.5
30
31    def run_once(self, host, source_id, sink_id, recorder_id,
32                 golden_file, switch_hsp=False,
33                 mute_duration_in_secs=None,
34                 volume_changes=None,
35                 record_secs=None):
36        """Running audio volume test.
37
38        mute_duration_in_secs and volume_changes couldn't be both not None.
39
40        @param host: device under test CrosHost
41        @param source_id: An ID defined in chameleon_audio_ids for source.
42        @param sink_id: An ID defined in chameleon_audio_ids for sink if needed.
43                        Currently this is only used on bluetooth.
44        @param recorder: An ID defined in chameleon_audio_ids for recording.
45        @param golden_file: A test file defined in audio_test_data.
46        @param switch_hsp: Run a recording process on Cros device. This is
47                           to trigger Cros switching from A2DP to HSP.
48        @param mute_duration_in_secs: List of each duration of mute. For example,
49                                      [0.4, 0.6] will have two delays, each
50                                      duration will be 0.4 secs and 0.6 secs.
51                                      And, between delays, there will be
52                                      KEEP_VOLUME_SECONDS secs sine wave.
53        @param volume_changes: List consisting of -1 and +1, where -1 denoting
54                           decreasing volume, +1 denoting increasing volume.
55                           Between each changes, the volume will be kept for
56                           KEEP_VOLUME_SECONDS secs.
57        @param record_secs: The duration of recording in seconds. If it is not
58                            set, duration of the test data will be used. If
59                            duration of test data is not set either, default
60                            RECORD_SECONDS will be used.
61
62        """
63        if (source_id == chameleon_audio_ids.CrosIds.SPEAKER and
64            not audio_test_utils.has_internal_speaker(host)):
65            return
66
67        chameleon_board = host.chameleon
68        factory = remote_facade_factory.RemoteFacadeFactory(
69                host, results_dir=self.resultsdir)
70
71        chameleon_board.setup_and_reset(self.outputdir)
72
73        widget_factory = chameleon_audio_helper.AudioWidgetFactory(
74                factory, host)
75
76        source = widget_factory.create_widget(source_id)
77        recorder = widget_factory.create_widget(recorder_id)
78
79        # Chameleon Mic does not need binding.
80        binding = (recorder_id != chameleon_audio_ids.ChameleonIds.MIC)
81
82        binder = None
83
84        if binding:
85            if sink_id:
86                sink = widget_factory.create_widget(sink_id)
87                binder = widget_factory.create_binder(source, sink, recorder)
88            else:
89                binder = widget_factory.create_binder(source, recorder)
90
91        start_volume, low_volume, high_volume = 75, 50, 100
92
93        if not record_secs:
94            if golden_file.duration_secs:
95                record_secs = golden_file.duration_secs
96            else:
97                record_secs = self.RECORD_SECONDS
98        logging.debug('Record duration: %f seconds', record_secs)
99
100        # Checks if the file is local or is served on web.
101        file_url = getattr(golden_file, 'url', None)
102
103        with chameleon_audio_helper.bind_widgets(binder):
104            # Checks the node selected by cras is correct.
105            time.sleep(self.DELAY_AFTER_BINDING)
106            audio_facade = factory.create_audio_facade()
107
108            audio_test_utils.dump_cros_audio_logs(
109                    host, audio_facade, self.resultsdir, 'after_binding')
110
111            audio_facade.set_chrome_active_volume(start_volume)
112
113            audio_test_utils.check_output_port(audio_facade, source.port_id)
114
115            if switch_hsp:
116                audio_test_utils.switch_to_hsp(audio_facade)
117
118            if not file_url:
119                logging.info('Setting playback data on Cros device')
120                source.set_playback_data(golden_file)
121
122            logging.info('Start recording from Chameleon.')
123            recorder.start_recording()
124
125            if not file_url:
126                logging.info('Start playing %s on Cros device',
127                             golden_file.path)
128                source.start_playback()
129            else:
130                logging.info('Start playing %s on Cros device using browser',
131                             file_url)
132                browser_facade = factory.create_browser_facade()
133                tab_descriptor = browser_facade.new_tab(file_url)
134
135            if volume_changes:
136                time.sleep(self.START_PLAYBACK_SECONDS)
137                for x in volume_changes:
138                    if x == -1:
139                        audio_facade.set_chrome_active_volume(low_volume)
140                    if x == +1:
141                        audio_facade.set_chrome_active_volume(high_volume)
142                    time.sleep(self.KEEP_VOLUME_SECONDS)
143                passed_time_secs = self.START_PLAYBACK_SECONDS
144                passed_time_secs += len(volume_changes) * self.KEEP_VOLUME_SECONDS
145                rest = max(0, record_secs - passed_time_secs)
146                time.sleep(rest)
147            elif mute_duration_in_secs:
148                time.sleep(self.START_PLAYBACK_SECONDS)
149                passed_time_seconds = self.START_PLAYBACK_SECONDS
150                for mute_secs in mute_duration_in_secs:
151                    audio_facade.set_chrome_active_volume(0)
152                    time.sleep(mute_secs)
153                    audio_facade.set_chrome_active_volume(start_volume)
154                    time.sleep(self.KEEP_VOLUME_SECONDS)
155                    passed_time_seconds += mute_secs + self.KEEP_VOLUME_SECONDS
156                rest = max(0, record_secs - passed_time_seconds)
157                time.sleep(rest)
158            else:
159                time.sleep(record_secs)
160
161            recorder.stop_recording()
162            logging.info('Stopped recording from Chameleon.')
163
164            audio_test_utils.dump_cros_audio_logs(
165                    host, audio_facade, self.resultsdir,
166                    'after_recording')
167
168            if file_url:
169                browser_facade.close_tab(tab_descriptor)
170            else:
171                source.stop_playback()
172
173            recorder.read_recorded_binary()
174            logging.info('Read recorded binary from Chameleon.')
175
176            recorded_file = os.path.join(
177                    self.resultsdir, "recorded.raw" )
178            logging.info('Saving recorded data to %s', recorded_file)
179            recorder.save_file(recorded_file)
180
181            audio_test_utils.check_recorded_frequency(
182                    golden_file, recorder,
183                    check_artifacts=True,
184                    mute_durations=mute_duration_in_secs,
185                    volume_changes=volume_changes)
186
187