blob: adedff3e93868924aaac28ed516f1d24bceb6a81 [file] [log] [blame]
Matthew Xieddf7e472013-03-01 18:41:02 -08001/*
2 * Copyright (C) 2013 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
17package android.bluetooth;
18
Tor Norbye2d497522015-04-23 17:10:21 -070019import android.Manifest;
Jeff Sharkey98af2e42018-02-16 10:14:57 -070020import android.annotation.RequiresFeature;
Tor Norbye2d497522015-04-23 17:10:21 -070021import android.annotation.RequiresPermission;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060022import android.annotation.SystemService;
Matthew Xieddf7e472013-03-01 18:41:02 -080023import android.content.Context;
Jeff Sharkey98af2e42018-02-16 10:14:57 -070024import android.content.pm.PackageManager;
Matthew Xieddf7e472013-03-01 18:41:02 -080025import android.os.RemoteException;
26import android.util.Log;
27
28import java.util.ArrayList;
29import java.util.List;
30
31/**
32 * High level manager used to obtain an instance of an {@link BluetoothAdapter}
33 * and to conduct overall Bluetooth Management.
34 * <p>
35 * Use {@link android.content.Context#getSystemService(java.lang.String)}
36 * with {@link Context#BLUETOOTH_SERVICE} to create an {@link BluetoothManager},
37 * then call {@link #getAdapter} to obtain the {@link BluetoothAdapter}.
Marie Janssen553c8c72017-01-12 16:00:30 -080038 * </p>
Matthew Xieddf7e472013-03-01 18:41:02 -080039 * <div class="special reference">
40 * <h3>Developer Guides</h3>
Hemal Patel65813df2016-08-17 13:18:14 -070041 * <p>
42 * For more information about using BLUETOOTH, read the <a href=
43 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
44 * guide.
45 * </p>
Matthew Xieddf7e472013-03-01 18:41:02 -080046 * </div>
47 *
48 * @see Context#getSystemService
49 * @see BluetoothAdapter#getDefaultAdapter()
50 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060051@SystemService(Context.BLUETOOTH_SERVICE)
Jeff Sharkey98af2e42018-02-16 10:14:57 -070052@RequiresFeature(PackageManager.FEATURE_BLUETOOTH)
Matthew Xieddf7e472013-03-01 18:41:02 -080053public final class BluetoothManager {
54 private static final String TAG = "BluetoothManager";
Myles Watson3ee31a72018-11-14 14:40:14 -080055 private static final boolean DBG = false;
Matthew Xieddf7e472013-03-01 18:41:02 -080056
57 private final BluetoothAdapter mAdapter;
58
59 /**
60 * @hide
61 */
62 public BluetoothManager(Context context) {
63 context = context.getApplicationContext();
64 if (context == null) {
65 throw new IllegalArgumentException(
66 "context not associated with any application (using a mock context?)");
67 }
68 // Legacy api - getDefaultAdapter does not take in the context
69 mAdapter = BluetoothAdapter.getDefaultAdapter();
bohuabe91db2018-12-18 12:18:45 -080070 if (mAdapter != null) {
71 mAdapter.setContext(context);
72 }
Matthew Xieddf7e472013-03-01 18:41:02 -080073 }
74
75 /**
76 * Get the default BLUETOOTH Adapter for this device.
77 *
78 * @return the default BLUETOOTH Adapter
79 */
80 public BluetoothAdapter getAdapter() {
81 return mAdapter;
82 }
83
84 /**
85 * Get the current connection state of the profile to the remote device.
86 *
87 * <p>This is not specific to any application configuration but represents
88 * the connection state of the local Bluetooth adapter for certain profile.
89 * This can be used by applications like status bar which would just like
90 * to know the state of Bluetooth.
91 *
Matthew Xieddf7e472013-03-01 18:41:02 -080092 * @param device Remote bluetooth device.
93 * @param profile GATT or GATT_SERVER
Jack Hea355e5e2017-08-22 16:06:54 -070094 * @return State of the profile connection. One of {@link BluetoothProfile#STATE_CONNECTED},
95 * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED},
96 * {@link BluetoothProfile#STATE_DISCONNECTING}
Matthew Xieddf7e472013-03-01 18:41:02 -080097 */
Tor Norbye2d497522015-04-23 17:10:21 -070098 @RequiresPermission(Manifest.permission.BLUETOOTH)
Matthew Xieddf7e472013-03-01 18:41:02 -080099 public int getConnectionState(BluetoothDevice device, int profile) {
Jack Hea355e5e2017-08-22 16:06:54 -0700100 if (DBG) Log.d(TAG, "getConnectionState()");
Matthew Xieddf7e472013-03-01 18:41:02 -0800101
102 List<BluetoothDevice> connectedDevices = getConnectedDevices(profile);
Jack Hea355e5e2017-08-22 16:06:54 -0700103 for (BluetoothDevice connectedDevice : connectedDevices) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800104 if (device.equals(connectedDevice)) {
105 return BluetoothProfile.STATE_CONNECTED;
106 }
107 }
108
109 return BluetoothProfile.STATE_DISCONNECTED;
110 }
111
112 /**
113 * Get connected devices for the specified profile.
114 *
115 * <p> Return the set of devices which are in state {@link BluetoothProfile#STATE_CONNECTED}
116 *
117 * <p>This is not specific to any application configuration but represents
118 * the connection state of Bluetooth for this profile.
119 * This can be used by applications like status bar which would just like
120 * to know the state of Bluetooth.
121 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800122 * @param profile GATT or GATT_SERVER
123 * @return List of devices. The list will be empty on error.
124 */
Tor Norbye2d497522015-04-23 17:10:21 -0700125 @RequiresPermission(Manifest.permission.BLUETOOTH)
Matthew Xieddf7e472013-03-01 18:41:02 -0800126 public List<BluetoothDevice> getConnectedDevices(int profile) {
Jack Hea355e5e2017-08-22 16:06:54 -0700127 if (DBG) Log.d(TAG, "getConnectedDevices");
Matthew Xieddf7e472013-03-01 18:41:02 -0800128 if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
129 throw new IllegalArgumentException("Profile not supported: " + profile);
130 }
131
132 List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
133
134 try {
135 IBluetoothManager managerService = mAdapter.getBluetoothManager();
Matthew Xiecdd94e32013-04-11 16:36:26 -0700136 IBluetoothGatt iGatt = managerService.getBluetoothGatt();
Matthew Xieddf7e472013-03-01 18:41:02 -0800137 if (iGatt == null) return connectedDevices;
138
139 connectedDevices = iGatt.getDevicesMatchingConnectionStates(
Jack Hea355e5e2017-08-22 16:06:54 -0700140 new int[]{BluetoothProfile.STATE_CONNECTED});
Matthew Xieddf7e472013-03-01 18:41:02 -0800141 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -0700142 Log.e(TAG, "", e);
Matthew Xieddf7e472013-03-01 18:41:02 -0800143 }
144
145 return connectedDevices;
146 }
147
148 /**
Matthew Xieddf7e472013-03-01 18:41:02 -0800149 * Get a list of devices that match any of the given connection
150 * states.
151 *
152 * <p> If none of the devices match any of the given states,
153 * an empty list will be returned.
154 *
155 * <p>This is not specific to any application configuration but represents
156 * the connection state of the local Bluetooth adapter for this profile.
157 * This can be used by applications like status bar which would just like
158 * to know the state of the local adapter.
159 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800160 * @param profile GATT or GATT_SERVER
Jack Hea355e5e2017-08-22 16:06:54 -0700161 * @param states Array of states. States can be one of {@link BluetoothProfile#STATE_CONNECTED},
162 * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED},
163 * {@link BluetoothProfile#STATE_DISCONNECTING},
Matthew Xieddf7e472013-03-01 18:41:02 -0800164 * @return List of devices. The list will be empty on error.
165 */
Tor Norbye2d497522015-04-23 17:10:21 -0700166 @RequiresPermission(Manifest.permission.BLUETOOTH)
Matthew Xieddf7e472013-03-01 18:41:02 -0800167 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int profile, int[] states) {
Jack Hea355e5e2017-08-22 16:06:54 -0700168 if (DBG) Log.d(TAG, "getDevicesMatchingConnectionStates");
Matthew Xieddf7e472013-03-01 18:41:02 -0800169
170 if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
171 throw new IllegalArgumentException("Profile not supported: " + profile);
172 }
173
174 List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
175
176 try {
177 IBluetoothManager managerService = mAdapter.getBluetoothManager();
Matthew Xiecdd94e32013-04-11 16:36:26 -0700178 IBluetoothGatt iGatt = managerService.getBluetoothGatt();
Matthew Xieddf7e472013-03-01 18:41:02 -0800179 if (iGatt == null) return devices;
180 devices = iGatt.getDevicesMatchingConnectionStates(states);
181 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -0700182 Log.e(TAG, "", e);
Matthew Xieddf7e472013-03-01 18:41:02 -0800183 }
184
185 return devices;
186 }
187
188 /**
189 * Open a GATT Server
190 * The callback is used to deliver results to Caller, such as connection status as well
191 * as the results of any other GATT server operations.
192 * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
193 * to conduct GATT server operations.
Jack Hea355e5e2017-08-22 16:06:54 -0700194 *
Matthew Xieddf7e472013-03-01 18:41:02 -0800195 * @param context App context
196 * @param callback GATT server callback handler that will receive asynchronous callbacks.
197 * @return BluetoothGattServer instance
198 */
199 public BluetoothGattServer openGattServer(Context context,
Jack Hea355e5e2017-08-22 16:06:54 -0700200 BluetoothGattServerCallback callback) {
Ganesh Ganapathi Battab88fa822014-04-18 10:00:40 -0700201
Jack Hea355e5e2017-08-22 16:06:54 -0700202 return (openGattServer(context, callback, BluetoothDevice.TRANSPORT_AUTO));
Ganesh Ganapathi Battab88fa822014-04-18 10:00:40 -0700203 }
204
205 /**
206 * Open a GATT Server
207 * The callback is used to deliver results to Caller, such as connection status as well
208 * as the results of any other GATT server operations.
209 * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
210 * to conduct GATT server operations.
Jack Hea355e5e2017-08-22 16:06:54 -0700211 *
Ganesh Ganapathi Battab88fa822014-04-18 10:00:40 -0700212 * @param context App context
213 * @param callback GATT server callback handler that will receive asynchronous callbacks.
Jack Hea355e5e2017-08-22 16:06:54 -0700214 * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
215 * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
216 * BluetoothDevice#TRANSPORT_LE}
Ganesh Ganapathi Battab88fa822014-04-18 10:00:40 -0700217 * @return BluetoothGattServer instance
218 * @hide
219 */
220 public BluetoothGattServer openGattServer(Context context,
Jack Hea355e5e2017-08-22 16:06:54 -0700221 BluetoothGattServerCallback callback, int transport) {
Matthew Xieddf7e472013-03-01 18:41:02 -0800222 if (context == null || callback == null) {
223 throw new IllegalArgumentException("null parameter: " + context + " " + callback);
224 }
225
226 // TODO(Bluetooth) check whether platform support BLE
227 // Do the check here or in GattServer?
228
229 try {
230 IBluetoothManager managerService = mAdapter.getBluetoothManager();
Matthew Xiecdd94e32013-04-11 16:36:26 -0700231 IBluetoothGatt iGatt = managerService.getBluetoothGatt();
Matthew Xieddf7e472013-03-01 18:41:02 -0800232 if (iGatt == null) {
233 Log.e(TAG, "Fail to get GATT Server connection");
234 return null;
235 }
Jack Hea355e5e2017-08-22 16:06:54 -0700236 BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt, transport);
Matthew Xieddf7e472013-03-01 18:41:02 -0800237 Boolean regStatus = mGattServer.registerCallback(callback);
Jack Hea355e5e2017-08-22 16:06:54 -0700238 return regStatus ? mGattServer : null;
Matthew Xieddf7e472013-03-01 18:41:02 -0800239 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -0700240 Log.e(TAG, "", e);
Matthew Xieddf7e472013-03-01 18:41:02 -0800241 return null;
242 }
243 }
244}