• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_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 device['Alias'] not in self.name_list:
46                        raise error.TestFail(
47                                'Tester "%s" is not one of the expected names '
48                                '"%s"' % (device['Alias'], str(self.name_list)))
49                    # Found the device
50                    device_found = True
51                    # Write out the RSSI now we've found it.
52                    self.write_perf_keyval({'rssi': int(device.get('RSSI', 0))})
53                    self.output_perf_value('rssi', int(device.get('RSSI', 0)),
54                                           'dBm')
55
56            if self.interactive:
57                item_name = device['Address'].replace(':', '')
58                html = '%s %s' % (cgi.escape(device['Address']),
59                                  cgi.escape(device['Alias']))
60
61                if device['Address'] in self.devices_discovered:
62                    self.interactive.replace_list_item(item_name, html)
63                else:
64                    self.interactive.append_list_item('devices', item_name,
65                                                      html)
66                    self.devices_discovered.append(device['Address'])
67
68                result = self.interactive.check_for_button()
69                if result == 0:
70                    device_found = True
71                elif result != -1:
72                    raise error.TestFail('User indicated test failed')
73
74        return device_found
75
76
77    def run_once(self):
78        """Running BLE test to discover a remote advertising device."""
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            self.name_list = [name, short_name]
97
98        if self.interactive:
99            self.interactive.login()
100
101            if self.tester:
102                self.interactive.append_output(
103                        '<p>The Tester is advertising as an LE peripheral. '
104                        '<p>The DUT is in the observer/discovery state. '
105                        '<p>Please verify that you can discover the tester ' +
106                        ('<b>%s</b> with address <b>%s</b> from the device.' %
107                         (cgi.escape(self.name),
108                          cgi.escape(self.address))))
109            else:
110                self.interactive.append_output(
111                        '<p>The DUT is in the observer/discovery state. '
112                        '<p>Please verify that you can discover the device.')
113
114            self.interactive.append_output('<h2>Devices Found</h2>')
115            self.interactive.append_list('devices')
116            self.devices_discovered = []
117
118            if self.tester:
119                self.interactive.append_buttons('Tester Found',
120                                                'Tester Not Found')
121            else:
122                self.interactive.append_buttons('Device Found',
123                                                'Device Not Found')
124
125        # Discover devices from the DUT.
126        for failed_attempts in range(0, 5):
127            if not self.device.start_discovery():
128                raise error.TestFail('Could not start discovery on DUT')
129            try:
130                utils.poll_for_condition(
131                        condition=self.find_device,
132                        desc='Device discovered from DUT',
133                        timeout=self.DISCOVERABLE_TIMEOUT)
134                # We only reach this if we find a device. Break out of the
135                # failed_attempts loop to bypass the "reached the end"
136                # condition.
137                break
138            except utils.TimeoutError:
139                # Capture the timeout error and try once more through the
140                # loop.
141                pass
142            finally:
143                if not self.device.stop_discovery():
144                    logging.warning('Failed to stop discovery on DUT')
145        else:
146            # We only reach this if we tried five times to find the device and
147            # failed.
148            raise error.TestFail('DUT could not discover device')
149        # Record how many attempts this took, hopefully we'll one day figure
150        # out a way to reduce this to zero and then the loop above can go
151        # away.
152        self.write_perf_keyval({'failed_attempts': failed_attempts })
153        self.output_perf_value('failed_attempts', failed_attempts, 'attempts')
154
155
156    def cleanup(self):
157        """Set the tester back to not advertising."""
158        if self.tester:
159            self.tester.set_advertising(False)
160            self.tester.set_discoverable(False)
161
162        super(bluetooth_Sanity_LEDiscovery, self).cleanup()
163