1# Lint as: python2, python3 2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6from __future__ import absolute_import 7 8import logging 9import time 10 11import common 12from autotest_lib.client.common_lib import error 13from autotest_lib.client.common_lib.cros.bluetooth import bluetooth_socket 14from autotest_lib.server.cros.bluetooth import bluetooth_adapter_tests 15 16DEVICE_ADDRESS = '01:02:03:04:05:06' 17ADDRESS_TYPE = 0 18 19class bluetooth_Health_DefaultStateTest( 20 bluetooth_adapter_tests.BluetoothAdapterTests): 21 """ 22 This class implements the default state test 23 and all the helper functions it needs. 24 """ 25 version = 1 26 27 28 29 def compare_property(self, bluez_property, mgmt_setting, current_settings): 30 """ Compare bluez property value and Kernel property 31 32 @param bluez_property : Bluez property to be compared 33 @param mgmt_setting : Bit mask of management setting 34 @param current_settings : Current kernel settings 35 @return : True if bluez property and the current settings agree """ 36 37 cur_kernel_value = 1 if mgmt_setting & current_settings else 0 38 return bluez_property == cur_kernel_value 39 40 def default_state_test(self): 41 """Test Default state of Bluetooth adapter after power cycling.""" 42 43 # Reset the adapter to the powered off state. 44 self.test_reset_off_adapter() 45 46 # Kernel default state depends on whether the kernel supports the 47 # BR/EDR Allowlist. When this is supported the 'connectable' setting 48 # remains unset and instead page scan is managed by the kernel based 49 # on whether or not a BR/EDR device is in the allowlist. 50 ( commands, events ) = self.read_supported_commands() 51 supports_add_device = bluetooth_socket.MGMT_OP_ADD_DEVICE in commands 52 53 # Read the initial state of the adapter. Verify that it is powered down. 54 ( address, bluetooth_version, manufacturer_id, 55 supported_settings, current_settings, class_of_device, 56 name, short_name ) = self.read_info() 57 self.log_settings('Initial state', current_settings) 58 59 if current_settings & bluetooth_socket.MGMT_SETTING_POWERED: 60 raise error.TestFail('Bluetooth adapter is powered') 61 62 # The other kernel settings (connectable, pairable, etc.) reflect the 63 # initial state before the bluetooth daemon adjusts them - we're ok 64 # with them being on or off during that brief period. 65 # 66 67 # Verify that the Bluetooth Daemon sees that it is also powered down, 68 # non-discoverable and not discovering devices. 69 bluez_properties = self.get_adapter_properties() 70 71 if bluez_properties['Powered']: 72 raise error.TestFail('Bluetooth daemon Powered property does not ' 73 'match kernel while powered off') 74 if not self.compare_property(bluez_properties['Discoverable'], 75 bluetooth_socket.MGMT_SETTING_DISCOVERABLE, 76 current_settings): 77 raise error.TestFail('Bluetooth daemon Discoverable property ' 78 'does not match kernel while powered off') 79 if bluez_properties['Discovering']: 80 raise error.TestFail('Bluetooth daemon believes adapter is ' 81 'discovering while powered off') 82 83 # Compare with the raw HCI state of the adapter as well, this should 84 # be just not "UP", otherwise something deeply screwy is happening. 85 flags = self.get_dev_info()[3] 86 self.log_flags('Initial state', flags) 87 88 if flags & bluetooth_socket.HCI_UP: 89 raise error.TestFail('HCI UP flag does not match kernel while ' 90 'powered off') 91 92 # Power on the adapter, then read the state again. Verify that it is 93 # powered up, pairable, but not discoverable. 94 self.test_power_on_adapter() 95 current_settings = self.read_info()[4] 96 self.log_settings("Powered up", current_settings) 97 98 if not current_settings & bluetooth_socket.MGMT_SETTING_POWERED: 99 raise error.TestFail('Bluetooth adapter is not powered') 100 101 # If the kernel does not supports the BR/EDR allowlist, the adapter 102 # should be generically connectable; 103 # if it doesn't, then it depends on previous settings. 104 if not supports_add_device: 105 if not current_settings & bluetooth_socket.MGMT_SETTING_CONNECTABLE: 106 raise error.TestFail('Bluetooth adapter is not connectable ' 107 'though kernel does not support ' 108 'BR/EDR allowlist') 109 110 # Verify that the Bluetooth Daemon sees the same state as the kernel 111 # and that it's not discovering. 112 bluez_properties = self.get_adapter_properties() 113 114 if not bluez_properties['Powered']: 115 raise error.TestFail('Bluetooth daemon Powered property does not ' 116 'match kernel while powered on') 117 if not self.compare_property(bluez_properties['Pairable'], 118 bluetooth_socket.MGMT_SETTING_PAIRABLE, 119 current_settings): 120 raise error.TestFail('Bluetooth daemon Pairable property does not ' 121 'match kernel while powered on') 122 if not self.compare_property(bluez_properties['Discoverable'], 123 bluetooth_socket.MGMT_SETTING_DISCOVERABLE, 124 current_settings): 125 raise error.TestFail('Bluetooth daemon Discoverable property ' 126 'does not match kernel while powered on') 127 if bluez_properties['Discovering']: 128 raise error.TestFail('Bluetooth daemon believes adapter is ' 129 'discovering while powered on') 130 131 # Compare with the raw HCI state of the adapter while powered up as 132 # well. 133 flags = self.get_dev_info()[3] 134 self.log_flags('Powered up', flags) 135 136 if not flags & bluetooth_socket.HCI_UP: 137 raise error.TestFail('HCI UP flag does not match kernel while ' 138 'powered on') 139 if not flags & bluetooth_socket.HCI_RUNNING: 140 raise error.TestFail('HCI RUNNING flag does not match kernel while ' 141 'powered on') 142 if bool(flags & bluetooth_socket.HCI_ISCAN) != \ 143 bool(bluez_properties['Discoverable']): 144 raise error.TestFail('HCI ISCAN flag does not match kernel while ' 145 'powered on') 146 if flags & bluetooth_socket.HCI_INQUIRY: 147 raise error.TestFail('HCI INQUIRY flag does not match kernel while ' 148 'powered on') 149 150 # If the kernel does not supports the BR/EDR allowlist, the adapter 151 # should generically connectable, so should it should be in PSCAN 152 # mode. This matches the management API "connectable" setting so far. 153 if not supports_add_device: 154 if not flags & bluetooth_socket.HCI_PSCAN: 155 raise error.TestFail('HCI PSCAN flag not set though kernel' 156 'does not supports BR/EDR allowlist') 157 158 # Now we can examine the differences. Try adding and removing a device 159 # from the kernel BR/EDR allowlist. The management API "connectable" 160 # setting should remain off, but we should be able to see the PSCAN 161 # flag come and go. 162 if supports_add_device: 163 # If PSCAN is currently on then device is CONNECTABLE 164 # or a previous add device which was not removed. 165 # Turn on and off DISCOVERABLE to turn off CONNECTABLE and 166 # PSCAN 167 if flags & bluetooth_socket.HCI_PSCAN: 168 if not (current_settings & 169 bluetooth_socket.MGMT_SETTING_CONNECTABLE): 170 raise error.TestFail('PSCAN on but device not CONNECTABLE') 171 logging.debug('Toggle Discoverable to turn off CONNECTABLE') 172 self.test_discoverable() 173 self.test_nondiscoverable() 174 current_settings = self.read_info()[4] 175 flags = self.get_dev_info()[3] 176 self.log_flags('Discoverability Toggled', flags) 177 if flags & bluetooth_socket.HCI_PSCAN: 178 raise error.TestFail('PSCAN on after toggling DISCOVERABLE') 179 180 previous_settings = current_settings 181 previous_flags = flags 182 183 self.add_device(DEVICE_ADDRESS, ADDRESS_TYPE, 1) 184 185 # Wait for a few seconds before reading the settings 186 time.sleep(3) 187 current_settings = self.read_info()[4] 188 self.log_settings("After add device", 189 current_settings) 190 191 flags = self.get_dev_info()[3] 192 self.log_flags('After add device', flags) 193 194 if current_settings != previous_settings: 195 self.log_settings("previous settings", previous_settings) 196 self.log_settings("current settings", current_settings) 197 raise error.TestFail( 198 'Bluetooth adapter settings changed after add device') 199 if not flags & bluetooth_socket.HCI_PSCAN: 200 raise error.TestFail('HCI PSCAN flag not set after add device') 201 202 # Remove the device again, and make sure the PSCAN flag goes away. 203 self.remove_device(DEVICE_ADDRESS, ADDRESS_TYPE) 204 205 # PSCAN is still enabled for a few seconds after remove device 206 # on older devices. Wait for few second before reading the settigs 207 time.sleep(3) 208 current_settings = self.read_info()[4] 209 self.log_settings("After remove device", current_settings) 210 211 flags = self.get_dev_info()[3] 212 self.log_flags('After remove device', flags) 213 214 if current_settings != previous_settings: 215 raise error.TestFail( 216 'Bluetooth adapter settings changed after remove device') 217 if flags & bluetooth_socket.HCI_PSCAN: 218 raise error.TestFail('HCI PSCAN flag set after remove device') 219 220 # Finally power off the adapter again, and verify that the adapter has 221 # returned to powered down. 222 self.test_power_off_adapter() 223 current_settings = self.read_info()[4] 224 self.log_settings("After power down", current_settings) 225 226 if current_settings & bluetooth_socket.MGMT_SETTING_POWERED: 227 raise error.TestFail('Bluetooth adapter is powered after power off') 228 229 # Verify that the Bluetooth Daemon sees the same state as the kernel. 230 bluez_properties = self.get_adapter_properties() 231 232 if bluez_properties['Powered']: 233 raise error.TestFail('Bluetooth daemon Powered property does not ' 234 'match kernel after power off') 235 if not self.compare_property(bluez_properties['Discoverable'], 236 bluetooth_socket.MGMT_SETTING_DISCOVERABLE, 237 current_settings): 238 raise error.TestFail('Bluetooth daemon Discoverable property ' 239 'does not match kernel after off') 240 if bluez_properties['Discovering']: 241 raise error.TestFail('Bluetooth daemon believes adapter is ' 242 'discovering after power off') 243 244 # And one last comparison with the raw HCI state of the adapter. 245 flags = self.get_dev_info()[3] 246 self.log_flags('After power down', flags) 247 248 if flags & bluetooth_socket.HCI_UP: 249 raise error.TestFail('HCI UP flag does not match kernel after ' 250 'power off') 251