blob: d5adbcc1ccff488fbd45e76e858d20b7945159ae [file] [log] [blame]
Scott James Remnant4dcd73f2013-07-22 15:00:24 -07001# 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
Scott James Remnantda9f43c2013-08-07 17:53:14 -07005import base64
6import json
7
Scott James Remnant4dcd73f2013-07-22 15:00:24 -07008from autotest_lib.client.cros import constants
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -07009from autotest_lib.server import autotest, hosts
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070010
11
12class BluetoothTester(object):
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070013 """BluetoothTester is a thin layer of logic over a remote tester.
14
15 The Autotest host object representing the remote tester, passed to this
16 class on initialization, can be accessed from its host property.
17
18 """
19
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070020
21 XMLRPC_BRINGUP_TIMEOUT_SECONDS = 60
22
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070023 def __init__(self, tester_host):
24 """Construct a BluetoothTester.
25
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070026 @param tester_host: host object representing a remote host.
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070027
28 """
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070029 self.host = tester_host
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070030 # Make sure the client library is on the device so that the proxy code
31 # is there when we try to call it.
32 client_at = autotest.Autotest(self.host)
33 client_at.install()
34 # Start up the XML-RPC proxy on the tester.
35 self._proxy = self.host.xmlrpc_connect(
36 constants.BLUETOOTH_TESTER_XMLRPC_SERVER_COMMAND,
37 constants.BLUETOOTH_TESTER_XMLRPC_SERVER_PORT,
38 command_name=
39 constants.BLUETOOTH_TESTER_XMLRPC_SERVER_CLEANUP_PATTERN,
40 ready_test_name=
41 constants.BLUETOOTH_TESTER_XMLRPC_SERVER_READY_METHOD,
42 timeout_seconds=self.XMLRPC_BRINGUP_TIMEOUT_SECONDS)
43
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070044
Scott James Remnantda9f43c2013-08-07 17:53:14 -070045 def setup(self, profile):
46 """Set up the tester with the given profile.
47
48 @param profile: Profile to use for this test, valid values are:
49 computer - a standard computer profile
50
51 @return True on success, False otherwise.
52
53 """
54 return self._proxy.setup(profile)
55
56
Scott James Remnantaec4edd2013-08-26 18:47:11 -070057 def set_discoverable(self, discoverable, timeout=0):
58 """Set the discoverable state of the controller.
59
60 @param discoverable: Whether controller should be discoverable.
61 @param timeout: Timeout in seconds before disabling discovery again,
62 ignored when discoverable is False, must not be zero when
63 discoverable is True.
64
65 @return True on success, False otherwise.
66
67 """
68 return self._proxy.set_discoverable(discoverable, timeout)
69
70
71 def read_info(self):
72 """Read the adapter information from the Kernel.
73
74 @return the information as a JSON-encoded tuple of:
75 ( address, bluetooth_version, manufacturer_id,
76 supported_settings, current_settings, class_of_device,
77 name, short_name )
78
79 """
80 return json.loads(self._proxy.read_info())
81
82
Scott James Remnantda9f43c2013-08-07 17:53:14 -070083 def discover_devices(self, br_edr=True, le_public=True, le_random=True):
84 """Discover remote devices.
85
86 Activates device discovery and collects the set of devices found,
87 returning them as a list.
88
89 @param br_edr: Whether to detect BR/EDR devices.
90 @param le_public: Whether to detect LE Public Address devices.
91 @param le_random: Whether to detect LE Random Address devices.
92
93 @return List of devices found as tuples with the format
94 (address, address_type, rssi, flags, base64-encoded eirdata),
95 or False if discovery could not be started.
96
97 """
98 devices = self._proxy.discover_devices(br_edr, le_public, le_random)
99 if devices == False:
100 return False
101
102 return (
103 (address, address_type, rssi, flags,
104 base64.decodestring(eirdata))
105 for address, address_type, rssi, flags, eirdata
106 in json.loads(devices)
107 )
108
109
Scott James Remnant4dcd73f2013-07-22 15:00:24 -0700110 def close(self):
111 """Tear down state associated with the client."""
112 # This kills the RPC server.
Scott James Remnant1c72d7a2013-07-29 15:00:04 -0700113 self.host.close()
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700114
115
Artem Rakhov448d52c2013-12-03 16:38:36 -0800116 def connect(self, address):
117 """Connect to device with the given address
118
119 @param address: Bluetooth address.
120
121 """
122 self._proxy.connect(address)
123
124
125 def service_search_request(self, uuids, max_rec_cnt):
126 """Send a Service Search Request
127
128 @param uuids: List of UUIDs (in 32-bit format) to look for.
129 @param max_rec_cnt: Maximum count of returned service records.
130
131 @return list of found services' service record handles
132
133 """
134 return self._proxy.service_search_request(uuids, max_rec_cnt)
135
136
Scott James Remnant8d2cbf32013-11-12 11:00:25 -0800137def create_host_from(device_host):
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700138 """Creates a host object for the Tester associated with a DUT.
139
140 Will raise an exception if there isn't a tester for the DUT.
141
Scott James Remnant8d2cbf32013-11-12 11:00:25 -0800142 @param device_host: Autotest host object for the DUT.
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700143
144 @return Autotest host object for the Tester.
145
146 """
147
Scott James Remnant8d2cbf32013-11-12 11:00:25 -0800148 device_hostname = device_host.hostname
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700149
Scott James Remnant8d2cbf32013-11-12 11:00:25 -0800150 parts = device_hostname.split('.')
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700151 parts[0] = parts[0] + '-bluetooth'
152 tester_hostname = '.'.join(parts)
153
154 return hosts.create_host(tester_hostname)