| # Copyright (c) 2013 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. |
| |
| from __future__ import absolute_import |
| |
| import logging |
| import time |
| |
| import common |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.common_lib.cros.bluetooth import bluetooth_socket |
| from autotest_lib.server.cros.bluetooth import bluetooth_adapter_tests |
| |
| DEVICE_ADDRESS = '01:02:03:04:05:06' |
| ADDRESS_TYPE = 0 |
| |
| class bluetooth_Health_DefaultStateTest( |
| bluetooth_adapter_tests.BluetoothAdapterTests): |
| """ |
| This class implements the default state test |
| and all the helper functions it needs. |
| """ |
| version = 1 |
| |
| |
| |
| def compare_property(self, bluez_property, mgmt_setting, current_settings): |
| """ Compare bluez property value and Kernel property |
| |
| @param bluez_property : Bluez property to be compared |
| @param mgmt_setting : Bit mask of management setting |
| @param current_settings : Current kernel settings |
| @return : True if bluez property and the current settings agree """ |
| |
| cur_kernel_value = 1 if mgmt_setting & current_settings else 0 |
| return bluez_property == cur_kernel_value |
| |
| def default_state_test(self): |
| """Test Default state of Bluetooth adapter after power cycling.""" |
| |
| # Reset the adapter to the powered off state. |
| self.test_reset_off_adapter() |
| |
| # Kernel default state depends on whether the kernel supports the |
| # BR/EDR Allowlist. When this is supported the 'connectable' setting |
| # remains unset and instead page scan is managed by the kernel based |
| # on whether or not a BR/EDR device is in the allowlist. |
| ( commands, events ) = self.read_supported_commands() |
| supports_add_device = bluetooth_socket.MGMT_OP_ADD_DEVICE in commands |
| |
| # Read the initial state of the adapter. Verify that it is powered down. |
| ( address, bluetooth_version, manufacturer_id, |
| supported_settings, current_settings, class_of_device, |
| name, short_name ) = self.read_info() |
| self.log_settings('Initial state', current_settings) |
| |
| if current_settings & bluetooth_socket.MGMT_SETTING_POWERED: |
| raise error.TestFail('Bluetooth adapter is powered') |
| |
| # The other kernel settings (connectable, pairable, etc.) reflect the |
| # initial state before the bluetooth daemon adjusts them - we're ok |
| # with them being on or off during that brief period. |
| # |
| |
| # Verify that the Bluetooth Daemon sees that it is also powered down, |
| # non-discoverable and not discovering devices. |
| bluez_properties = self.get_adapter_properties() |
| |
| if bluez_properties['Powered']: |
| raise error.TestFail('Bluetooth daemon Powered property does not ' |
| 'match kernel while powered off') |
| if not self.compare_property(bluez_properties['Discoverable'], |
| bluetooth_socket.MGMT_SETTING_DISCOVERABLE, |
| current_settings): |
| raise error.TestFail('Bluetooth daemon Discoverable property ' |
| 'does not match kernel while powered off') |
| if bluez_properties['Discovering']: |
| raise error.TestFail('Bluetooth daemon believes adapter is ' |
| 'discovering while powered off') |
| |
| # Compare with the raw HCI state of the adapter as well, this should |
| # be just not "UP", otherwise something deeply screwy is happening. |
| flags = self.get_dev_info()[3] |
| self.log_flags('Initial state', flags) |
| |
| if flags & bluetooth_socket.HCI_UP: |
| raise error.TestFail('HCI UP flag does not match kernel while ' |
| 'powered off') |
| |
| # Power on the adapter, then read the state again. Verify that it is |
| # powered up, pairable, but not discoverable. |
| self.test_power_on_adapter() |
| current_settings = self.read_info()[4] |
| self.log_settings("Powered up", current_settings) |
| |
| if not current_settings & bluetooth_socket.MGMT_SETTING_POWERED: |
| raise error.TestFail('Bluetooth adapter is not powered') |
| |
| # If the kernel does not supports the BR/EDR allowlist, the adapter |
| # should be generically connectable; |
| # if it doesn't, then it depends on previous settings. |
| if not supports_add_device: |
| if not current_settings & bluetooth_socket.MGMT_SETTING_CONNECTABLE: |
| raise error.TestFail('Bluetooth adapter is not connectable ' |
| 'though kernel does not support ' |
| 'BR/EDR allowlist') |
| |
| # Verify that the Bluetooth Daemon sees the same state as the kernel |
| # and that it's not discovering. |
| bluez_properties = self.get_adapter_properties() |
| |
| if not bluez_properties['Powered']: |
| raise error.TestFail('Bluetooth daemon Powered property does not ' |
| 'match kernel while powered on') |
| if not self.compare_property(bluez_properties['Pairable'], |
| bluetooth_socket.MGMT_SETTING_PAIRABLE, |
| current_settings): |
| raise error.TestFail('Bluetooth daemon Pairable property does not ' |
| 'match kernel while powered on') |
| if not self.compare_property(bluez_properties['Discoverable'], |
| bluetooth_socket.MGMT_SETTING_DISCOVERABLE, |
| current_settings): |
| raise error.TestFail('Bluetooth daemon Discoverable property ' |
| 'does not match kernel while powered on') |
| if bluez_properties['Discovering']: |
| raise error.TestFail('Bluetooth daemon believes adapter is ' |
| 'discovering while powered on') |
| |
| # Compare with the raw HCI state of the adapter while powered up as |
| # well. |
| flags = self.get_dev_info()[3] |
| self.log_flags('Powered up', flags) |
| |
| if not flags & bluetooth_socket.HCI_UP: |
| raise error.TestFail('HCI UP flag does not match kernel while ' |
| 'powered on') |
| if not flags & bluetooth_socket.HCI_RUNNING: |
| raise error.TestFail('HCI RUNNING flag does not match kernel while ' |
| 'powered on') |
| if bool(flags & bluetooth_socket.HCI_ISCAN) != \ |
| bool(bluez_properties['Discoverable']): |
| raise error.TestFail('HCI ISCAN flag does not match kernel while ' |
| 'powered on') |
| if flags & bluetooth_socket.HCI_INQUIRY: |
| raise error.TestFail('HCI INQUIRY flag does not match kernel while ' |
| 'powered on') |
| |
| # If the kernel does not supports the BR/EDR allowlist, the adapter |
| # should generically connectable, so should it should be in PSCAN |
| # mode. This matches the management API "connectable" setting so far. |
| if not supports_add_device: |
| if not flags & bluetooth_socket.HCI_PSCAN: |
| raise error.TestFail('HCI PSCAN flag not set though kernel' |
| 'does not supports BR/EDR allowlist') |
| |
| # Now we can examine the differences. Try adding and removing a device |
| # from the kernel BR/EDR allowlist. The management API "connectable" |
| # setting should remain off, but we should be able to see the PSCAN |
| # flag come and go. |
| if supports_add_device: |
| # If PSCAN is currently on then device is CONNECTABLE |
| # or a previous add device which was not removed. |
| # Turn on and off DISCOVERABLE to turn off CONNECTABLE and |
| # PSCAN |
| if flags & bluetooth_socket.HCI_PSCAN: |
| if not (current_settings & |
| bluetooth_socket.MGMT_SETTING_CONNECTABLE): |
| raise error.TestFail('PSCAN on but device not CONNECTABLE') |
| logging.debug('Toggle Discoverable to turn off CONNECTABLE') |
| self.test_discoverable() |
| self.test_nondiscoverable() |
| current_settings = self.read_info()[4] |
| flags = self.get_dev_info()[3] |
| self.log_flags('Discoverability Toggled', flags) |
| if flags & bluetooth_socket.HCI_PSCAN: |
| raise error.TestFail('PSCAN on after toggling DISCOVERABLE') |
| |
| previous_settings = current_settings |
| previous_flags = flags |
| |
| self.add_device(DEVICE_ADDRESS, ADDRESS_TYPE, 1) |
| |
| # Wait for a few seconds before reading the settings |
| time.sleep(3) |
| current_settings = self.read_info()[4] |
| self.log_settings("After add device", |
| current_settings) |
| |
| flags = self.get_dev_info()[3] |
| self.log_flags('After add device', flags) |
| |
| if current_settings != previous_settings: |
| self.log_settings("previous settings", previous_settings) |
| self.log_settings("current settings", current_settings) |
| raise error.TestFail( |
| 'Bluetooth adapter settings changed after add device') |
| if not flags & bluetooth_socket.HCI_PSCAN: |
| raise error.TestFail('HCI PSCAN flag not set after add device') |
| |
| # Remove the device again, and make sure the PSCAN flag goes away. |
| self.remove_device(DEVICE_ADDRESS, ADDRESS_TYPE) |
| |
| # PSCAN is still enabled for a few seconds after remove device |
| # on older devices. Wait for few second before reading the settigs |
| time.sleep(3) |
| current_settings = self.read_info()[4] |
| self.log_settings("After remove device", current_settings) |
| |
| flags = self.get_dev_info()[3] |
| self.log_flags('After remove device', flags) |
| |
| if current_settings != previous_settings: |
| raise error.TestFail( |
| 'Bluetooth adapter settings changed after remove device') |
| if flags & bluetooth_socket.HCI_PSCAN: |
| raise error.TestFail('HCI PSCAN flag set after remove device') |
| |
| # Finally power off the adapter again, and verify that the adapter has |
| # returned to powered down. |
| self.test_power_off_adapter() |
| current_settings = self.read_info()[4] |
| self.log_settings("After power down", current_settings) |
| |
| if current_settings & bluetooth_socket.MGMT_SETTING_POWERED: |
| raise error.TestFail('Bluetooth adapter is powered after power off') |
| |
| # Verify that the Bluetooth Daemon sees the same state as the kernel. |
| bluez_properties = self.get_adapter_properties() |
| |
| if bluez_properties['Powered']: |
| raise error.TestFail('Bluetooth daemon Powered property does not ' |
| 'match kernel after power off') |
| if not self.compare_property(bluez_properties['Discoverable'], |
| bluetooth_socket.MGMT_SETTING_DISCOVERABLE, |
| current_settings): |
| raise error.TestFail('Bluetooth daemon Discoverable property ' |
| 'does not match kernel after off') |
| if bluez_properties['Discovering']: |
| raise error.TestFail('Bluetooth daemon believes adapter is ' |
| 'discovering after power off') |
| |
| # And one last comparison with the raw HCI state of the adapter. |
| flags = self.get_dev_info()[3] |
| self.log_flags('After power down', flags) |
| |
| if flags & bluetooth_socket.HCI_UP: |
| raise error.TestFail('HCI UP flag does not match kernel after ' |
| 'power off') |