blob: 033b9d2fcf103776923e4ea143b1b56f6748fed3 [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 Remnant1ca2e0e2013-07-31 16:49:07 -07005import json
Scott James Remnant4dcd73f2013-07-22 15:00:24 -07006
Hsinyu Chaoe0b08e62015-08-11 10:50:37 +00007from autotest_lib.client.cros import constants
Scott James Remnant4dcd73f2013-07-22 15:00:24 -07008from autotest_lib.server import autotest
9
10
Scott James Remnant8d2cbf32013-11-12 11:00:25 -080011class BluetoothDevice(object):
12 """BluetoothDevice is a thin layer of logic over a remote DUT.
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070013
14 The Autotest host object representing the remote DUT, passed to this
15 class on initialization, can be accessed from its host property.
16
17 """
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070018
19 XMLRPC_BRINGUP_TIMEOUT_SECONDS = 60
Katherine Threlkeld88aa1432015-07-30 11:44:35 -070020 XMLRPC_LOG_PATH = '/var/log/bluetooth_xmlrpc_device.log'
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070021
Scott James Remnant8d2cbf32013-11-12 11:00:25 -080022 def __init__(self, device_host):
23 """Construct a BluetoothDevice.
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070024
Scott James Remnant8d2cbf32013-11-12 11:00:25 -080025 @param device_host: host object representing a remote host.
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070026
27 """
Scott James Remnant8d2cbf32013-11-12 11:00:25 -080028 self.host = device_host
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070029 # Make sure the client library is on the device so that the proxy code
30 # is there when we try to call it.
31 client_at = autotest.Autotest(self.host)
32 client_at.install()
33 # Start up the XML-RPC proxy on the client.
34 self._proxy = self.host.xmlrpc_connect(
Scott James Remnant8d2cbf32013-11-12 11:00:25 -080035 constants.BLUETOOTH_DEVICE_XMLRPC_SERVER_COMMAND,
36 constants.BLUETOOTH_DEVICE_XMLRPC_SERVER_PORT,
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070037 command_name=
Scott James Remnant8d2cbf32013-11-12 11:00:25 -080038 constants.BLUETOOTH_DEVICE_XMLRPC_SERVER_CLEANUP_PATTERN,
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070039 ready_test_name=
Scott James Remnant8d2cbf32013-11-12 11:00:25 -080040 constants.BLUETOOTH_DEVICE_XMLRPC_SERVER_READY_METHOD,
Katherine Threlkeld88aa1432015-07-30 11:44:35 -070041 timeout_seconds=self.XMLRPC_BRINGUP_TIMEOUT_SECONDS,
42 logfile=self.XMLRPC_LOG_PATH)
Scott James Remnant4dcd73f2013-07-22 15:00:24 -070043
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070044
Scott James Remnanta6442f52013-07-24 15:04:55 -070045 def reset_on(self):
46 """Reset the adapter and settings and power up the adapter.
47
48 @return True on success, False otherwise.
49
50 """
51 return self._proxy.reset_on()
52
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070053
Scott James Remnanta6442f52013-07-24 15:04:55 -070054 def reset_off(self):
55 """Reset the adapter and settings, leave the adapter powered off.
56
57 @return True on success, False otherwise.
58
59 """
60 return self._proxy.reset_off()
61
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070062
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -070063 def has_adapter(self):
64 """@return True if an adapter is present, False if not."""
65 return self._proxy.has_adapter()
66
67
Scott James Remnanta6442f52013-07-24 15:04:55 -070068 def set_powered(self, powered):
69 """Set the adapter power state.
70
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070071 @param powered: adapter power state to set (True or False).
Scott James Remnanta6442f52013-07-24 15:04:55 -070072
73 @return True on success, False otherwise.
74
75 """
76 return self._proxy.set_powered(powered)
77
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070078
Scott James Remnanta6442f52013-07-24 15:04:55 -070079 def set_discoverable(self, discoverable):
80 """Set the adapter discoverable state.
81
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070082 @param discoverable: adapter discoverable state to set (True or False).
Scott James Remnanta6442f52013-07-24 15:04:55 -070083
84 @return True on success, False otherwise.
85
86 """
87 return self._proxy.set_discoverable(discoverable)
88
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070089
Scott James Remnanta6442f52013-07-24 15:04:55 -070090 def set_pairable(self, pairable):
91 """Set the adapter pairable state.
92
Scott James Remnant1c72d7a2013-07-29 15:00:04 -070093 @param pairable: adapter pairable state to set (True or False).
Scott James Remnanta6442f52013-07-24 15:04:55 -070094
95 @return True on success, False otherwise.
96
97 """
98 return self._proxy.set_pairable(pairable)
99
Scott James Remnant1c72d7a2013-07-29 15:00:04 -0700100
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700101 def get_adapter_properties(self):
102 """Read the adapter properties from the Bluetooth Daemon.
103
Scott James Remnantaec4edd2013-08-26 18:47:11 -0700104 @return the properties as a dictionary on success,
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700105 the value False otherwise.
106
107 """
108 return json.loads(self._proxy.get_adapter_properties())
109
110
Scott James Remnant50915ad2014-12-01 13:51:39 -0800111 def read_version(self):
112 """Read the version of the management interface from the Kernel.
113
Scott James Remnante59d5b92014-12-01 14:21:47 -0800114 @return the version as a tuple of:
Scott James Remnant50915ad2014-12-01 13:51:39 -0800115 ( version, revision )
116
117 """
118 return json.loads(self._proxy.read_version())
119
120
121 def read_supported_commands(self):
122 """Read the set of supported commands from the Kernel.
123
Scott James Remnante59d5b92014-12-01 14:21:47 -0800124 @return set of supported commands as arrays in a tuple of:
Scott James Remnant50915ad2014-12-01 13:51:39 -0800125 ( commands, events )
126
127 """
128 return json.loads(self._proxy.read_supported_commands())
129
130
131 def read_index_list(self):
132 """Read the list of currently known controllers from the Kernel.
133
Scott James Remnante59d5b92014-12-01 14:21:47 -0800134 @return array of controller indexes.
Scott James Remnant50915ad2014-12-01 13:51:39 -0800135
136 """
137 return json.loads(self._proxy.read_index_list())
138
139
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700140 def read_info(self):
141 """Read the adapter information from the Kernel.
142
Scott James Remnantaec4edd2013-08-26 18:47:11 -0700143 @return the information as a tuple of:
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700144 ( address, bluetooth_version, manufacturer_id,
145 supported_settings, current_settings, class_of_device,
146 name, short_name )
147
148 """
149 return json.loads(self._proxy.read_info())
150
151
Scott James Remnantabea37c2014-12-01 14:22:23 -0800152 def add_device(self, address, address_type, action):
153 """Add a device to the Kernel action list.
154
155 @param address: Address of the device to add.
156 @param address_type: Type of device in @address.
157 @param action: Action to take.
158
159 @return tuple of ( address, address_type ) on success,
160 None on failure.
161
162 """
163 return json.loads(self._proxy.add_device(address, address_type, action))
164
165
166 def remove_device(self, address, address_type):
167 """Remove a device from the Kernel action list.
168
169 @param address: Address of the device to remove.
170 @param address_type: Type of device in @address.
171
172 @return tuple of ( address, address_type ) on success,
173 None on failure.
174
175 """
176 return json.loads(self._proxy.remove_device(address, address_type))
177
178
Scott James Remnantaec4edd2013-08-26 18:47:11 -0700179 def get_devices(self):
180 """Read information about remote devices known to the adapter.
181
Scott James Remnante59d5b92014-12-01 14:21:47 -0800182 @return the properties of each device as an array of
Scott James Remnantaec4edd2013-08-26 18:47:11 -0700183 dictionaries on success, the value False otherwise.
184
185 """
186 return json.loads(self._proxy.get_devices())
187
188
189 def start_discovery(self):
190 """Start discovery of remote devices.
191
192 Obtain the discovered device information using get_devices(), called
193 stop_discovery() when done.
194
195 @return True on success, False otherwise.
196
197 """
198 return self._proxy.start_discovery()
199
200
201 def stop_discovery(self):
202 """Stop discovery of remote devices.
203
204 @return True on success, False otherwise.
205
206 """
207 return self._proxy.stop_discovery()
208
209
Scott James Remnantc7fd7a42014-12-01 16:43:38 -0800210 def get_dev_info(self):
211 """Read raw HCI device information.
212
213 @return tuple of (index, name, address, flags, device_type, bus_type,
214 features, pkt_type, link_policy, link_mode,
215 acl_mtu, acl_pkts, sco_mtu, sco_pkts,
216 err_rx, err_tx, cmd_tx, evt_rx, acl_tx, acl_rx,
217 sco_tx, sco_rx, byte_rx, byte_tx) on success,
218 None on failure.
219
220 """
221 return json.loads(self._proxy.get_dev_info())
222
223
Artem Rakhovb144dce2014-02-20 21:02:09 -0800224 def register_profile(self, path, uuid, options):
225 """Register new profile (service).
226
227 @param path: Path to the profile object.
228 @param uuid: Service Class ID of the service as string.
229 @param options: Dictionary of options for the new service, compliant
230 with BlueZ D-Bus Profile API standard.
231
232 @return True on success, False otherwise.
233
234 """
235 return self._proxy.register_profile(path, uuid, options)
236
237
Cheng-Yi Chiangdc6442b2015-07-08 16:07:02 +0800238 def has_device(self, address):
239 """Checks if the device with a given address exists.
240
241 @param address: Address of the device.
242
243 @returns: True if there is a device with that address.
244 False otherwise.
245
246 """
247 return self._proxy.has_device(address)
248
249
Cheng-Yi Chiang212d4692015-05-25 22:08:14 +0800250 def pair_legacy_device(self, address, pin, timeout):
251 """Pairs a device with a given pin code.
252
253 Registers an agent who handles pin code request and
254 pairs a device with known pin code.
255
256 @param address: Address of the device to pair.
257 @param pin: The pin code of the device to pair.
258 @param timeout: The timeout in seconds for pairing.
259
260 @returns: True on success. False otherwise.
261
262 """
263 return self._proxy.pair_legacy_device(address, pin, timeout)
264
265
266 def connect_device(self, address):
267 """Connects a device.
268
269 Connects a device if it is not connected.
270
271 @param address: Address of the device to connect.
272
273 @returns: True on success. False otherwise.
274
275 """
276 return self._proxy.connect_device(address)
277
278
279 def disconnect_device(self, address):
280 """Disconnects a device.
281
282 Disconnects a device if it is connected.
283
284 @param address: Address of the device to disconnect.
285
286 @returns: True on success. False otherwise.
287
288 """
289 return self._proxy.disconnect_device(address)
290
291
Katherine Threlkeld88aa1432015-07-30 11:44:35 -0700292 def copy_logs(self, destination):
293 """Copy the logs generated by this device to a given location.
294
295 @param destination: destination directory for the logs.
296
297 """
298 self.host.collect_logs(self.XMLRPC_LOG_PATH, destination)
299
300
Scott James Remnant4dcd73f2013-07-22 15:00:24 -0700301 def close(self):
302 """Tear down state associated with the client."""
Scott James Remnantda9f43c2013-08-07 17:53:14 -0700303 # Turn off the discoverable flag since it may affect future tests.
304 self._proxy.set_discoverable(False)
Scott James Remnanta6442f52013-07-24 15:04:55 -0700305 # Leave the adapter powered off, but don't do a full reset.
306 self._proxy.set_powered(False)
Scott James Remnant4dcd73f2013-07-22 15:00:24 -0700307 # This kills the RPC server.
Scott James Remnant1c72d7a2013-07-29 15:00:04 -0700308 self.host.close()