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