Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 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 | |
Scott James Remnant | 1ca2e0e | 2013-07-31 16:49:07 -0700 | [diff] [blame] | 5 | import json |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 6 | |
Hsinyu Chao | e0b08e6 | 2015-08-11 10:50:37 +0000 | [diff] [blame] | 7 | from autotest_lib.client.cros import constants |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 8 | from autotest_lib.server import autotest |
| 9 | |
| 10 | |
Scott James Remnant | 8d2cbf3 | 2013-11-12 11:00:25 -0800 | [diff] [blame] | 11 | class BluetoothDevice(object): |
| 12 | """BluetoothDevice is a thin layer of logic over a remote DUT. |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 13 | |
| 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 Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 18 | |
| 19 | XMLRPC_BRINGUP_TIMEOUT_SECONDS = 60 |
Katherine Threlkeld | 88aa143 | 2015-07-30 11:44:35 -0700 | [diff] [blame] | 20 | XMLRPC_LOG_PATH = '/var/log/bluetooth_xmlrpc_device.log' |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 21 | |
Scott James Remnant | 8d2cbf3 | 2013-11-12 11:00:25 -0800 | [diff] [blame] | 22 | def __init__(self, device_host): |
| 23 | """Construct a BluetoothDevice. |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 24 | |
Scott James Remnant | 8d2cbf3 | 2013-11-12 11:00:25 -0800 | [diff] [blame] | 25 | @param device_host: host object representing a remote host. |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 26 | |
| 27 | """ |
Scott James Remnant | 8d2cbf3 | 2013-11-12 11:00:25 -0800 | [diff] [blame] | 28 | self.host = device_host |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 29 | # 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. |
Roshan Pius | 58e5dd3 | 2015-10-16 15:16:42 -0700 | [diff] [blame] | 34 | self._proxy = self.host.rpc_server_tracker.xmlrpc_connect( |
Scott James Remnant | 8d2cbf3 | 2013-11-12 11:00:25 -0800 | [diff] [blame] | 35 | constants.BLUETOOTH_DEVICE_XMLRPC_SERVER_COMMAND, |
| 36 | constants.BLUETOOTH_DEVICE_XMLRPC_SERVER_PORT, |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 37 | command_name= |
Scott James Remnant | 8d2cbf3 | 2013-11-12 11:00:25 -0800 | [diff] [blame] | 38 | constants.BLUETOOTH_DEVICE_XMLRPC_SERVER_CLEANUP_PATTERN, |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 39 | ready_test_name= |
Scott James Remnant | 8d2cbf3 | 2013-11-12 11:00:25 -0800 | [diff] [blame] | 40 | constants.BLUETOOTH_DEVICE_XMLRPC_SERVER_READY_METHOD, |
Katherine Threlkeld | 88aa143 | 2015-07-30 11:44:35 -0700 | [diff] [blame] | 41 | timeout_seconds=self.XMLRPC_BRINGUP_TIMEOUT_SECONDS, |
| 42 | logfile=self.XMLRPC_LOG_PATH) |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 43 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 44 | # Get some static information about the bluetooth adapter. |
| 45 | properties = self.get_adapter_properties() |
| 46 | self.bluez_version = properties.get('Name') |
| 47 | self.address = properties.get('Address') |
| 48 | self.bluetooth_class = properties.get('Class') |
| 49 | self.UUIDs = properties.get('UUIDs') |
| 50 | |
| 51 | |
| 52 | def start_bluetoothd(self): |
| 53 | """start bluetoothd. |
| 54 | |
| 55 | @returns: True if bluetoothd is started correctly. |
| 56 | False otherwise. |
| 57 | |
| 58 | """ |
| 59 | return self._proxy.start_bluetoothd() |
| 60 | |
| 61 | |
| 62 | def stop_bluetoothd(self): |
| 63 | """stop bluetoothd. |
| 64 | |
| 65 | @returns: True if bluetoothd is stopped correctly. |
| 66 | False otherwise. |
| 67 | |
| 68 | """ |
| 69 | return self._proxy.stop_bluetoothd() |
| 70 | |
| 71 | |
| 72 | def is_bluetoothd_running(self): |
| 73 | """Is bluetoothd running? |
| 74 | |
| 75 | @returns: True if bluetoothd is running |
| 76 | |
| 77 | """ |
| 78 | return self._proxy.is_bluetoothd_running() |
| 79 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 80 | |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 81 | def reset_on(self): |
| 82 | """Reset the adapter and settings and power up the adapter. |
| 83 | |
| 84 | @return True on success, False otherwise. |
| 85 | |
| 86 | """ |
| 87 | return self._proxy.reset_on() |
| 88 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 89 | |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 90 | def reset_off(self): |
| 91 | """Reset the adapter and settings, leave the adapter powered off. |
| 92 | |
| 93 | @return True on success, False otherwise. |
| 94 | |
| 95 | """ |
| 96 | return self._proxy.reset_off() |
| 97 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 98 | |
Scott James Remnant | 1ca2e0e | 2013-07-31 16:49:07 -0700 | [diff] [blame] | 99 | def has_adapter(self): |
| 100 | """@return True if an adapter is present, False if not.""" |
| 101 | return self._proxy.has_adapter() |
| 102 | |
| 103 | |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 104 | def set_powered(self, powered): |
| 105 | """Set the adapter power state. |
| 106 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 107 | @param powered: adapter power state to set (True or False). |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 108 | |
| 109 | @return True on success, False otherwise. |
| 110 | |
| 111 | """ |
| 112 | return self._proxy.set_powered(powered) |
| 113 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 114 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 115 | def is_powered_on(self): |
| 116 | """Is the adapter powered on? |
| 117 | |
| 118 | @returns: True if the adapter is powered on |
| 119 | |
| 120 | """ |
| 121 | properties = self.get_adapter_properties() |
| 122 | return bool(properties.get(u'Powered')) |
| 123 | |
| 124 | |
| 125 | def get_hci(self): |
| 126 | """Get hci of the adapter; normally, it is 'hci0'. |
| 127 | |
| 128 | @returns: the hci name of the adapter. |
| 129 | |
| 130 | """ |
| 131 | dev_info = self.get_dev_info() |
| 132 | hci = (dev_info[1] if isinstance(dev_info, list) and |
| 133 | len(dev_info) > 1 else None) |
| 134 | return hci |
| 135 | |
| 136 | |
| 137 | def get_address(self): |
| 138 | """Get the bluetooth address of the adapter. |
| 139 | |
| 140 | An example of the bluetooth address of the adapter: '6C:29:95:1A:D4:6F' |
| 141 | |
| 142 | @returns: the bluetooth address of the adapter. |
| 143 | |
| 144 | """ |
| 145 | return self.address |
| 146 | |
| 147 | |
| 148 | def get_bluez_version(self): |
| 149 | """Get bluez version. |
| 150 | |
| 151 | An exmaple of bluez version: 'BlueZ 5.39' |
| 152 | |
| 153 | @returns: the bluez version |
| 154 | |
| 155 | """ |
| 156 | return self.bluez_version |
| 157 | |
| 158 | |
| 159 | def get_bluetooth_class(self): |
| 160 | """Get the bluetooth class of the adapter. |
| 161 | |
| 162 | An example of the bluetooth class of a chromebook: 4718852 |
| 163 | |
| 164 | @returns: the bluetooth class. |
| 165 | |
| 166 | """ |
| 167 | return self.bluetooth_class |
| 168 | |
| 169 | |
| 170 | def get_UUIDs(self): |
| 171 | """Get the UUIDs. |
| 172 | |
| 173 | An example of UUIDs: |
| 174 | [u'00001112-0000-1000-8000-00805f9b34fb', |
| 175 | u'00001801-0000-1000-8000-00805f9b34fb', |
| 176 | u'0000110a-0000-1000-8000-00805f9b34fb', |
| 177 | u'0000111f-0000-1000-8000-00805f9b34fb', |
| 178 | u'00001200-0000-1000-8000-00805f9b34fb', |
| 179 | u'00001800-0000-1000-8000-00805f9b34fb'] |
| 180 | |
| 181 | @returns: the list of the UUIDs. |
| 182 | |
| 183 | """ |
| 184 | return self.UUIDs |
| 185 | |
| 186 | |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 187 | def set_discoverable(self, discoverable): |
| 188 | """Set the adapter discoverable state. |
| 189 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 190 | @param discoverable: adapter discoverable state to set (True or False). |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 191 | |
| 192 | @return True on success, False otherwise. |
| 193 | |
| 194 | """ |
| 195 | return self._proxy.set_discoverable(discoverable) |
| 196 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 197 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 198 | def is_discoverable(self): |
| 199 | """Is the adapter in the discoverable state? |
| 200 | |
| 201 | @return True if discoverable. False otherwise. |
| 202 | |
| 203 | """ |
| 204 | properties = self.get_adapter_properties() |
| 205 | return properties.get('Discoverable') == 1 |
| 206 | |
| 207 | |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 208 | def set_pairable(self, pairable): |
| 209 | """Set the adapter pairable state. |
| 210 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 211 | @param pairable: adapter pairable state to set (True or False). |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 212 | |
| 213 | @return True on success, False otherwise. |
| 214 | |
| 215 | """ |
| 216 | return self._proxy.set_pairable(pairable) |
| 217 | |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 218 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 219 | def is_pairable(self): |
| 220 | """Is the adapter in the pairable state? |
| 221 | |
| 222 | @return True if pairable. False otherwise. |
| 223 | |
| 224 | """ |
| 225 | properties = self.get_adapter_properties() |
| 226 | return properties.get('Pairable') == 1 |
| 227 | |
| 228 | |
Scott James Remnant | 1ca2e0e | 2013-07-31 16:49:07 -0700 | [diff] [blame] | 229 | def get_adapter_properties(self): |
| 230 | """Read the adapter properties from the Bluetooth Daemon. |
| 231 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 232 | An example of the adapter properties looks like |
| 233 | {u'Name': u'BlueZ 5.35', |
| 234 | u'Alias': u'Chromebook', |
| 235 | u'Modalias': u'bluetooth:v00E0p2436d0400', |
| 236 | u'Powered': 1, |
| 237 | u'DiscoverableTimeout': 180, |
| 238 | u'PairableTimeout': 0, |
| 239 | u'Discoverable': 0, |
| 240 | u'Address': u'6C:29:95:1A:D4:6F', |
| 241 | u'Discovering': 0, |
| 242 | u'Pairable': 1, |
| 243 | u'Class': 4718852, |
| 244 | u'UUIDs': [u'00001112-0000-1000-8000-00805f9b34fb', |
| 245 | u'00001801-0000-1000-8000-00805f9b34fb', |
| 246 | u'0000110a-0000-1000-8000-00805f9b34fb', |
| 247 | u'0000111f-0000-1000-8000-00805f9b34fb', |
| 248 | u'00001200-0000-1000-8000-00805f9b34fb', |
| 249 | u'00001800-0000-1000-8000-00805f9b34fb']} |
| 250 | |
Scott James Remnant | aec4edd | 2013-08-26 18:47:11 -0700 | [diff] [blame] | 251 | @return the properties as a dictionary on success, |
Scott James Remnant | 1ca2e0e | 2013-07-31 16:49:07 -0700 | [diff] [blame] | 252 | the value False otherwise. |
| 253 | |
| 254 | """ |
| 255 | return json.loads(self._proxy.get_adapter_properties()) |
| 256 | |
| 257 | |
Scott James Remnant | 50915ad | 2014-12-01 13:51:39 -0800 | [diff] [blame] | 258 | def read_version(self): |
| 259 | """Read the version of the management interface from the Kernel. |
| 260 | |
Scott James Remnant | e59d5b9 | 2014-12-01 14:21:47 -0800 | [diff] [blame] | 261 | @return the version as a tuple of: |
Scott James Remnant | 50915ad | 2014-12-01 13:51:39 -0800 | [diff] [blame] | 262 | ( version, revision ) |
| 263 | |
| 264 | """ |
| 265 | return json.loads(self._proxy.read_version()) |
| 266 | |
| 267 | |
| 268 | def read_supported_commands(self): |
| 269 | """Read the set of supported commands from the Kernel. |
| 270 | |
Scott James Remnant | e59d5b9 | 2014-12-01 14:21:47 -0800 | [diff] [blame] | 271 | @return set of supported commands as arrays in a tuple of: |
Scott James Remnant | 50915ad | 2014-12-01 13:51:39 -0800 | [diff] [blame] | 272 | ( commands, events ) |
| 273 | |
| 274 | """ |
| 275 | return json.loads(self._proxy.read_supported_commands()) |
| 276 | |
| 277 | |
| 278 | def read_index_list(self): |
| 279 | """Read the list of currently known controllers from the Kernel. |
| 280 | |
Scott James Remnant | e59d5b9 | 2014-12-01 14:21:47 -0800 | [diff] [blame] | 281 | @return array of controller indexes. |
Scott James Remnant | 50915ad | 2014-12-01 13:51:39 -0800 | [diff] [blame] | 282 | |
| 283 | """ |
| 284 | return json.loads(self._proxy.read_index_list()) |
| 285 | |
| 286 | |
Scott James Remnant | 1ca2e0e | 2013-07-31 16:49:07 -0700 | [diff] [blame] | 287 | def read_info(self): |
| 288 | """Read the adapter information from the Kernel. |
| 289 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 290 | An example of the adapter information looks like |
| 291 | [u'6C:29:95:1A:D4:6F', 6, 2, 65535, 2769, 4718852, u'Chromebook', u''] |
| 292 | |
Scott James Remnant | aec4edd | 2013-08-26 18:47:11 -0700 | [diff] [blame] | 293 | @return the information as a tuple of: |
Scott James Remnant | 1ca2e0e | 2013-07-31 16:49:07 -0700 | [diff] [blame] | 294 | ( address, bluetooth_version, manufacturer_id, |
| 295 | supported_settings, current_settings, class_of_device, |
| 296 | name, short_name ) |
| 297 | |
| 298 | """ |
| 299 | return json.loads(self._proxy.read_info()) |
| 300 | |
| 301 | |
Scott James Remnant | abea37c | 2014-12-01 14:22:23 -0800 | [diff] [blame] | 302 | def add_device(self, address, address_type, action): |
| 303 | """Add a device to the Kernel action list. |
| 304 | |
| 305 | @param address: Address of the device to add. |
| 306 | @param address_type: Type of device in @address. |
| 307 | @param action: Action to take. |
| 308 | |
| 309 | @return tuple of ( address, address_type ) on success, |
| 310 | None on failure. |
| 311 | |
| 312 | """ |
| 313 | return json.loads(self._proxy.add_device(address, address_type, action)) |
| 314 | |
| 315 | |
| 316 | def remove_device(self, address, address_type): |
| 317 | """Remove a device from the Kernel action list. |
| 318 | |
| 319 | @param address: Address of the device to remove. |
| 320 | @param address_type: Type of device in @address. |
| 321 | |
| 322 | @return tuple of ( address, address_type ) on success, |
| 323 | None on failure. |
| 324 | |
| 325 | """ |
| 326 | return json.loads(self._proxy.remove_device(address, address_type)) |
| 327 | |
| 328 | |
Scott James Remnant | aec4edd | 2013-08-26 18:47:11 -0700 | [diff] [blame] | 329 | def get_devices(self): |
| 330 | """Read information about remote devices known to the adapter. |
| 331 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 332 | An example of the device information of RN-42 looks like |
| 333 | [{u'Name': u'RNBT-A96F', |
| 334 | u'Alias': u'RNBT-A96F', |
| 335 | u'Adapter': u'/org/bluez/hci0', |
| 336 | u'LegacyPairing': 0, |
| 337 | u'Paired': 1, |
| 338 | u'Connected': 0, |
| 339 | u'UUIDs': [u'00001124-0000-1000-8000-00805f9b34fb'], |
| 340 | u'Address': u'00:06:66:75:A9:6F', |
| 341 | u'Icon': u'input-mouse', |
| 342 | u'Class': 1408, |
| 343 | u'Trusted': 1, |
| 344 | u'Blocked': 0}] |
| 345 | |
Scott James Remnant | e59d5b9 | 2014-12-01 14:21:47 -0800 | [diff] [blame] | 346 | @return the properties of each device as an array of |
Scott James Remnant | aec4edd | 2013-08-26 18:47:11 -0700 | [diff] [blame] | 347 | dictionaries on success, the value False otherwise. |
| 348 | |
| 349 | """ |
| 350 | return json.loads(self._proxy.get_devices()) |
| 351 | |
| 352 | |
Joseph Hwang | f064e0f | 2016-05-23 16:46:45 +0800 | [diff] [blame] | 353 | def get_device_properties(self, address): |
| 354 | """Read information about remote devices known to the adapter. |
| 355 | |
| 356 | An example of the device information of RN-42 looks like |
| 357 | |
| 358 | @param address: Address of the device to pair. |
| 359 | @param pin: The pin code of the device to pair. |
| 360 | @param timeout: The timeout in seconds for pairing. |
| 361 | |
| 362 | @returns: a dictionary of device properties of the device on success; |
| 363 | an empty dictionary otherwise. |
| 364 | |
| 365 | """ |
| 366 | return json.loads(self._proxy.get_device_by_address(address)) |
| 367 | |
| 368 | for device in self.get_devices(): |
| 369 | if device.get['Address'] == address: |
| 370 | return device |
| 371 | return dict() |
| 372 | |
| 373 | |
Scott James Remnant | aec4edd | 2013-08-26 18:47:11 -0700 | [diff] [blame] | 374 | def start_discovery(self): |
| 375 | """Start discovery of remote devices. |
| 376 | |
| 377 | Obtain the discovered device information using get_devices(), called |
| 378 | stop_discovery() when done. |
| 379 | |
| 380 | @return True on success, False otherwise. |
| 381 | |
| 382 | """ |
| 383 | return self._proxy.start_discovery() |
| 384 | |
| 385 | |
| 386 | def stop_discovery(self): |
| 387 | """Stop discovery of remote devices. |
| 388 | |
| 389 | @return True on success, False otherwise. |
| 390 | |
| 391 | """ |
| 392 | return self._proxy.stop_discovery() |
| 393 | |
| 394 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 395 | def is_discovering(self): |
| 396 | """Is it discovering? |
| 397 | |
| 398 | @return True if it is discovering. False otherwise. |
| 399 | |
| 400 | """ |
| 401 | return self.get_adapter_properties().get('Discovering') == 1 |
| 402 | |
| 403 | |
Scott James Remnant | c7fd7a4 | 2014-12-01 16:43:38 -0800 | [diff] [blame] | 404 | def get_dev_info(self): |
| 405 | """Read raw HCI device information. |
| 406 | |
Joseph Hwang | 97ff05d | 2016-05-10 16:07:22 +0800 | [diff] [blame] | 407 | An example of the device information looks like: |
| 408 | [0, u'hci0', u'6C:29:95:1A:D4:6F', 13, 0, 1, 581900950526, 52472, 7, |
| 409 | 32768, 1021, 5, 96, 6, 0, 0, 151, 151, 0, 0, 0, 0, 1968, 12507] |
| 410 | |
Scott James Remnant | c7fd7a4 | 2014-12-01 16:43:38 -0800 | [diff] [blame] | 411 | @return tuple of (index, name, address, flags, device_type, bus_type, |
| 412 | features, pkt_type, link_policy, link_mode, |
| 413 | acl_mtu, acl_pkts, sco_mtu, sco_pkts, |
| 414 | err_rx, err_tx, cmd_tx, evt_rx, acl_tx, acl_rx, |
| 415 | sco_tx, sco_rx, byte_rx, byte_tx) on success, |
| 416 | None on failure. |
| 417 | |
| 418 | """ |
| 419 | return json.loads(self._proxy.get_dev_info()) |
| 420 | |
| 421 | |
Artem Rakhov | b144dce | 2014-02-20 21:02:09 -0800 | [diff] [blame] | 422 | def register_profile(self, path, uuid, options): |
| 423 | """Register new profile (service). |
| 424 | |
| 425 | @param path: Path to the profile object. |
| 426 | @param uuid: Service Class ID of the service as string. |
| 427 | @param options: Dictionary of options for the new service, compliant |
| 428 | with BlueZ D-Bus Profile API standard. |
| 429 | |
| 430 | @return True on success, False otherwise. |
| 431 | |
| 432 | """ |
| 433 | return self._proxy.register_profile(path, uuid, options) |
| 434 | |
| 435 | |
Cheng-Yi Chiang | dc6442b | 2015-07-08 16:07:02 +0800 | [diff] [blame] | 436 | def has_device(self, address): |
| 437 | """Checks if the device with a given address exists. |
| 438 | |
| 439 | @param address: Address of the device. |
| 440 | |
| 441 | @returns: True if there is a device with that address. |
| 442 | False otherwise. |
| 443 | |
| 444 | """ |
| 445 | return self._proxy.has_device(address) |
| 446 | |
| 447 | |
Joseph Hwang | f064e0f | 2016-05-23 16:46:45 +0800 | [diff] [blame] | 448 | def device_is_paired(self, address): |
| 449 | """Checks if a device is paired. |
| 450 | |
| 451 | @param address: address of the device. |
| 452 | |
| 453 | @returns: True if device is paired. False otherwise. |
| 454 | |
| 455 | """ |
| 456 | return self._proxy.device_is_paired(address) |
| 457 | |
| 458 | |
| 459 | def set_trusted(self, address, trusted=True): |
| 460 | """Set the device trusted. |
| 461 | |
| 462 | @param address: The bluetooth address of the device. |
| 463 | @param trusted: True or False indicating whether to set trusted or not. |
| 464 | |
| 465 | @returns: True if successful. False otherwise. |
| 466 | |
| 467 | """ |
| 468 | return self._proxy.set_trusted(address, trusted) |
| 469 | |
| 470 | |
| 471 | def pair_legacy_device(self, address, pin, trusted, timeout): |
Cheng-Yi Chiang | 212d469 | 2015-05-25 22:08:14 +0800 | [diff] [blame] | 472 | """Pairs a device with a given pin code. |
| 473 | |
| 474 | Registers an agent who handles pin code request and |
| 475 | pairs a device with known pin code. |
| 476 | |
| 477 | @param address: Address of the device to pair. |
| 478 | @param pin: The pin code of the device to pair. |
Joseph Hwang | f064e0f | 2016-05-23 16:46:45 +0800 | [diff] [blame] | 479 | @param trusted: indicating whether to set the device trusted. |
Cheng-Yi Chiang | 212d469 | 2015-05-25 22:08:14 +0800 | [diff] [blame] | 480 | @param timeout: The timeout in seconds for pairing. |
| 481 | |
| 482 | @returns: True on success. False otherwise. |
| 483 | |
| 484 | """ |
Joseph Hwang | f064e0f | 2016-05-23 16:46:45 +0800 | [diff] [blame] | 485 | return self._proxy.pair_legacy_device(address, pin, trusted, timeout) |
| 486 | |
| 487 | |
| 488 | def remove_device_object(self, address): |
| 489 | """Removes a device object and the pairing information. |
| 490 | |
| 491 | Calls RemoveDevice method to remove remote device |
| 492 | object and the pairing information. |
| 493 | |
| 494 | @param address: address of the device to unpair. |
| 495 | |
| 496 | @returns: True on success. False otherwise. |
| 497 | |
| 498 | """ |
| 499 | return self._proxy.remove_device_object(address) |
Cheng-Yi Chiang | 212d469 | 2015-05-25 22:08:14 +0800 | [diff] [blame] | 500 | |
| 501 | |
| 502 | def connect_device(self, address): |
| 503 | """Connects a device. |
| 504 | |
| 505 | Connects a device if it is not connected. |
| 506 | |
| 507 | @param address: Address of the device to connect. |
| 508 | |
| 509 | @returns: True on success. False otherwise. |
| 510 | |
| 511 | """ |
| 512 | return self._proxy.connect_device(address) |
| 513 | |
| 514 | |
Cheng-Yi Chiang | a532852 | 2015-10-21 14:46:41 +0800 | [diff] [blame] | 515 | def device_is_connected(self, address): |
| 516 | """Checks if a device is connected. |
| 517 | |
| 518 | @param address: Address of the device to check if it is connected. |
| 519 | |
| 520 | @returns: True if device is connected. False otherwise. |
| 521 | |
| 522 | """ |
| 523 | return self._proxy.device_is_connected(address) |
| 524 | |
| 525 | |
Cheng-Yi Chiang | 212d469 | 2015-05-25 22:08:14 +0800 | [diff] [blame] | 526 | def disconnect_device(self, address): |
| 527 | """Disconnects a device. |
| 528 | |
| 529 | Disconnects a device if it is connected. |
| 530 | |
| 531 | @param address: Address of the device to disconnect. |
| 532 | |
| 533 | @returns: True on success. False otherwise. |
| 534 | |
| 535 | """ |
| 536 | return self._proxy.disconnect_device(address) |
| 537 | |
| 538 | |
Joseph Hwang | efaf035 | 2016-09-29 14:53:33 +0800 | [diff] [blame] | 539 | def btmon_start(self): |
| 540 | """Start btmon monitoring.""" |
| 541 | self._proxy.btmon_start() |
| 542 | |
| 543 | |
| 544 | def btmon_stop(self): |
| 545 | """Stop btmon monitoring.""" |
| 546 | self._proxy.btmon_stop() |
| 547 | |
| 548 | |
| 549 | def btmon_get(self): |
| 550 | """Get btmon output contents. |
| 551 | |
| 552 | @returns: the recorded btmon output. |
| 553 | |
| 554 | """ |
| 555 | return self._proxy.btmon_get() |
| 556 | |
| 557 | |
| 558 | def btmon_find(self, pattern_str): |
| 559 | """Find if a pattern string exists in btmon output. |
| 560 | |
| 561 | @param pattern_str: the pattern string to find. |
| 562 | |
| 563 | @returns: True on success. False otherwise. |
| 564 | |
| 565 | """ |
| 566 | return self._proxy.btmon_find(pattern_str) |
| 567 | |
| 568 | |
| 569 | def register_advertisement(self, advertisement_data): |
| 570 | """Register an advertisement. |
| 571 | |
| 572 | Note that rpc supports only conformable types. Hence, a |
| 573 | dict about the advertisement is passed as a parameter such |
| 574 | that the advertisement object could be contructed on the host. |
| 575 | |
| 576 | @param advertisement_data: a dict of the advertisement for |
| 577 | the adapter to register. |
| 578 | |
| 579 | @returns: True on success. False otherwise. |
| 580 | |
| 581 | """ |
| 582 | return self._proxy.register_advertisement(advertisement_data) |
| 583 | |
| 584 | |
| 585 | def set_advertising_intervals(self, min_adv_interval_ms, |
| 586 | max_adv_interval_ms): |
| 587 | """Set advertising intervals. |
| 588 | |
| 589 | @param min_adv_interval_ms: the min advertising interval in ms. |
| 590 | @param max_adv_interval_ms: the max advertising interval in ms. |
| 591 | |
| 592 | @returns: True on success. False otherwise. |
| 593 | |
| 594 | """ |
| 595 | return self._proxy.set_advertising_intervals(min_adv_interval_ms, |
| 596 | max_adv_interval_ms) |
| 597 | |
| 598 | |
| 599 | def reset_advertising(self): |
| 600 | """Reset advertising. |
| 601 | |
| 602 | This includes unregister all advertisements, reset advertising |
| 603 | intervals, and disable advertising. |
| 604 | |
| 605 | @returns: True on success. False otherwise. |
| 606 | |
| 607 | """ |
| 608 | return self._proxy.reset_advertising() |
| 609 | |
| 610 | |
Katherine Threlkeld | 88aa143 | 2015-07-30 11:44:35 -0700 | [diff] [blame] | 611 | def copy_logs(self, destination): |
| 612 | """Copy the logs generated by this device to a given location. |
| 613 | |
| 614 | @param destination: destination directory for the logs. |
| 615 | |
| 616 | """ |
| 617 | self.host.collect_logs(self.XMLRPC_LOG_PATH, destination) |
| 618 | |
| 619 | |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 620 | def close(self): |
| 621 | """Tear down state associated with the client.""" |
Scott James Remnant | da9f43c | 2013-08-07 17:53:14 -0700 | [diff] [blame] | 622 | # Turn off the discoverable flag since it may affect future tests. |
| 623 | self._proxy.set_discoverable(False) |
Scott James Remnant | a6442f5 | 2013-07-24 15:04:55 -0700 | [diff] [blame] | 624 | # Leave the adapter powered off, but don't do a full reset. |
| 625 | self._proxy.set_powered(False) |
Scott James Remnant | 4dcd73f | 2013-07-22 15:00:24 -0700 | [diff] [blame] | 626 | # This kills the RPC server. |
Scott James Remnant | 1c72d7a | 2013-07-29 15:00:04 -0700 | [diff] [blame] | 627 | self.host.close() |