blob: 753de408d228cb016c4f09a12a0f39f7752f8b0d [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
Artem Rakhovba130382014-02-26 17:39:57 -0800125 def service_search_request(self, uuids, max_rec_cnt, preferred_size=32,
126 forced_pdu_size=None):
Artem Rakhov448d52c2013-12-03 16:38:36 -0800127 """Send a Service Search Request
128
Artem Rakhovba130382014-02-26 17:39:57 -0800129 @param uuids: List of UUIDs (as integers) to look for.
Artem Rakhov448d52c2013-12-03 16:38:36 -0800130 @param max_rec_cnt: Maximum count of returned service records.
Artem Rakhovca443b52014-01-10 17:18:24 -0800131 @param preferred_size: Preffered size of UUIDs in bits (16, 32, or 128).
Artem Rakhovba130382014-02-26 17:39:57 -0800132 @param forced_pdu_size: Use certain PDU size parameter instead of
133 calculating actual length of sequence.
Artem Rakhov448d52c2013-12-03 16:38:36 -0800134
Artem Rakhovba130382014-02-26 17:39:57 -0800135 @return list of found services' service record handles or Error Code
Artem Rakhov448d52c2013-12-03 16:38:36 -0800136
137 """
Artem Rakhovca443b52014-01-10 17:18:24 -0800138 return self._proxy.service_search_request(uuids, max_rec_cnt,
Artem Rakhovba130382014-02-26 17:39:57 -0800139 preferred_size,
140 forced_pdu_size)
Artem Rakhov448d52c2013-12-03 16:38:36 -0800141
142
Scott James Remnant8d2cbf32013-11-12 11:00:25 -0800143def create_host_from(device_host):
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700144 """Creates a host object for the Tester associated with a DUT.
145
146 Will raise an exception if there isn't a tester for the DUT.
147
Scott James Remnant8d2cbf32013-11-12 11:00:25 -0800148 @param device_host: Autotest host object for the DUT.
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700149
150 @return Autotest host object for the Tester.
151
152 """
153
Scott James Remnant8d2cbf32013-11-12 11:00:25 -0800154 device_hostname = device_host.hostname
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700155
Scott James Remnant8d2cbf32013-11-12 11:00:25 -0800156 parts = device_hostname.split('.')
Scott James Remnant85593072014-02-25 17:43:16 -0800157 parts[0] = parts[0] + '-router'
Scott James Remnant1ca2e0e2013-07-31 16:49:07 -0700158 tester_hostname = '.'.join(parts)
159
160 return hosts.create_host(tester_hostname)