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