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"""
17This test script exercises different onLost/onFound scenarios.
18"""
19
20from queue import Empty
21from acts import utils
22from acts.test_decorators import test_tracker_info
23from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
24from acts.test_utils.bt.bt_constants import ble_advertise_settings_modes
25from acts.test_utils.bt.bt_constants import ble_scan_settings_callback_types
26from acts.test_utils.bt.BleEnum import ScanSettingsMatchMode
27from acts.test_utils.bt.BleEnum import ScanSettingsMatchNum
28from acts.test_utils.bt.bt_constants import ble_scan_settings_modes
29from acts.test_utils.bt.bt_constants import ble_scan_settings_match_modes
30from acts.test_utils.bt.bt_constants import ble_scan_settings_match_nums
31from acts.test_utils.bt.bt_constants import adv_succ
32from acts.test_utils.bt.bt_test_utils import cleanup_scanners_and_advertisers
33from acts.test_utils.bt.bt_test_utils import reset_bluetooth
34from acts.test_utils.bt.bt_constants import scan_result
35
36
37class BleOnLostOnFoundTest(BluetoothBaseTest):
38    default_timeout = 10
39    active_scan_callback_list = []
40    active_adv_callback_list = []
41
42    def __init__(self, controllers):
43        BluetoothBaseTest.__init__(self, controllers)
44        self.scn_ad = self.android_devices[0]
45        self.adv_ad = self.android_devices[1]
46
47    def setup_class(self):
48        super(BluetoothBaseTest, self).setup_class()
49        utils.set_location_service(self.scn_ad, True)
50        utils.set_location_service(self.adv_ad, True)
51        return True
52
53    def teardown_test(self):
54        cleanup_scanners_and_advertisers(
55            self.scn_ad, self.active_adv_callback_list, self.adv_ad,
56            self.active_adv_callback_list)
57        self.active_adv_callback_list = []
58        self.active_scan_callback_list = []
59
60    def on_exception(self, test_name, begin_time):
61        reset_bluetooth(self.android_devices)
62
63    def _start_generic_advertisement_include_device_name(self):
64        self.adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
65        self.adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode(
66            ble_advertise_settings_modes['low_latency'])
67        advertise_data = self.adv_ad.droid.bleBuildAdvertiseData()
68        advertise_settings = self.adv_ad.droid.bleBuildAdvertiseSettings()
69        advertise_callback = self.adv_ad.droid.bleGenBleAdvertiseCallback()
70        self.adv_ad.droid.bleStartBleAdvertising(
71            advertise_callback, advertise_data, advertise_settings)
72        self.adv_ad.ed.pop_event(
73            adv_succ.format(advertise_callback), self.default_timeout)
74        self.active_adv_callback_list.append(advertise_callback)
75        return advertise_callback
76
77    def _verify_no_events_found(self, event_name):
78        try:
79            self.scn_ad.ed.pop_event(event_name, self.default_timeout)
80            self.log.error("Found an event when none was expected.")
81            return False
82        except Empty:
83            self.log.info("No scan result found as expected.")
84            return True
85
86    @BluetoothBaseTest.bt_test_wrap
87    @test_tracker_info(uuid='9bd7fd09-71c9-4623-90f0-9a895eb37409')
88    def test_onlost_onfound_defaults(self):
89        """Test generic onlost/onfound defaults.
90
91        Tests basic onFound/onLost functionality.
92
93        Steps:
94        1. Setup dut0 scanner and start scan with this setup:
95          Scan Mode: SCAN_MODE_LOW_LATENCY
96          Callback Type: CALLBACK_TYPE_FOUND_AND_LOST
97          Match Mode: AGGRESSIVE
98          Num of Matches: MATCH_NUM_ONE_ADVERTISEMENT
99          Filter: Device name of dut1
100        2. Start an advertisement on dut1, include device name
101        3. Find an onFound event
102        4. Stop the advertisement on dut1
103        5. Find an onLost event
104
105        Expected Result:
106        Find an onLost and an onFound event successfully.
107
108        Returns:
109          Pass if True
110          Fail if False
111
112        TAGS: LE, Advertising, Scanning, onLost, onFound
113        Priority: 0
114        """
115        filter_list = self.scn_ad.droid.bleGenFilterList()
116        self.scn_ad.droid.bleSetScanFilterDeviceName(
117            self.adv_ad.droid.bluetoothGetLocalName())
118        self.scn_ad.droid.bleSetScanSettingsScanMode(ble_scan_settings_modes[
119            'low_latency'])
120        self.scn_ad.droid.bleSetScanSettingsCallbackType(
121            ble_scan_settings_callback_types['found_and_lost'])
122        self.scn_ad.droid.bleSetScanSettingsMatchMode(
123            ble_scan_settings_match_modes['aggresive'])
124        self.scn_ad.droid.bleSetScanSettingsNumOfMatches(
125            ble_scan_settings_match_nums['one'])
126        scan_settings = self.scn_ad.droid.bleBuildScanSetting()
127        scan_callback = self.scn_ad.droid.bleGenScanCallback()
128        self.scn_ad.droid.bleBuildScanFilter(filter_list)
129        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
130                                          scan_callback)
131        self.active_scan_callback_list.append(scan_callback)
132        adv_callback = self._start_generic_advertisement_include_device_name()
133        event = self.scn_ad.ed.pop_event(
134            scan_result.format(scan_callback), self.default_timeout * 3)
135        found_callback_type = event['data']['CallbackType']
136        if event['data']['CallbackType'] != ble_scan_settings_callback_types[
137                'first_match']:
138            self.log.info(
139                "Found Callbacreset_bluetoothkType:{}, Expected CallbackType:{}".
140                format(found_callback_type, ble_scan_settings_callback_types[
141                    'first_match']))
142            return False
143        self.adv_ad.droid.bleStopBleAdvertising(adv_callback)
144        event = self.scn_ad.ed.pop_event(
145            scan_result.format(scan_callback), self.default_timeout * 4)
146        found_callback_type = event['data']['CallbackType']
147        if found_callback_type != ble_scan_settings_callback_types[
148                'match_lost']:
149            self.log.info(
150                "Found CallbackType:{}, Expected CallbackType:{}".format(
151                    found_callback_type, ble_scan_settings_callback_types[
152                        'match_lost']))
153            return False
154        return True
155
156    @BluetoothBaseTest.bt_test_wrap
157    @test_tracker_info(uuid='10b48dc9-0c2a-46a3-8890-5cde3004a996')
158    def test_onlost_onfound_match_mode_sticky(self):
159        """Test generic onlost/onfound in sticky mode.
160
161        Tests basic onFound/onLost functionality.
162
163        Steps:
164        1. Setup dut0 scanner and start scan with this setup:
165          Scan Mode: SCAN_MODE_LOW_LATENCY
166          Callback Type: CALLBACK_TYPE_FOUND_AND_LOST
167          Match Mode: STICKY
168          Num of Matches: MATCH_NUM_ONE_ADVERTISEMENT
169          Filter: Device name of dut1
170        2. Start an advertisement on dut1, include device name
171        3. Find an onFound event
172        4. Stop the advertisement on dut1
173        5. Find an onLost event
174
175        Expected Result:
176        Find an onLost and an onFound event successfully.
177
178        Returns:
179          Pass if True
180          Fail if False
181
182        TAGS: LE, Advertising, Scanning, onLost, onFound
183        Priority: 1
184        """
185        filter_list = self.scn_ad.droid.bleGenFilterList()
186        self.scn_ad.droid.bleSetScanFilterDeviceName(
187            self.adv_ad.droid.bluetoothGetLocalName())
188        self.scn_ad.droid.bleSetScanSettingsScanMode(ble_scan_settings_modes[
189            'low_latency'])
190        self.scn_ad.droid.bleSetScanSettingsCallbackType(
191            ble_scan_settings_callback_types['found_and_lost'])
192        self.scn_ad.droid.bleSetScanSettingsMatchMode(
193            ble_scan_settings_match_modes['sticky'])
194        self.scn_ad.droid.bleSetScanSettingsNumOfMatches(
195            ble_scan_settings_match_nums['one'])
196        scan_settings = self.scn_ad.droid.bleBuildScanSetting()
197        scan_callback = self.scn_ad.droid.bleGenScanCallback()
198        self.scn_ad.droid.bleBuildScanFilter(filter_list)
199        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
200                                          scan_callback)
201        self.active_scan_callback_list.append(scan_callback)
202        adv_callback = self._start_generic_advertisement_include_device_name()
203        event = self.scn_ad.ed.pop_event(
204            scan_result.format(scan_callback), self.default_timeout * 3)
205        found_callback_type = event['data']['CallbackType']
206        if event['data']['CallbackType'] != ble_scan_settings_callback_types[
207                'first_match']:
208            self.log.info(
209                "Found CallbackType:{}, Expected CallbackType:{}".format(
210                    found_callback_type, ble_scan_settings_callback_types[
211                        'first_match']))
212            return False
213        self.adv_ad.droid.bleStopBleAdvertising(adv_callback)
214        event = self.scn_ad.ed.pop_event(
215            scan_result.format(scan_callback), self.default_timeout * 4)
216        found_callback_type = event['data']['CallbackType']
217        if found_callback_type != ble_scan_settings_callback_types[
218                'match_lost']:
219            self.log.info(
220                "Found CallbackType:{}, Expected CallbackType:{}".format(
221                    found_callback_type, ble_scan_settings_callback_types[
222                        'match_lost']))
223            return False
224        return True
225
226    @BluetoothBaseTest.bt_test_wrap
227    @test_tracker_info(uuid='4fefed82-7800-41be-8272-aac076640fed')
228    def test_onlost_onfound_match_num_few(self):
229        """Test generic onlost/onfound num few.
230
231        Tests basic onFound/onLost functionality.
232
233        Steps:
234        1. Setup dut0 scanner and start scan with this setup:
235          Scan Mode: SCAN_MODE_LOW_LATENCY
236          Callback Type: CALLBACK_TYPE_FOUND_AND_LOST
237          Match Mode: AGGRESSIVE
238          Num of Matches: MATCH_NUM_FEW_ADVERTISEMENT
239          Filter: Device name of dut1
240        2. Start an advertisement on dut1, include device name
241        3. Find an onFound event
242        4. Stop the advertisement on dut1
243        5. Find an onLost event
244
245        Expected Result:
246        Find an onLost and an onFound event successfully.
247
248        Returns:
249          Pass if True
250          Fail if False
251
252        TAGS: LE, Advertising, Scanning, onLost, onFound
253        Priority: 1
254        """
255        filter_list = self.scn_ad.droid.bleGenFilterList()
256        self.scn_ad.droid.bleSetScanFilterDeviceName(
257            self.adv_ad.droid.bluetoothGetLocalName())
258        self.scn_ad.droid.bleSetScanSettingsScanMode(ble_scan_settings_modes[
259            'low_latency'])
260        self.scn_ad.droid.bleSetScanSettingsCallbackType(
261            ble_scan_settings_callback_types['found_and_lost'])
262        self.scn_ad.droid.bleSetScanSettingsMatchMode(
263            ble_scan_settings_match_modes['aggresive'])
264        self.scn_ad.droid.bleSetScanSettingsNumOfMatches(
265            ble_scan_settings_match_nums['few'])
266        scan_settings = self.scn_ad.droid.bleBuildScanSetting()
267        scan_callback = self.scn_ad.droid.bleGenScanCallback()
268        self.scn_ad.droid.bleBuildScanFilter(filter_list)
269        self.scn_ad.droid.bleStartBleScan(filter_list, scan_settings,
270                                          scan_callback)
271        self.active_scan_callback_list.append(scan_callback)
272        adv_callback = self._start_generic_advertisement_include_device_name()
273        event = self.scn_ad.ed.pop_event(
274            scan_result.format(scan_callback), self.default_timeout * 3)
275        found_callback_type = event['data']['CallbackType']
276        if event['data']['CallbackType'] != ble_scan_settings_callback_types[
277                'first_match']:
278            self.log.info(
279                "Found CallbackType:{}, Expected CallbackType:{}".format(
280                    found_callback_type, ble_scan_settings_callback_types[
281                        'first_match']))
282            return False
283        self.adv_ad.droid.bleStopBleAdvertising(adv_callback)
284        event = self.scn_ad.ed.pop_event(
285            scan_result.format(scan_callback), self.default_timeout * 4)
286        found_callback_type = event['data']['CallbackType']
287        if found_callback_type != ble_scan_settings_callback_types[
288                'match_lost']:
289            self.log.info(
290                "Found CallbackType:{}, Expected CallbackType:{}".format(
291                    found_callback_type, ble_scan_settings_callback_types[
292                        'match_lost']))
293            return False
294        return True
295