• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Lint as: python2, python3
2# Copyright 2021 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 LE LLT health tests"""
6
7from autotest_lib.server.cros.bluetooth import advertisements_data
8
9DEFAULT_MIN_ADV_INTERVAL = 200
10DEFAULT_MAX_ADV_INTERVAL = 500
11
12from autotest_lib.server.cros.bluetooth.\
13     bluetooth_adapter_controller_role_tests \
14     import bluetooth_AdapterControllerRoleTests
15from autotest_lib.server.cros.bluetooth.bluetooth_adapter_quick_tests \
16     import BluetoothAdapterQuickTests
17from autotest_lib.server.cros.bluetooth.bluetooth_adapter_hidreports_tests \
18     import BluetoothAdapterHIDReportTests
19from autotest_lib.server.cros.bluetooth.bluetooth_adapter_better_together \
20     import BluetoothAdapterBetterTogether
21
22
23class bluetooth_AdapterLLTHealth(BluetoothAdapterHIDReportTests,
24                                 bluetooth_AdapterControllerRoleTests,
25                                 BluetoothAdapterBetterTogether):
26    """A Batch of Bluetooth LE LLT health tests. This test is written
27       as a batch of tests in order to reduce test time, since auto-test
28       ramp up time is costly. The batch is using BluetoothAdapterQuickTests
29       wrapper methods to start and end a test and a batch of tests.
30
31       This class can be called to run the entire test batch or to run a
32       specific test only
33    """
34
35    test_wrapper = BluetoothAdapterQuickTests.quick_test_test_decorator
36    batch_wrapper = BluetoothAdapterQuickTests.quick_test_batch_decorator
37
38
39    def discover_and_pair(self, device):
40        """Discovers and pairs given device. Automatically connects too.
41
42           @param device: meta object for bt peer device
43        """
44        self.test_discover_device(device.address)
45        self.test_pairing(device.address, device.pin, trusted=True)
46        self.test_connection_by_adapter(device.address)
47
48
49    def start_connectable_advertisement(self):
50        """ Initiate connectable advertising from DUT """
51        # Register and start advertising instance
52        # We ignore failure because the test isn't able to verify
53        # the min/max advertising intervals, but this is ok.
54        self.test_reset_advertising()
55        self.test_set_advertising_intervals(DEFAULT_MIN_ADV_INTERVAL,
56                                            DEFAULT_MAX_ADV_INTERVAL)
57        self.test_register_advertisement(advertisements_data.ADVERTISEMENTS[0],
58                                         1)
59
60
61    def pair_and_test_central(self, peripheral):
62        """Connects DUT as central to a peripheral device.
63
64           @param peripheral: meta object for bt peer device
65        """
66        # Pair the central device first -
67        # necessary for later connection to peripheral
68        self.pair_adapter_to_device(peripheral)
69        self.test_device_set_discoverable(peripheral, False)
70
71        self.start_connectable_advertisement()
72        # Discover DUT from peer
73        self.test_discover_by_device(peripheral)
74        # Connect to DUT from peer, putting DUT in peripheral role
75        self.test_connection_by_device(peripheral)
76        self.test_reset_advertising()
77
78
79    @test_wrapper('LLT: 1 Central 1 Peripheral. Order of connection CP',
80                  devices={
81                          'BLE_KEYBOARD': 1,
82                          'BLE_MOUSE': 1
83                  })
84    def llt_1c1p_connect_cp(self):
85        """Tests llt with two peer devices.
86           Connects DUT as central to first device
87           and as peripheral to second device,
88           sends small amount of data over the connection
89        """
90
91        self.verify_controller_capability(
92                        required_roles=['central-peripheral'])
93
94        central = self.devices['BLE_MOUSE'][0]
95        peripheral = self.devices['BLE_KEYBOARD'][0]
96        # Establish connection from DUT as LE Central
97        self.discover_and_pair(central)
98
99        self.test_hid_device_created(central.address)
100        # Verify data transfer over the DUT LE central Connection
101        self.test_mouse_left_click(central)
102
103        # Now establish second connection with DUT as LE Peripheral
104        self.bluetooth_le_facade = self.bluetooth_facade
105        self.pair_and_test_central(peripheral)
106        self.run_keyboard_tests(peripheral)
107
108        # Verify data over LE Central connection again
109        self.test_mouse_left_click(central)
110
111        # Disconnect connections from DUT
112        self.test_disconnection_by_adapter(central.address)
113        self.test_disconnection_by_device(peripheral)
114
115
116    @test_wrapper('LLT: 1 Central 1 Peripheral. Order of connection PC',
117                  devices={
118                          'BLE_KEYBOARD': 1,
119                          'BLE_MOUSE': 1
120                  })
121    def llt_1c1p_connect_pc(self):
122        """Tests llt with two peer devices,
123           Connects DUT as peripheral to first device
124           and as central to second device,
125           sends small amount of data over the connection
126        """
127
128        self.verify_controller_capability(
129                        required_roles=['central-peripheral'])
130
131        central = self.devices['BLE_MOUSE'][0]
132        peripheral = self.devices['BLE_KEYBOARD'][0]
133        # Establish the first connection with DUT as LE Peripheral
134        self.bluetooth_le_facade = self.bluetooth_facade
135
136        # Connect to DUT from peer, putting DUT in peripheral role
137        # Try transferring data over connection
138        self.pair_and_test_central(peripheral)
139        self.run_keyboard_tests(peripheral)
140
141        # Establish  second connection from DUT as LE Central
142        self.discover_and_pair(central)
143        self.test_hid_device_created(central.address)
144        # Verify data transfer over the DUT LE Central Connection
145        self.test_mouse_left_click(central)
146        # Verfiy LE peripheral connection again
147        self.run_keyboard_tests(peripheral)
148
149        # Disconnect connections from DUT
150        self.test_disconnection_by_adapter(central.address)
151        self.test_disconnection_by_device(peripheral)
152
153
154    @test_wrapper('LLT: 1 Central 1 Peripheral while DUT advertising.'
155                  'Order of connection PC',
156                  devices={
157                          'BLE_KEYBOARD': 1,
158                          'BLE_MOUSE': 1
159                  })
160    def llt_1c1p_connect_pc_while_adv(self):
161        """Tests llt with two peer devices, while DUT advertising.
162           Connects DUT while advertising
163           as peripheral to first device
164           and as central to second device,
165           sends small amount of data over the connection
166        """
167
168        self.verify_controller_capability(
169                        required_roles=['central-peripheral'])
170
171        central = self.devices['BLE_MOUSE'][0]
172        peripheral = self.devices['BLE_KEYBOARD'][0]
173        # Establish the first connection with DUT as LE Peripheral
174        self.bluetooth_le_facade = self.bluetooth_facade
175
176        # Connect to DUT from peer, putting DUT in peripheral role
177        # Try transferring data over connection
178        self.pair_and_test_central(peripheral)
179        self.run_keyboard_tests(peripheral)
180
181        # Establish second connection from DUT as LE Central
182        # while advertising in progress
183        self.start_connectable_advertisement()
184        self.discover_and_pair(central)
185        self.test_hid_device_created(central.address)
186
187        # Verify data transfer over the DUT LE Central Connection
188        self.test_mouse_left_click(central)
189        # Verfiy LE Peripheral connection again
190        self.run_keyboard_tests(peripheral)
191
192        # Disconnect connections from DUT
193        self.test_disconnection_by_adapter(central.address)
194        self.test_disconnection_by_device(peripheral)
195        self.test_reset_advertising()
196
197
198    @test_wrapper('LLT: 2 Central 1 Peripheral. Order of connection CCP',
199                  devices={
200                          'BLE_KEYBOARD': 1,
201                          'BLE_MOUSE': 1,
202                          'BLE_PHONE': 1
203                  })
204    def llt_2c1p_connect_ccp(self):
205        """Tests llt with three peer devices.
206           Connects DUT as central to first and second devices,
207           connects DUT as peripheral to third device,
208           sends small amount of data over the connection
209        """
210
211        self.verify_controller_capability(
212                        required_roles=['central-peripheral'])
213
214        central_1 = self.devices['BLE_PHONE'][0]
215        central_2 = self.devices['BLE_MOUSE'][0]
216        peripheral = self.devices['BLE_KEYBOARD'][0]
217        # Establish two connections from DUT as LE Central
218        self.discover_and_pair(central_2)
219        self.test_hid_device_created(central_2.address)
220
221        # Verify data transfer over two DUT LE Central Connections
222        self.test_mouse_left_click(central_2)
223
224        central_1.RemoveDevice(self.bluetooth_facade.address)
225        self.test_smart_unlock_llt(address=central_1.address)
226
227        # Establish third connection with DUT as LE Peripheral
228        self.bluetooth_le_facade = self.bluetooth_facade
229        self.pair_and_test_central(peripheral)
230        self.run_keyboard_tests(peripheral)
231
232        # Verify data transfer over two DUT LE Central Connections
233        self.test_mouse_left_click(central_2)
234
235        # Disconnect connections from DUT
236        self.test_disconnection_by_adapter(central_1.address)
237        self.test_disconnection_by_adapter(central_2.address)
238        self.test_disconnection_by_device(peripheral)
239
240
241    @test_wrapper('LLT: 2 Central 1 Peripheral. Order of connection PCC',
242                  devices={
243                          'BLE_KEYBOARD': 1,
244                          'BLE_MOUSE': 1,
245                          'BLE_PHONE': 1
246                  })
247    def llt_2c1p_connect_pcc(self):
248        """Tests llt with three peer devices.
249           Connects DUT as peripheral to first device
250           and as central to second and third device,
251           sends small amount of data over the connection
252        """
253
254        self.verify_controller_capability(
255                        required_roles=['central-peripheral'])
256
257        central_1 = self.devices['BLE_PHONE'][0]
258        central_2 = self.devices['BLE_MOUSE'][0]
259        peripheral = self.devices['BLE_KEYBOARD'][0]
260
261        # Establish the first connection with DUT as LE Peripheral
262        self.bluetooth_le_facade = self.bluetooth_facade
263
264        # Connect to DUT from peer, putting DUT in peripheral role
265        # Try transferring data over connection
266        self.pair_and_test_central(peripheral)
267        self.run_keyboard_tests(peripheral)
268
269        # Establish connections from DUT as LE Central
270        self.discover_and_pair(central_2)
271        self.test_hid_device_created(central_2.address)
272
273        # Verify data transfer over two DUT LE Central Connections
274        self.test_mouse_left_click(central_2)
275
276        # Establish third connection
277        central_1.RemoveDevice(self.bluetooth_facade.address)
278        self.test_smart_unlock_llt(address=central_1.address)
279
280        # Verify once again data transfer over DUT LE Peripheral connection
281        self.run_keyboard_tests(peripheral)
282
283        # Disconnect connections from DUT
284        self.test_disconnection_by_adapter(central_1.address)
285        self.test_disconnection_by_adapter(central_2.address)
286        self.test_disconnection_by_device(peripheral)
287
288
289    @test_wrapper('LLT: 2 Central 1 Peripheral. Order of connection CPC',
290                  devices={
291                          'BLE_KEYBOARD': 1,
292                          'BLE_MOUSE': 1,
293                          'BLE_PHONE': 1
294                  })
295    def llt_2c1p_connect_cpc(self):
296        """Tests llt with three peer devices.
297           Connects DUT as central to first device,
298           as peripheral to second and as central to third device,
299           sends small amount of data over the connection
300        """
301
302        self.verify_controller_capability(
303                        required_roles=['central-peripheral'])
304
305        central_1 = self.devices['BLE_PHONE'][0]
306        central_2 = self.devices['BLE_MOUSE'][0]
307        peripheral = self.devices['BLE_KEYBOARD'][0]
308
309        # Establish the first connection with DUT as LE Central
310        central_1.RemoveDevice(self.bluetooth_facade.address)
311        self.test_smart_unlock_llt(address=central_1.address)
312
313        # Establish the second connection with DUT as LE Peripheral
314        self.bluetooth_le_facade = self.bluetooth_facade
315
316        # Connect to DUT from peer, putting DUT in peripheral role
317        # Try transferring data over connection
318        self.pair_and_test_central(peripheral)
319        self.run_keyboard_tests(peripheral)
320
321        # Establish third connections from DUT as LE Central
322        self.discover_and_pair(central_2)
323        self.test_hid_device_created(central_2.address)
324
325        # Verify data transfer over second LE Central Connections
326        self.test_mouse_left_click(central_2)
327        # Verify once again data transfer over DUT LE Peripheral connection
328        self.run_keyboard_tests(peripheral)
329
330        # Disconnect connections from DUT
331        self.test_disconnection_by_adapter(central_1.address)
332        self.test_disconnection_by_adapter(central_2.address)
333        self.test_disconnection_by_device(peripheral)
334
335
336    @test_wrapper('LLT: 2 Central 1 Peripheral while DUT advertising.'
337                  'Order of connection PCC',
338                  devices={
339                          'BLE_KEYBOARD': 1,
340                          'BLE_MOUSE': 1,
341                          'BLE_PHONE': 1
342                  })
343    def llt_2c1p_connect_pcc_while_adv(self):
344        """Tests llt with three peer devices.
345           Connects DUT as peripheral to first device
346           and as central to second and third device while advertising,
347           sends small amount of data over the connection
348        """
349
350        self.verify_controller_capability(
351                        required_roles=['central-peripheral'])
352
353        central_1 = self.devices['BLE_MOUSE'][0]
354        central_2 = self.devices['BLE_PHONE'][0]
355        peripheral = self.devices['BLE_KEYBOARD'][0]
356
357        # Establish the first connection with DUT as LE Peripheral
358        self.bluetooth_le_facade = self.bluetooth_facade
359
360        # Connect to DUT from peer, putting DUT in peripheral role
361        # Try transferring data over connection
362        self.pair_and_test_central(peripheral)
363        self.run_keyboard_tests(peripheral)
364
365        # Connect as first LE Central while DUT is advertising
366        self.start_connectable_advertisement()
367        self.discover_and_pair(central_1)
368        self.test_hid_device_created(central_1.address)
369
370        # Establish second LE connection from DUT as LE Central
371        central_2.RemoveDevice(self.bluetooth_facade.address)
372        self.test_smart_unlock_llt(address=central_2.address)
373
374        # Verify data transfer over first LE Central Connections
375        self.test_mouse_left_click(central_1)
376        # Verify once again data transfer over DUT LE Peripheral connection
377        self.run_keyboard_tests(peripheral)
378
379        # Disconnect connections from DUT
380        self.test_disconnection_by_adapter(central_1.address)
381        self.test_disconnection_by_adapter(central_2.address)
382        self.test_disconnection_by_device(peripheral)
383        self.test_reset_advertising()
384
385
386    @test_wrapper('LLT: 2 Central 1 Peripheral while DUT Advertising.'
387                  'Order of connection CPC',
388                  devices={
389                          'BLE_KEYBOARD': 1,
390                          'BLE_MOUSE': 1,
391                          'BLE_PHONE': 1
392                  })
393    def llt_2c1p_connect_cpc_while_adv(self):
394        """Tests llt with three peer devices.
395           Connects DUT while advertising as central to first device,
396           as peripheral to second and as central to third device,
397           sends small amount of data over the connection
398        """
399
400        self.verify_controller_capability(
401                        required_roles=['central-peripheral'])
402
403        central_1 = self.devices['BLE_PHONE'][0]
404        central_2 = self.devices['BLE_MOUSE'][0]
405        peripheral = self.devices['BLE_KEYBOARD'][0]
406
407        self.bluetooth_le_facade = self.bluetooth_facade
408        # Establish the first connection with DUT as LE Central
409        # while advertising in progress
410        self.start_connectable_advertisement()
411        central_1.RemoveDevice(self.bluetooth_facade.address)
412        self.test_smart_unlock_llt(address=central_1.address)
413
414        # Establish the second connection with DUT as LE Peripheral
415        # Try transferring data over connection
416        self.pair_and_test_central(peripheral)
417        self.run_keyboard_tests(peripheral)
418
419        # Establish third connections from DUT as LE Central
420        self.discover_and_pair(central_2)
421        self.test_hid_device_created(central_2.address)
422
423        # Verify data transfer over second LE Central Connections
424        self.test_mouse_left_click(central_2)
425        # Verify once again data transfer over DUT LE Peripheral connection
426        self.run_keyboard_tests(peripheral)
427
428        # Disconnect connections from DUT
429        self.test_disconnection_by_adapter(central_1.address)
430        self.test_disconnection_by_adapter(central_2.address)
431        self.test_disconnection_by_device(peripheral)
432        self.test_reset_advertising()
433
434
435    @test_wrapper('LLT: 1 Central 2 Peripheral. Order of connection CPP',
436                  devices={
437                          'BLE_KEYBOARD': 1,
438                          'BLE_MOUSE': 1,
439                          'BLE_PHONE': 1
440                  })
441    def llt_2p1c_connect_cpp(self):
442        """Tests llt with three peer devices.
443           Connects DUT as central to first device
444           and as peripheral to second and third devices,
445           sends small amount of data over the connection
446        """
447
448        self.verify_controller_capability(
449                        required_roles=['central-peripheral'])
450
451        peripheral_1 = self.devices['BLE_KEYBOARD'][0]
452        central_peer = self.devices['BLE_PHONE'][0]
453        peripheral_2 = self.devices['BLE_MOUSE'][0]
454
455        # Establish connection from DUT as LE Central
456        central_peer.RemoveDevice(self.bluetooth_facade.address)
457        self.test_smart_unlock_llt(address=central_peer.address)
458
459        self.bluetooth_le_facade = self.bluetooth_facade
460
461        # Connect to DUT from peer, putting DUT in peripheral role
462        # Try transferring data over connection
463        self.pair_and_test_central(peripheral_1)
464        self.run_keyboard_tests(peripheral_1)
465
466        # Establish and Verify second LE peripheral connection
467        self.pair_and_test_central(peripheral_2)
468
469        # Try transferring data over connection
470        self.test_mouse_left_click(peripheral_2)
471        # Verify traffic from LE Peripheral connections again
472        self.run_keyboard_tests(peripheral_1)
473        self.test_mouse_left_click(peripheral_2)
474
475        # Disconnect connections from DUT
476        self.test_disconnection_by_adapter(central_peer.address)
477        self.test_disconnection_by_device(peripheral_1)
478        self.test_disconnection_by_device(peripheral_2)
479
480
481    @test_wrapper('LLT: 1 Central 2 Peripheral. Order of connection PCP',
482                  devices={
483                          'BLE_KEYBOARD': 1,
484                          'BLE_MOUSE': 1,
485                          'BLE_PHONE': 1
486                  })
487    def llt_2p1c_connect_pcp(self):
488        """Tests llt with three peer devices.
489           Connects DUT as peripheral to first device,
490           as central to second and as peripheral to third devices,
491           sends small amount of data over the connection
492        """
493
494        self.verify_controller_capability(
495                        required_roles=['central-peripheral'])
496
497        peripheral_1 = self.devices['BLE_KEYBOARD'][0]
498        central_peer = self.devices['BLE_PHONE'][0]
499        peripheral_2 = self.devices['BLE_MOUSE'][0]
500
501        self.bluetooth_le_facade = self.bluetooth_facade
502
503        # Connect to DUT from peer, putting DUT in peripheral role
504        # Try transferring data over connection
505        self.pair_and_test_central(peripheral_1)
506        self.run_keyboard_tests(peripheral_1)
507
508        # Establish connection from DUT as LE Central
509        central_peer.RemoveDevice(self.bluetooth_facade.address)
510        self.test_smart_unlock_llt(address=central_peer.address)
511
512        # Establish and Verify second LE peripheral connection
513        self.pair_and_test_central(peripheral_2)
514
515        # Try transferring data over connection
516        self.test_mouse_left_click(peripheral_2)
517        # Verify traffic from LE Peripheral connections again
518        self.run_keyboard_tests(peripheral_1)
519        self.test_mouse_left_click(peripheral_2)
520
521        # Disconnect connections from DUT
522        self.test_disconnection_by_adapter(central_peer.address)
523        self.test_disconnection_by_device(peripheral_1)
524        self.test_disconnection_by_device(peripheral_2)
525
526
527    @test_wrapper('LLT: 1 Central 2 Peripheral. Order of connection PPC',
528                  devices={
529                          'BLE_KEYBOARD': 1,
530                          'BLE_MOUSE': 1,
531                          'BLE_PHONE': 1
532                  })
533    def llt_2p1c_connect_ppc(self):
534        """Tests llt with three peer devices.
535           Connects DUT as peripheral to first and second devices
536           and as central to third device,
537           sends small amount of data over the connection
538        """
539
540        self.verify_controller_capability(
541                        required_roles=['central-peripheral'])
542
543        peripheral_1 = self.devices['BLE_KEYBOARD'][0]
544        central_peer = self.devices['BLE_PHONE'][0]
545        peripheral_2 = self.devices['BLE_MOUSE'][0]
546
547        self.bluetooth_le_facade = self.bluetooth_facade
548
549        # Connect to DUT from peer, putting DUT in peripheral role
550        # Try transferring data over connection
551        self.pair_and_test_central(peripheral_1)
552        self.run_keyboard_tests(peripheral_1)
553
554        # Establish and Verify second LE peripheral connection
555        self.pair_and_test_central(peripheral_2)
556
557        # Try transferring data over connection
558        self.test_mouse_left_click(peripheral_2)
559
560        # Verify data transfer over two DUT LE Central Connections
561        central_peer.RemoveDevice(self.bluetooth_facade.address)
562        self.test_smart_unlock_llt(address=central_peer.address)
563        # Verify traffic from LE Peripheral connections again
564        self.run_keyboard_tests(peripheral_1)
565        self.test_mouse_left_click(peripheral_2)
566
567        # Disconnect connections from DUT
568        self.test_disconnection_by_adapter(central_peer.address)
569        self.test_disconnection_by_device(peripheral_1)
570        self.test_disconnection_by_device(peripheral_2)
571
572
573    @batch_wrapper('LLT Health')
574    def llt_health_batch_run(self, num_iterations=1, test_name=None):
575        """Run the LE LLT health test batch or a specific given test.
576           The wrapper of this method is implemented in batch_decorator.
577           Using the decorator a test batch method can implement the only its
578           core tests invocations and let the decorator handle the wrapper,
579           which is taking care for whether to run a specific test or the
580           batch as a whole, and running the batch in iterations
581
582           @param num_iterations: how many iterations to run
583           @param test_name: specific test to run otherwise None to run the
584                             whole batch
585        """
586        self.llt_1c1p_connect_cp()
587        self.llt_1c1p_connect_pc()
588        self.llt_1c1p_connect_pc_while_adv()
589        self.llt_2c1p_connect_ccp()
590        self.llt_2c1p_connect_pcc()
591        self.llt_2c1p_connect_cpc()
592        self.llt_2c1p_connect_pcc_while_adv()
593        self.llt_2c1p_connect_cpc_while_adv()
594        self.llt_2p1c_connect_cpp()
595        self.llt_2p1c_connect_pcp()
596        self.llt_2p1c_connect_ppc()
597
598
599    def run_once(self,
600                 host,
601                 num_iterations=1,
602                 args_dict=None,
603                 test_name=None,
604                 flag='Quick Health'):
605        """Run the batch of Bluetooth LE LLT health tests
606
607        @param host: the DUT, usually a chromebook
608        @param num_iterations: the number of rounds to execute the test
609        @test_name: the test to run, or None for all tests
610        """
611
612        # Initialize and run the test batch or the requested specific test
613        self.quick_test_init(host,
614                             use_btpeer=True,
615                             flag=flag,
616                             args_dict=args_dict)
617        self.llt_health_batch_run(num_iterations, test_name)
618        self.quick_test_cleanup()
619