1 # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import logging 6 7 from autotest_lib.client.common_lib import error 8 from autotest_lib.client.common_lib.cros.bluetooth import bluetooth_socket 9 from autotest_lib.server.cros.bluetooth import bluetooth_test 10 11 DEVICE_ADDRESS = '01:02:03:04:05:06' 12 ADDRESS_TYPE = 0 13 14 class bluetooth_Sanity_DefaultState(bluetooth_test.BluetoothTest): 15 """ 16 Verify that the Bluetooth adapter has correct state. 17 """ 18 version = 1 19 20 def _log_settings(self, msg, settings): 21 strs = [] 22 if settings & bluetooth_socket.MGMT_SETTING_POWERED: 23 strs.append("POWERED") 24 if settings & bluetooth_socket.MGMT_SETTING_CONNECTABLE: 25 strs.append("CONNECTABLE") 26 if settings & bluetooth_socket.MGMT_SETTING_FAST_CONNECTABLE: 27 strs.append("FAST-CONNECTABLE") 28 if settings & bluetooth_socket.MGMT_SETTING_DISCOVERABLE: 29 strs.append("DISCOVERABLE") 30 if settings & bluetooth_socket.MGMT_SETTING_PAIRABLE: 31 strs.append("PAIRABLE") 32 if settings & bluetooth_socket.MGMT_SETTING_LINK_SECURITY: 33 strs.append("LINK-SECURITY") 34 if settings & bluetooth_socket.MGMT_SETTING_SSP: 35 strs.append("SSP") 36 if settings & bluetooth_socket.MGMT_SETTING_BREDR: 37 strs.append("BR/EDR") 38 if settings & bluetooth_socket.MGMT_SETTING_HS: 39 strs.append("HS") 40 if settings & bluetooth_socket.MGMT_SETTING_LE: 41 strs.append("LE") 42 logging.debug(msg + ': %s', " ".join(strs)) 43 44 def _log_flags(self, msg, flags): 45 strs = [] 46 if flags & bluetooth_socket.HCI_UP: 47 strs.append("UP") 48 else: 49 strs.append("DOWN") 50 if flags & bluetooth_socket.HCI_INIT: 51 strs.append("INIT") 52 if flags & bluetooth_socket.HCI_RUNNING: 53 strs.append("RUNNING") 54 if flags & bluetooth_socket.HCI_PSCAN: 55 strs.append("PSCAN") 56 if flags & bluetooth_socket.HCI_ISCAN: 57 strs.append("ISCAN") 58 if flags & bluetooth_socket.HCI_AUTH: 59 strs.append("AUTH") 60 if flags & bluetooth_socket.HCI_ENCRYPT: 61 strs.append("ENCRYPT") 62 if flags & bluetooth_socket.HCI_INQUIRY: 63 strs.append("INQUIRY") 64 if flags & bluetooth_socket.HCI_RAW: 65 strs.append("RAW") 66 logging.debug(msg + ' [HCI]: %s', " ".join(strs)) 67 68 def cleanup(self): 69 """ Test specific cleanup 70 Remove any devices added to whitelist 71 """ 72 self.device.remove_device(DEVICE_ADDRESS, ADDRESS_TYPE) 73 super(bluetooth_Sanity_DefaultState, self).cleanup() 74 75 76 def compare_property(self, bluez_property, mgmt_setting, current_settings): 77 """ Compare bluez property value and Kernel property 78 79 @param bluez_property : Bluez property to be compared 80 @param mgmt_setting : Bit mask of management setting 81 @param current_settings : Current kernel settings 82 @return : True if bluez property and the current settings agree """ 83 84 cur_kernel_value = 1 if mgmt_setting & current_settings else 0 85 return bluez_property == cur_kernel_value 86 87 def run_once(self): 88 """Test Default state of Bluetooth adapter after power cycling.""" 89 90 # Reset the adapter to the powered off state. 91 if not self.device.reset_off(): 92 raise error.TestFail('DUT could not be reset to initial state') 93 94 # Kernel default state depends on whether the kernel supports the 95 # BR/EDR Whitelist. When this is supported the 'connectable' setting 96 # remains unset and instead page scan is managed by the kernel based 97 # on whether or not a BR/EDR device is in the whitelist. 98 ( commands, events ) = self.device.read_supported_commands() 99 supports_add_device = bluetooth_socket.MGMT_OP_ADD_DEVICE in commands 100 101 # Read the initial state of the adapter. Verify that it is powered down. 102 ( address, bluetooth_version, manufacturer_id, 103 supported_settings, current_settings, class_of_device, 104 name, short_name ) = self.device.read_info() 105 self._log_settings('Initial state', current_settings) 106 107 if current_settings & bluetooth_socket.MGMT_SETTING_POWERED: 108 raise error.TestFail('Bluetooth adapter is powered') 109 110 # The other kernel settings (connectable, pairable, etc.) reflect the 111 # initial state before the bluetooth daemon adjusts them - we're ok 112 # with them being on or off during that brief period. 113 # 114 115 # Verify that the Bluetooth Daemon sees that it is also powered down, 116 # non-discoverable and not discovering devices. 117 bluez_properties = self.device.get_adapter_properties() 118 119 if bluez_properties['Powered']: 120 raise error.TestFail('Bluetooth daemon Powered property does not ' 121 'match kernel while powered off') 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 off') 127 if bluez_properties['Discovering']: 128 raise error.TestFail('Bluetooth daemon believes adapter is ' 129 'discovering while powered off') 130 131 # Compare with the raw HCI state of the adapter as well, this should 132 # be just not "UP", otherwise something deeply screwy is happening. 133 flags = self.device.get_dev_info()[3] 134 self._log_flags('Initial state', flags) 135 136 if flags & bluetooth_socket.HCI_UP: 137 raise error.TestFail('HCI UP flag does not match kernel while ' 138 'powered off') 139 140 # Power on the adapter, then read the state again. Verify that it is 141 # powered up, pairable, but not discoverable. 142 self.device.set_powered(True) 143 current_settings = self.device.read_info()[4] 144 self._log_settings("Powered up", current_settings) 145 146 if not current_settings & bluetooth_socket.MGMT_SETTING_POWERED: 147 raise error.TestFail('Bluetooth adapter is not powered') 148 if not current_settings & bluetooth_socket.MGMT_SETTING_PAIRABLE: 149 raise error.TestFail('Bluetooth adapter is not pairable') 150 151 # If the kernel does not supports the BR/EDR whitelist, the adapter 152 # should be generically connectable; 153 # if it doesn't, then it depends on previous settings. 154 if not supports_add_device: 155 if not current_settings & bluetooth_socket.MGMT_SETTING_CONNECTABLE: 156 raise error.TestFail('Bluetooth adapter is not connectable ' 157 'though kernel does not support ' 158 'BR/EDR whitelist') 159 160 # Verify that the Bluetooth Daemon sees the same state as the kernel 161 # and that it's not discovering. 162 bluez_properties = self.device.get_adapter_properties() 163 164 if not bluez_properties['Powered']: 165 raise error.TestFail('Bluetooth daemon Powered property does not ' 166 'match kernel while powered on') 167 if not bluez_properties['Pairable']: 168 raise error.TestFail('Bluetooth daemon Pairable property does not ' 169 'match kernel while powered on') 170 if not self.compare_property(bluez_properties['Discoverable'], 171 bluetooth_socket.MGMT_SETTING_DISCOVERABLE, 172 current_settings): 173 raise error.TestFail('Bluetooth daemon Discoverable property ' 174 'does not match kernel while powered on') 175 if bluez_properties['Discovering']: 176 raise error.TestFail('Bluetooth daemon believes adapter is ' 177 'discovering while powered on') 178 179 # Compare with the raw HCI state of the adapter while powered up as 180 # well. 181 flags = self.device.get_dev_info()[3] 182 self._log_flags('Powered up', flags) 183 184 if not flags & bluetooth_socket.HCI_UP: 185 raise error.TestFail('HCI UP flag does not match kernel while ' 186 'powered on') 187 if not flags & bluetooth_socket.HCI_RUNNING: 188 raise error.TestFail('HCI RUNNING flag does not match kernel while ' 189 'powered on') 190 if flags & bluetooth_socket.HCI_ISCAN: 191 raise error.TestFail('HCI ISCAN flag does not match kernel while ' 192 'powered on') 193 if flags & bluetooth_socket.HCI_INQUIRY: 194 raise error.TestFail('HCI INQUIRY flag does not match kernel while ' 195 'powered on') 196 197 # If the kernel does not supports the BR/EDR whitelist, the adapter 198 # should generically connectable, so should it should be in PSCAN 199 # mode. This matches the management API "connectable" setting so far. 200 if not supports_add_device: 201 if not flags & bluetooth_socket.HCI_PSCAN: 202 raise error.TestFail('HCI PSCAN flag not set though kernel' 203 'does not supports BR/EDR whitelist') 204 205 # Now we can examine the differences. Try adding and removing a device 206 # from the kernel BR/EDR whitelist. The management API "connectable" 207 # setting should remain off, but we should be able to see the PSCAN 208 # flag come and go. 209 if supports_add_device: 210 # If PSCAN is currently on then device is CONNECTABLE 211 # or a previous add device which was not removed. 212 # Turn on and off DISCOVERABLE to turn off CONNECTABLE and 213 # PSCAN 214 if flags & bluetooth_socket.HCI_PSCAN: 215 if not (current_settings & 216 bluetooth_socket.MGMT_SETTING_CONNECTABLE): 217 raise error.TestFail('PSCAN on but device not CONNECTABLE') 218 logging.debug('Toggle Discoverable to turn off CONNECTABLE') 219 self.device.set_discoverable(True) 220 self.device.set_discoverable(False) 221 current_settings = self.device.read_info()[4] 222 flags = self.device.get_dev_info()[3] 223 self._log_flags('Discoverability Toggled', flags) 224 if flags & bluetooth_socket.HCI_PSCAN: 225 raise error.TestFail('PSCAN on after toggling DISCOVERABLE') 226 227 previous_settings = current_settings 228 previous_flags = flags 229 230 self.device.add_device(DEVICE_ADDRESS, ADDRESS_TYPE, 1) 231 232 current_settings = self.device.read_info()[4] 233 self._log_settings("After add device", current_settings) 234 235 flags = self.device.get_dev_info()[3] 236 self._log_flags('After add device', flags) 237 238 if current_settings != previous_settings: 239 self._log_settings("previous settings", previous_settings) 240 self._log_settings("current settings", current_settings) 241 raise error.TestFail( 242 'Bluetooth adapter settings changed after add device') 243 if not flags & bluetooth_socket.HCI_PSCAN: 244 raise error.TestFail('HCI PSCAN flag not set after add device') 245 246 # Remove the device again, and make sure the PSCAN flag goes away. 247 self.device.remove_device(DEVICE_ADDRESS, ADDRESS_TYPE) 248 249 current_settings = self.device.read_info()[4] 250 self._log_settings("After remove device", current_settings) 251 252 flags = self.device.get_dev_info()[3] 253 self._log_flags('After remove device', flags) 254 255 if current_settings != previous_settings: 256 raise error.TestFail( 257 'Bluetooth adapter settings changed after remove device') 258 if flags & bluetooth_socket.HCI_PSCAN: 259 raise error.TestFail('HCI PSCAN flag set after remove device') 260 261 # Finally power off the adapter again, and verify that the adapter has 262 # returned to powered down. 263 self.device.set_powered(False) 264 current_settings = self.device.read_info()[4] 265 self._log_settings("After power down", current_settings) 266 267 if current_settings & bluetooth_socket.MGMT_SETTING_POWERED: 268 raise error.TestFail('Bluetooth adapter is powered after power off') 269 270 # Verify that the Bluetooth Daemon sees the same state as the kernel. 271 bluez_properties = self.device.get_adapter_properties() 272 273 if bluez_properties['Powered']: 274 raise error.TestFail('Bluetooth daemon Powered property does not ' 275 'match kernel after power off') 276 if not self.compare_property(bluez_properties['Discoverable'], 277 bluetooth_socket.MGMT_SETTING_DISCOVERABLE, 278 current_settings): 279 raise error.TestFail('Bluetooth daemon Discoverable property ' 280 'does not match kernel after off') 281 if bluez_properties['Discovering']: 282 raise error.TestFail('Bluetooth daemon believes adapter is ' 283 'discovering after power off') 284 285 # And one last comparison with the raw HCI state of the adapter. 286 flags = self.device.get_dev_info()[3] 287 self._log_flags('After power down', flags) 288 289 if flags & bluetooth_socket.HCI_UP: 290 raise error.TestFail('HCI UP flag does not match kernel after ' 291 'power off') 292