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