1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.snippet.bluetooth;
18 
19 import android.bluetooth.BluetoothManager;
20 import android.content.Context;
21 
22 import androidx.test.platform.app.InstrumentationRegistry;
23 
24 import com.google.android.mobly.snippet.Snippet;
25 import com.google.android.mobly.snippet.rpc.Rpc;
26 
27 import org.json.JSONArray;
28 import org.json.JSONException;
29 import org.json.JSONObject;
30 
31 
32 public class BluetoothGattMultiDevicesSnippet implements Snippet {
33     private static final String TAG = "BluetoothGattMultiDevicesSnippet";
34 
35     private BluetoothGattMultiDevicesServer mGattServer;
36     private BluetoothGattMultiDevicesClient mGattClient;
37 
38     private Context mContext;
39     private BluetoothManager mBluetoothManager;
40 
BluetoothGattMultiDevicesSnippet()41     public BluetoothGattMultiDevicesSnippet() {
42         mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
43         mBluetoothManager = mContext.getSystemService(BluetoothManager.class);
44     }
45 
46     @Rpc(description = "Reset the state of client + server")
reset()47     public void reset() {
48         mGattServer = new BluetoothGattMultiDevicesServer(mContext, mBluetoothManager);
49         mGattClient = new BluetoothGattMultiDevicesClient(mContext, mBluetoothManager);
50     }
51 
52     @Rpc(description = "Creates Bluetooth GATT server with a given UUID and advertises it.")
createAndAdvertiseServer(String uuid)53     public void createAndAdvertiseServer(String uuid) {
54         try {
55             Utils.adoptShellPermission();
56             mGattServer.createAndAdvertiseServer(uuid);
57         } finally {
58             Utils.dropShellPermission();
59         }
60     }
61 
62     @Rpc(
63             description =
64                     "Creates Bluetooth GATT server with a given UUID and ties it to an"
65                             + " advertisement.")
createAndAdvertiseIsolatedServer(String uuid)66     public void createAndAdvertiseIsolatedServer(String uuid) {
67         try {
68             Utils.adoptShellPermission();
69             mGattServer.createAndAdvertiseIsolatedServer(uuid);
70         } finally {
71             Utils.dropShellPermission();
72         }
73     }
74 
75     @Rpc(description = "Connect to the peer device advertising the specified UUID")
connectGatt(String uuid)76     public String connectGatt(String uuid) throws JSONException {
77         try {
78             Utils.adoptShellPermission();
79             return Utils.convertBtDeviceToJson(mGattClient.connect(uuid));
80         } finally {
81             Utils.dropShellPermission();
82         }
83     }
84 
85     @Rpc(description = "Disconnect to the peer device advertising the specified UUID")
disconnectGatt(String uuid)86     public boolean disconnectGatt(String uuid) throws JSONException {
87         try {
88             Utils.adoptShellPermission();
89             return mGattClient.disconnect(uuid);
90         } finally {
91             Utils.dropShellPermission();
92         }
93     }
94 
95     @Rpc(description = "Get all the devices connected to the GATT server")
getConnectedDevices()96     public JSONArray getConnectedDevices() throws JSONException {
97         try {
98             Utils.adoptShellPermission();
99             return Utils.convertBtDevicesToJson(mGattServer.getConnectedDevices());
100         } finally {
101             Utils.dropShellPermission();
102         }
103     }
104 
105     @Rpc(description = "Generate local OOB data to used for bonding with the server")
generateServerLocalOobData()106     public JSONObject generateServerLocalOobData() throws JSONException {
107         try {
108             Utils.adoptShellPermission();
109             return Utils.convertOobDataToJson(mGattServer.generateLocalOObData());
110         } finally {
111             Utils.dropShellPermission();
112         }
113     }
114 
115     @Rpc(description = "Create a bond with the server using local OOB data generated on the server")
createBondOob(String uuid, JSONObject jsonObject)116     public String createBondOob(String uuid, JSONObject jsonObject) throws JSONException {
117         try {
118             Utils.adoptShellPermission();
119             return Utils.convertBtDeviceToJson(mGattClient.createBondOob(
120                     uuid, Utils.convertJsonToOobData(jsonObject)));
121         } finally {
122             Utils.dropShellPermission();
123         }
124     }
125 
126     @Rpc(description = "Create a bond with the server using local OOB data generated on the server")
removeBond(String uuid)127     public boolean removeBond(String uuid) {
128         try {
129             Utils.adoptShellPermission();
130             return mGattClient.removeBond(uuid);
131         } finally {
132             Utils.dropShellPermission();
133         }
134     }
135 
136     @Rpc(description = "Enables Bluetooth")
enableBluetooth()137     public void enableBluetooth() {
138         try {
139             Utils.adoptShellPermission();
140             mBluetoothManager.getAdapter().enable();
141         } finally {
142             Utils.dropShellPermission();
143         }
144     }
145 
146     @Rpc(description = "Disable Bluetooth")
disableBluetooth()147     public void disableBluetooth() {
148         try {
149             Utils.adoptShellPermission();
150             mBluetoothManager.getAdapter().disable();
151         } finally {
152             Utils.dropShellPermission();
153         }
154     }
155 
156     @Rpc(description = "Checks Bluetooth state")
isBluetoothOn()157     public boolean isBluetoothOn() {
158         return mBluetoothManager.getAdapter().isEnabled();
159     }
160 
161     @Rpc(description = "Whether the connected peer has a service of the given UUID")
containsService(String uuid)162     public boolean containsService(String uuid) {
163         try {
164             Utils.adoptShellPermission();
165             return mGattClient.containsService(uuid);
166         } finally {
167             Utils.dropShellPermission();
168         }
169     }
170 }
171