blob: ba0805fe867d8f905ba0fc77b25d79b575def37f [file] [log] [blame]
tturney1bdf77d2015-12-28 17:46:13 -08001#/usr/bin/env python3.4
2#
3# Copyright (C) 2016 The Android Open Source Project
Ang Li73697b32015-12-03 00:41:53 +00004#
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
Ang Li5bd83f32016-05-23 14:39:38 -070017import logging
Ang Li73697b32015-12-03 00:41:53 +000018import random
19import pprint
20import string
tturney50f851d2016-07-07 11:07:37 -070021from queue import Empty
Ang Li73697b32015-12-03 00:41:53 +000022import threading
23import time
tturney03a45ae2016-05-24 15:36:05 -070024from acts import utils
Ang Li73697b32015-12-03 00:41:53 +000025
tturneye3170f02016-05-19 14:37:00 -070026from subprocess import call
Ang Li73697b32015-12-03 00:41:53 +000027
tturney0ab6f012016-05-09 13:59:27 -070028from acts.test_utils.bt.BleEnum import AdvertiseSettingsAdvertiseMode
29from acts.test_utils.bt.BleEnum import ScanSettingsCallbackType
30from acts.test_utils.bt.BleEnum import ScanSettingsMatchMode
31from acts.test_utils.bt.BleEnum import ScanSettingsMatchNum
32from acts.test_utils.bt.BleEnum import ScanSettingsScanResultType
33from acts.test_utils.bt.BleEnum import ScanSettingsScanMode
34from acts.test_utils.bt.BleEnum import ScanSettingsReportDelaySeconds
35from acts.test_utils.bt.BleEnum import AdvertiseSettingsAdvertiseType
36from acts.test_utils.bt.BleEnum import AdvertiseSettingsAdvertiseTxPower
37from acts.test_utils.bt.BleEnum import ScanSettingsMatchNum
38from acts.test_utils.bt.BleEnum import ScanSettingsScanResultType
39from acts.test_utils.bt.BleEnum import ScanSettingsScanMode
Sanket Agarwal54ad6232016-05-17 20:24:51 -070040from acts.test_utils.bt.BtEnum import BluetoothProfile
41from acts.test_utils.bt.BtEnum import BluetoothProfileState
tturney0ab6f012016-05-09 13:59:27 -070042from acts.test_utils.bt.BtEnum import BluetoothScanModeType
tturneye3170f02016-05-19 14:37:00 -070043from acts.test_utils.bt.BtEnum import RfcommUuid
tturneyb92368a2016-09-13 10:43:15 -070044from acts.test_utils.tel.tel_test_utils import toggle_airplane_mode
45from acts.test_utils.tel.tel_test_utils import verify_http_connection
Ang Li73697b32015-12-03 00:41:53 +000046from acts.utils import exe_cmd
47
tturneyb92368a2016-09-13 10:43:15 -070048DEFAULT_TIMEOUT = 15
49DEFAULT_RFCOMM_TIMEOUT = 10000
50MAGIC_PAN_CONNECT_TIMEOUT = 5
51DEFAULT_DISCOVERY_TIMEOUT = 3
52
Ang Li5bd83f32016-05-23 14:39:38 -070053log = logging
Ang Li73697b32015-12-03 00:41:53 +000054
55# Callback strings
Ang Li73697b32015-12-03 00:41:53 +000056scan_result = "BleScan{}onScanResults"
57scan_failed = "BleScan{}onScanFailed"
Ang Li73697b32015-12-03 00:41:53 +000058batch_scan_result = "BleScan{}onBatchScanResult"
59adv_fail = "BleAdvertise{}onFailure"
60adv_succ = "BleAdvertise{}onSuccess"
61bluetooth_off = "BluetoothStateChangedOff"
62bluetooth_on = "BluetoothStateChangedOn"
Sanket Agarwal54ad6232016-05-17 20:24:51 -070063mtu_changed = "GattConnect{}onMtuChanged"
Sanket Agarwald09c7d82016-05-17 20:24:51 -070064bluetooth_profile_connection_state_changed = \
65 "BluetoothProfileConnectionStateChanged"
Ang Li73697b32015-12-03 00:41:53 +000066
67# rfcomm test uuids
68rfcomm_secure_uuid = "fa87c0d0-afac-11de-8a39-0800200c9a66"
69rfcomm_insecure_uuid = "8ce255c0-200a-11e0-ac64-0800200c9a66"
70
tturney57eb93a2016-06-21 13:58:06 -070071advertisements_to_devices = {}
Ang Li73697b32015-12-03 00:41:53 +000072
tturneyb92368a2016-09-13 10:43:15 -070073batch_scan_not_supported_list = ["Nexus 4",
74 "Nexus 5",
75 "Nexus 7", ]
Ang Li73697b32015-12-03 00:41:53 +000076
77
tturney951533f2016-06-23 11:24:25 -070078class BtTestUtilsError(Exception):
79 pass
80
tturneyb92368a2016-09-13 10:43:15 -070081
tturneyc8e17bf2016-07-12 10:32:42 -070082def scan_and_verify_n_advertisements(scn_ad, max_advertisements):
tturneyed249972016-09-13 11:07:49 -070083 """Verify that input number of advertisements can be found from the scanning
84 Android device.
85
86 Args:
87 scn_ad: The Android device to start LE scanning on.
88 max_advertisements: The number of advertisements the scanner expects to
89 find.
90
91 Returns:
92 True if successful, false if unsuccessful.
93 """
tturneyc8e17bf2016-07-12 10:32:42 -070094 test_result = False
95 address_list = []
96 filter_list = scn_ad.droid.bleGenFilterList()
97 scn_ad.droid.bleBuildScanFilter(filter_list)
98 scan_settings = scn_ad.droid.bleBuildScanSetting()
99 scan_callback = scn_ad.droid.bleGenScanCallback()
100 scn_ad.droid.bleStartBleScan(filter_list, scan_settings, scan_callback)
101 start_time = time.time()
tturneyb92368a2016-09-13 10:43:15 -0700102 while (start_time + DEFAULT_TIMEOUT) > time.time():
tturneyc8e17bf2016-07-12 10:32:42 -0700103 event = None
104 try:
105 event = scn_ad.ed.pop_event(
tturneyb92368a2016-09-13 10:43:15 -0700106 scan_result.format(scan_callback), DEFAULT_TIMEOUT)
tturneyc8e17bf2016-07-12 10:32:42 -0700107 except Empty as error:
108 raise BtTestUtilsError("Failed to find scan event: {}".format(
109 error))
110 address = event['data']['Result']['deviceInfo']['address']
111 if address not in address_list:
112 address_list.append(address)
113 if len(address_list) == max_advertisements:
114 test_result = True
115 break
116 scn_ad.droid.bleStopBleScan(scan_callback)
117 return test_result
118
119
120def setup_n_advertisements(adv_ad, num_advertisements):
tturneyed249972016-09-13 11:07:49 -0700121 """Setup input number of advertisements on input Android device.
122
123 Args:
124 adv_ad: The Android device to start LE advertisements on.
125 num_advertisements: The number of advertisements to start.
126
127 Returns:
128 advertise_callback_list: List of advertisement callback ids.
129 """
tturneyc8e17bf2016-07-12 10:32:42 -0700130 adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode(
131 AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value)
132 advertise_data = adv_ad.droid.bleBuildAdvertiseData()
133 advertise_settings = adv_ad.droid.bleBuildAdvertiseSettings()
134 advertise_callback_list = []
135 for i in range(num_advertisements):
136 advertise_callback = adv_ad.droid.bleGenBleAdvertiseCallback()
137 advertise_callback_list.append(advertise_callback)
138 adv_ad.droid.bleStartBleAdvertising(advertise_callback, advertise_data,
139 advertise_settings)
140 try:
141 adv_ad.ed.pop_event(
tturneyb92368a2016-09-13 10:43:15 -0700142 adv_succ.format(advertise_callback), DEFAULT_TIMEOUT)
tturneyc8e17bf2016-07-12 10:32:42 -0700143 log.info("Advertisement {} started.".format(i + 1))
144 except Empty as error:
145 log.error("Advertisement {} failed to start.".format(i + 1))
146 raise BtTestUtilsError("Test failed with Empty error: {}".format(
147 error))
148 return advertise_callback_list
149
150
151def teardown_n_advertisements(adv_ad, num_advertisements,
152 advertise_callback_list):
tturneyed249972016-09-13 11:07:49 -0700153 """Stop input number of advertisements on input Android device.
154
155 Args:
156 adv_ad: The Android device to stop LE advertisements on.
157 num_advertisements: The number of advertisements to stop.
158 advertise_callback_list: The list of advertisement callbacks to stop.
159
160 Returns:
161 True if successful, false if unsuccessful.
162 """
tturneyc8e17bf2016-07-12 10:32:42 -0700163 for n in range(num_advertisements):
164 adv_ad.droid.bleStopBleAdvertising(advertise_callback_list[n])
165 return True
166
tturney951533f2016-06-23 11:24:25 -0700167
Ang Li73697b32015-12-03 00:41:53 +0000168def generate_ble_scan_objects(droid):
tturneyed249972016-09-13 11:07:49 -0700169 """Generate generic LE scan objects.
170
171 Args:
172 droid: The droid object to generate LE scan objects from.
173
174 Returns:
175 filter_list: The generated scan filter list id.
176 scan_settings: The generated scan settings id.
177 scan_callback: The generated scan callback id.
178 """
Ang Li73697b32015-12-03 00:41:53 +0000179 filter_list = droid.bleGenFilterList()
180 scan_settings = droid.bleBuildScanSetting()
181 scan_callback = droid.bleGenScanCallback()
182 return filter_list, scan_settings, scan_callback
183
184
185def generate_ble_advertise_objects(droid):
tturneyed249972016-09-13 11:07:49 -0700186 """Generate generic LE advertise objects.
187
188 Args:
189 droid: The droid object to generate advertise LE objects from.
190
191 Returns:
192 advertise_callback: The generated advertise callback id.
193 advertise_data: The generated advertise data id.
194 advertise_settings: The generated advertise settings id.
195 """
Ang Li73697b32015-12-03 00:41:53 +0000196 advertise_callback = droid.bleGenBleAdvertiseCallback()
197 advertise_data = droid.bleBuildAdvertiseData()
198 advertise_settings = droid.bleBuildAdvertiseSettings()
199 return advertise_callback, advertise_data, advertise_settings
200
201
tturney1ce8dc62016-02-18 09:55:53 -0800202def setup_multiple_devices_for_bt_test(android_devices):
tturneyed249972016-09-13 11:07:49 -0700203 """A common setup routine for Bluetooth on input Android device list.
204
205 Things this function sets up:
206 1. Resets Bluetooth
207 2. Set Bluetooth local name to random string of size 4
208 3. Disable BLE background scanning.
209 4. Enable Bluetooth snoop logging.
210
211 Args:
212 android_devices: Android device list to setup Bluetooth on.
213
214 Returns:
215 True if successful, false if unsuccessful.
216 """
Ang Li73697b32015-12-03 00:41:53 +0000217 log.info("Setting up Android Devices")
tturney03a45ae2016-05-24 15:36:05 -0700218 # TODO: Temp fix for an selinux error.
219 for ad in android_devices:
220 ad.adb.shell("setenforce 0")
Ang Li73697b32015-12-03 00:41:53 +0000221 threads = []
tturney1ce8dc62016-02-18 09:55:53 -0800222 try:
223 for a in android_devices:
224 thread = threading.Thread(target=reset_bluetooth, args=([[a]]))
225 threads.append(thread)
226 thread.start()
227 for t in threads:
228 t.join()
Ang Li73697b32015-12-03 00:41:53 +0000229
tturney1ce8dc62016-02-18 09:55:53 -0800230 for a in android_devices:
231 d = a.droid
232 setup_result = d.bluetoothSetLocalName(generate_id_by_size(4))
233 if not setup_result:
tturneye3170f02016-05-19 14:37:00 -0700234 log.error("Failed to set device name.")
tturney1ce8dc62016-02-18 09:55:53 -0800235 return setup_result
236 d.bluetoothDisableBLE()
237 bonded_devices = d.bluetoothGetBondedDevices()
238 for b in bonded_devices:
239 d.bluetoothUnbond(b['address'])
240 for a in android_devices:
241 setup_result = a.droid.bluetoothConfigHciSnoopLog(True)
242 if not setup_result:
tturneye3170f02016-05-19 14:37:00 -0700243 log.error("Failed to enable Bluetooth Hci Snoop Logging.")
tturney1ce8dc62016-02-18 09:55:53 -0800244 return setup_result
tturneye3170f02016-05-19 14:37:00 -0700245 except Exception as err:
246 log.error("Something went wrong in multi device setup: {}".format(err))
tturney1ce8dc62016-02-18 09:55:53 -0800247 return False
Ang Li73697b32015-12-03 00:41:53 +0000248 return setup_result
249
250
tturney50f851d2016-07-07 11:07:37 -0700251def bluetooth_enabled_check(ad):
tturneyed249972016-09-13 11:07:49 -0700252 """Checks if the Bluetooth state is enabled, if not it will attempt to
253 enable it.
254
255 Args:
256 ad: The Android device list to enable Bluetooth on.
257
258 Returns:
259 True if successful, false if unsuccessful.
260 """
tturney50f851d2016-07-07 11:07:37 -0700261 if not ad.droid.bluetoothCheckState():
262 ad.droid.bluetoothToggleState(True)
263 expected_bluetooth_on_event_name = bluetooth_on
264 try:
tturneyb92368a2016-09-13 10:43:15 -0700265 ad.ed.pop_event(expected_bluetooth_on_event_name, DEFAULT_TIMEOUT)
tturney50f851d2016-07-07 11:07:37 -0700266 except Empty:
267 log.info("Failed to toggle Bluetooth on (no broadcast received).")
268 # Try one more time to poke at the actual state.
269 if ad.droid.bluetoothCheckState():
270 log.info(".. actual state is ON")
271 return True
272 log.error(".. actual state is OFF")
273 return False
274 return True
275
276
tturney1ce8dc62016-02-18 09:55:53 -0800277def reset_bluetooth(android_devices):
tturneyed249972016-09-13 11:07:49 -0700278 """Resets Bluetooth state of input Android device list.
279
280 Args:
281 android_devices: The Android device list to reset Bluetooth state on.
282
283 Returns:
284 True if successful, false if unsuccessful.
Ang Li73697b32015-12-03 00:41:53 +0000285 """
tturney1ce8dc62016-02-18 09:55:53 -0800286 for a in android_devices:
287 droid, ed = a.droid, a.ed
tturneyc12b6ec2016-03-30 13:39:40 -0700288 log.info("Reset state of bluetooth on device: {}".format(
289 droid.getBuildSerial()))
Ang Li73697b32015-12-03 00:41:53 +0000290 if droid.bluetoothCheckState() is True:
291 droid.bluetoothToggleState(False)
292 expected_bluetooth_off_event_name = bluetooth_off
293 try:
tturneyc12b6ec2016-03-30 13:39:40 -0700294 ed.pop_event(expected_bluetooth_off_event_name,
tturneyb92368a2016-09-13 10:43:15 -0700295 DEFAULT_TIMEOUT)
Ang Li73697b32015-12-03 00:41:53 +0000296 except Exception:
tturney0ab6f012016-05-09 13:59:27 -0700297 log.error("Failed to toggle Bluetooth off.")
Ang Li73697b32015-12-03 00:41:53 +0000298 return False
299 # temp sleep for b/17723234
300 time.sleep(3)
tturney50f851d2016-07-07 11:07:37 -0700301 if not bluetooth_enabled_check(a):
Ang Li73697b32015-12-03 00:41:53 +0000302 return False
303 return True
304
305
tturney57eb93a2016-06-21 13:58:06 -0700306def determine_max_advertisements(android_device):
tturneyed249972016-09-13 11:07:49 -0700307 """Determines programatically how many advertisements the Android device
308 supports.
309
310 Args:
311 android_device: The Android device to determine max advertisements of.
312
313 Returns:
314 The maximum advertisement count.
315 """
tturney57eb93a2016-06-21 13:58:06 -0700316 log.info("Determining number of maximum concurrent advertisements...")
317 advertisement_count = 0
tturneyb9d94242016-07-06 17:28:59 -0700318 bt_enabled = False
tturney57eb93a2016-06-21 13:58:06 -0700319 if not android_device.droid.bluetoothCheckState():
320 android_device.droid.bluetoothToggleState(True)
321 try:
322 android_device.ed.pop_event(expected_bluetooth_on_event_name,
tturneyb92368a2016-09-13 10:43:15 -0700323 DEFAULT_TIMEOUT)
tturney57eb93a2016-06-21 13:58:06 -0700324 except Exception:
325 log.info("Failed to toggle Bluetooth on (no broadcast received).")
326 # Try one more time to poke at the actual state.
327 if android_device.droid.bluetoothCheckState() is True:
328 log.info(".. actual state is ON")
329 else:
330 log.error(
331 "Failed to turn Bluetooth on. Setting default advertisements to 1")
tturneyb9d94242016-07-06 17:28:59 -0700332 advertisement_count = -1
tturney57eb93a2016-06-21 13:58:06 -0700333 return advertisement_count
334 advertise_callback_list = []
335 advertise_data = android_device.droid.bleBuildAdvertiseData()
336 advertise_settings = android_device.droid.bleBuildAdvertiseSettings()
337 while (True):
338 advertise_callback = android_device.droid.bleGenBleAdvertiseCallback()
339 advertise_callback_list.append(advertise_callback)
340
341 android_device.droid.bleStartBleAdvertising(
342 advertise_callback, advertise_data, advertise_settings)
343 try:
344 android_device.ed.pop_event(
tturneyb92368a2016-09-13 10:43:15 -0700345 adv_succ.format(advertise_callback), DEFAULT_TIMEOUT)
tturney57eb93a2016-06-21 13:58:06 -0700346 log.info("Advertisement {} started.".format(advertisement_count +
347 1))
348 advertisement_count += 1
349 except Exception as err:
350 log.info(
tturneyb92368a2016-09-13 10:43:15 -0700351 "Advertisement failed to start. Reached max advertisements at {}".
352 format(advertisement_count))
tturney57eb93a2016-06-21 13:58:06 -0700353 break
tturneyf02ac392016-09-21 10:37:35 -0700354 try:
tturney57eb93a2016-06-21 13:58:06 -0700355 for adv in advertise_callback_list:
356 android_device.droid.bleStopBleAdvertising(adv)
tturneyf02ac392016-09-21 10:37:35 -0700357 except Exception:
358 log.error("Failed to stop advertisingment, resetting Bluetooth.")
359 reset_bluetooth([android_device])
tturney57eb93a2016-06-21 13:58:06 -0700360 return advertisement_count
361
362
tturney1ce8dc62016-02-18 09:55:53 -0800363def get_advanced_droid_list(android_devices):
tturneyed249972016-09-13 11:07:49 -0700364 """Add max_advertisement and batch_scan_supported attributes to input
365 Android devices
366
367 This will programatically determine maximum LE advertisements of each
368 input Android device.
369
370 Args:
371 android_devices: The Android devices to setup.
372
373 Returns:
374 List of Android devices with new attribtues.
375 """
Ang Li73697b32015-12-03 00:41:53 +0000376 droid_list = []
tturney1ce8dc62016-02-18 09:55:53 -0800377 for a in android_devices:
378 d, e = a.droid, a.ed
Ang Li73697b32015-12-03 00:41:53 +0000379 model = d.getBuildModel()
tturney0ab6f012016-05-09 13:59:27 -0700380 max_advertisements = 1
Ang Li73697b32015-12-03 00:41:53 +0000381 batch_scan_supported = True
382 if model in advertisements_to_devices.keys():
383 max_advertisements = advertisements_to_devices[model]
tturney57eb93a2016-06-21 13:58:06 -0700384 else:
385 max_advertisements = determine_max_advertisements(a)
tturneyb9d94242016-07-06 17:28:59 -0700386 max_tries = 3
387 #Retry to calculate max advertisements
388 while max_advertisements == -1 and max_tries > 0:
tturneyb92368a2016-09-13 10:43:15 -0700389 log.info("Attempts left to determine max advertisements: {}".
390 format(max_tries))
tturneyb9d94242016-07-06 17:28:59 -0700391 max_advertisements = determine_max_advertisements(a)
392 max_tries -= 1
tturney57eb93a2016-06-21 13:58:06 -0700393 advertisements_to_devices[model] = max_advertisements
394 if model in batch_scan_not_supported_list:
395 batch_scan_supported = False
Ang Li73697b32015-12-03 00:41:53 +0000396 role = {
397 'droid': d,
398 'ed': e,
399 'max_advertisements': max_advertisements,
400 'batch_scan_supported': batch_scan_supported
401 }
402 droid_list.append(role)
403 return droid_list
404
405
tturneyc12b6ec2016-03-30 13:39:40 -0700406def generate_id_by_size(
407 size,
408 chars=(
409 string.ascii_lowercase + string.ascii_uppercase + string.digits)):
tturneyed249972016-09-13 11:07:49 -0700410 """Generate random ascii characters of input size and input char types
411
412 Args:
413 size: Input size of string.
414 chars: (Optional) Chars to use in generating a random string.
415
416 Returns:
417 String of random input chars at the input size.
418 """
Ang Li73697b32015-12-03 00:41:53 +0000419 return ''.join(random.choice(chars) for _ in range(size))
420
421
tturneyed249972016-09-13 11:07:49 -0700422def cleanup_scanners_and_advertisers(scn_android_device, scn_callback_list,
tturney1ce8dc62016-02-18 09:55:53 -0800423 adv_android_device, adv_callback_list):
tturneyed249972016-09-13 11:07:49 -0700424 """Try to gracefully stop all scanning and advertising instances.
425
426 Args:
427 scn_android_device: The Android device that is actively scanning.
428 scn_callback_list: The scan callback id list that needs to be stopped.
429 adv_android_device: The Android device that is actively advertising.
430 adv_callback_list: The advertise callback id list that needs to be
431 stopped.
Ang Li73697b32015-12-03 00:41:53 +0000432 """
tturney1ce8dc62016-02-18 09:55:53 -0800433 scan_droid, scan_ed = scn_android_device.droid, scn_android_device.ed
434 adv_droid = adv_android_device.droid
Ang Li73697b32015-12-03 00:41:53 +0000435 try:
tturneyed249972016-09-13 11:07:49 -0700436 for scan_callback in scn_callback_list:
Ang Li73697b32015-12-03 00:41:53 +0000437 scan_droid.bleStopBleScan(scan_callback)
tturneye3170f02016-05-19 14:37:00 -0700438 except Exception as err:
tturneyb92368a2016-09-13 10:43:15 -0700439 log.debug("Failed to stop LE scan... reseting Bluetooth. Error {}".
440 format(err))
tturney1ce8dc62016-02-18 09:55:53 -0800441 reset_bluetooth([scn_android_device])
Ang Li73697b32015-12-03 00:41:53 +0000442 try:
443 for adv_callback in adv_callback_list:
444 adv_droid.bleStopBleAdvertising(adv_callback)
tturneye3170f02016-05-19 14:37:00 -0700445 except Exception as err:
446 log.debug(
tturneyb92368a2016-09-13 10:43:15 -0700447 "Failed to stop LE advertisement... reseting Bluetooth. Error {}".
448 format(err))
tturney1ce8dc62016-02-18 09:55:53 -0800449 reset_bluetooth([adv_android_device])
Ang Li73697b32015-12-03 00:41:53 +0000450
451
tturney1ce8dc62016-02-18 09:55:53 -0800452def get_mac_address_of_generic_advertisement(scan_ad, adv_ad):
tturneyed249972016-09-13 11:07:49 -0700453 """Start generic advertisement and get it's mac address by LE scanning.
454
455 Args:
456 scan_ad: The Android device to use as the scanner.
457 adv_ad: The Android device to use as the advertiser.
458
459 Returns:
460 mac_address: The mac address of the advertisement.
461 advertise_callback: The advertise callback id of the active
462 advertisement.
463 """
tturney1ce8dc62016-02-18 09:55:53 -0800464 adv_ad.droid.bleSetAdvertiseDataIncludeDeviceName(True)
465 adv_ad.droid.bleSetAdvertiseSettingsAdvertiseMode(
Ang Li73697b32015-12-03 00:41:53 +0000466 AdvertiseSettingsAdvertiseMode.ADVERTISE_MODE_LOW_LATENCY.value)
tturney1ce8dc62016-02-18 09:55:53 -0800467 adv_ad.droid.bleSetAdvertiseSettingsIsConnectable(True)
468 adv_ad.droid.bleSetAdvertiseSettingsTxPowerLevel(
Ang Li73697b32015-12-03 00:41:53 +0000469 AdvertiseSettingsAdvertiseTxPower.ADVERTISE_TX_POWER_HIGH.value)
470 advertise_callback, advertise_data, advertise_settings = (
tturney1ce8dc62016-02-18 09:55:53 -0800471 generate_ble_advertise_objects(adv_ad.droid))
tturneyc12b6ec2016-03-30 13:39:40 -0700472 adv_ad.droid.bleStartBleAdvertising(advertise_callback, advertise_data,
473 advertise_settings)
tturney951533f2016-06-23 11:24:25 -0700474 try:
tturneyb9d94242016-07-06 17:28:59 -0700475 adv_ad.ed.pop_event(
tturneyb4c57fa2016-10-05 13:24:01 -0700476 adv_succ.format(advertise_callback),
tturneyb92368a2016-09-13 10:43:15 -0700477 DEFAULT_TIMEOUT)
tturney50f851d2016-07-07 11:07:37 -0700478 except Empty as err:
tturneyb9d94242016-07-06 17:28:59 -0700479 raise BtTestUtilsError(
480 "Advertiser did not start successfully {}".format(err))
tturney1ce8dc62016-02-18 09:55:53 -0800481 filter_list = scan_ad.droid.bleGenFilterList()
482 scan_settings = scan_ad.droid.bleBuildScanSetting()
483 scan_callback = scan_ad.droid.bleGenScanCallback()
tturneyc12b6ec2016-03-30 13:39:40 -0700484 scan_ad.droid.bleSetScanFilterDeviceName(
485 adv_ad.droid.bluetoothGetLocalName())
tturney1ce8dc62016-02-18 09:55:53 -0800486 scan_ad.droid.bleBuildScanFilter(filter_list)
487 scan_ad.droid.bleStartBleScan(filter_list, scan_settings, scan_callback)
tturney951533f2016-06-23 11:24:25 -0700488 try:
489 event = scan_ad.ed.pop_event(
tturneyb92368a2016-09-13 10:43:15 -0700490 "BleScan{}onScanResults".format(scan_callback), DEFAULT_TIMEOUT)
tturney50f851d2016-07-07 11:07:37 -0700491 except Empty as err:
tturneyb9d94242016-07-06 17:28:59 -0700492 raise BtTestUtilsError("Scanner did not find advertisement {}".format(
493 err))
Ang Li73697b32015-12-03 00:41:53 +0000494 mac_address = event['data']['Result']['deviceInfo']['address']
tturney1ce8dc62016-02-18 09:55:53 -0800495 scan_ad.droid.bleStopBleScan(scan_callback)
Ang Li73697b32015-12-03 00:41:53 +0000496 return mac_address, advertise_callback
497
498
Sanket Agarwalc8fdc1a2016-07-06 16:39:34 -0700499def enable_bluetooth(droid, ed):
500 if droid.bluetoothCheckState() is True:
501 return True
502
503 droid.bluetoothToggleState(True)
504 expected_bluetooth_on_event_name = bluetooth_on
505 try:
506 ed.pop_event(expected_bluetooth_on_event_name, default_timeout)
507 except Exception:
508 log.info("Failed to toggle Bluetooth on (no broadcast received)")
509 if droid.bluetoothCheckState() is True:
510 log.info(".. actual state is ON")
511 return True
512 log.info(".. actual state is OFF")
513 return False
514
515 return True
516
517
tturneyed249972016-09-13 11:07:49 -0700518def disable_bluetooth(droid):
519 """Disable Bluetooth on input Droid object.
Ang Li73697b32015-12-03 00:41:53 +0000520
tturneyed249972016-09-13 11:07:49 -0700521 Args:
522 droid: The droid object to disable Bluetooth on.
Ang Li73697b32015-12-03 00:41:53 +0000523
tturneyed249972016-09-13 11:07:49 -0700524 Returns:
525 True if successful, false if unsuccessful.
526 """
Ang Li73697b32015-12-03 00:41:53 +0000527 if droid.bluetoothCheckState() is True:
528 droid.bluetoothToggleState(False)
529 if droid.bluetoothCheckState() is True:
530 return False
531 return True
532
533
tturney1ce8dc62016-02-18 09:55:53 -0800534def set_bt_scan_mode(ad, scan_mode_value):
tturneyed249972016-09-13 11:07:49 -0700535 """Set Android device's Bluetooth scan mode.
536
537 Args:
538 ad: The Android device to set the scan mode on.
539 scan_mode_value: The value to set the scan mode to.
540
541 Returns:
542 True if successful, false if unsuccessful.
543 """
tturney1ce8dc62016-02-18 09:55:53 -0800544 droid, ed = ad.droid, ad.ed
tturneyf02ac392016-09-21 10:37:35 -0700545 if scan_mode_value == BluetoothScanModeType.STATE_OFF.value:
tturneyed249972016-09-13 11:07:49 -0700546 disable_bluetooth(droid)
Ang Li73697b32015-12-03 00:41:53 +0000547 scan_mode = droid.bluetoothGetScanMode()
tturney1ce8dc62016-02-18 09:55:53 -0800548 reset_bluetooth([ad])
Ang Li73697b32015-12-03 00:41:53 +0000549 if scan_mode != scan_mode_value:
550 return False
tturneyf02ac392016-09-21 10:37:35 -0700551 elif scan_mode_value == BluetoothScanModeType.SCAN_MODE_NONE.value:
Ang Li73697b32015-12-03 00:41:53 +0000552 droid.bluetoothMakeUndiscoverable()
553 scan_mode = droid.bluetoothGetScanMode()
554 if scan_mode != scan_mode_value:
555 return False
tturneyf02ac392016-09-21 10:37:35 -0700556 elif scan_mode_value == BluetoothScanModeType.SCAN_MODE_CONNECTABLE.value:
Ang Li73697b32015-12-03 00:41:53 +0000557 droid.bluetoothMakeUndiscoverable()
558 droid.bluetoothMakeConnectable()
559 scan_mode = droid.bluetoothGetScanMode()
560 if scan_mode != scan_mode_value:
561 return False
562 elif (scan_mode_value ==
tturneyf02ac392016-09-21 10:37:35 -0700563 BluetoothScanModeType.SCAN_MODE_CONNECTABLE_DISCOVERABLE.value):
Ang Li73697b32015-12-03 00:41:53 +0000564 droid.bluetoothMakeDiscoverable()
565 scan_mode = droid.bluetoothGetScanMode()
566 if scan_mode != scan_mode_value:
567 return False
568 else:
569 # invalid scan mode
570 return False
571 return True
572
573
574def set_device_name(droid, name):
tturneyed249972016-09-13 11:07:49 -0700575 """Set and check Bluetooth local name on input droid object.
576
577 Args:
578 droid: Droid object to set local name on.
579 name: the Bluetooth local name to set.
580
581 Returns:
582 True if successful, false if unsuccessful.
583 """
Ang Li73697b32015-12-03 00:41:53 +0000584 droid.bluetoothSetLocalName(name)
Ang Li73697b32015-12-03 00:41:53 +0000585 time.sleep(2)
586 droid_name = droid.bluetoothGetLocalName()
587 if droid_name != name:
588 return False
589 return True
590
591
592def check_device_supported_profiles(droid):
tturneyed249972016-09-13 11:07:49 -0700593 """Checks for Android device supported profiles.
594
595 Args:
596 droid: The droid object to query.
597
598 Returns:
599 A dictionary of supported profiles.
600 """
Ang Li73697b32015-12-03 00:41:53 +0000601 profile_dict = {}
602 profile_dict['hid'] = droid.bluetoothHidIsReady()
603 profile_dict['hsp'] = droid.bluetoothHspIsReady()
604 profile_dict['a2dp'] = droid.bluetoothA2dpIsReady()
605 profile_dict['avrcp'] = droid.bluetoothAvrcpIsReady()
606 return profile_dict
607
608
Ram Periathiruvadie3f9a702016-07-26 17:41:59 -0700609def log_energy_info(android_devices, state):
610 """Logs energy info of input Android devices.
611
612 Args:
613 android_devices: input Android device list to log energy info from.
614 state: the input state to log. Usually 'Start' or 'Stop' for logging.
615
616 Returns:
617 A logging string of the Bluetooth energy info reported.
618 """
619 return_string = "{} Energy info collection:\n".format(state)
620 # Bug: b/31966929
621 return return_string
622
623
Ang Li73697b32015-12-03 00:41:53 +0000624def pair_pri_to_sec(pri_droid, sec_droid):
tturneyed249972016-09-13 11:07:49 -0700625 """Pairs pri droid to sec droid.
626
627 Args:
628 pri_droid: Droid initiating pairing.
629 sec_droid: Droid accepting pairing.
630
631 Returns:
632 True if pairing is successful, false if uncsuccsessful.
633 """
Sanket Agarwalc4637db2016-04-06 10:43:14 -0700634 # Enable discovery on sec_droid so that pri_droid can find it.
635 # The timeout here is based on how much time it would take for two devices
636 # to pair with each other once pri_droid starts seeing devices.
tturneye3170f02016-05-19 14:37:00 -0700637 log.info(
638 "Bonding device {} to {}".format(pri_droid.bluetoothGetLocalAddress(),
639 sec_droid.bluetoothGetLocalAddress()))
tturneyb92368a2016-09-13 10:43:15 -0700640 sec_droid.bluetoothMakeDiscoverable(DEFAULT_TIMEOUT)
tturney182241b2016-05-17 16:53:44 -0700641 target_address = sec_droid.bluetoothGetLocalAddress()
tturneye3170f02016-05-19 14:37:00 -0700642 log.debug("Starting paring helper on each device")
Ang Li73697b32015-12-03 00:41:53 +0000643 pri_droid.bluetoothStartPairingHelper()
644 sec_droid.bluetoothStartPairingHelper()
tturneye3170f02016-05-19 14:37:00 -0700645 log.info("Primary device starting discovery and executing bond")
tturney182241b2016-05-17 16:53:44 -0700646 result = pri_droid.bluetoothDiscoverAndBond(target_address)
Sanket Agarwalc4637db2016-04-06 10:43:14 -0700647 # Loop until we have bonded successfully or timeout.
tturneyb92368a2016-09-13 10:43:15 -0700648 end_time = time.time() + DEFAULT_TIMEOUT
tturneye3170f02016-05-19 14:37:00 -0700649 log.info("Verifying devices are bonded")
Sanket Agarwalc4637db2016-04-06 10:43:14 -0700650 while time.time() < end_time:
651 bonded_devices = pri_droid.bluetoothGetBondedDevices()
Sanket Agarwalc4637db2016-04-06 10:43:14 -0700652 bonded = False
653 for d in bonded_devices:
tturney182241b2016-05-17 16:53:44 -0700654 if d['address'] == target_address:
tturneye3170f02016-05-19 14:37:00 -0700655 log.info("Successfully bonded to device")
tturney0ab6f012016-05-09 13:59:27 -0700656 return True
Sanket Agarwalc4637db2016-04-06 10:43:14 -0700657 # Timed out trying to bond.
tturneyf50dc602016-09-13 10:21:05 -0700658 log.info("Failed to bond devices.")
Sanket Agarwalc4637db2016-04-06 10:43:14 -0700659 return False
Ang Li73697b32015-12-03 00:41:53 +0000660
tturney57eb93a2016-06-21 13:58:06 -0700661
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700662def connect_pri_to_sec(log, pri_droid, sec_droid, profiles_set):
663 """Connects pri droid to secondary droid.
664
665 Args:
tturneyed249972016-09-13 11:07:49 -0700666 pri_droid: Droid initiating connection.
667 sec_droid: Droid accepting connection.
668 profiles_set: Set of profiles to be connected.
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700669
670 Returns:
tturneyed249972016-09-13 11:07:49 -0700671 True of connection is successful, false if unsuccessful.
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700672 """
673 # Check if we support all profiles.
674 supported_profiles = [i.value for i in BluetoothProfile]
675 for profile in profiles_set:
676 if profile not in supported_profiles:
677 log.info("Profile {} is not supported list {}".format(
678 profile, supported_profiles))
679 return False
680
681 # First check that devices are bonded.
682 paired = False
683 for paired_device in pri_droid.droid.bluetoothGetBondedDevices():
684 if paired_device['address'] == \
685 sec_droid.bluetoothGetLocalAddress():
686 paired = True
687 break
688
689 if not paired:
tturney57eb93a2016-06-21 13:58:06 -0700690 log.info("{} not paired to {}".format(pri_droid.droid.getBuildSerial(),
691 sec_droid.getBuildSerial()))
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700692 return False
693
694 # Now try to connect them, the following call will try to initiate all
695 # connections.
tturney57eb93a2016-06-21 13:58:06 -0700696 pri_droid.droid.bluetoothConnectBonded(sec_droid.bluetoothGetLocalAddress(
697 ))
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700698
699 profile_connected = set()
700 log.info("Profiles to be connected {}".format(profiles_set))
701 while not profile_connected.issuperset(profiles_set):
702 try:
703 profile_event = pri_droid.ed.pop_event(
tturneyb92368a2016-09-13 10:43:15 -0700704 bluetooth_profile_connection_state_changed, DEFAULT_TIMEOUT)
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700705 log.info("Got event {}".format(profile_event))
706 except Exception:
707 log.error("Did not get {} profiles left {}".format(
708 bluetooth_profile_connection_state_changed, profile_connected))
709 return False
710
711 profile = profile_event['data']['profile']
712 state = profile_event['data']['state']
713 device_addr = profile_event['data']['addr']
714
tturneyf02ac392016-09-21 10:37:35 -0700715 if state == BluetoothProfileState.STATE_CONNECTED.value and \
Sanket Agarwald09c7d82016-05-17 20:24:51 -0700716 device_addr == sec_droid.bluetoothGetLocalAddress():
717 profile_connected.add(profile)
718 log.info("Profiles connected until now {}".format(profile_connected))
719 # Failure happens inside the while loop. If we came here then we already
720 # connected.
721 return True
Ang Li73697b32015-12-03 00:41:53 +0000722
tturney57eb93a2016-06-21 13:58:06 -0700723
Ram Periathiruvadie3f9a702016-07-26 17:41:59 -0700724def disconnect_pri_from_sec(log, pri_droid, sec_droid, profiles_list):
725 """
726 Disconnect primary from secondary on a specific set of profiles
727 Args:
728 pri_droid - Primary android_device initiating disconnection
729 sec_droid - secondary device's droid (sl4a interface to keep the method signature the same
730 connect_pri_to_sec above)
731 profiles_list - List of profiles we want to disconnect from
732
733 Returns:
734 True on Success
735 False on Failure
736 """
737 # Sanity check to see if all the profiles in the given set is supported
738 supported_profiles = [i.value for i in BluetoothProfile]
739 for profile in profiles_list:
740 if profile not in supported_profiles:
741 log.info("Profile {} is not in supported list {}".format(
742 profile, supported_profiles))
743 return False
744
745 #Disconnecting on a already disconnected profile is a nop, so not checking for the connection state
746 pri_droid.droid.bluetoothDisconnectConnectedProfile(
747 sec_droid.bluetoothGetLocalAddress(), profiles_list)
748 profile_disconnected = set()
749 log.info("Disconnecting from profiles: {}".format(profiles_list))
750
751 while not profile_disconnected.issuperset(profiles_list):
752 try:
753 profile_event = pri_droid.ed.pop_event(
754 bluetooth_profile_connection_state_changed, default_timeout)
755 log.info("Got event {}".format(profile_event))
756 except Exception:
757 log.error("Did not disconnect from Profiles")
758 return False
759
760 profile = profile_event['data']['profile']
761 state = profile_event['data']['state']
762 device_addr = profile_event['data']['addr']
763
764 if state == BluetoothProfileState.STATE_DISCONNECTED.value and \
765 device_addr == sec_droid.bluetoothGetLocalAddress():
766 profile_disconnected.add(profile)
767 log.info("Profiles disconnected so far {}".format(
768 profile_disconnected))
769
770 return True
771
772
tturney1ce8dc62016-02-18 09:55:53 -0800773def take_btsnoop_logs(android_devices, testcase, testname):
tturneyed249972016-09-13 11:07:49 -0700774 """Pull btsnoop logs from an input list of android devices.
775
776 Args:
777 android_devices: the list of Android devices to pull btsnoop logs from.
778 testcase: Name of the test calss that triggered this snoop log.
779 testname: Name of the test case that triggered this bug report.
780 """
tturney1ce8dc62016-02-18 09:55:53 -0800781 for a in android_devices:
tturney03a45ae2016-05-24 15:36:05 -0700782 take_btsnoop_log(a, testcase, testname)
Ang Li73697b32015-12-03 00:41:53 +0000783
Ang Li73697b32015-12-03 00:41:53 +0000784
tturneyed249972016-09-13 11:07:49 -0700785def take_btsnoop_log(ad, testcase, testname):
Ang Li73697b32015-12-03 00:41:53 +0000786 """Grabs the btsnoop_hci log on a device and stores it in the log directory
787 of the test class.
788
789 If you want grab the btsnoop_hci log, call this function with android_device
790 objects in on_fail. Bug report takes a relative long time to take, so use
791 this cautiously.
792
tturneyed249972016-09-13 11:07:49 -0700793 Args:
794 ad: The android_device instance to take bugreport on.
795 testcase: Name of the test calss that triggered this snoop log.
796 testname: Name of the test case that triggered this bug report.
Ang Li73697b32015-12-03 00:41:53 +0000797 """
tturneyed249972016-09-13 11:07:49 -0700798 testname = "".join(x for x in testname if x.isalnum())
tturneyf02ac392016-09-21 10:37:35 -0700799 serial = ad.droid.getBuildSerial()
800 device_model = ad.droid.getBuildModel()
801 device_model = device_model.replace(" ", "")
802 out_name = ','.join((testname, device_model, serial))
803 snoop_path = ad.log_path + "/BluetoothSnoopLogs"
804 utils.create_dir(snoop_path)
805 cmd = ''.join(("adb -s ", serial, " pull /sdcard/btsnoop_hci.log ",
806 snoop_path + '/' + out_name, ".btsnoop_hci.log"))
807 testcase.log.info("Test failed, grabbing the bt_snoop logs on {} {}."
808 .format(device_model, serial))
809 exe_cmd(cmd)
Ang Li73697b32015-12-03 00:41:53 +0000810
811
tturneye3170f02016-05-19 14:37:00 -0700812def kill_bluetooth_process(ad):
tturneyed249972016-09-13 11:07:49 -0700813 """Kill Bluetooth process on Android device.
814
815 Args:
816 ad: Android device to kill BT process on.
817 """
tturneye3170f02016-05-19 14:37:00 -0700818 log.info("Killing Bluetooth process.")
819 pid = ad.adb.shell(
820 "ps | grep com.android.bluetooth | awk '{print $2}'").decode('ascii')
tturney57eb93a2016-06-21 13:58:06 -0700821 call(["adb -s " + ad.serial + " shell kill " + pid], shell=True)
Ang Li73697b32015-12-03 00:41:53 +0000822
823
tturney24506942016-08-23 10:53:17 -0700824def orchestrate_rfcomm_connection(client_ad,
825 server_ad,
tturneyb92368a2016-09-13 10:43:15 -0700826 accept_timeout_ms=DEFAULT_RFCOMM_TIMEOUT):
tturney24506942016-08-23 10:53:17 -0700827 """Sets up the RFCOMM connection between two Android devices.
tturneye3170f02016-05-19 14:37:00 -0700828
tturney24506942016-08-23 10:53:17 -0700829 Args:
tturneyed249972016-09-13 11:07:49 -0700830 client_ad: the Android device performing the connection.
831 server_ad: the Android device accepting the connection.
tturney24506942016-08-23 10:53:17 -0700832 Returns:
833 True if connection was successful, false if unsuccessful.
834 """
tturney96970fd2016-08-31 17:36:09 -0700835 server_ad.droid.bluetoothStartPairingHelper()
836 client_ad.droid.bluetoothStartPairingHelper()
tturney24506942016-08-23 10:53:17 -0700837 server_ad.droid.bluetoothRfcommBeginAcceptThread(
tturney96970fd2016-08-31 17:36:09 -0700838 RfcommUuid.DEFAULT_UUID.value, accept_timeout_ms)
tturney24506942016-08-23 10:53:17 -0700839 client_ad.droid.bluetoothRfcommBeginConnectThread(
840 server_ad.droid.bluetoothGetLocalAddress())
tturneyb92368a2016-09-13 10:43:15 -0700841 end_time = time.time() + DEFAULT_TIMEOUT
tturney24506942016-08-23 10:53:17 -0700842 result = False
843 test_result = True
844 while time.time() < end_time:
845 if len(client_ad.droid.bluetoothRfcommActiveConnections()) > 0:
tturney96970fd2016-08-31 17:36:09 -0700846 test_result = True
tturney24506942016-08-23 10:53:17 -0700847 log.info("RFCOMM Client Connection Active")
848 break
tturney96970fd2016-08-31 17:36:09 -0700849 else:
850 test_result = False
851 time.sleep(1)
tturney24506942016-08-23 10:53:17 -0700852 if not test_result:
853 log.error("Failed to establish an RFCOMM connection")
854 return False
855 return True
tturneye3170f02016-05-19 14:37:00 -0700856
857
858def write_read_verify_data(client_ad, server_ad, msg, binary=False):
tturneyed249972016-09-13 11:07:49 -0700859 """Verify that the client wrote data to the server Android device correctly.
860
861 Args:
862 client_ad: the Android device to perform the write.
863 server_ad: the Android device to read the data written.
864 msg: the message to write.
865 binary: if the msg arg is binary or not.
866
867 Returns:
868 True if the data written matches the data read, false if not.
869 """
tturneye3170f02016-05-19 14:37:00 -0700870 log.info("Write message.")
871 try:
872 if binary:
873 client_ad.droid.bluetoothRfcommWriteBinary(msg)
874 else:
875 client_ad.droid.bluetoothRfcommWrite(msg)
876 except Exception as err:
877 log.error("Failed to write data: {}".format(err))
878 return False
879 log.info("Read message.")
880 try:
881 if binary:
tturney57eb93a2016-06-21 13:58:06 -0700882 read_msg = server_ad.droid.bluetoothRfcommReadBinary().rstrip(
883 "\r\n")
tturneye3170f02016-05-19 14:37:00 -0700884 else:
885 read_msg = server_ad.droid.bluetoothRfcommRead()
886 except Exception as err:
887 log.error("Failed to read data: {}".format(err))
888 return False
889 log.info("Verify message.")
890 if msg != read_msg:
tturney57eb93a2016-06-21 13:58:06 -0700891 log.error("Mismatch! Read: {}, Expected: {}".format(read_msg, msg))
tturneye3170f02016-05-19 14:37:00 -0700892 return False
893 return True
tturney51eaa382016-05-17 13:28:24 -0700894
tturney24506942016-08-23 10:53:17 -0700895
896def clear_bonded_devices(ad):
tturneyed249972016-09-13 11:07:49 -0700897 """Clear bonded devices from the input Android device.
tturney24506942016-08-23 10:53:17 -0700898
899 Args:
tturneyed249972016-09-13 11:07:49 -0700900 ad: the Android device performing the connection.
tturney24506942016-08-23 10:53:17 -0700901 Returns:
902 True if clearing bonded devices was successful, false if unsuccessful.
903 """
904 bonded_device_list = ad.droid.bluetoothGetBondedDevices()
905 for device in bonded_device_list:
906 device_address = device['address']
907 if not ad.droid.bluetoothUnbond(device_address):
908 log.error("Failed to unbond {}".format(device_address))
909 return False
910 log.info("Successfully unbonded {}".format(device_address))
911 return True
912
tturneyb92368a2016-09-13 10:43:15 -0700913
tturney96970fd2016-08-31 17:36:09 -0700914def verify_server_and_client_connected(client_ad, server_ad):
tturneyed249972016-09-13 11:07:49 -0700915 """Verify that input server and client Android devices are connected.
916
917 This code is under the assumption that there will only be
918 a single connection.
919
920 Args:
921 client_ad: the Android device to check number of active connections.
922 server_ad: the Android device to check number of active connections.
923
924 Returns:
925 True both server and client have at least 1 active connection,
926 false if unsuccessful.
927 """
tturney96970fd2016-08-31 17:36:09 -0700928 test_result = True
929 if len(server_ad.droid.bluetoothRfcommActiveConnections()) == 0:
930 log.error("No rfcomm connections found on server.")
931 test_result = False
932 if len(client_ad.droid.bluetoothRfcommActiveConnections()) == 0:
933 log.error("No rfcomm connections found on client.")
934 test_result = False
935 return test_result
tturneyb92368a2016-09-13 10:43:15 -0700936
937
938def orchestrate_and_verify_pan_connection(pan_dut, panu_dut):
939 """Setups up a PAN conenction between two android devices.
940
941 Args:
942 pan_dut: the Android device providing tethering services
943 panu_dut: the Android device using the internet connection from the
944 pan_dut
945 Returns:
946 True if PAN connection and verification is successful,
947 false if unsuccessful.
948 """
949 if not toggle_airplane_mode(log, panu_dut, True):
950 log.error("Failed to toggle airplane mode on")
951 return False
952 if not bluetooth_enabled_check(panu_dut):
953 return False
954 pan_dut.droid.bluetoothPanSetBluetoothTethering(True)
955 if not (pair_pri_to_sec(pan_dut.droid, panu_dut.droid)):
956 return False
957 if not pan_dut.droid.bluetoothPanIsTetheringOn():
958 log.error("Failed to enable Bluetooth tethering.")
959 return False
960 # Magic sleep needed to give the stack time in between bonding and
961 # connecting the PAN profile.
962 time.sleep(MAGIC_PAN_CONNECT_TIMEOUT)
963 panu_dut.droid.bluetoothConnectBonded(
964 pan_dut.droid.bluetoothGetLocalAddress())
965 if not verify_http_connection(log, panu_dut):
966 log.error("Can't verify http connection on PANU device.")
967 if not verify_http_connection(log, pan_dut):
968 log.info("Can't verify http connection on PAN service device")
969 return False
970 return True