257 lines
9.7 KiB
Python
257 lines
9.7 KiB
Python
# Lint as: python2, python3
|
|
# Copyright 2019 The Chromium OS Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
"""
|
|
Server side bluetooth tests on adapter pairing and connecting to a bluetooth
|
|
HID device.
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
|
|
import logging
|
|
import time
|
|
|
|
import common
|
|
from autotest_lib.server.cros.bluetooth import bluetooth_adapter_tests
|
|
from six.moves import range
|
|
|
|
|
|
class BluetoothAdapterPairingTests(
|
|
bluetooth_adapter_tests.BluetoothAdapterTests):
|
|
"""Server side bluetooth adapter pairing and connecting to bluetooth device
|
|
|
|
This test tries to verify that the adapter of the DUT could
|
|
pair and connect to a bluetooth HID device correctly.
|
|
|
|
In particular, the following subtests are performed. Look at the
|
|
docstrings of the subtests for more details.
|
|
-
|
|
|
|
Refer to BluetoothAdapterTests for all subtests performed in this test.
|
|
|
|
"""
|
|
|
|
# TODO(josephsih): Reduce the sleep intervals to speed up the tests.
|
|
PAIR_TEST_SLEEP_SECS = 5
|
|
|
|
def pairing_test(self, device, check_connected_method=lambda device: True,
|
|
pairing_twice=False, suspend_resume=False, reboot=False):
|
|
"""Running Bluetooth adapter tests about pairing to a device."""
|
|
|
|
# Reset the adapter to forget previously paired devices if any.
|
|
self.test_reset_on_adapter()
|
|
|
|
# The adapter must be set to the pairable state.
|
|
self.test_pairable()
|
|
|
|
# Test if the adapter could discover the target device.
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
self.test_discover_device(device.address)
|
|
|
|
# Test if the discovered device class of service is correct.
|
|
self.test_device_class_of_service(device.address,
|
|
device.class_of_service)
|
|
|
|
# Test if the discovered device class of device is correct.
|
|
self.test_device_class_of_device(device.address,
|
|
device.class_of_device)
|
|
|
|
# Verify that the adapter could pair with the device.
|
|
# Also set the device trusted when pairing is done.
|
|
# Device will be connected at the end of pairing.
|
|
self.test_pairing(device.address, device.pin, trusted=True)
|
|
|
|
# Test if the discovered device name is correct.
|
|
# Sometimes, it takes quite a long time after discovering
|
|
# the device (more than 60 seconds) to resolve the device name.
|
|
# Hence, it is safer to test the device name after pairing and
|
|
# connection is done.
|
|
self.test_device_name(device.address, device.name)
|
|
|
|
# Run hid test to make sure profile is connected
|
|
check_connected_method(device)
|
|
|
|
# Test if the device is still connected after suspend/resume.
|
|
if suspend_resume:
|
|
self.suspend_resume()
|
|
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
self.test_device_is_paired(device.address)
|
|
|
|
|
|
# check if peripheral is connected after suspend resume
|
|
if not self.ignore_failure(check_connected_method, device):
|
|
logging.info("device not connected after suspend_resume")
|
|
self.test_connection_by_device(device)
|
|
else:
|
|
logging.info("device remains connected after suspend_resume")
|
|
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
check_connected_method(device)
|
|
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
self.test_device_name(device.address, device.name)
|
|
|
|
# Test if the device is still connected after reboot.
|
|
# if reboot:
|
|
# self.host.reboot()
|
|
|
|
# time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
# self.test_device_is_paired(device.address)
|
|
|
|
# # After a reboot, we need to wake the peripheral
|
|
# # as it is not connected.
|
|
# time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
# self.test_connection_by_adapter(device.address)
|
|
|
|
# time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
# self.test_device_is_connected(device.address)
|
|
|
|
# time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
# self.test_device_name(device.address, device.name)
|
|
|
|
# Verify that the adapter could disconnect the device.
|
|
self.test_disconnection_by_adapter(device.address)
|
|
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
if device.can_init_connection:
|
|
# Verify that the device could initiate the connection.
|
|
self.test_connection_by_device(device)
|
|
|
|
# With raspberry pi peer, it takes a moment before the device is
|
|
# registered as an input device. Without delay, the input recorder
|
|
# doesn't find the device
|
|
time.sleep(1)
|
|
check_connected_method(device)
|
|
else:
|
|
# Reconnect so that we can test disconnection from the kit
|
|
self.test_connection_by_adapter(device.address)
|
|
|
|
# TODO(alent): Needs a new capability, but this is a good proxy
|
|
if device.can_init_connection:
|
|
# Verify that the device could initiate the disconnection.
|
|
self.test_disconnection_by_device(device)
|
|
else:
|
|
# Reconnect so that we can test disconnection from the kit
|
|
self.test_disconnection_by_adapter(device.address)
|
|
|
|
# Verify that the adapter could remove the paired device.
|
|
self.test_remove_pairing(device.address)
|
|
|
|
# Check if the device could be re-paired after being forgotten.
|
|
if pairing_twice:
|
|
# Test if the adapter could discover the target device again.
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
self.test_discover_device(device.address)
|
|
|
|
# Verify that the adapter could pair with the device again.
|
|
# Also set the device trusted when pairing is done.
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
self.test_pairing(device.address, device.pin, trusted=True)
|
|
|
|
# Verify that the adapter could remove the paired device again.
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
self.test_remove_pairing(device.address)
|
|
|
|
|
|
def connect_disconnect_loop(self, device, loops):
|
|
"""Perform a connect disconnect loop test"""
|
|
|
|
# First pair and disconnect, to emulate real life scenario
|
|
self.test_discover_device(device.address)
|
|
# self.bluetooth_facade.is_discovering() doesn't work as expected:
|
|
# crbug:905374
|
|
# self.test_stop_discovery()
|
|
time.sleep(self.PAIR_TEST_SLEEP_SECS)
|
|
self.test_pairing(device.address, device.pin, trusted=True)
|
|
|
|
# Verify device is now connected
|
|
self.test_device_is_connected(device.address)
|
|
self.test_hid_device_created(device.address)
|
|
|
|
# Disconnect the device
|
|
self.test_disconnection_by_adapter(device.address)
|
|
total_duration_by_adapter = 0
|
|
loop_cnt = 0
|
|
for i in range(0, loops):
|
|
|
|
# Verify device didn't connect automatically
|
|
time.sleep(2)
|
|
self.test_device_is_not_connected(device.address)
|
|
|
|
start_time = time.time()
|
|
self.test_connection_by_adapter(device.address)
|
|
end_time = time.time()
|
|
time_diff = end_time - start_time
|
|
|
|
# Verify device is now connected
|
|
self.test_device_is_connected(device.address)
|
|
self.test_hid_device_created(device.address)
|
|
|
|
self.test_disconnection_by_adapter(device.address)
|
|
|
|
if not bool(self.fails):
|
|
loop_cnt += 1
|
|
total_duration_by_adapter += time_diff
|
|
logging.info('%d: Connection establishment duration %f sec',
|
|
i, time_diff)
|
|
else:
|
|
break
|
|
|
|
if not bool(self.fails):
|
|
logging.info('Average duration (by adapter) %f sec',
|
|
total_duration_by_adapter/loop_cnt)
|
|
|
|
|
|
def auto_reconnect_loop(self,
|
|
device,
|
|
loops,
|
|
check_connected_method=lambda device: True,
|
|
restart_adapter=False):
|
|
"""Running a loop to verify the paired peer can auto reconnect"""
|
|
|
|
# Let the adapter pair, and connect to the target device first
|
|
self.test_discover_device(device.address)
|
|
self.test_pairing(device.address, device.pin, trusted=True)
|
|
|
|
# Verify device is now connected
|
|
self.test_connection_by_adapter(device.address)
|
|
self.test_hid_device_created(device.address)
|
|
|
|
total_reconnection_duration = 0
|
|
loop_cnt = 0
|
|
for i in range(loops):
|
|
# Restart either the adapter or the peer
|
|
if restart_adapter:
|
|
self.test_power_off_adapter()
|
|
self.test_power_on_adapter()
|
|
start_time = time.time()
|
|
else:
|
|
# Restart and clear peer HID device
|
|
self.restart_peers()
|
|
start_time = time.time()
|
|
|
|
# Verify that the device is reconnected. Wait for the input device
|
|
# to become available before checking the profile connection.
|
|
self.test_device_is_connected(device.address)
|
|
self.test_hid_device_created(device.address)
|
|
|
|
check_connected_method(device)
|
|
end_time = time.time()
|
|
time_diff = end_time - start_time
|
|
|
|
if not bool(self.fails):
|
|
total_reconnection_duration += time_diff
|
|
loop_cnt += 1
|
|
logging.info('%d: Reconnection duration %f sec', i, time_diff)
|
|
else:
|
|
break
|
|
|
|
if not bool(self.fails):
|
|
logging.info('Average Reconnection duration %f sec',
|
|
total_reconnection_duration/loop_cnt)
|