• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2020 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"""A Batch of Bluetooth AUdio Health tests"""
6
7import time
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.cros.bluetooth.bluetooth_audio_test_data import (
11        A2DP, A2DP_LONG, AVRCP, HFP_WBS, HFP_NBS)
12from autotest_lib.server.cros.bluetooth.bluetooth_adapter_audio_tests import (
13        BluetoothAdapterAudioTests)
14from autotest_lib.server.cros.bluetooth.bluetooth_adapter_quick_tests import (
15        BluetoothAdapterQuickTests)
16
17
18class bluetooth_AdapterAUHealth(BluetoothAdapterQuickTests,
19                                BluetoothAdapterAudioTests):
20    """A Batch of Bluetooth audio health tests."""
21
22    test_wrapper = BluetoothAdapterQuickTests.quick_test_test_decorator
23    batch_wrapper = BluetoothAdapterQuickTests.quick_test_batch_decorator
24
25
26    def au_run_method(self, device, test_method, test_profile):
27        """audio procedure of running a specified test method.
28
29        @param device: the bt peer device
30        @param test_method: the audio test method to run
31        @param test_profile: which test profile is used,
32                             A2DP, HFP_WBS or HFP_NBS
33        """
34        self.test_reset_on_adapter()
35        self.test_bluetoothd_running()
36        self.initialize_bluetooth_audio(device, test_profile)
37        self.test_device_set_discoverable(device, True)
38        self.test_discover_device(device.address)
39        self.test_pairing(device.address, device.pin, trusted=True)
40        self.test_connection_by_adapter(device.address)
41        test_method()
42        self.test_disconnection_by_adapter(device.address)
43        self.cleanup_bluetooth_audio(device, test_profile)
44
45
46    def _au_a2dp_test(self, test_profile, duration=0):
47        """A2DP test with sinewaves on the two channels.
48
49        @param test_profile: which test profile is used, A2DP or A2DP_LONG.
50        @param duration: the duration to test a2dp. The unit is in seconds.
51                if duration is 0, use the default duration in test_profile.
52        """
53        device = self.devices['BLUETOOTH_AUDIO'][0]
54        self.au_run_method(device,
55                           lambda: self.test_a2dp_sinewaves(
56                                   device, test_profile, duration),
57                           test_profile)
58
59
60    @test_wrapper('A2DP sinewave test', devices={'BLUETOOTH_AUDIO':1})
61    def au_a2dp_test(self):
62        """A2DP test with sinewaves on the two channels."""
63        self._au_a2dp_test(A2DP)
64
65    # The A2DP long test is a stress test. Exclude it from the AVL.
66    @test_wrapper('A2DP sinewave long test', devices={'BLUETOOTH_AUDIO':1},
67                  flags=['Quick Health'])
68    def au_a2dp_long_test(self, duration=600):
69        """A2DP long test with sinewaves on the two channels.
70
71        @param duration: the duration to test a2dp. The unit is in seconds.
72        """
73        self._au_a2dp_test(A2DP_LONG, duration=duration)
74
75
76    def check_wbs_capability(self):
77        """Check if the DUT supports WBS capability.
78
79        @raises: TestNAError if the dut does not support wbs.
80        """
81        capabilities, err = self.bluetooth_facade.get_supported_capabilities()
82        return err is None and bool(capabilities.get('wide band speech'))
83
84
85    def au_hfp_run_method(self, device, test_method, test_profile):
86        """Run an HFP test with the specified test method.
87
88        @param device: the bt peer device
89        @param test_method: the specific HFP WBS test method
90        @param test_profile: which test profile is used, HFP_WBS or HFP_NBS
91        """
92        if self.check_wbs_capability():
93            if test_profile == HFP_WBS:
94                # Restart cras to ensure that cras goes back to the default
95                # selection of either WBS or NBS.
96                # Any board that supports WBS should use WBS by default, unless
97                # it's overridden by CRAS' config.
98                # Do not enable WBS explicitly in the test so we can catch if
99                # the default selection goes wrong.
100                self.restart_cras()
101                # The audio team suggests a simple 2-second sleep.
102                time.sleep(2)
103            elif test_profile == HFP_NBS:
104                # Cras may be in either WBS or NBS mode. Disable WBS explicitly.
105                if not self.bluetooth_facade.enable_wbs(False):
106                    raise error.TestError('failed to disable wbs')
107        else:
108            if test_profile == HFP_WBS:
109                # Skip the WBS test on a board that does not support WBS.
110                raise error.TestNAError(
111                        'The DUT does not support WBS. Skip the test.')
112            elif test_profile == HFP_NBS:
113                # Restart cras to ensure that cras goes back to the default
114                # selection of either WBS or NBS.
115                # Any board that does not support WBS should use NBS by default.
116                # Do not enable NBS explicitly in the test so we can catch if
117                # the default selection goes wrong.
118                self.restart_cras()
119                # The audio team suggests a simple 2-second sleep.
120                time.sleep(2)
121
122        self.au_run_method(
123                device, lambda: test_method(device, test_profile), test_profile)
124
125
126    # TODO(b/163284498) Realtek not ready for WBS yet pending on cras patches.
127    @test_wrapper('HFP WBS sinewave test with dut as source',
128                  skip_chipsets=['Realtek-RTL8822C-USB'],
129                  devices={'BLUETOOTH_AUDIO':1})
130    def au_hfp_wbs_dut_as_source_test(self):
131        """HFP WBS test with sinewave streaming from dut to peer."""
132        device = self.devices['BLUETOOTH_AUDIO'][0]
133        self.au_hfp_run_method(device, self.test_hfp_dut_as_source, HFP_WBS)
134
135
136    # TODO(b/163284498) Realtek not ready for WBS yet pending on cras patches.
137    @test_wrapper('HFP WBS sinewave test with dut as sink',
138                  skip_chipsets=['Realtek-RTL8822C-USB'],
139                  devices={'BLUETOOTH_AUDIO':1})
140    def au_hfp_wbs_dut_as_sink_test(self):
141        """HFP WBS test with sinewave streaming from peer to dut."""
142        device = self.devices['BLUETOOTH_AUDIO'][0]
143        self.au_hfp_run_method(device, self.test_hfp_dut_as_sink, HFP_WBS)
144
145
146    @test_wrapper('HFP NBS sinewave test with dut as source',
147                  devices={'BLUETOOTH_AUDIO':1})
148    def au_hfp_nbs_dut_as_source_test(self):
149        """HFP NBS test with sinewave streaming from dut to peer."""
150        device = self.devices['BLUETOOTH_AUDIO'][0]
151        self.au_hfp_run_method(device, self.test_hfp_dut_as_source, HFP_NBS)
152
153
154    @test_wrapper('HFP NBS sinewave test with dut as sink',
155                  devices={'BLUETOOTH_AUDIO':1})
156    def au_hfp_nbs_dut_as_sink_test(self):
157        """HFP NBS test with sinewave streaming from peer to dut."""
158        device = self.devices['BLUETOOTH_AUDIO'][0]
159        self.au_hfp_run_method(device, self.test_hfp_dut_as_sink, HFP_NBS)
160
161
162    @test_wrapper('HFP WBS VISQOL test with dut as sink',
163                  devices={'BLUETOOTH_AUDIO':1})
164    def au_hfp_wbs_dut_as_sink_visqol_test(self):
165        """HFP WBS VISQOL test with audio streaming from peer to dut"""
166        device = self.devices['BLUETOOTH_AUDIO'][0]
167        self.au_hfp_run_method(device, self.test_hfp_dut_as_sink_visqol_score,
168                               HFP_WBS)
169
170
171    @test_wrapper('HFP WBS VISQOL test with dut as source',
172                  devices={'BLUETOOTH_AUDIO':1})
173    def au_hfp_wbs_dut_as_source_visqol_test(self):
174        """HFP WBS VISQOL test with audio streaming from dut to peer"""
175        device = self.devices['BLUETOOTH_AUDIO'][0]
176        self.au_hfp_run_method(device, self.test_hfp_dut_as_source_visqol_score,
177                               HFP_WBS)
178
179    @test_wrapper('HFP NBS VISQOL test with dut as sink',
180                  devices={'BLUETOOTH_AUDIO':1})
181    def au_hfp_nbs_dut_as_sink_visqol_test(self):
182        """HFP NBS VISQOL test with audio streaming from peer to dut"""
183        device = self.devices['BLUETOOTH_AUDIO'][0]
184        self.au_hfp_run_method(device, self.test_hfp_dut_as_sink_visqol_score,
185                               HFP_NBS)
186
187
188    @test_wrapper('HFP NBS VISQOL test with dut as source',
189                  devices={'BLUETOOTH_AUDIO':1})
190    def au_hfp_nbs_dut_as_source_visqol_test(self):
191        """HFP NBS VISQOL test with audio streaming from dut to peer"""
192        device = self.devices['BLUETOOTH_AUDIO'][0]
193        self.au_hfp_run_method(device, self.test_hfp_dut_as_source_visqol_score,
194                               HFP_NBS)
195
196
197    def au_run_avrcp_method(self, device, test_method):
198        """avrcp procedure of running a specified test method.
199
200        @param device: the bt peer device
201        @param test_method: the avrcp test method to run
202        """
203        def wrapped_test_method(device):
204            """A wrapper method to initialize and cleanup avrcp tests.
205
206            @param device: the bt peer device
207            """
208            self.initialize_bluetooth_player(device)
209            test_method(device)
210            self.cleanup_bluetooth_player(device)
211
212        self.au_run_method(
213                device, lambda: wrapped_test_method(device), AVRCP)
214
215
216    @test_wrapper('avrcp command test', devices={'BLUETOOTH_AUDIO':1})
217    def au_avrcp_command_test(self):
218        """AVRCP test to examine commands reception."""
219        device = self.devices['BLUETOOTH_AUDIO'][0]
220        self.au_run_avrcp_method(device, self.test_avrcp_commands)
221
222
223    # Add 'Quick Health' to flags to exclude the test from AVL.
224    # When this test is stable enough later, remove the flags here.
225    @test_wrapper('avrcp media info test', devices={'BLUETOOTH_AUDIO':1},
226                  flags=['Quick Health'])
227    def au_avrcp_media_info_test(self):
228        """AVRCP test to examine metadata propgation."""
229        device = self.devices['BLUETOOTH_AUDIO'][0]
230        self.au_run_avrcp_method(device, self.test_avrcp_media_info)
231
232
233    @batch_wrapper('Bluetooth Audio Batch Health Tests')
234    def au_health_batch_run(self, num_iterations=1, test_name=None):
235        """Run the bluetooth audio health test batch or a specific given test.
236
237        @param num_iterations: how many iterations to run
238        @param test_name: specific test to run otherwise None to run the
239                whole batch
240        """
241        self.au_a2dp_test()
242        self.au_a2dp_long_test()
243        self.au_hfp_nbs_dut_as_source_test()
244        self.au_hfp_nbs_dut_as_sink_test()
245        self.au_hfp_wbs_dut_as_source_test()
246        self.au_hfp_wbs_dut_as_sink_test()
247        self.au_hfp_wbs_dut_as_source_visqol_test()
248        self.au_hfp_wbs_dut_as_sink_visqol_test()
249        self.au_hfp_nbs_dut_as_source_visqol_test()
250        self.au_hfp_nbs_dut_as_sink_visqol_test()
251        self.au_avrcp_command_test()
252        self.au_avrcp_media_info_test()
253
254
255    def run_once(self,
256                 host,
257                 num_iterations=1,
258                 args_dict=None,
259                 test_name=None,
260                 flag='Quick Health'):
261        """Run the batch of Bluetooth stand health tests
262
263        @param host: the DUT, usually a chromebook
264        @param num_iterations: the number of rounds to execute the test
265        @param test_name: the test to run, or None for all tests
266        """
267        self.host = host
268
269        self.quick_test_init(host,
270                             use_btpeer=True,
271                             flag=flag,
272                             args_dict=args_dict)
273        self.au_health_batch_run(num_iterations, test_name)
274        self.quick_test_cleanup()
275