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