Home | History | Annotate | Download | only in bluetooth_Sanity_DefaultState
      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