1#!/usr/bin/env python3
2#
3#   Copyright 2018 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import collections
18import json
19import logging
20import math
21import os
22import random
23import re
24import requests
25import socket
26import time
27
28from acts.controllers.fuchsia_lib.base_lib import BaseLib
29
30
31class FuchsiaBtcLib(BaseLib):
32    # Class representing the Bluetooth Controller Library.
33
34    def __init__(self, addr, tc, client_id):
35        self.address = addr
36        self.test_counter = tc
37        self.client_id = client_id
38
39    def acceptPairing(self):
40        """Accepts incomming pairing requests.
41
42        Returns:
43            Dictionary, None if success, error if error.
44        """
45        test_cmd = "bt_control_facade.BluetoothAcceptPairing"
46        test_args = {}
47        test_id = self.build_id(self.test_counter)
48        self.test_counter += 1
49
50        return self.send_command(test_id, test_cmd, test_args)
51
52    def setDiscoverable(self, discoverable):
53        """Sets the device to be discoverable over BR/EDR.
54
55        Args:
56            discoverable: A bool object for setting Bluetooth
57              device discoverable or not.
58
59        Returns:
60            Dictionary, None if success, error if error.
61        """
62        test_cmd = "bt_control_facade.BluetoothSetDiscoverable"
63        test_args = {"discoverable": discoverable}
64        test_id = self.build_id(self.test_counter)
65        self.test_counter += 1
66
67        return self.send_command(test_id, test_cmd, test_args)
68
69    def setName(self, name):
70        """Sets the local Bluetooth name of the device.
71
72        Args:
73            name: A string that represents the name to set.
74
75        Returns:
76            Dictionary, None if success, error if error.
77        """
78        test_cmd = "bt_control_facade.BluetoothSetName"
79        test_args = {"name": name}
80        test_id = self.build_id(self.test_counter)
81        self.test_counter += 1
82
83        return self.send_command(test_id, test_cmd, test_args)
84
85    def inputPairingPin(self, pin):
86        """Inputs the pairing pin to the Fuchsia devices' pairing delegate.
87
88        Args:
89            pin: A string that represents the pin to input.
90
91        Returns:
92            Dictionary, None if success, error if error.
93        """
94        test_cmd = "bt_control_facade.BluetoothInputPairingPin"
95        test_args = {"pin": pin}
96        test_id = self.build_id(self.test_counter)
97        self.test_counter += 1
98
99        return self.send_command(test_id, test_cmd, test_args)
100
101    def getPairingPin(self):
102        """Gets the pairing pin from the Fuchsia devices' pairing delegate.
103
104        Returns:
105            Dictionary, None if success, error if error.
106        """
107        test_cmd = "bt_control_facade.BluetoothGetPairingPin"
108        test_args = {}
109        test_id = self.build_id(self.test_counter)
110        self.test_counter += 1
111
112        return self.send_command(test_id, test_cmd, test_args)
113
114    def initBluetoothControl(self):
115        """Initialises the Bluetooth Control Interface proxy in SL4F.
116
117        Returns:
118            Dictionary, None if success, error if error.
119        """
120        test_cmd = "bt_control_facade.BluetoothInitControl"
121        test_args = {}
122        test_id = self.build_id(self.test_counter)
123        self.test_counter += 1
124
125        return self.send_command(test_id, test_cmd, test_args)
126
127    def requestDiscovery(self, discovery):
128        """Start or stop Bluetooth Control device discovery.
129
130        Args:
131            discovery: A bool object representing starting or stopping
132              device discovery.
133
134        Returns:
135            Dictionary, None if success, error if error.
136        """
137        test_cmd = "bt_control_facade.BluetoothRequestDiscovery"
138        test_args = {"discovery": discovery}
139        test_id = self.build_id(self.test_counter)
140        self.test_counter += 1
141
142        return self.send_command(test_id, test_cmd, test_args)
143
144    def getKnownRemoteDevices(self):
145        """Get known remote BR/EDR and LE devices.
146
147        Returns:
148            Dictionary, None if success, error if error.
149        """
150        test_cmd = "bt_control_facade.BluetoothGetKnownRemoteDevices"
151        test_args = {}
152        test_id = self.build_id(self.test_counter)
153        self.test_counter += 1
154
155        return self.send_command(test_id, test_cmd, test_args)
156
157    def forgetDevice(self, identifier):
158        """Forgets a devices pairing.
159
160        Args:
161            identifier: A string representing the device id.
162
163        Returns:
164            Dictionary, None if success, error if error.
165        """
166        test_cmd = "bt_control_facade.BluetoothForgetDevice"
167        test_args = {"identifier": identifier}
168        test_id = self.build_id(self.test_counter)
169        self.test_counter += 1
170
171        return self.send_command(test_id, test_cmd, test_args)
172
173    def disconnectDevice(self, identifier):
174        """Disconnects a devices.
175
176        Args:
177            identifier: A string representing the device id.
178
179        Returns:
180            Dictionary, None if success, error if error.
181        """
182        test_cmd = "bt_control_facade.BluetoothDisconnectDevice"
183        test_args = {"identifier": identifier}
184        test_id = self.build_id(self.test_counter)
185        self.test_counter += 1
186
187        return self.send_command(test_id, test_cmd, test_args)
188
189    def connectDevice(self, identifier):
190        """Connects to a devices.
191
192        Args:
193            identifier: A string representing the device id.
194
195        Returns:
196            Dictionary, None if success, error if error.
197        """
198        test_cmd = "bt_control_facade.BluetoothConnectDevice"
199        test_args = {"identifier": identifier}
200        test_id = self.build_id(self.test_counter)
201        self.test_counter += 1
202
203        return self.send_command(test_id, test_cmd, test_args)
204
205    def getActiveAdapterAddress(self):
206        """Gets the current Active Adapter's address.
207
208        Returns:
209            Dictionary, String address if success, error if error.
210        """
211        test_cmd = "bt_control_facade.BluetoothGetActiveAdapterAddress"
212        test_args = {}
213        test_id = self.build_id(self.test_counter)
214        self.test_counter += 1
215
216        return self.send_command(test_id, test_cmd, test_args)
217
218    def pair(self, identifier, pairing_security_level, non_bondable,
219             transport):
220        """Pairs to a device.
221
222        Args:
223            identifier: A string representing the device id.
224            pairing_security_level: The security level required for this pairing request
225                represented as a u64. (Only for LE pairing)
226                Available Values
227                1 - ENCRYPTED: Encrypted without MITM protection (unauthenticated)
228                2 - AUTHENTICATED: Encrypted with MITM protection (authenticated).
229                None: No pairing security level.
230            non_bondable: A bool representing whether the pairing mode is bondable or not. None is
231                also accepted. False if bondable, True if non-bondable.
232            transport: A u64 representing the transport type.
233                Available Values
234                1 - BREDR: Classic BR/EDR transport
235                2 - LE: Bluetooth Low Energy Transport
236
237        Returns:
238            Dictionary, None if success, error if error.
239        """
240        test_cmd = "bt_control_facade.BluetoothPairDevice"
241        test_args = {
242            "identifier": identifier,
243            "pairing_security_level": pairing_security_level,
244            "non_bondable": non_bondable,
245            "transport": transport,
246        }
247        test_id = self.build_id(self.test_counter)
248        self.test_counter += 1
249        return self.send_command(test_id, test_cmd, test_args)
250
251    def setIOCapabilities(self, input, output):
252        """Sets the I/O capabilities during pairing.
253
254        Args:
255            input: String - The input I/O capabilities to use
256                Available Values:
257                NONE - Input capability type None
258                CONFIRMATION - Input capability type confirmation
259                KEYBOARD - Input capability type Keyboard
260            output: String - The output I/O Capabilities to use
261                Available Values:
262                NONE - Output capability type None
263                DISPLAY - output capability type Display
264
265        Returns:
266            Dictionary, None if success, error if error.
267        """
268        test_cmd = "bt_control_facade.BluetoothSetIOCapabilities"
269        test_args = {
270            "input": input,
271            "output": output,
272        }
273        test_id = self.build_id(self.test_counter)
274        self.test_counter += 1
275        return self.send_command(test_id, test_cmd, test_args)
276