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 5import cgi 6import logging 7 8from autotest_lib.client.bin import utils 9from autotest_lib.client.common_lib import error 10from autotest_lib.server.cros.bluetooth import bluetooth_test 11 12 13class bluetooth_Sanity_Discovery(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 computer. 85 if not self.tester.setup('computer'): 86 raise error.TestFail('Tester could not be initialized') 87 # Make the tester discoverable 88 self.tester.set_discoverable(True, self.DISCOVERABLE_TIMEOUT) 89 # Read the tester information so we know what we're looking for. 90 ( address, bluetooth_version, manufacturer_id, 91 supported_settings, current_settings, class_of_device, 92 name, short_name ) = self.tester.read_info() 93 self.address = address 94 self.name = name 95 96 if self.interactive: 97 self.interactive.login() 98 99 if self.tester: 100 self.interactive.append_output( 101 '<p>The Tester is in the discoverable state. ' 102 '<p>The DUT is in the page scan/discovery state. ' 103 '<p>Please verify that you can discover the tester ' + 104 ('<b>%s</b> with address <b>%s</b> from the device.' % 105 (cgi.escape(self.name), 106 cgi.escape(self.address)))) 107 else: 108 self.interactive.append_output( 109 '<p>The DUT is in the page scan/discovery state. ' 110 '<p>Please verify that you can discover the device.') 111 112 self.interactive.append_output('<h2>Devices Found</h2>') 113 self.interactive.append_list('devices') 114 self.devices_discovered = [] 115 116 if self.tester: 117 self.interactive.append_buttons('Tester Found', 118 'Tester Not Found') 119 else: 120 self.interactive.append_buttons('Device Found', 121 'Device Not Found') 122 123 # Discover devices from the DUT. 124 for failed_attempts in range(0, 5): 125 if not self.device.start_discovery(): 126 raise error.TestFail('Could not start discovery on DUT') 127 try: 128 utils.poll_for_condition( 129 condition=self.find_device, 130 desc='Device discovered from DUT', 131 timeout=self.DISCOVERABLE_TIMEOUT) 132 # We only reach this if we find a device. Break out of the 133 # failed_attempts loop to bypass the "reached the end" 134 # condition. 135 break 136 except utils.TimeoutError: 137 # Capture the timeout error and try once more through the 138 # loop. 139 pass 140 finally: 141 if not self.device.stop_discovery(): 142 logging.warning('Failed to stop discovery on DUT') 143 else: 144 # We only reach this if we tried five times to find the device and 145 # failed. 146 raise error.TestFail('DUT could not discover device') 147 # Record how many attempts this took, hopefully we'll one day figure 148 # out a way to reduce this to zero and then the loop above can go 149 # away. 150 self.write_perf_keyval({'failed_attempts': failed_attempts }) 151 self.output_perf_value('failed_attempts', failed_attempts, 'attempts') 152 153 154 def cleanup(self): 155 """Set the tester back to undiscoverable.""" 156 if self.tester: 157 self.tester.set_discoverable(False) 158 159 super(bluetooth_Sanity_Discovery, self).cleanup() 160