• 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 ARC audio playback test using the Chameleon board."""
6
7import logging
8import os
9import time
10
11from autotest_lib.client.bin import utils
12from autotest_lib.client.cros.chameleon import audio_test_utils
13from autotest_lib.client.cros.chameleon import chameleon_audio_helper
14from autotest_lib.client.cros.chameleon import chameleon_audio_ids
15from autotest_lib.client.cros.multimedia import arc_resource_common
16from autotest_lib.server import autotest
17from autotest_lib.server.cros.audio import audio_test
18from autotest_lib.server.cros.multimedia import remote_facade_factory
19
20
21class audio_AudioARCPlayback(audio_test.AudioTest):
22    """Server side ARC audio playback test.
23
24    This test talks to a Chameleon board and a Cros device to verify
25    audio playback function of the Cros device with ARC.
26
27    """
28    version = 1
29    DELAY_AFTER_BINDING = 0.5
30    WAIT_CLIENT_READY_TIMEOUT_SECS = 150
31    WAIT_PLAYBACK_SECS = 10
32
33    def run_once(self, host, source_id, sink_id, recorder_id,
34                 golden_file, switch_hsp=False):
35        """Runs record test through ARC on Cros device.
36
37        @param host: device under test, a CrosHost.
38        @param source_id: An ID defined in chameleon_audio_ids for source.
39        @param sink_id: An ID defined in chameleon_audio_ids for sink if needed.
40                        Currently this is only used on bluetooth.
41        @param recorder_id: An ID defined in chameleon_audio_ids for recording.
42        @param golden_file: A test file defined in audio_test_data.
43        @param switch_hsp: Run a recording process on Cros device. This is
44                           to trigger Cros switching from A2DP to HSP.
45
46        """
47        self.host = host
48
49        if (source_id == chameleon_audio_ids.CrosIds.SPEAKER and
50            not audio_test_utils.has_internal_speaker(host)):
51            return
52
53        self.client_at = None
54
55        # Runs a client side test to start Chrome and install Play Music app.
56        self.setup_playmusic_app()
57
58        # Do not start Chrome because client side test had started it.
59        # Do not install autotest because client side test had installed it.
60        factory = remote_facade_factory.RemoteFacadeFactory(
61                host, no_chrome=True, install_autotest=False,
62                results_dir=self.resultsdir)
63
64        # Setup Chameleon and create widgets.
65        host.chameleon.setup_and_reset(self.outputdir)
66
67        widget_factory = chameleon_audio_helper.AudioWidgetFactory(
68                factory, host)
69
70        source = widget_factory.create_widget(source_id, use_arc=True)
71        recorder = widget_factory.create_widget(recorder_id)
72
73        # Chameleon Mic does not need binding.
74        binding = (recorder_id != chameleon_audio_ids.ChameleonIds.MIC)
75
76        binder = None
77
78        if binding:
79            if sink_id:
80                sink = widget_factory.create_widget(sink_id)
81                binder = widget_factory.create_binder(source, sink, recorder)
82            else:
83                binder = widget_factory.create_binder(source, recorder)
84
85        # Second peak ratio is determined by quality of audio path.
86        second_peak_ratio = audio_test_utils.get_second_peak_ratio(
87                source_id=source_id,
88                recorder_id=recorder_id,
89                is_hsp=switch_hsp)
90
91        with chameleon_audio_helper.bind_widgets(binder):
92            time.sleep(self.DELAY_AFTER_BINDING)
93
94            audio_facade = factory.create_audio_facade()
95
96            audio_test_utils.dump_cros_audio_logs(
97                    host, audio_facade, self.resultsdir, 'after_binding')
98
99            # Checks the node selected by CRAS is correct.
100            audio_test_utils.check_output_port(audio_facade, source.port_id)
101
102            if switch_hsp:
103                audio_test_utils.switch_to_hsp(audio_facade)
104
105            logging.info('Setting playback file on Cros device')
106            source.set_playback_data(golden_file)
107
108            logging.info('Start recording from Chameleon')
109            recorder.start_recording()
110
111            logging.info('Start playing %s on Cros device',
112                         golden_file.path)
113            source.start_playback()
114
115            time.sleep(self.WAIT_PLAYBACK_SECS)
116
117            recorder.stop_recording()
118            logging.info('Stopped recording from Chameleon.')
119
120            audio_test_utils.dump_cros_audio_logs(
121                    host, audio_facade, self.resultsdir,
122                    'after_recording')
123
124            recorder.read_recorded_binary()
125            logging.info('Read recorded binary from Chameleon.')
126
127            recorded_file = os.path.join(self.resultsdir, "recorded.raw")
128            logging.info('Saving recorded data to %s', recorded_file)
129            recorder.save_file(recorded_file)
130
131            audio_test_utils.check_recorded_frequency(
132                    golden_file, recorder,
133                    second_peak_ratio=second_peak_ratio)
134
135
136    def run_client_side_test(self):
137        """Runs a client side test on Cros device in background."""
138        self.client_at = autotest.Autotest(self.host)
139        logging.info('Start running client side test %s',
140                     arc_resource_common.PlayMusicProps.TEST_NAME)
141        self.client_at.run_test(
142                arc_resource_common.PlayMusicProps.TEST_NAME,
143                background=True)
144
145
146    def setup_playmusic_app(self):
147        """Setups Play Music app on Cros device.
148
149        Runs a client side test on Cros device to start Chrome and ARC and
150        install Play Music app.
151        Wait for it to be ready.
152
153        """
154        # Removes ready tag that server side test should wait for later.
155        self.remove_ready_tag()
156
157        # Runs the client side test.
158        self.run_client_side_test()
159
160        logging.info('Waiting for client side Play Music app to be ready')
161
162        # Waits for ready tag to be posted by client side test.
163        utils.poll_for_condition(condition=self.ready_tag_exists,
164                                 timeout=self.WAIT_CLIENT_READY_TIMEOUT_SECS,
165                                 desc='Wait for client side test being ready',
166                                 sleep_interval=1)
167
168        logging.info('Client side Play Music app is ready')
169
170
171    def cleanup(self):
172        """Cleanup of the test."""
173        self.touch_exit_tag()
174        super(audio_AudioARCPlayback, self).cleanup()
175
176
177    def remove_ready_tag(self):
178        """Removes ready tag on Cros device."""
179        if self.ready_tag_exists():
180            self.host.run(command='rm %s' % (
181                    arc_resource_common.PlayMusicProps.READY_TAG_FILE))
182
183
184    def touch_exit_tag(self):
185        """Touches exit tag on Cros device to stop client side test."""
186        self.host.run(command='touch %s' % (
187                arc_resource_common.PlayMusicProps.EXIT_TAG_FILE))
188
189
190    def ready_tag_exists(self):
191        """Checks if ready tag exists.
192
193        @returns: True if the tag file exists. False otherwise.
194
195        """
196        return self.host.path_exists(
197                arc_resource_common.PlayMusicProps.READY_TAG_FILE)
198