1# Lint as: python2, python3
2# Copyright 2022 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""A Batch of Bluetooth Quality Report tests"""
6
7import collections
8import time
9
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.cros.bluetooth.bluetooth_audio_test_data import (
12        A2DP_MEDIUM, HFP_WBS, HFP_NBS, HFP_WBS_MEDIUM, HFP_NBS_MEDIUM)
13from autotest_lib.server.cros.bluetooth.bluetooth_adapter_qr_tests import (
14        BluetoothAdapterQRTests, QR_UNSUPPORTED_CHIPSETS)
15from autotest_lib.server.cros.bluetooth.bluetooth_adapter_quick_tests import (
16        BluetoothAdapterQuickTests)
17
18
19class bluetooth_AdapterQRHealth(BluetoothAdapterQuickTests,
20                                BluetoothAdapterQRTests):
21    """A Batch of Bluetooth audio health tests"""
22
23    test_wrapper = BluetoothAdapterQuickTests.quick_test_test_decorator
24    batch_wrapper = BluetoothAdapterQuickTests.quick_test_batch_decorator
25
26    def run_test_method(self,
27                        devices,
28                        test_method,
29                        test_profile,
30                        logging_and_check=True):
31        """Common procedure to run a specific test method.
32
33        @param devices: a list of devices.
34        @param test_method: the test method to run.
35        @param test_profile: audio test profile to use.
36        @param logging_and_check: set this to True to opend the quality
37                                  report log checking.
38        """
39
40        if not isinstance(devices, collections.Iterable):
41            devices = (devices, )
42
43        num_devices = len(devices)
44
45        # Make sure WBS profile works fine.
46        if test_profile in (HFP_WBS, HFP_WBS_MEDIUM):
47            if self.check_wbs_capability():
48                if not self.bluetooth_facade.enable_wbs(True):
49                    raise error.TestError('failed to enble wbs')
50            else:
51                raise error.TestNAError(
52                        'The DUT does not support WBS. Skip the test.')
53        elif test_profile in (HFP_NBS, HFP_NBS_MEDIUM):
54            if not self.bluetooth_facade.enable_wbs(False):
55                raise error.TestError('failed to disable wbs')
56
57        time.sleep(3)
58
59        self.test_reset_on_adapter()
60        self.test_bluetoothd_running()
61
62        for device in devices:
63            if device.device_type == 'BLUETOOTH_AUDIO':
64                self.initialize_bluetooth_audio(device, test_profile)
65
66            self.test_discover_device(device.address)
67            self.test_pairing(device.address, device.pin, trusted=True)
68            self.test_connection_by_adapter(device.address)
69
70            time.sleep(2)
71
72        if logging_and_check:
73            self.dut_btmon_log_path = self.start_new_btmon()
74            self.enable_disable_debug_log(enable=True)
75            self.enable_disable_quality_debug_log(enable=True)
76
77        test_method()
78
79        if logging_and_check:
80            self.test_send_log()
81            self.check_qr_event_log(num_devices=num_devices)
82            self.enable_disable_quality_debug_log(enable=False)
83            self.enable_disable_debug_log(enable=False)
84
85        for device in devices:
86            self.test_disconnection_by_adapter(device.address)
87
88            if device.device_type == 'BLUETOOTH_AUDIO':
89                self.cleanup_bluetooth_audio(device, test_profile)
90
91    # Remove flags=['Quick Health'] when this test is migrated to stable suite.
92    @test_wrapper('Quality Report A2DP test',
93                  devices={'BLUETOOTH_AUDIO': 1},
94                  flags=['Quick Health'],
95                  skip_chipsets=QR_UNSUPPORTED_CHIPSETS)
96    def qr_a2dp_test(self):
97        """Quality Report A2DP test"""
98        device = self.devices['BLUETOOTH_AUDIO'][0]
99        test_profile = A2DP_MEDIUM
100        test_method = lambda: self.qr_a2dp(device, test_profile)
101
102        self.run_test_method(device, test_method, test_profile)
103
104    # Remove flags=['Quick Health'] when this test is migrated to stable suite.
105    @test_wrapper('Quality Report power cycle and A2DP test',
106                  devices={'BLUETOOTH_AUDIO': 1},
107                  flags=['Quick Health'],
108                  skip_chipsets=QR_UNSUPPORTED_CHIPSETS)
109    def qr_power_cycle_a2dp_test(self):
110        """Quality Report power cycle and A2DP test"""
111        device = self.devices['BLUETOOTH_AUDIO'][0]
112        test_profile = A2DP_MEDIUM
113        test_method = lambda: self.qr_power_cycle_a2dp(device, test_profile)
114
115        self.run_test_method(device, test_method, test_profile)
116
117    # Remove flags=['Quick Health'] when this test is migrated to stable suite.
118    @test_wrapper('Quality Report HFP NBS dut as source test',
119                  devices={'BLUETOOTH_AUDIO': 1},
120                  flags=['Quick Health'],
121                  skip_chipsets=QR_UNSUPPORTED_CHIPSETS)
122    def qr_hfp_nbs_dut_as_src_test(self):
123        """Quality Report HFP NBS dut as source test"""
124        device = self.devices['BLUETOOTH_AUDIO'][0]
125        test_profile = HFP_NBS_MEDIUM
126        test_method = lambda: self.qr_hfp_dut_as_src(device, test_profile)
127
128        self.run_test_method(device, test_method, test_profile)
129
130    # Remove flags=['Quick Health'] when this test is migrated to stable suite.
131    @test_wrapper('Quality Report HFP WBS dut as source test',
132                  devices={'BLUETOOTH_AUDIO': 1},
133                  flags=['Quick Health'],
134                  skip_chipsets=QR_UNSUPPORTED_CHIPSETS)
135    def qr_hfp_wbs_dut_as_src_test(self):
136        """Quality Report HFP WBS dut as source test"""
137        device = self.devices['BLUETOOTH_AUDIO'][0]
138        test_profile = HFP_WBS_MEDIUM
139        test_method = lambda: self.qr_hfp_dut_as_src(device, test_profile)
140
141        self.run_test_method(device, test_method, test_profile)
142
143    # Remove flags=['Quick Health'] when this test is migrated to stable suite.
144    @test_wrapper('Quality Report disabled A2DP test',
145                  devices={'BLUETOOTH_AUDIO': 1},
146                  flags=['Quick Health'],
147                  skip_chipsets=QR_UNSUPPORTED_CHIPSETS)
148    def qr_disabled_a2dp_test(self):
149        """Quality Report disabled A2DP test"""
150        device = self.devices['BLUETOOTH_AUDIO'][0]
151        test_profile = A2DP_MEDIUM
152        test_method = lambda: self.qr_disabled_a2dp(device, test_profile)
153
154        self.run_test_method(device,
155                             test_method,
156                             test_profile,
157                             logging_and_check=False)
158
159    # Remove flags=['Quick Health'] when this test is migrated to stable suite.
160    @test_wrapper('Quality Report A2DP and classic keyboard test',
161                  devices={
162                          'BLUETOOTH_AUDIO': 1,
163                          "KEYBOARD": 1
164                  },
165                  flags=['Quick Health'],
166                  skip_chipsets=QR_UNSUPPORTED_CHIPSETS)
167    def qr_a2dp_cl_keyboard_test(self):
168        """Quality Report A2DP and classic keyboard test"""
169        audio_device = self.devices['BLUETOOTH_AUDIO'][0]
170        keyboard_device = self.devices['KEYBOARD'][0]
171        test_profile = A2DP_MEDIUM
172        test_method = lambda: self.qr_a2dp_cl_keyboard(
173                audio_device, keyboard_device, test_profile)
174
175        self.run_test_method((audio_device, keyboard_device),
176                             test_method,
177                             test_profile)
178
179    # Remove flags=['Quick Health'] when this test is migrated to stable suite.
180    @test_wrapper(
181            'Quality Report HFP WBS dut as sink and classic keyboard test',
182            devices={
183                    'BLUETOOTH_AUDIO': 1,
184                    'KEYBOARD': 1
185            },
186            flags=['Quick Health'],
187            skip_chipsets=QR_UNSUPPORTED_CHIPSETS)
188    def qr_hfp_wbs_dut_as_sink_cl_keyboard_test(self):
189        """Quality Report HFP WBS dut as sink and classic keyboard test"""
190        audio_device = self.devices['BLUETOOTH_AUDIO'][0]
191        keyboard_device = self.devices['KEYBOARD'][0]
192        test_profile = HFP_WBS_MEDIUM
193        test_method = lambda: self.qr_hfp_dut_as_sink_cl_keyboard(
194                audio_device, keyboard_device, test_profile)
195
196        self.run_test_method((audio_device, keyboard_device),
197                             test_method,
198                             test_profile)
199
200    # Remove flags=['Quick Health'] when this test is migrated to stable suite.
201    @test_wrapper(
202            'Quality Report HFP NBS dut as sink and classic keyboard test',
203            devices={
204                    'BLUETOOTH_AUDIO': 1,
205                    'KEYBOARD': 1
206            },
207            flags=['Quick Health'],
208            skip_chipsets=QR_UNSUPPORTED_CHIPSETS)
209    def qr_hfp_nbs_dut_as_sink_cl_keyboard_test(self):
210        """Quality Report HFP NBS dut as sink and classic keyboard test"""
211        audio_device = self.devices['BLUETOOTH_AUDIO'][0]
212        keyboard_device = self.devices['KEYBOARD'][0]
213        test_profile = HFP_NBS_MEDIUM
214        test_method = lambda: self.qr_hfp_dut_as_sink_cl_keyboard(
215                audio_device, keyboard_device, test_profile)
216
217        self.run_test_method((audio_device, keyboard_device),
218                             test_method,
219                             test_profile)
220
221    @batch_wrapper('Bluetooth BQR Batch Health Tests')
222    def qr_health_batch_run(self, num_iterations=1, test_name=None):
223        """Run the bluetooth audio health test batch or a specific given test.
224
225        @param num_iterations: how many iterations to run
226        @param test_name: specific test to run otherwise None to run the
227                whole batch
228        """
229        self.qr_a2dp_test()
230        self.qr_power_cycle_a2dp_test()
231        self.qr_hfp_nbs_dut_as_src_test()
232        self.qr_hfp_wbs_dut_as_src_test()
233        self.qr_disabled_a2dp_test()
234        self.qr_a2dp_cl_keyboard_test()
235        self.qr_hfp_wbs_dut_as_sink_cl_keyboard_test()
236        self.qr_hfp_nbs_dut_as_sink_cl_keyboard_test()
237
238    def run_once(self,
239                 host,
240                 num_iterations=1,
241                 args_dict=None,
242                 test_name=None,
243                 flag='Quick Health'):
244        """Run the batch of Bluetooth stand health tests
245
246        @param host: the DUT, usually a chromebook
247        @param num_iterations: the number of rounds to execute the test
248        @param test_name: the test to run, or None for all tests
249        """
250        self.host = host
251
252        self.quick_test_init(host,
253                             use_btpeer=True,
254                             flag=flag,
255                             args_dict=args_dict)
256        self.qr_health_batch_run(num_iterations, test_name)
257        self.quick_test_cleanup()
258