1#/usr/bin/env python3.4
2#
3# Copyright (C) 2017 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"""
17This test script exercises different scan filters with different screen states.
18"""
19
20import concurrent
21import json
22import pprint
23import time
24
25from queue import Empty
26from acts import utils
27from acts.test_decorators import test_tracker_info
28from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
29from acts.test_utils.bt.bt_constants import adv_succ
30from acts.test_utils.bt.bt_constants import ble_advertise_settings_modes
31from acts.test_utils.bt.bt_constants import ble_scan_settings_modes
32from acts.test_utils.bt.bt_constants import bt_default_timeout
33from acts.test_utils.bt.bt_constants import scan_result
34from acts.test_utils.bt.bt_test_utils import batch_scan_result
35from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
36from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects
37from acts.test_utils.bt.bt_test_utils import reset_bluetooth
38
39
40class BleScanScreenStateTest(BluetoothBaseTest):
41    advertise_callback = -1
42    max_concurrent_scans = 27
43    scan_callback = -1
44    shorter_scan_timeout = 2
45
46    def __init__(self, controllers):
47        BluetoothBaseTest.__init__(self, controllers)
48        self.scn_ad = self.android_devices[0]
49        self.adv_ad = self.android_devices[1]
50
51    def setup_class(self):
52        super(BluetoothBaseTest, self).setup_class()
53        utils.set_location_service(self.scn_ad, True)
54        utils.set_location_service(self.adv_ad, True)
55        return True
56
57    def _setup_generic_advertisement(self):
58        self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode(
59            ble_advertise_settings_modes['low_latency'])
60        self.advertise_callback, advertise_data, advertise_settings = (
61            generate_ble_advertise_objects(self.adv_ad.droid))
62        self.adv_ad.droid.bleStartBleAdvertising(
63            self.advertise_callback, advertise_data, advertise_settings)
64        try:
65            self.adv_ad.ed.pop_event(adv_succ.format(self.advertise_callback))
66        except Empty:
67            self.log.error("Failed to start advertisement.")
68            return False
69        return True
70
71    def _setup_scan_with_no_filters(self):
72        filter_list, scan_settings, self.scan_callback = \
73            generate_ble_scan_objects(self.scn_ad.droid)
74        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
75                                          self.scan_callback)
76
77    def _scan_found_results(self):
78        try:
79            self.scn_ad.ed.pop_event(
80                scan_result.format(self.scan_callback), bt_default_timeout)
81            self.log.info("Found an advertisement.")
82        except Empty:
83            self.log.info("Did not find an advertisement.")
84            return False
85        return True
86
87    @BluetoothBaseTest.bt_test_wrap
88    @test_tracker_info(uuid='9b695819-e5a8-48b3-87a0-f90422998bf9')
89    def test_scan_no_filters_screen_on(self):
90        """Test LE scanning is successful with no filters and screen on.
91
92        Test LE scanning is successful with no filters and screen on. Scan
93        results should be found.
94
95        Steps:
96        1. Setup advertisement
97        2. Turn on screen
98        3. Start scanner without filters
99        4. Verify scan results are found
100        5. Teardown advertisement and scanner
101
102        Expected Result:
103        Scan results should be found.
104
105        Returns:
106          Pass if True
107          Fail if False
108
109        TAGS: LE, Advertising, Filtering, Scanning, Screen
110        Priority: 2
111        """
112        # Step 1
113        if not self._setup_generic_advertisement():
114            return False
115
116        # Step 2
117        self.scn_ad.droid.wakeUpNow()
118
119        # Step 3
120        self._setup_scan_with_no_filters()
121
122        # Step 4
123        if not self._scan_found_results():
124            return False
125
126        # Step 5
127        self.adv_ad.droid.bleStopBleAdvertising(self.advertise_callback)
128        self.scn_ad.droid.bleStopBleScan(self.scan_callback)
129        return True
130
131    @BluetoothBaseTest.bt_test_wrap
132    @test_tracker_info(uuid='38fb6959-f07b-4501-814b-81a498e3efc4')
133    def test_scan_no_filters_screen_off(self):
134        """Test LE scanning is successful with no filters and screen off.
135
136        Test LE scanning is successful with no filters and screen off. No scan
137        results should be found.
138
139        Steps:
140        1. Setup advertisement
141        2. Turn off screen
142        3. Start scanner without filters
143        4. Verify no scan results are found
144        5. Teardown advertisement and scanner
145
146        Expected Result:
147        No scan results should be found.
148
149        Returns:
150          Pass if True
151          Fail if False
152
153        TAGS: LE, Advertising, Filtering, Scanning, Screen
154        Priority: 1
155        """
156        # Step 1
157        if not self._setup_generic_advertisement():
158            return False
159
160        # Step 2
161        self.scn_ad.droid.goToSleepNow()
162        # Give the device time to go to sleep
163        time.sleep(2)
164
165        # Step 3
166        self._setup_scan_with_no_filters()
167
168        # Step 4
169        if self._scan_found_results():
170            return False
171
172        # Step 5
173        self.adv_ad.droid.bleStopBleAdvertising(self.advertise_callback)
174        self.scn_ad.droid.bleStopBleScan(self.scan_callback)
175        return True
176
177    @BluetoothBaseTest.bt_test_wrap
178    @test_tracker_info(uuid='7186ef2f-096a-462e-afde-b0e3d4ecdd83')
179    def test_scan_filters_works_with_screen_off(self):
180        """Test LE scanning is successful with filters and screen off.
181
182        Test LE scanning is successful with no filters and screen off. No scan
183        results should be found.
184
185        Steps:
186        1. Setup advertisement
187        2. Turn off screen
188        3. Start scanner with filters
189        4. Verify scan results are found
190        5. Teardown advertisement and scanner
191
192        Expected Result:
193        Scan results should be found.
194
195        Returns:
196          Pass if True
197          Fail if False
198
199        TAGS: LE, Advertising, Filtering, Scanning, Screen
200        Priority: 1
201        """
202        # Step 1
203        adv_device_name = self.adv_ad.droid.bluetoothGetLocalName()
204        print(adv_device_name)
205        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
206        if not self._setup_generic_advertisement():
207            return False
208
209        # Step 2
210        self.scn_ad.droid.goToSleepNow()
211
212        # Step 3
213        self.scn_ad.droid.bleSetScanFilterDeviceName(adv_device_name)
214        filter_list, scan_settings, self.scan_callback = generate_ble_scan_objects(
215            self.scn_ad.droid)
216        self.scn_ad.droid.bleBuildScanFilter(filter_list)
217        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
218                                          self.scan_callback)
219
220        # Step 4
221        if not self._scan_found_results():
222            return False
223
224        # Step 5
225        self.adv_ad.droid.bleStopBleAdvertising(self.advertise_callback)
226        self.scn_ad.droid.bleStopBleScan(self.scan_callback)
227        return True
228
229    @BluetoothBaseTest.bt_test_wrap
230    @test_tracker_info(uuid='02cd6dca-149e-439b-8427-a2edc7864265')
231    def test_scan_no_filters_screen_off_then_turn_on(self):
232        """Test start LE scan with no filters while screen is off then turn on.
233
234        Test that a scan without filters will not return results while the
235        screen is off but will return results when the screen turns on.
236
237        Steps:
238        1. Setup advertisement
239        2. Turn off screen
240        3. Start scanner without filters
241        4. Verify no scan results are found
242        5. Turn screen on
243        6. Verify scan results are found
244        7. Teardown advertisement and scanner
245
246        Expected Result:
247        Scan results should only come in when the screen is on.
248
249        Returns:
250          Pass if True
251          Fail if False
252
253        TAGS: LE, Advertising, Filtering, Scanning, Screen
254        Priority: 2
255        """
256        # Step 1
257        if not self._setup_generic_advertisement():
258            return False
259
260        # Step 2
261        self.scn_ad.droid.goToSleepNow()
262        # Give the device time to go to sleep
263        time.sleep(2)
264
265        # Step 3
266        self._setup_scan_with_no_filters()
267
268        # Step 4
269        if self._scan_found_results():
270            return False
271
272        # Step 5
273        self.scn_ad.droid.wakeUpNow()
274
275        # Step 6
276        if not self._scan_found_results():
277            return False
278
279        # Step 7
280        self.adv_ad.droid.bleStopBleAdvertising(self.advertise_callback)
281        self.scn_ad.droid.bleStopBleScan(self.scan_callback)
282        return True
283
284    @BluetoothBaseTest.bt_test_wrap
285    @test_tracker_info(uuid='eb9fc373-f5e8-4a55-9750-02b7a11893d1')
286    def test_scan_no_filters_screen_on_then_turn_off(self):
287        """Test start LE scan with no filters while screen is on then turn off.
288
289        Test that a scan without filters will not return results while the
290        screen is off but will return results when the screen turns on.
291
292        Steps:
293        1. Setup advertisement
294        2. Turn off screen
295        3. Start scanner without filters
296        4. Verify no scan results are found
297        5. Turn screen on
298        6. Verify scan results are found
299        7. Teardown advertisement and scanner
300
301        Expected Result:
302        Scan results should only come in when the screen is on.
303
304        Returns:
305          Pass if True
306          Fail if False
307
308        TAGS: LE, Advertising, Filtering, Scanning, Screen
309        Priority: 2
310        """
311        # Step 1
312        if not self._setup_generic_advertisement():
313            return False
314
315        # Step 2
316        self.scn_ad.droid.wakeUpNow()
317
318        # Step 3
319        self._setup_scan_with_no_filters()
320
321        # Step 4
322        if not self._scan_found_results():
323            return False
324
325        # Step 5
326        self.scn_ad.droid.goToSleepNow()
327        # Give the device time to go to sleep
328        time.sleep(2)
329        self.scn_ad.ed.clear_all_events()
330
331        # Step 6
332        if self._scan_found_results():
333            return False
334
335        # Step 7
336        self.adv_ad.droid.bleStopBleAdvertising(self.advertise_callback)
337        self.scn_ad.droid.bleStopBleScan(self.scan_callback)
338        return True
339
340    @BluetoothBaseTest.bt_test_wrap
341    @test_tracker_info(uuid='41d90e11-b0a8-4eed-bff1-c19678920762')
342    def test_scan_no_filters_screen_toggling(self):
343        """Test start LE scan with no filters and test screen toggling.
344
345        Test that a scan without filters will not return results while the
346        screen is off and return results while the screen is on.
347
348        Steps:
349        1. Setup advertisement
350        2. Turn off screen
351        3. Start scanner without filters
352        4. Verify no scan results are found
353        5. Turn screen on
354        6. Verify scan results are found
355        7. Repeat steps 1-6 10 times
356        7. Teardown advertisement and scanner
357
358        Expected Result:
359        Scan results should only come in when the screen is on.
360
361        Returns:
362          Pass if True
363          Fail if False
364
365        TAGS: LE, Advertising, Filtering, Scanning, Screen
366        Priority: 3
367        """
368        iterations = 10
369        # Step 1
370        if not self._setup_generic_advertisement():
371            return False
372
373        for i in range(iterations):
374            self.log.info("Starting iteration {}".format(i + 1))
375            # Step 2
376            self.scn_ad.droid.goToSleepNow()
377            # Give the device time to go to sleep
378            time.sleep(2)
379            self.scn_ad.ed.clear_all_events()
380
381            # Step 3
382            self._setup_scan_with_no_filters()
383
384            # Step 4
385            if self._scan_found_results():
386                return False
387
388            # Step 5
389            self.scn_ad.droid.wakeUpNow()
390
391            # Step 6
392            if not self._scan_found_results():
393                return False
394
395        # Step 7
396        self.adv_ad.droid.bleStopBleAdvertising(self.advertise_callback)
397        self.scn_ad.droid.bleStopBleScan(self.scan_callback)
398        return True
399
400    @BluetoothBaseTest.bt_test_wrap
401    @test_tracker_info(uuid='7a2fe7ef-b15f-4e93-a2f0-40e2f7d9cbcb')
402    def test_opportunistic_scan_no_filters_screen_off_then_on(self):
403        """Test opportunistic scanning does not find results with screen off.
404
405        Test LE scanning is successful with no filters and screen off. No scan
406        results should be found.
407
408        Steps:
409        1. Setup advertisement
410        2. Turn off screen
411        3. Start opportunistic scan without filters
412        4. Start scan without filters
413        5. Verify no scan results are found on either scan instance
414        6. Wake up phone
415        7. Verify scan results on each scan instance
416        8. Teardown advertisement and scanner
417
418        Expected Result:
419        No scan results should be found.
420
421        Returns:
422          Pass if True
423          Fail if False
424
425        TAGS: LE, Advertising, Filtering, Scanning, Screen
426        Priority: 1
427        """
428        # Step 1
429        if not self._setup_generic_advertisement():
430            return False
431
432        # Step 2
433        self.scn_ad.droid.goToSleepNow()
434        # Give the device time to go to sleep
435        time.sleep(2)
436
437        # Step 3
438        self.scn_ad.droid.bleSetScanSettingsScanMode(ble_scan_settings_modes[
439            'opportunistic'])
440        filter_list, scan_settings, scan_callback = generate_ble_scan_objects(
441            self.scn_ad.droid)
442        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
443                                          scan_callback)
444
445        # Step 4
446        filter_list2, scan_settings2, scan_callback2 = generate_ble_scan_objects(
447            self.scn_ad.droid)
448        self.scn_ad.droid.bleStartBleScan(filter_list2, scan_settings2,
449                                          scan_callback2)
450
451        # Step 5
452        try:
453            self.scn_ad.ed.pop_event(
454                scan_result.format(scan_callback), self.shorter_scan_timeout)
455            self.log.error("Found an advertisement on opportunistic scan.")
456            return False
457        except Empty:
458            self.log.info("Did not find an advertisement.")
459        try:
460            self.scn_ad.ed.pop_event(
461                scan_result.format(scan_callback2), self.shorter_scan_timeout)
462            self.log.error("Found an advertisement on scan instance.")
463            return False
464        except Empty:
465            self.log.info("Did not find an advertisement.")
466
467        # Step 6
468        self.scn_ad.droid.wakeUpNow()
469
470        # Step 7
471        try:
472            self.scn_ad.ed.pop_event(
473                scan_result.format(scan_callback), self.shorter_scan_timeout)
474            self.log.info("Found an advertisement on opportunistic scan.")
475        except Empty:
476            self.log.error(
477                "Did not find an advertisement on opportunistic scan.")
478            return False
479        try:
480            self.scn_ad.ed.pop_event(
481                scan_result.format(scan_callback2), self.shorter_scan_timeout)
482            self.log.info("Found an advertisement on scan instance.")
483        except Empty:
484            self.log.info("Did not find an advertisement.")
485            return False
486
487        # Step 8
488        self.adv_ad.droid.bleStopBleAdvertising(self.advertise_callback)
489        self.scn_ad.droid.bleStopBleScan(scan_callback)
490        self.scn_ad.droid.bleStopBleScan(scan_callback2)
491        return True
492
493    @BluetoothBaseTest.bt_test_wrap
494    @test_tracker_info(uuid='406f1a2e-160f-4fb2-8a87-6403996df36e')
495    def test_max_scan_no_filters_screen_off_then_turn_on(self):
496        """Test start max scans with no filters while screen is off then turn on
497
498        Test that max LE scan without filters will not return results while the
499        screen is off but will return results when the screen turns on.
500
501        Steps:
502        1. Setup advertisement
503        2. Turn off screen
504        3. Start scanner without filters and verify no scan results
505        4. Turn screen on
506        5. Verify scan results are found on each scan callback
507        6. Teardown advertisement and all scanner
508
509        Expected Result:
510        Scan results should only come in when the screen is on.
511
512        Returns:
513          Pass if True
514          Fail if False
515
516        TAGS: LE, Advertising, Filtering, Scanning, Screen
517        Priority: 2
518        """
519        # Step 1
520        if not self._setup_generic_advertisement():
521            return False
522
523        # Step 2
524        self.scn_ad.droid.goToSleepNow()
525        # Give the device time to go to sleep
526        time.sleep(2)
527
528        # Step 3
529        scan_callback_list = []
530        for _ in range(self.max_concurrent_scans):
531            filter_list, scan_settings, scan_callback = \
532                generate_ble_scan_objects(self.scn_ad.droid)
533            self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
534                                              scan_callback)
535            scan_callback_list.append(scan_callback)
536            try:
537                self.scn_ad.ed.pop_event(
538                    scan_result.format(self.scan_callback),
539                    self.shorter_scan_timeout)
540                self.log.info("Found an advertisement.")
541                return False
542            except Empty:
543                self.log.info("Did not find an advertisement.")
544
545        # Step 4
546        self.scn_ad.droid.wakeUpNow()
547
548        # Step 5
549        for callback in scan_callback_list:
550            try:
551                self.scn_ad.ed.pop_event(
552                    scan_result.format(callback), self.shorter_scan_timeout)
553                self.log.info("Found an advertisement.")
554            except Empty:
555                self.log.info("Did not find an advertisement.")
556                return False
557
558        # Step 7
559        self.adv_ad.droid.bleStopBleAdvertising(self.advertise_callback)
560        for callback in scan_callback_list:
561            self.scn_ad.droid.bleStopBleScan(callback)
562        return True
563