• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright (C) 2016 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6# use this file except in compliance with the License. You may obtain a copy of
7# the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations under
15# the License.
16"""
17Test script to exercises different ways Ble Advertisements can run in
18concurrency. This test was designed to be run in a shield box.
19"""
20
21import concurrent
22import time
23
24from queue import Empty
25from acts.test_decorators import test_tracker_info
26from acts_contrib.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
27from acts_contrib.test_utils.bt.bt_test_utils import BtTestUtilsError
28from acts_contrib.test_utils.bt.bt_constants import ble_advertise_settings_modes
29from acts_contrib.test_utils.bt.bt_constants import ble_scan_settings_callback_types
30from acts_contrib.test_utils.bt.bt_constants import ble_scan_settings_modes
31from acts_contrib.test_utils.bt.bt_constants import adv_succ
32from acts_contrib.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
33from acts_contrib.test_utils.bt.bt_test_utils import generate_ble_scan_objects
34from acts_contrib.test_utils.bt.bt_test_utils import get_advanced_droid_list
35from acts_contrib.test_utils.bt.bt_test_utils import reset_bluetooth
36from acts_contrib.test_utils.bt.bt_test_utils import scan_and_verify_n_advertisements
37from acts_contrib.test_utils.bt.bt_constants import scan_result
38from acts_contrib.test_utils.bt.bt_test_utils import setup_n_advertisements
39from acts_contrib.test_utils.bt.bt_test_utils import take_btsnoop_logs
40from acts_contrib.test_utils.bt.bt_test_utils import teardown_n_advertisements
41
42
43class ConcurrentBleAdvertisingTest(BluetoothBaseTest):
44    default_timeout = 10
45    droid_list = []
46    max_advertisements = -1
47
48    def setup_class(self):
49        super().setup_class()
50        self.scn_ad = self.android_devices[0]
51        self.adv_ad = self.android_devices[1]
52        self.droid_list = get_advanced_droid_list(self.android_devices)
53        self.max_advertisements = self.droid_list[1]['max_advertisements']
54
55    def setup_test(self):
56        super().setup_test()
57        return reset_bluetooth(self.android_devices)
58
59    def _verify_n_advertisements(self, num_advertisements):
60        try:
61            advertise_callback_list = setup_n_advertisements(
62                self.adv_ad, num_advertisements)
63        except BtTestUtilsError:
64            return False
65        try:
66            scan_and_verify_n_advertisements(self.scn_ad, num_advertisements)
67        except BtTestUtilsError:
68            return False
69        teardown_n_advertisements(self.adv_ad, len(advertise_callback_list),
70                                  advertise_callback_list)
71        return True
72
73    @BluetoothBaseTest.bt_test_wrap
74    @test_tracker_info(uuid='abc03874-6d7a-4b5d-9f29-18731a102793')
75    def test_max_advertisements_defaults(self):
76        """Testing max advertisements.
77
78        Test that a single device can have the max advertisements
79        concurrently advertising.
80
81        Steps:
82        1. Setup the scanning android device.
83        2. Setup the advertiser android device.
84        3. Start scanning on the max_advertisements as defined in the script.
85        4. Verify that all advertisements are found.
86
87        Expected Result:
88        All advertisements should start without errors.
89
90        Returns:
91          Pass if True
92          Fail if False
93
94        TAGS: LE, Advertising, Concurrency
95        Priority: 0
96        """
97        return self._verify_n_advertisements(self.max_advertisements)
98
99    @BluetoothBaseTest.bt_test_wrap
100    @test_tracker_info(uuid='50ee137e-eb71-40ef-b72f-a5fd646190d2')
101    def test_max_advertisements_include_device_name_and_filter_device_name(
102            self):
103        """Testing max advertisement variant.
104
105        Test that a single device can have the max advertisements
106        concurrently advertising. Include the device name as a part of the filter
107        and advertisement data.
108
109        Steps:
110        1. Setup the scanning android device.
111        2. Setup the advertiser android device.
112        3. Include device name in each advertisement.
113        4. Include device name filter in the scanner.
114        5. Start scanning on the max_advertisements as defined in the script.
115        6. Verify that all advertisements are found.
116
117        Expected Result:
118        All advertisements should start without errors.
119
120        Returns:
121          Pass if True
122          Fail if False
123
124        TAGS: LE, Advertising, Concurrency
125        Priority: 2
126        """
127        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
128        self.scn_ad.droid.bleSetScanFilterDeviceName(
129            self.adv_ad.droid.bluetoothGetLocalName())
130        return self._verify_n_advertisements(self.max_advertisements)
131
132    @BluetoothBaseTest.bt_test_wrap
133    @test_tracker_info(uuid='f7e9ba2b-6286-4510-a8a0-f1df831056c0')
134    def test_max_advertisements_exclude_device_name_and_filter_device_name(
135            self):
136        """Test max advertisement variant.
137
138        Test that a single device can have the max advertisements concurrently
139        advertising. Include the device name as a part of the filter but not the
140        advertisement data.
141
142        Steps:
143        1. Setup the scanning android device.
144        2. Setup the advertiser android device.
145        3. Include device name filter in the scanner.
146        4. Start scanning on the max_advertisements as defined in the script.
147        5. Verify that no advertisements are found.
148
149        Expected Result:
150        All advertisements should start without errors.
151
152        Returns:
153          Pass if True
154          Fail if False
155
156        TAGS: LE, Advertising, Concurrency
157        Priority: 2
158        """
159        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(False)
160        self.scn_ad.droid.bleSetScanFilterDeviceName(
161            self.adv_ad.droid.bluetoothGetLocalName())
162        return not self._verify_n_advertisements(self.max_advertisements)
163
164    @BluetoothBaseTest.bt_test_wrap
165    @test_tracker_info(uuid='6ce102d7-61e1-4ca0-bcfb-767437b86c2b')
166    def test_max_advertisements_with_manufacturer_data(self):
167        """Test max advertisement variant.
168
169        Test that a single device can have the max advertisements concurrently
170        advertising. Include the manufacturer data as a part of the filter and
171        advertisement data.
172
173        Steps:
174        1. Setup the scanning android device.
175        2. Setup the advertiser android device.
176        3. Include manufacturer data in each advertisement.
177        4. Include manufacturer data filter in the scanner.
178        5. Start scanning on the max_advertisements as defined in the script.
179        6. Verify that all advertisements are found.
180
181        Expected Result:
182        All advertisements should start without errors.
183
184        Returns:
185          Pass if True
186          Fail if False
187
188        TAGS: LE, Advertising, Concurrency
189        Priority: 2
190        """
191        self.scn_ad.droid.bleSetScanFilterManufacturerData(1, [1])
192        self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, [1])
193        return self._verify_n_advertisements(self.max_advertisements)
194
195    @BluetoothBaseTest.bt_test_wrap
196    @test_tracker_info(uuid='2fc7d5e8-1539-42a8-8681-ce0b8bfc0924')
197    def test_max_advertisements_with_manufacturer_data_mask(self):
198        """Test max advertisements variant.
199
200        Test that a single device can have the max advertisements concurrently
201        advertising. Include the manufacturer data mask as a part of the filter
202        and advertisement data.
203
204        Steps:
205        1. Setup the scanning android device.
206        2. Setup the advertiser android device.
207        3. Include manufacturer data in each advertisement.
208        4. Include manufacturer data mask filter in the scanner.
209        5. Start scanning on the max_advertisements as defined in the script.
210        6. Verify that all advertisements are found.
211
212        Expected Result:
213        All advertisements should start without errors.
214
215        Returns:
216          Pass if True
217          Fail if False
218
219        TAGS: LE, Advertising, Concurrency
220        Priority: 2
221        """
222        self.scn_ad.droid.bleSetScanFilterManufacturerData(1, [1], [1])
223        self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, [1])
224        return self._verify_n_advertisements(self.max_advertisements)
225
226    @BluetoothBaseTest.bt_test_wrap
227    @test_tracker_info(uuid='9ef615ed-1705-44ae-ab5b-f7e8fb4bb770')
228    def test_max_advertisements_with_service_data(self):
229        """Test max advertisement variant.
230
231        Test that a single device can have the max advertisements concurrently
232        advertising. Include the service data as a part of the filter and
233        advertisement data.
234
235        Steps:
236        1. Setup the scanning android device.
237        2. Setup the advertiser android device.
238        3. Include service data in each advertisement.
239        4. Include service data filter in the scanner.
240        5. Start scanning on the max_advertisements as defined in the script.
241        6. Verify that all advertisements are found.
242
243        Expected Result:
244        All advertisements should start without errors.
245
246        Returns:
247          Pass if True
248          Fail if False
249
250        TAGS: LE, Advertising, Concurrency
251        Priority: 2
252        """
253        test_result = True
254        filter_list = self.scn_ad.droid.bleGenFilterList()
255        self.scn_ad.droid.bleSetScanFilterServiceData(
256            "0000110A-0000-1000-8000-00805F9B34FB", [11, 17, 80])
257        self.adv_ad.droid.bleAddAdvertiseDataServiceData(
258            "0000110A-0000-1000-8000-00805F9B34FB", [11, 17, 80])
259        return self._verify_n_advertisements(self.max_advertisements)
260
261    @BluetoothBaseTest.bt_test_wrap
262    @test_tracker_info(uuid='9ef615ed-1705-44ae-ab5b-f7e8fb4bb770')
263    def test_max_advertisements_with_manufacturer_data_mask_and_include_device_name(
264            self):
265        """Test max advertisement variant.
266
267        Test that a single device can have the max advertisements concurrently
268        advertising. Include the device name and manufacturer data as a part of
269        the filter and advertisement data.
270
271        Steps:
272        1. Setup the scanning android device.
273        2. Setup the advertiser android device.
274        3. Include device name and manufacturer data in each advertisement.
275        4. Include device name and manufacturer data filter in the scanner.
276        5. Start scanning on the max_advertisements as defined in the script.
277        6. Verify that all advertisements are found.
278
279        Expected Result:
280        All advertisements should start without errors.
281
282        Returns:
283          Pass if True
284          Fail if False
285
286        TAGS: LE, Advertising, Concurrency
287        Priority: 2
288        """
289        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
290        self.scn_ad.droid.bleSetScanFilterDeviceName(
291            self.adv_ad.droid.bluetoothGetLocalName())
292        self.scn_ad.droid.bleSetScanFilterManufacturerData(1, [1], [1])
293        self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, [1])
294        return self._verify_n_advertisements(self.max_advertisements)
295
296    @BluetoothBaseTest.bt_test_wrap
297    @test_tracker_info(uuid='c2ca85fb-6663-431d-aa30-5286a85dbbe0')
298    def test_max_advertisements_with_service_uuids(self):
299        """Test max advertisement variant.
300
301        Test that a single device can have the max advertisements concurrently
302        advertising. Include the service uuid as a part of the filter and
303        advertisement data.
304
305        Steps:
306        1. Setup the scanning android device.
307        2. Setup the advertiser android device.
308        3. Include service uuid in each advertisement.
309        4. Include service uuid filter in the scanner.
310        5. Start scanning on the max_advertisements as defined in the script.
311        6. Verify that all advertisements are found.
312
313        Expected Result:
314        All advertisements should start without errors.
315
316        Returns:
317          Pass if True
318          Fail if False
319
320        TAGS: LE, Advertising, Concurrency
321        Priority: 1
322        """
323        self.scn_ad.droid.bleSetScanFilterServiceUuid(
324            "00000000-0000-1000-8000-00805f9b34fb")
325        self.adv_ad.droid.bleSetAdvertiseDataSetServiceUuids(
326            ["00000000-0000-1000-8000-00805f9b34fb"])
327        return self._verify_n_advertisements(self.max_advertisements)
328
329    @BluetoothBaseTest.bt_test_wrap
330    @test_tracker_info(uuid='756e026f-64d7-4a2f-935a-3790c0ac4503')
331    def test_max_advertisements_with_service_uuid_and_service_mask(self):
332        """Test max advertisements variant.
333
334        Test that a single device can have the max advertisements concurrently
335        advertising. Include the service mask as a part of the filter and
336        advertisement data.
337
338        Steps:
339        1. Setup the scanning android device.
340        2. Setup the advertiser android device.
341        3. Include service uuid in each advertisement.
342        4. Include service mask filter in the scanner.
343        5. Start scanning on the max_advertisements as defined in the script.
344        6. Verify that all advertisements are found.
345
346        Expected Result:
347        All advertisements should start without errors.
348
349        Returns:
350          Pass if True
351          Fail if False
352
353        TAGS: LE, Advertising, Concurrency
354        Priority: 2
355        """
356        self.scn_ad.droid.bleSetScanFilterServiceUuid(
357            "00000000-0000-1000-8000-00805f9b34fb",
358            "00000000-0000-1000-8000-00805f9b34fb")
359        self.adv_ad.droid.bleSetAdvertiseDataSetServiceUuids(
360            ["00000000-0000-1000-8000-00805f9b34fb"])
361        return self._verify_n_advertisements(self.max_advertisements)
362
363    @BluetoothBaseTest.bt_test_wrap
364    @test_tracker_info(uuid='79c4b6cd-9f07-49a9-829f-69b29ea8d322')
365    def test_max_advertisements_plus_one(self):
366        """Test max advertisements plus one.
367
368        Test that a single device can have the max advertisements concurrently
369        advertising but fail on starting the max advertisements plus one.
370        filter and advertisement data.
371
372        Steps:
373        1. Setup the scanning android device.
374        2. Setup the advertiser android device.
375        3. Start max_advertisements + 1.
376
377        Expected Result:
378        The last advertisement should fail.
379
380        Returns:
381          Pass if True
382          Fail if False
383
384        TAGS: LE, Advertising, Concurrency
385        Priority: 0
386        """
387        return not self._verify_n_advertisements(self.max_advertisements + 1)
388
389    @BluetoothBaseTest.bt_test_wrap
390    @test_tracker_info(uuid='0bd6e490-a501-4fe1-88e5-9b77970c0b95')
391    def test_start_two_advertisements_on_same_callback(self):
392        """Test invalid advertisement scenario.
393
394        Test that a single device cannot have two advertisements start on the
395        same callback.
396
397        Steps:
398        1. Setup the scanning android device.
399        2. Setup the advertiser android device.
400        3. Call start ble advertising on the same callback.
401
402        Expected Result:
403        The second call of start advertising on the same callback should fail.
404
405        Returns:
406          Pass if True
407          Fail if False
408
409        TAGS: LE, Advertising, Concurrency
410        Priority: 1
411        """
412        test_result = True
413        advertise_callback, advertise_data, advertise_settings = (
414            generate_ble_advertise_objects(self.adv_ad.droid))
415        self.adv_ad.droid.bleStartBleAdvertising(advertise_callback,
416                                                 advertise_data,
417                                                 advertise_settings)
418        try:
419            self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback),
420                                     self.default_timeout)
421        except Empty as error:
422            self.log.error("Test failed with Empty error: {}".format(error))
423            return False
424        except concurrent.futures._base.TimeoutError as error:
425            self.log.debug(
426                "Test failed, filtering callback onSuccess never occurred: {}".
427                format(error))
428        try:
429            self.adv_ad.droid.bleStartBleAdvertising(advertise_callback,
430                                                     advertise_data,
431                                                     advertise_settings)
432            self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback),
433                                     self.default_timeout)
434            test_result = False
435        except Empty as error:
436            self.log.debug("Test passed with Empty error: {}".format(error))
437        except concurrent.futures._base.TimeoutError as error:
438            self.log.debug(
439                "Test passed, filtering callback onSuccess never occurred: {}".
440                format(error))
441
442        return test_result
443
444    @BluetoothBaseTest.bt_test_wrap
445    @test_tracker_info(uuid='12632b31-22b9-4121-80b6-1263b9d90909')
446    def test_toggle_advertiser_bt_state(self):
447        """Test forcing stopping advertisements.
448
449        Test that a single device resets its callbacks when the bluetooth state is
450        reset. There should be no advertisements.
451
452        Steps:
453        1. Setup the scanning android device.
454        2. Setup the advertiser android device.
455        3. Call start ble advertising.
456        4. Toggle bluetooth on and off.
457        5. Scan for any advertisements.
458
459        Expected Result:
460        No advertisements should be found after toggling Bluetooth on the
461        advertising device.
462
463        Returns:
464          Pass if True
465          Fail if False
466
467        TAGS: LE, Advertising, Concurrency
468        Priority: 2
469        """
470        test_result = True
471        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
472        advertise_callback, advertise_data, advertise_settings = (
473            generate_ble_advertise_objects(self.adv_ad.droid))
474        self.adv_ad.droid.bleStartBleAdvertising(advertise_callback,
475                                                 advertise_data,
476                                                 advertise_settings)
477        try:
478            self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback),
479                                     self.default_timeout)
480        except Empty as error:
481            self.log.error("Test failed with Empty error: {}".format(error))
482            return False
483        except concurrent.futures._base.TimeoutError as error:
484            self.log.error(
485                "Test failed, filtering callback onSuccess never occurred: {}".
486                format(error))
487        self.scn_ad.droid.bleSetScanSettingsScanMode(
488            ble_scan_settings_modes['low_latency'])
489        self.scn_ad.droid.bleSetScanFilterDeviceName(
490            self.adv_ad.droid.bluetoothGetLocalName())
491        filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
492            self.scn_ad.droid)
493        self.scn_ad.droid.bleBuildScanFilter(filter_list)
494        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
495                                          scan_callback)
496        try:
497            self.scn_ad.ed.pop_event(scan_result.format(scan_callback),
498                                     self.default_timeout)
499        except Empty as error:
500            self.log.error("Test failed with: {}".format(error))
501            return False
502        self.scn_ad.droid.bleStopBleScan(scan_callback)
503        test_result = reset_bluetooth([self.android_devices[1]])
504        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
505                                          scan_callback)
506        if not test_result:
507            return False
508        try:
509            expected_event = scan_result.format(scan_callback)
510            event = self.scn_ad.ed.pop_event(expected_event,
511                                             self.default_timeout)
512            self.log.error("Event {} not expected. Found: {}".format(
513                expected_event, event))
514            return False
515        except Empty as error:
516            self.log.debug("Test passed with: {}".format(error))
517        self.scn_ad.droid.bleStopBleScan(scan_callback)
518        self.adv_ad.droid.bleStopBleAdvertising(advertise_callback)
519        return True
520
521    @BluetoothBaseTest.bt_test_wrap
522    @test_tracker_info(uuid='785c5c77-d5d4-4d0f-8b7b-3eb1f1646d2c')
523    def test_restart_advertise_callback_after_bt_toggle(self):
524        """Test starting an advertisement on a cleared out callback.
525
526        Test that a single device resets its callbacks when the bluetooth state
527        is reset.
528
529        Steps:
530        1. Setup the scanning android device.
531        2. Setup the advertiser android device.
532        3. Call start ble advertising.
533        4. Toggle bluetooth on and off.
534        5. Call start ble advertising on the same callback.
535
536        Expected Result:
537        Starting an advertisement on a callback id after toggling bluetooth
538        should fail.
539
540        Returns:
541          Pass if True
542          Fail if False
543
544        TAGS: LE, Advertising, Concurrency
545        Priority: 1
546        """
547        test_result = True
548        advertise_callback, advertise_data, advertise_settings = (
549            generate_ble_advertise_objects(self.adv_ad.droid))
550        self.adv_ad.droid.bleStartBleAdvertising(advertise_callback,
551                                                 advertise_data,
552                                                 advertise_settings)
553        try:
554            self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback),
555                                     self.default_timeout)
556        except Empty as error:
557            self.log.error("Test failed with Empty error: {}".format(error))
558            test_result = False
559        except concurrent.futures._base.TimeoutError as error:
560            self.log.debug(
561                "Test failed, filtering callback onSuccess never occurred: {}".
562                format(error))
563        test_result = reset_bluetooth([self.android_devices[1]])
564        if not test_result:
565            return test_result
566        self.adv_ad.droid.bleStartBleAdvertising(advertise_callback,
567                                                 advertise_data,
568                                                 advertise_settings)
569        try:
570            self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback),
571                                     self.default_timeout)
572        except Empty as error:
573            self.log.error("Test failed with Empty error: {}".format(error))
574            test_result = False
575        except concurrent.futures._base.TimeoutError as error:
576            self.log.debug(
577                "Test failed, filtering callback onSuccess never occurred: {}".
578                format(error))
579        return test_result
580
581    @BluetoothBaseTest.bt_test_wrap
582    @test_tracker_info(uuid='dd5529b7-6774-4580-8b29-d84568c15442')
583    def test_timeout(self):
584        """Test starting advertiser with timeout.
585
586        Test that when a timeout is used, the advertiser is cleaned properly,
587        and next one can be started.
588
589        Steps:
590        1. Setup the advertiser android device with 4 second timeout.
591        2. Call start ble advertising.
592        3. Wait 5 seconds, to make sure advertiser times out.
593        4. Repeat steps 1-4 four times.
594
595        Expected Result:
596        Starting the advertising should succeed each time.
597
598        Returns:
599          Pass if True
600          Fail if False
601
602        TAGS: LE, Advertising, Concurrency
603        Priority: 1
604        """
605        advertise_timeout_s = 4
606        num_iterations = 4
607        test_result = True
608
609        for i in range(0, num_iterations):
610            advertise_callback, advertise_data, advertise_settings = (
611                generate_ble_advertise_objects(self.adv_ad.droid))
612
613            self.adv_ad.droid.bleSetAdvertiseSettingsTimeout(
614                advertise_timeout_s * 1000)
615
616            self.adv_ad.droid.bleStartBleAdvertising(advertise_callback,
617                                                     advertise_data,
618                                                     advertise_settings)
619            try:
620                self.adv_ad.ed.pop_event(adv_succ.format(advertise_callback),
621                                         self.default_timeout)
622            except Empty as error:
623                self.log.error(
624                    "Test failed with Empty error: {}".format(error))
625                test_result = False
626            except concurrent.futures._base.TimeoutError as error:
627                self.log.debug(
628                    "Test failed, filtering callback onSuccess never occurred: {}"
629                    .format(error))
630
631            if not test_result:
632                return test_result
633
634            time.sleep(advertise_timeout_s + 1)
635
636        return test_result
637