• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#/usr/bin/env python3.4
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 os
23import time
24
25from queue import Empty
26from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
27from acts.test_utils.bt.BleEnum import AdvertiseSettingsAdvertiseMode
28from acts.test_utils.bt.BleEnum import ScanSettingsCallbackType
29from acts.test_utils.bt.BleEnum import ScanSettingsScanMode
30from acts.test_utils.bt.bt_test_utils import adv_succ
31from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
32from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects
33from acts.test_utils.bt.bt_test_utils import get_advanced_droid_list
34from acts.test_utils.bt.bt_test_utils import reset_bluetooth
35from acts.test_utils.bt.bt_test_utils import scan_result
36from acts.test_utils.bt.bt_test_utils import take_btsnoop_logs
37
38
39class ConcurrentBleAdvertisingTest(BluetoothBaseTest):
40    default_timeout = 10
41    max_advertisements = 4
42
43    def __init__(self, controllers):
44        BluetoothBaseTest.__init__(self, controllers)
45        self.droid_list = get_advanced_droid_list(self.android_devices)
46        self.scn_ad = self.android_devices[0]
47        self.adv_ad = self.android_devices[1]
48        self.max_advertisements = self.droid_list[1]['max_advertisements']
49        if self.max_advertisements == 0:
50            self.tests = ()
51            return
52
53    def on_fail(self, test_name, begin_time):
54        self.log.debug(
55            "Test {} failed. Gathering bugreport and btsnoop logs".format(
56                test_name))
57        take_btsnoop_logs(self.android_devices, self, test_name)
58        reset_bluetooth(self.android_devices)
59
60    def setup_test(self):
61        return reset_bluetooth(self.android_devices)
62
63    def _verify_n_advertisements(self, num_advertisements, filter_list):
64        test_result = False
65        address_list = []
66        self.scn_ad.droid.bleSetScanSettingsCallbackType(
67            ScanSettingsCallbackType.CALLBACK_TYPE_ALL_MATCHES.value)
68        self.scn_ad.droid.bleSetScanSettingsScanMode(
69            ScanSettingsScanMode.SCAN_MODE_LOW_LATENCY.value)
70        self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode(
71            AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value)
72        advertise_data = self.adv_ad.droid.bleBuildAdvertiseData()
73        advertise_settings = self.adv_ad.droid.bleBuildAdvertiseSettings()
74        advertise_callback_list = []
75        for i in range(num_advertisements):
76            advertise_callback = self.adv_ad.droid.bleGenBleAdvertiseCallback()
77            advertise_callback_list.append(advertise_callback)
78            self.adv_ad.droid.bleStartBleAdvertising(
79                advertise_callback, advertise_data, advertise_settings)
80            try:
81                self.adv_ad.ed.pop_event(
82                    adv_succ.format(advertise_callback), self.default_timeout)
83                self.log.info("Advertisement {} started.".format(i + 1))
84            except Empty as error:
85                self.log.info("Advertisement {} failed to start.".format(i +
86                                                                         1))
87                self.log.debug("Test failed with Empty error: {}".format(
88                    error))
89                return False
90            except concurrent.futures._base.TimeoutError as error:
91                self.log.debug(
92                    "Test failed, filtering callback onSuccess never occurred: "
93                    "{}".format(error))
94                return False
95        scan_settings = self.scn_ad.droid.bleBuildScanSetting()
96        scan_callback = self.scn_ad.droid.bleGenScanCallback()
97        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
98                                          scan_callback)
99        start_time = time.time()
100        while (start_time + self.default_timeout) > time.time():
101            event = None
102            try:
103                event = self.scn_ad.ed.pop_event(
104                    scan_result.format(scan_callback), self.default_timeout)
105            except Empty as error:
106                self.log.debug("Test failed with: {}".format(error))
107                return test_result
108            except concurrent.futures._base.TimeoutError as error:
109                self.log.debug("Test failed with: {}".format(error))
110                return test_result
111            address = event['data']['Result']['deviceInfo']['address']
112            if address not in address_list:
113                address_list.append(address)
114            if len(address_list) == num_advertisements:
115                test_result = True
116                break
117        for callback in advertise_callback_list:
118            self.adv_ad.droid.bleStopBleAdvertising(callback)
119        self.scn_ad.droid.bleStopBleScan(scan_callback)
120        return test_result
121
122    @BluetoothBaseTest.bt_test_wrap
123    def test_max_advertisements_defaults(self):
124        """Testing max advertisements.
125
126        Test that a single device can have the max advertisements
127        concurrently advertising.
128
129        Steps:
130        1. Setup the scanning android device.
131        2. Setup the advertiser android device.
132        3. Start scanning on the max_advertisements as defined in the script.
133        4. Verify that all advertisements are found.
134
135        Expected Result:
136        All advertisements should start without errors.
137
138        Returns:
139          Pass if True
140          Fail if False
141
142        TAGS: LE, Advertising, Concurrency
143        Priority: 0
144        """
145        test_result = True
146        filter_list = self.scn_ad.droid.bleGenFilterList()
147        self.scn_ad.droid.bleBuildScanFilter(filter_list)
148        test_result = self._verify_n_advertisements(self.max_advertisements,
149                                                    filter_list)
150        return test_result
151
152    @BluetoothBaseTest.bt_test_wrap
153    def test_max_advertisements_include_device_name_and_filter_device_name(
154            self):
155        """Testing max advertisement variant.
156
157        Test that a single device can have the max advertisements
158        concurrently advertising. Include the device name as a part of the filter
159        and advertisement data.
160
161        Steps:
162        1. Setup the scanning android device.
163        2. Setup the advertiser android device.
164        3. Include device name in each advertisement.
165        4. Include device name filter in the scanner.
166        5. Start scanning on the max_advertisements as defined in the script.
167        6. Verify that all advertisements are found.
168
169        Expected Result:
170        All advertisements should start without errors.
171
172        Returns:
173          Pass if True
174          Fail if False
175
176        TAGS: LE, Advertising, Concurrency
177        Priority: 2
178        """
179        test_result = True
180        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
181        filter_list = self.scn_ad.droid.bleGenFilterList()
182        self.scn_ad.droid.bleSetScanFilterDeviceName(
183            self.adv_ad.droid.bluetoothGetLocalName())
184        self.scn_ad.droid.bleBuildScanFilter(filter_list)
185        test_result = self._verify_n_advertisements(self.max_advertisements,
186                                                    filter_list)
187        return test_result
188
189    @BluetoothBaseTest.bt_test_wrap
190    def test_max_advertisements_exclude_device_name_and_filter_device_name(
191            self):
192        """Test max advertisement variant.
193
194        Test that a single device can have the max advertisements concurrently
195        advertising. Include the device name as a part of the filter but not the
196        advertisement data.
197
198        Steps:
199        1. Setup the scanning android device.
200        2. Setup the advertiser android device.
201        3. Include device name filter in the scanner.
202        4. Start scanning on the max_advertisements as defined in the script.
203        5. Verify that no advertisements are found.
204
205        Expected Result:
206        All advertisements should start without errors.
207
208        Returns:
209          Pass if True
210          Fail if False
211
212        TAGS: LE, Advertising, Concurrency
213        Priority: 2
214        """
215        test_result = True
216        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(False)
217        filter_list = self.scn_ad.droid.bleGenFilterList()
218        self.scn_ad.droid.bleSetScanFilterDeviceName(
219            self.adv_ad.droid.bluetoothGetLocalName())
220        self.scn_ad.droid.bleBuildScanFilter(filter_list)
221        test_result = self._verify_n_advertisements(self.max_advertisements,
222                                                    filter_list)
223        return not test_result
224
225    @BluetoothBaseTest.bt_test_wrap
226    def test_max_advertisements_with_manufacturer_data(self):
227        """Test max advertisement variant.
228
229        Test that a single device can have the max advertisements concurrently
230        advertising. Include the manufacturer data as a part of the filter and
231        advertisement data.
232
233        Steps:
234        1. Setup the scanning android device.
235        2. Setup the advertiser android device.
236        3. Include manufacturer data in each advertisement.
237        4. Include manufacturer data filter in the scanner.
238        5. Start scanning on the max_advertisements as defined in the script.
239        6. Verify that all advertisements are found.
240
241        Expected Result:
242        All advertisements should start without errors.
243
244        Returns:
245          Pass if True
246          Fail if False
247
248        TAGS: LE, Advertising, Concurrency
249        Priority: 2
250        """
251        test_result = True
252        filter_list = self.scn_ad.droid.bleGenFilterList()
253        self.scn_ad.droid.bleSetScanFilterManufacturerData(1, "1")
254        self.scn_ad.droid.bleBuildScanFilter(filter_list)
255        self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, "1")
256        test_result = self._verify_n_advertisements(self.max_advertisements,
257                                                    filter_list)
258        return test_result
259
260    @BluetoothBaseTest.bt_test_wrap
261    def test_max_advertisements_with_manufacturer_data_mask(self):
262        """Test max advertisements variant.
263
264        Test that a single device can have the max advertisements concurrently
265        advertising. Include the manufacturer data mask as a part of the filter
266        and advertisement data.
267
268        Steps:
269        1. Setup the scanning android device.
270        2. Setup the advertiser android device.
271        3. Include manufacturer data in each advertisement.
272        4. Include manufacturer data mask filter in the scanner.
273        5. Start scanning on the max_advertisements as defined in the script.
274        6. Verify that all advertisements are found.
275
276        Expected Result:
277        All advertisements should start without errors.
278
279        Returns:
280          Pass if True
281          Fail if False
282
283        TAGS: LE, Advertising, Concurrency
284        Priority: 2
285        """
286        test_result = True
287        filter_list = self.scn_ad.droid.bleGenFilterList()
288        self.scn_ad.droid.bleSetScanFilterManufacturerData(1, "1", "1")
289        self.scn_ad.droid.bleBuildScanFilter(filter_list)
290        self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, "1")
291        test_result = self._verify_n_advertisements(self.max_advertisements,
292                                                    filter_list)
293        return test_result
294
295    @BluetoothBaseTest.bt_test_wrap
296    def test_max_advertisements_with_service_data(self):
297        """Test max advertisement variant.
298
299        Test that a single device can have the max advertisements concurrently
300        advertising. Include the service data as a part of the filter and
301        advertisement data.
302
303        Steps:
304        1. Setup the scanning android device.
305        2. Setup the advertiser android device.
306        3. Include service data in each advertisement.
307        4. Include service data filter in the scanner.
308        5. Start scanning on the max_advertisements as defined in the script.
309        6. Verify that all advertisements are found.
310
311        Expected Result:
312        All advertisements should start without errors.
313
314        Returns:
315          Pass if True
316          Fail if False
317
318        TAGS: LE, Advertising, Concurrency
319        Priority: 2
320        """
321        test_result = True
322        filter_list = self.scn_ad.droid.bleGenFilterList()
323        self.scn_ad.droid.bleSetScanFilterServiceData(
324            "0000110A-0000-1000-8000-00805F9B34FB", "11,17,80")
325        self.scn_ad.droid.bleBuildScanFilter(filter_list)
326        self.adv_ad.droid.bleAddAdvertiseDataServiceData(
327            "0000110A-0000-1000-8000-00805F9B34FB", "11,17,80")
328        test_result = self._verify_n_advertisements(self.max_advertisements,
329                                                    filter_list)
330        return test_result
331
332    @BluetoothBaseTest.bt_test_wrap
333    def test_max_advertisements_with_manufacturer_data_mask_and_include_device_name(
334            self):
335        """Test max advertisement variant.
336
337        Test that a single device can have the max advertisements concurrently
338        advertising. Include the device name and manufacturer data as a part of
339        the filter and advertisement data.
340
341        Steps:
342        1. Setup the scanning android device.
343        2. Setup the advertiser android device.
344        3. Include device name and manufacturer data in each advertisement.
345        4. Include device name and manufacturer data filter in the scanner.
346        5. Start scanning on the max_advertisements as defined in the script.
347        6. Verify that all advertisements are found.
348
349        Expected Result:
350        All advertisements should start without errors.
351
352        Returns:
353          Pass if True
354          Fail if False
355
356        TAGS: LE, Advertising, Concurrency
357        Priority: 2
358        """
359        test_result = True
360        filter_list = self.scn_ad.droid.bleGenFilterList()
361        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
362        self.scn_ad.droid.bleSetScanFilterDeviceName(
363            self.adv_ad.droid.bluetoothGetLocalName())
364        self.scn_ad.droid.bleSetScanFilterManufacturerData(1, "1", "1")
365        self.scn_ad.droid.bleBuildScanFilter(filter_list)
366        self.adv_ad.droid.bleAddAdvertiseDataManufacturerId(1, "1")
367        test_result = self._verify_n_advertisements(self.max_advertisements,
368                                                    filter_list)
369        return test_result
370
371    @BluetoothBaseTest.bt_test_wrap
372    def test_max_advertisements_with_service_uuids(self):
373        """Test max advertisement variant.
374
375        Test that a single device can have the max advertisements concurrently
376        advertising. Include the service uuid as a part of the filter and
377        advertisement data.
378
379        Steps:
380        1. Setup the scanning android device.
381        2. Setup the advertiser android device.
382        3. Include service uuid in each advertisement.
383        4. Include service uuid filter in the scanner.
384        5. Start scanning on the max_advertisements as defined in the script.
385        6. Verify that all advertisements are found.
386
387        Expected Result:
388        All advertisements should start without errors.
389
390        Returns:
391          Pass if True
392          Fail if False
393
394        TAGS: LE, Advertising, Concurrency
395        Priority: 1
396        """
397        test_result = True
398        filter_list = self.scn_ad.droid.bleGenFilterList()
399        self.scn_ad.droid.bleSetScanFilterServiceUuid(
400            "00000000-0000-1000-8000-00805f9b34fb")
401        self.scn_ad.droid.bleBuildScanFilter(filter_list)
402        self.adv_ad.droid.bleSetAdvertiseDataSetServiceUuids(
403            ["00000000-0000-1000-8000-00805f9b34fb"])
404        test_result = self._verify_n_advertisements(self.max_advertisements,
405                                                    filter_list)
406        return test_result
407
408    @BluetoothBaseTest.bt_test_wrap
409    def test_max_advertisements_with_service_uuid_and_service_mask(self):
410        """Test max advertisements variant.
411
412        Test that a single device can have the max advertisements concurrently
413        advertising. Include the service mask as a part of the filter and
414        advertisement data.
415
416        Steps:
417        1. Setup the scanning android device.
418        2. Setup the advertiser android device.
419        3. Include service uuid in each advertisement.
420        4. Include service mask filter in the scanner.
421        5. Start scanning on the max_advertisements as defined in the script.
422        6. Verify that all advertisements are found.
423
424        Expected Result:
425        All advertisements should start without errors.
426
427        Returns:
428          Pass if True
429          Fail if False
430
431        TAGS: LE, Advertising, Concurrency
432        Priority: 2
433        """
434        test_result = True
435        filter_list = self.scn_ad.droid.bleGenFilterList()
436        self.scn_ad.droid.bleSetScanFilterServiceUuid(
437            "00000000-0000-1000-8000-00805f9b34fb",
438            "00000000-0000-1000-8000-00805f9b34fb")
439        self.scn_ad.droid.bleBuildScanFilter(filter_list)
440        self.adv_ad.droid.bleSetAdvertiseDataSetServiceUuids(
441            ["00000000-0000-1000-8000-00805f9b34fb"])
442        test_result = self._verify_n_advertisements(self.max_advertisements,
443                                                    filter_list)
444        return test_result
445
446    @BluetoothBaseTest.bt_test_wrap
447    def test_max_advertisements_plus_one(self):
448        """Test max advertisements plus one.
449
450        Test that a single device can have the max advertisements concurrently
451        advertising but fail on starting the max advertisements plus one.
452        filter and advertisement data.
453
454        Steps:
455        1. Setup the scanning android device.
456        2. Setup the advertiser android device.
457        3. Start max_advertisements + 1.
458
459        Expected Result:
460        The last advertisement should fail.
461
462        Returns:
463          Pass if True
464          Fail if False
465
466        TAGS: LE, Advertising, Concurrency
467        Priority: 0
468        """
469        test_result = True
470        filter_list = self.scn_ad.droid.bleGenFilterList()
471        self.scn_ad.droid.bleBuildScanFilter(filter_list)
472        test_result = self._verify_n_advertisements(
473            self.max_advertisements + 1, filter_list)
474        return not test_result
475
476    @BluetoothBaseTest.bt_test_wrap
477    def test_start_two_advertisements_on_same_callback(self):
478        """Test invalid advertisement scenario.
479
480        Test that a single device cannot have two advertisements start on the
481        same callback.
482
483        Steps:
484        1. Setup the scanning android device.
485        2. Setup the advertiser android device.
486        3. Call start ble advertising on the same callback.
487
488        Expected Result:
489        The second call of start advertising on the same callback should fail.
490
491        Returns:
492          Pass if True
493          Fail if False
494
495        TAGS: LE, Advertising, Concurrency
496        Priority: 1
497        """
498        test_result = True
499        advertise_callback, advertise_data, advertise_settings = (
500            generate_ble_advertise_objects(self.adv_ad.droid))
501        self.adv_ad.droid.bleStartBleAdvertising(
502            advertise_callback, advertise_data, advertise_settings)
503        try:
504            self.adv_ad.ed.pop_event(
505                adv_succ.format(advertise_callback), self.default_timeout)
506        except Empty as error:
507            self.log.debug("Test failed with Empty error: {}".format(error))
508            return False
509        except concurrent.futures._base.TimeoutError as error:
510            self.log.debug(
511                "Test failed, filtering callback onSuccess never occurred: {}"
512                .format(error))
513        try:
514            self.adv_ad.droid.bleStartBleAdvertising(
515                advertise_callback, advertise_data, advertise_settings)
516            self.adv_ad.ed.pop_event(
517                adv_succ.format(advertise_callback), self.default_timeout)
518            test_result = False
519        except Empty as error:
520            self.log.debug("Test passed with Empty error: {}".format(error))
521        except concurrent.futures._base.TimeoutError as error:
522            self.log.debug(
523                "Test passed, filtering callback onSuccess never occurred: {}"
524                .format(error))
525
526        return test_result
527
528    @BluetoothBaseTest.bt_test_wrap
529    def test_toggle_advertiser_bt_state(self):
530        """Test forcing stopping advertisements.
531
532        Test that a single device resets its callbacks when the bluetooth state is
533        reset. There should be no advertisements.
534
535        Steps:
536        1. Setup the scanning android device.
537        2. Setup the advertiser android device.
538        3. Call start ble advertising.
539        4. Toggle bluetooth on and off.
540        5. Scan for any advertisements.
541
542        Expected Result:
543        No advertisements should be found after toggling Bluetooth on the
544        advertising device.
545
546        Returns:
547          Pass if True
548          Fail if False
549
550        TAGS: LE, Advertising, Concurrency
551        Priority: 2
552        """
553        test_result = True
554        advertise_callback, advertise_data, advertise_settings = (
555            generate_ble_advertise_objects(self.adv_ad.droid))
556        self.adv_ad.droid.bleStartBleAdvertising(
557            advertise_callback, advertise_data, advertise_settings)
558        try:
559            self.adv_ad.ed.pop_event(
560                adv_succ.format(advertise_callback), self.default_timeout)
561        except Empty as error:
562            self.log.debug("Test failed with Empty error: {}".format(error))
563            return False
564        except concurrent.futures._base.TimeoutError as error:
565            self.log.debug(
566                "Test failed, filtering callback onSuccess never occurred: {}".format(
567                    error))
568        filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
569            self.scn_ad.droid)
570        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
571                                          scan_callback)
572        try:
573            self.scn_ad.ed.pop_event(
574                scan_result.format(scan_callback), self.default_timeout)
575        except Empty as error:
576            self.log.debug("Test failed with: {}".format(error))
577            return False
578        except concurrent.futures._base.TimeoutError as error:
579            self.log.debug("Test failed with: {}".format(error))
580            return False
581        self.scn_ad.droid.bleStopBleScan(scan_callback)
582        test_result = reset_bluetooth([self.android_devices[1]])
583        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
584                                          scan_callback)
585        if not test_result:
586            return test_result
587        try:
588            self.scn_ad.ed.pop_event(
589                scan_result.format(scan_callback), self.default_timeout)
590            return False
591        except Empty as error:
592            self.log.debug("Test passed with: {}".format(error))
593        except concurrent.futures._base.TimeoutError as error:
594            self.log.debug("Test passed with: {}".format(error))
595        self.scn_ad.droid.bleStopBleScan(scan_callback)
596        self.adv_ad.droid.bleStopBleAdvertising(advertise_callback)
597        return test_result
598
599    @BluetoothBaseTest.bt_test_wrap
600    def test_restart_advertise_callback_after_bt_toggle(self):
601        """Test starting an advertisement on a cleared out callback.
602
603        Test that a single device resets its callbacks when the bluetooth state
604        is reset.
605
606        Steps:
607        1. Setup the scanning android device.
608        2. Setup the advertiser android device.
609        3. Call start ble advertising.
610        4. Toggle bluetooth on and off.
611        5. Call start ble advertising on the same callback.
612
613        Expected Result:
614        Starting an advertisement on a callback id after toggling bluetooth
615        should fail.
616
617        Returns:
618          Pass if True
619          Fail if False
620
621        TAGS: LE, Advertising, Concurrency
622        Priority: 1
623        """
624        test_result = True
625        advertise_callback, advertise_data, advertise_settings = (
626            generate_ble_advertise_objects(self.adv_ad.droid))
627        self.adv_ad.droid.bleStartBleAdvertising(
628            advertise_callback, advertise_data, advertise_settings)
629        try:
630            self.adv_ad.ed.pop_event(
631                adv_succ.format(advertise_callback), self.default_timeout)
632        except Empty as error:
633            self.log.debug("Test failed with Empty error: {}".format(error))
634            test_result = False
635        except concurrent.futures._base.TimeoutError as error:
636            self.log.debug(
637                "Test failed, filtering callback onSuccess never occurred: {}".format(
638                    error))
639        test_result = reset_bluetooth([self.android_devices[1]])
640        if not test_result:
641            return test_result
642        self.adv_ad.droid.bleStartBleAdvertising(
643            advertise_callback, advertise_data, advertise_settings)
644        try:
645            self.adv_ad.ed.pop_event(
646                adv_succ.format(advertise_callback), self.default_timeout)
647        except Empty as error:
648            self.log.debug("Test failed with Empty error: {}".format(error))
649            test_result = False
650        except concurrent.futures._base.TimeoutError as error:
651            self.log.debug(
652                "Test failed, filtering callback onSuccess never occurred: {}".format(
653                    error))
654        return test_result
655