Home | History | Annotate | Download | only in bluetooth_Sanity_LEDiscovery
      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 cgi
      6 import logging
      7 
      8 from autotest_lib.client.bin import utils
      9 from autotest_lib.client.common_lib import error
     10 from autotest_lib.server.cros.bluetooth import bluetooth_test
     11 
     12 
     13 class bluetooth_Sanity_LEDiscovery(bluetooth_test.BluetoothTest):
     14     """
     15     Verify that the client can discover the tester.
     16     """
     17     version = 1
     18 
     19     # How long should the tester remain discoverable?
     20     DISCOVERABLE_TIMEOUT=180
     21 
     22     def find_device(self):
     23         """Retrieve devices from client and look for tester.
     24 
     25         @return True if device has been found, False otherwise.
     26 
     27         """
     28         # Get the set of devices known to the DUT.
     29         devices = self.device.get_devices()
     30         if devices == False:
     31             raise error.TestFail('Could not retrieve devices from DUT')
     32 
     33         device_found = False
     34         for device in devices:
     35             if self.tester:
     36                 if self.address == device['Address']:
     37                     logging.info('Found tester with RSSI %d',
     38                                  device.get('RSSI'))
     39                     # Check name as well; if the name and alias fields don't
     40                     # match, that means it hasn't been requested yet, so
     41                     # wait until next time.
     42                     if device.get('Name') != device['Alias']:
     43                         logging.info('Device name not yet received')
     44                         continue
     45                     if self.name != device['Alias']:
     46                         raise error.TestFail(
     47                                 'Tester did not have expected name ' +
     48                                 '"%s" != "%s"' % (device['Alias'],
     49                                                   self.name))
     50                     # Found the device
     51                     device_found = True
     52                     # Write out the RSSI now we've found it.
     53                     self.write_perf_keyval({'rssi': int(device.get('RSSI', 0))})
     54                     self.output_perf_value('rssi', int(device.get('RSSI', 0)),
     55                                            'dBm')
     56 
     57             if self.interactive:
     58                 item_name = device['Address'].replace(':', '')
     59                 html = '%s %s' % (cgi.escape(device['Address']),
     60                                   cgi.escape(device['Alias']))
     61 
     62                 if device['Address'] in self.devices_discovered:
     63                     self.interactive.replace_list_item(item_name, html)
     64                 else:
     65                     self.interactive.append_list_item('devices', item_name,
     66                                                       html)
     67                     self.devices_discovered.append(device['Address'])
     68 
     69                 result = self.interactive.check_for_button()
     70                 if result == 0:
     71                     device_found = True
     72                 elif result != -1:
     73                     raise error.TestFail('User indicated test failed')
     74 
     75         return device_found
     76 
     77 
     78     def run_once(self):
     79         # Reset the adapter to the powered on state.
     80         if not self.device.reset_on():
     81             raise error.TestFail('DUT could not be reset to initial state')
     82 
     83         if self.tester:
     84             # Setup the tester as a generic LE peripheral.
     85             if not self.tester.setup('peripheral'):
     86                 raise error.TestFail('Tester could not be initialized')
     87             # Enable general discoverable advertising on the tester
     88             self.tester.set_discoverable(True)
     89             self.tester.set_advertising(True)
     90             # Read the tester information so we know what we're looking for.
     91             ( address, bluetooth_version, manufacturer_id,
     92               supported_settings, current_settings, class_of_device,
     93               name, short_name ) = self.tester.read_info()
     94             self.address = address
     95             self.name = name
     96 
     97         if self.interactive:
     98             self.interactive.login()
     99 
    100             if self.tester:
    101                 self.interactive.append_output(
    102                         '<p>The Tester is advertising as an LE peripheral. '
    103                         '<p>The DUT is in the observer/discovery state. '
    104                         '<p>Please verify that you can discover the tester ' +
    105                         ('<b>%s</b> with address <b>%s</b> from the device.' %
    106                          (cgi.escape(self.name),
    107                           cgi.escape(self.address))))
    108             else:
    109                 self.interactive.append_output(
    110                         '<p>The DUT is in the observer/discovery state. '
    111                         '<p>Please verify that you can discover the device.')
    112 
    113             self.interactive.append_output('<h2>Devices Found</h2>')
    114             self.interactive.append_list('devices')
    115             self.devices_discovered = []
    116 
    117             if self.tester:
    118                 self.interactive.append_buttons('Tester Found',
    119                                                 'Tester Not Found')
    120             else:
    121                 self.interactive.append_buttons('Device Found',
    122                                                 'Device Not Found')
    123 
    124         # Discover devices from the DUT.
    125         for failed_attempts in range(0, 5):
    126             if not self.device.start_discovery():
    127                 raise error.TestFail('Could not start discovery on DUT')
    128             try:
    129                 utils.poll_for_condition(
    130                         condition=self.find_device,
    131                         desc='Device discovered from DUT',
    132                         timeout=self.DISCOVERABLE_TIMEOUT)
    133                 # We only reach this if we find a device. Break out of the
    134                 # failed_attempts loop to bypass the "reached the end"
    135                 # condition.
    136                 break
    137             except utils.TimeoutError:
    138                 # Capture the timeout error and try once more through the
    139                 # loop.
    140                 pass
    141             finally:
    142                 if not self.device.stop_discovery():
    143                     logging.warning('Failed to stop discovery on DUT')
    144         else:
    145             # We only reach this if we tried five times to find the device and
    146             # failed.
    147             raise error.TestFail('DUT could not discover device')
    148         # Record how many attempts this took, hopefully we'll one day figure
    149         # out a way to reduce this to zero and then the loop above can go
    150         # away.
    151         self.write_perf_keyval({'failed_attempts': failed_attempts })
    152         self.output_perf_value('failed_attempts', failed_attempts, 'attempts')
    153 
    154 
    155     def cleanup(self):
    156         """Set the tester back to not advertising."""
    157         if self.tester:
    158             self.tester.set_advertising(False)
    159             self.tester.set_discoverable(False)
    160 
    161         super(bluetooth_Sanity_LEDiscovery, self).cleanup()
    162