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.common_lib import error
9from autotest_lib.client.common_lib.cros.bluetooth import bluetooth_socket
10from autotest_lib.server.cros.bluetooth import bluetooth_test
11
12
13class bluetooth_Sanity_Discoverable(bluetooth_test.BluetoothTest):
14    """
15    Verify that the client is discoverable from the tester.
16    """
17    version = 1
18
19
20    def discover_device(self):
21        """Discover the Bluetooth Device using the Tester.
22
23        @return True if found with expected name, False if not found,
24          Exception if found device did not have expected name.
25
26        """
27        devices = self.tester.discover_devices()
28        if devices == False:
29            raise error.TestFail('Tester could not discover devices')
30
31        # Iterate the devices we received in the discovery phase and
32        # look for the DUT.
33        for address, address_type, rssi, flags, eirdata in devices:
34            if address == self.adapter['Address']:
35                logging.info('Found device with RSSI %d', rssi)
36                found_device = True
37
38                # Make sure we picked up a name for the device along
39                # the way.
40                eir = bluetooth_socket.parse_eir(eirdata)
41                try:
42                    eir_name = eir[bluetooth_socket.EIR_NAME_COMPLETE]
43                    if eir_name != self.adapter['Alias']:
44                        raise error.TestFail(
45                                'Device did not have expected name ' +
46                                '"%s" != "%s"' %
47                                (eir_name, self.adapter['Alias']))
48
49                    # Write out the RSSI now we've found it.
50                    self.write_perf_keyval({'rssi': int(rssi)})
51                    self.output_perf_value('rssi', int(rssi), 'dBm')
52                    return True
53                except KeyError:
54                    logging.warning('Device did not have a name')
55        else:
56            logging.warning('Failed to find device')
57
58        return False
59
60    def run_once(self):
61        # Reset the adapter to the powered on, discoverable state.
62        if not (self.device.reset_on() and
63                self.device.set_discoverable(True)):
64            raise error.TestFail('DUT could not be reset to initial state')
65
66        self.adapter = self.device.get_adapter_properties()
67
68        if self.interactive:
69            self.interactive.login()
70            self.interactive.append_output(
71                    '<p>The DUT is in the discoverable state. '
72                    '<p>Please verify that you can discover the device ' +
73                    ('<b>%s</b> with address <b>%s</b> from the tester.' %
74                     (cgi.escape(self.adapter['Alias']),
75                      cgi.escape(self.adapter['Address']))))
76
77        if self.tester:
78            # Setup the tester as a generic computer.
79            if not self.tester.setup('computer'):
80                raise error.TestFail('Tester could not be initialized')
81
82            # Since radio is involved, this test is not 100% reliable; instead
83            # we repeat a few times until it succeeds.
84            for failed_attempts in range(0, 5):
85                if self.discover_device():
86                    break
87            else:
88                raise error.TestFail('Expected device was not found')
89
90            # Record how many attempts this took, hopefully we'll one day figure
91            # out a way to reduce this to zero and then the loop above can go
92            # away.
93            self.write_perf_keyval({'failed_attempts': failed_attempts })
94            self.output_perf_value('failed_attempts', failed_attempts,
95                                   'attempts')
96
97        if self.interactive:
98            self.interactive.append_buttons('Device Found', 'Device Not Found')
99            result = self.interactive.wait_for_button(timeout=600)
100            if result != 0:
101                raise error.TestFail('User indicated test failed')
102