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