blob: a4718cffd8183815bbf73fdfa5a3ed6e6b764197 [file] [log] [blame]
# 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)