blob: 4afd520c99c5caaf8bd8fc26df1342b997ed83ea [file] [log] [blame]
Nick Pellybd022f42009-08-14 18:33:38 -07001/*
Myles Watson125b5452017-11-27 16:41:47 -08002 * Copyright 2009-2016 The Android Open Source Project
3 * Copyright 2015 Samsung LSI
Nick Pellybd022f42009-08-14 18:33:38 -07004 *
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 */
17
18package android.bluetooth;
19
Tor Norbye2d497522015-04-23 17:10:21 -070020import android.Manifest;
21import android.annotation.IntDef;
22import android.annotation.RequiresPermission;
Nick Pellyde893f52009-09-08 13:15:33 -070023import android.annotation.SdkConstant;
24import android.annotation.SdkConstant.SdkConstantType;
Wei Wangd91f1932015-03-19 15:09:56 -070025import android.annotation.SystemApi;
Mathew Inwood4dc66d32018-08-01 15:07:20 +010026import android.annotation.UnsupportedAppUsage;
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -070027import android.app.ActivityThread;
Wei Wang6d811182014-05-22 12:10:25 -070028import android.bluetooth.le.BluetoothLeAdvertiser;
29import android.bluetooth.le.BluetoothLeScanner;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -080030import android.bluetooth.le.PeriodicAdvertisingManager;
Wei Wangaf74e662014-07-09 14:03:42 -070031import android.bluetooth.le.ScanCallback;
Wei Wangc3059cc2014-07-23 23:34:00 -070032import android.bluetooth.le.ScanFilter;
33import android.bluetooth.le.ScanRecord;
Wei Wang9fb17912014-07-01 15:10:06 -070034import android.bluetooth.le.ScanResult;
Wei Wangaf74e662014-07-09 14:03:42 -070035import android.bluetooth.le.ScanSettings;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070036import android.content.Context;
Adam Lesinski010bf372016-04-11 12:18:18 -070037import android.os.BatteryStats;
Wei Wang46ab7232015-05-07 16:25:33 -070038import android.os.Binder;
Ugo Yu4a33b882019-01-08 09:00:09 +080039import android.os.Handler;
Nick Pellyf242b7b2009-10-08 00:12:45 +020040import android.os.IBinder;
Nick Pellyaef439e2009-09-28 12:33:17 -070041import android.os.ParcelUuid;
Nick Pellybd022f42009-08-14 18:33:38 -070042import android.os.RemoteException;
Adam Lesinski010bf372016-04-11 12:18:18 -070043import android.os.ResultReceiver;
Nick Pellyf242b7b2009-10-08 00:12:45 +020044import android.os.ServiceManager;
Adam Lesinski010bf372016-04-11 12:18:18 -070045import android.os.SynchronousResultReceiver;
Ajay Panickerb6e1daf2016-02-29 16:09:14 -080046import android.os.SystemProperties;
Nick Pellybd022f42009-08-14 18:33:38 -070047import android.util.Log;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070048import android.util.Pair;
Wei Wang18c76932013-10-29 21:05:37 -070049
Nick Pellybd022f42009-08-14 18:33:38 -070050import java.io.IOException;
Tor Norbye2d497522015-04-23 17:10:21 -070051import java.lang.annotation.Retention;
52import java.lang.annotation.RetentionPolicy;
fredc903ac6f2012-04-24 03:59:57 -070053import java.util.ArrayList;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070054import java.util.Arrays;
Nick Pellybd022f42009-08-14 18:33:38 -070055import java.util.Collections;
Matthew Xiecdd94e32013-04-11 16:36:26 -070056import java.util.HashMap;
Wei Wang18c76932013-10-29 21:05:37 -070057import java.util.HashSet;
Wei Wang9fb17912014-07-01 15:10:06 -070058import java.util.List;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070059import java.util.Locale;
Matthew Xiecdd94e32013-04-11 16:36:26 -070060import java.util.Map;
Nick Pelly24bb9b82009-10-02 20:34:18 -070061import java.util.Set;
Nick Pelly16fb88a2009-10-07 07:44:03 +020062import java.util.UUID;
Adam Lesinski010bf372016-04-11 12:18:18 -070063import java.util.concurrent.TimeoutException;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -070064import java.util.concurrent.locks.ReentrantReadWriteLock;
Nick Pellybd022f42009-08-14 18:33:38 -070065
66/**
Scott Main9fab0ae2009-11-03 18:17:59 -080067 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
68 * lets you perform fundamental Bluetooth tasks, such as initiate
69 * device discovery, query a list of bonded (paired) devices,
70 * instantiate a {@link BluetoothDevice} using a known MAC address, and create
71 * a {@link BluetoothServerSocket} to listen for connection requests from other
Matthew Xieb30f91e2013-05-29 10:19:06 -070072 * devices, and start a scan for Bluetooth LE devices.
Scott Main9fab0ae2009-11-03 18:17:59 -080073 *
74 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
Marie Janssen553c8c72017-01-12 16:00:30 -080075 * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}.
76 * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter}
77 * method instead.
78 * </p><p>
Scott Main9fab0ae2009-11-03 18:17:59 -080079 * Fundamentally, this is your starting point for all
80 * Bluetooth actions. Once you have the local adapter, you can get a set of
81 * {@link BluetoothDevice} objects representing all paired devices with
82 * {@link #getBondedDevices()}; start device discovery with
83 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
Stanley Tnge48468d2017-11-22 16:04:40 -080084 * listen for incoming RFComm connection requests with {@link
Stanley Tng1bff4ba2018-06-29 14:05:04 -070085 * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
86 * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
Matthew Xieb30f91e2013-05-29 10:19:06 -070087 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
Marie Janssen553c8c72017-01-12 16:00:30 -080088 * </p>
89 * <p>This class is thread safe.</p>
Scott Main9fab0ae2009-11-03 18:17:59 -080090 * <p class="note"><strong>Note:</strong>
91 * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
92 * permission and some also require the
93 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
Marie Janssen553c8c72017-01-12 16:00:30 -080094 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080095 * <div class="special reference">
96 * <h3>Developer Guides</h3>
Hemal Patel65813df2016-08-17 13:18:14 -070097 * <p>
Jack Hea355e5e2017-08-22 16:06:54 -070098 * For more information about using Bluetooth, read the <a href=
Hemal Patel65813df2016-08-17 13:18:14 -070099 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
100 * guide.
101 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -0800102 * </div>
103 *
Scott Main9fab0ae2009-11-03 18:17:59 -0800104 * {@see BluetoothDevice}
105 * {@see BluetoothServerSocket}
Nick Pellybd022f42009-08-14 18:33:38 -0700106 */
107public final class BluetoothAdapter {
108 private static final String TAG = "BluetoothAdapter";
fredc0f420372012-04-12 00:02:00 -0700109 private static final boolean DBG = true;
Matthew Xie3b6214f2012-08-29 00:12:29 -0700110 private static final boolean VDBG = false;
Nick Pellybd022f42009-08-14 18:33:38 -0700111
Nick Pellyde893f52009-09-08 13:15:33 -0700112 /**
Svet Ganov408abf72015-05-12 19:13:36 -0700113 * Default MAC address reported to a client that does not have the
114 * android.permission.LOCAL_MAC_ADDRESS permission.
115 *
116 * @hide
117 */
118 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
119
120 /**
Nick Pellyb24e11b2009-09-08 17:40:43 -0700121 * Sentinel error value for this class. Guaranteed to not equal any other
122 * integer constant in this class. Provided as a convenience for functions
123 * that require a sentinel error value, for example:
124 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
125 * BluetoothAdapter.ERROR)</code>
126 */
Nick Pelly005b2282009-09-10 10:21:56 -0700127 public static final int ERROR = Integer.MIN_VALUE;
Nick Pellyb24e11b2009-09-08 17:40:43 -0700128
129 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700130 * Broadcast Action: The state of the local Bluetooth adapter has been
131 * changed.
132 * <p>For example, Bluetooth has been turned on or off.
Nick Pelly005b2282009-09-10 10:21:56 -0700133 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700134 * #EXTRA_PREVIOUS_STATE} containing the new and old states
135 * respectively.
136 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
137 */
Myles Watson125b5452017-11-27 16:41:47 -0800138 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
139 ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
Nick Pellybd022f42009-08-14 18:33:38 -0700140
Nick Pellyde893f52009-09-08 13:15:33 -0700141 /**
142 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
143 * intents to request the current power state. Possible values are:
144 * {@link #STATE_OFF},
145 * {@link #STATE_TURNING_ON},
146 * {@link #STATE_ON},
147 * {@link #STATE_TURNING_OFF},
148 */
Myles Watson125b5452017-11-27 16:41:47 -0800149 public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
Nick Pellyde893f52009-09-08 13:15:33 -0700150 /**
151 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
152 * intents to request the previous power state. Possible values are:
153 * {@link #STATE_OFF},
154 * {@link #STATE_TURNING_ON},
155 * {@link #STATE_ON},
Etan Cohenfd840dd2015-04-23 18:25:08 -0700156 * {@link #STATE_TURNING_OFF}
Nick Pellyde893f52009-09-08 13:15:33 -0700157 */
158 public static final String EXTRA_PREVIOUS_STATE =
Nick Pelly005b2282009-09-10 10:21:56 -0700159 "android.bluetooth.adapter.extra.PREVIOUS_STATE";
Nick Pellybd022f42009-08-14 18:33:38 -0700160
Tor Norbye2d497522015-04-23 17:10:21 -0700161 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700162 @IntDef(prefix = { "STATE_" }, value = {
Myles Watson125b5452017-11-27 16:41:47 -0800163 STATE_OFF,
164 STATE_TURNING_ON,
165 STATE_ON,
166 STATE_TURNING_OFF,
167 STATE_BLE_TURNING_ON,
168 STATE_BLE_ON,
169 STATE_BLE_TURNING_OFF
170 })
Tor Norbye2d497522015-04-23 17:10:21 -0700171 @Retention(RetentionPolicy.SOURCE)
Myles Watson125b5452017-11-27 16:41:47 -0800172 public @interface AdapterState {}
Tor Norbye2d497522015-04-23 17:10:21 -0700173
Nick Pellyde893f52009-09-08 13:15:33 -0700174 /**
175 * Indicates the local Bluetooth adapter is off.
176 */
Nick Pelly005b2282009-09-10 10:21:56 -0700177 public static final int STATE_OFF = 10;
Nick Pellyde893f52009-09-08 13:15:33 -0700178 /**
179 * Indicates the local Bluetooth adapter is turning on. However local
180 * clients should wait for {@link #STATE_ON} before attempting to
181 * use the adapter.
182 */
Nick Pelly005b2282009-09-10 10:21:56 -0700183 public static final int STATE_TURNING_ON = 11;
Nick Pellyde893f52009-09-08 13:15:33 -0700184 /**
185 * Indicates the local Bluetooth adapter is on, and ready for use.
186 */
Nick Pelly005b2282009-09-10 10:21:56 -0700187 public static final int STATE_ON = 12;
Nick Pellyde893f52009-09-08 13:15:33 -0700188 /**
189 * Indicates the local Bluetooth adapter is turning off. Local clients
190 * should immediately attempt graceful disconnection of any remote links.
191 */
Nick Pelly005b2282009-09-10 10:21:56 -0700192 public static final int STATE_TURNING_OFF = 13;
Nick Pellyde893f52009-09-08 13:15:33 -0700193
194 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800195 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
Jack Hea355e5e2017-08-22 16:06:54 -0700196 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800197 * @hide
198 */
199 public static final int STATE_BLE_TURNING_ON = 14;
200
201 /**
202 * Indicates the local Bluetooth adapter is in LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700203 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800204 * @hide
205 */
206 public static final int STATE_BLE_ON = 15;
207
208 /**
209 * Indicates the local Bluetooth adapter is turning off LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700210 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800211 * @hide
212 */
213 public static final int STATE_BLE_TURNING_OFF = 16;
214
215 /**
Stanley Tnge48468d2017-11-22 16:04:40 -0800216 * UUID of the GATT Read Characteristics for LE_PSM value.
217 *
218 * @hide
219 */
220 public static final UUID LE_PSM_CHARACTERISTIC_UUID =
221 UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
222
223 /**
Marie Janssencb21ad72016-12-13 10:51:02 -0800224 * Human-readable string helper for AdapterState
Jack Hea355e5e2017-08-22 16:06:54 -0700225 *
Marie Janssencb21ad72016-12-13 10:51:02 -0800226 * @hide
227 */
228 public static String nameForState(@AdapterState int state) {
Jack Hea355e5e2017-08-22 16:06:54 -0700229 switch (state) {
230 case STATE_OFF:
231 return "OFF";
232 case STATE_TURNING_ON:
233 return "TURNING_ON";
234 case STATE_ON:
235 return "ON";
236 case STATE_TURNING_OFF:
237 return "TURNING_OFF";
238 case STATE_BLE_TURNING_ON:
239 return "BLE_TURNING_ON";
240 case STATE_BLE_ON:
241 return "BLE_ON";
242 case STATE_BLE_TURNING_OFF:
243 return "BLE_TURNING_OFF";
244 default:
245 return "?!?!? (" + state + ")";
Marie Janssencb21ad72016-12-13 10:51:02 -0800246 }
247 }
248
249 /**
Nick Pelly18b1e792009-09-24 11:14:15 -0700250 * Activity Action: Show a system activity that requests discoverable mode.
Scott Main6d95fc02009-11-19 17:00:19 -0800251 * This activity will also request the user to turn on Bluetooth if it
Nick Pelly1acdcc12009-09-28 10:33:55 -0700252 * is not currently enabled.
Nick Pelly18b1e792009-09-24 11:14:15 -0700253 * <p>Discoverable mode is equivalent to {@link
254 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
255 * this Bluetooth adapter when they perform a discovery.
Scott Main6d95fc02009-11-19 17:00:19 -0800256 * <p>For privacy, Android is not discoverable by default.
257 * <p>The sender of this Intent can optionally use extra field {@link
Nick Pelly18b1e792009-09-24 11:14:15 -0700258 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
259 * discoverability. Currently the default duration is 120 seconds, and
260 * maximum duration is capped at 300 seconds for each request.
261 * <p>Notification of the result of this activity is posted using the
262 * {@link android.app.Activity#onActivityResult} callback. The
263 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800264 * will be the duration (in seconds) of discoverability or
265 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
266 * discoverability or an error has occurred.
Nick Pelly18b1e792009-09-24 11:14:15 -0700267 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
Scott Main6d95fc02009-11-19 17:00:19 -0800268 * for global notification whenever the scan mode changes. For example, an
269 * application can be notified when the device has ended discoverability.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700270 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pelly18b1e792009-09-24 11:14:15 -0700271 */
Myles Watson125b5452017-11-27 16:41:47 -0800272 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
273 ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
Nick Pelly18b1e792009-09-24 11:14:15 -0700274
275 /**
276 * Used as an optional int extra field in {@link
277 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
278 * for discoverability in seconds. The current default is 120 seconds, and
279 * requests over 300 seconds will be capped. These values could change.
280 */
281 public static final String EXTRA_DISCOVERABLE_DURATION =
282 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
283
284 /**
Nick Pelly1acdcc12009-09-28 10:33:55 -0700285 * Activity Action: Show a system activity that allows the user to turn on
286 * Bluetooth.
287 * <p>This system activity will return once Bluetooth has completed turning
288 * on, or the user has decided not to turn Bluetooth on.
289 * <p>Notification of the result of this activity is posted using the
290 * {@link android.app.Activity#onActivityResult} callback. The
291 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800292 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
293 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
294 * has rejected the request or an error has occurred.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700295 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
296 * for global notification whenever Bluetooth is turned on or off.
297 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
298 */
Myles Watson125b5452017-11-27 16:41:47 -0800299 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
300 ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
Nick Pelly1acdcc12009-09-28 10:33:55 -0700301
302 /**
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700303 * Activity Action: Show a system activity that allows the user to turn off
304 * Bluetooth. This is used only if permission review is enabled which is for
305 * apps targeting API less than 23 require a permission review before any of
306 * the app's components can run.
307 * <p>This system activity will return once Bluetooth has completed turning
308 * off, or the user has decided not to turn Bluetooth off.
309 * <p>Notification of the result of this activity is posted using the
310 * {@link android.app.Activity#onActivityResult} callback. The
311 * <code>resultCode</code>
312 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
313 * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
314 * has rejected the request or an error has occurred.
315 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
316 * for global notification whenever Bluetooth is turned on or off.
317 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
318 *
319 * @hide
320 */
Myles Watson125b5452017-11-27 16:41:47 -0800321 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
322 ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE";
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700323
324 /**
Wei Wangd91f1932015-03-19 15:09:56 -0700325 * Activity Action: Show a system activity that allows user to enable BLE scans even when
326 * Bluetooth is turned off.<p>
327 *
328 * Notification of result of this activity is posted using
329 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
330 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
331 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
332 * error occurred.
333 *
334 * @hide
335 */
336 @SystemApi
337 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
338 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
339 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
340
341 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700342 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
343 * has changed.
Nick Pelly005b2282009-09-10 10:21:56 -0700344 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700345 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
346 * respectively.
347 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
348 */
Myles Watson125b5452017-11-27 16:41:47 -0800349 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
350 ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
Nick Pellyde893f52009-09-08 13:15:33 -0700351
352 /**
353 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
354 * intents to request the current scan mode. Possible values are:
355 * {@link #SCAN_MODE_NONE},
356 * {@link #SCAN_MODE_CONNECTABLE},
357 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
358 */
Nick Pelly005b2282009-09-10 10:21:56 -0700359 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700360 /**
361 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
362 * intents to request the previous scan mode. Possible values are:
363 * {@link #SCAN_MODE_NONE},
364 * {@link #SCAN_MODE_CONNECTABLE},
365 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
366 */
367 public static final String EXTRA_PREVIOUS_SCAN_MODE =
Nick Pelly005b2282009-09-10 10:21:56 -0700368 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700369
Tor Norbye2d497522015-04-23 17:10:21 -0700370 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700371 @IntDef(prefix = { "SCAN_" }, value = {
372 SCAN_MODE_NONE,
373 SCAN_MODE_CONNECTABLE,
374 SCAN_MODE_CONNECTABLE_DISCOVERABLE
375 })
Tor Norbye2d497522015-04-23 17:10:21 -0700376 @Retention(RetentionPolicy.SOURCE)
Myles Watson125b5452017-11-27 16:41:47 -0800377 public @interface ScanMode {}
Tor Norbye2d497522015-04-23 17:10:21 -0700378
Nick Pellyde893f52009-09-08 13:15:33 -0700379 /**
380 * Indicates that both inquiry scan and page scan are disabled on the local
381 * Bluetooth adapter. Therefore this device is neither discoverable
382 * nor connectable from remote Bluetooth devices.
383 */
Nick Pelly005b2282009-09-10 10:21:56 -0700384 public static final int SCAN_MODE_NONE = 20;
Nick Pellyde893f52009-09-08 13:15:33 -0700385 /**
386 * Indicates that inquiry scan is disabled, but page scan is enabled on the
387 * local Bluetooth adapter. Therefore this device is not discoverable from
388 * remote Bluetooth devices, but is connectable from remote devices that
389 * have previously discovered this device.
390 */
Nick Pelly005b2282009-09-10 10:21:56 -0700391 public static final int SCAN_MODE_CONNECTABLE = 21;
Nick Pellyde893f52009-09-08 13:15:33 -0700392 /**
393 * Indicates that both inquiry scan and page scan are enabled on the local
394 * Bluetooth adapter. Therefore this device is both discoverable and
395 * connectable from remote Bluetooth devices.
396 */
Nick Pelly005b2282009-09-10 10:21:56 -0700397 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
Nick Pellybd022f42009-08-14 18:33:38 -0700398
Nick Pelly005b2282009-09-10 10:21:56 -0700399 /**
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -0700400 * Device only has a display.
401 *
402 * @hide
403 */
404 public static final int IO_CAPABILITY_OUT = 0;
405
406 /**
407 * Device has a display and the ability to input Yes/No.
408 *
409 * @hide
410 */
411 public static final int IO_CAPABILITY_IO = 1;
412
413 /**
414 * Device only has a keyboard for entry but no display.
415 *
416 * @hide
417 */
418 public static final int IO_CAPABILITY_IN = 2;
419
420 /**
421 * Device has no Input or Output capability.
422 *
423 * @hide
424 */
425 public static final int IO_CAPABILITY_NONE = 3;
426
427 /**
428 * Device has a display and a full keyboard.
429 *
430 * @hide
431 */
432 public static final int IO_CAPABILITY_KBDISP = 4;
433
434 /**
435 * Maximum range value for Input/Output capabilities.
436 *
437 * <p>This should be updated when adding a new Input/Output capability. Other code
438 * like validation depends on this being accurate.
439 *
440 * @hide
441 */
442 public static final int IO_CAPABILITY_MAX = 5;
443
444 /**
445 * The Input/Output capability of the device is unknown.
446 *
447 * @hide
448 */
449 public static final int IO_CAPABILITY_UNKNOWN = 255;
450
Pulkit Bhuwalka80238142018-04-20 16:56:53 -0700451 /** @hide */
452 @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE,
453 IO_CAPABILITY_KBDISP})
454 @Retention(RetentionPolicy.SOURCE)
455 public @interface IoCapability {}
456
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -0700457 /**
Nick Pelly005b2282009-09-10 10:21:56 -0700458 * Broadcast Action: The local Bluetooth adapter has started the remote
459 * device discovery process.
460 * <p>This usually involves an inquiry scan of about 12 seconds, followed
461 * by a page scan of each new device to retrieve its Bluetooth name.
462 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
463 * remote Bluetooth devices are found.
464 * <p>Device discovery is a heavyweight procedure. New connections to
465 * remote Bluetooth devices should not be attempted while discovery is in
466 * progress, and existing connections will experience limited bandwidth
467 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
468 * discovery.
469 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
470 */
Myles Watson125b5452017-11-27 16:41:47 -0800471 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
472 ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
Nick Pelly005b2282009-09-10 10:21:56 -0700473 /**
474 * Broadcast Action: The local Bluetooth adapter has finished the device
475 * discovery process.
476 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
477 */
Myles Watson125b5452017-11-27 16:41:47 -0800478 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
479 ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
Nick Pelly005b2282009-09-10 10:21:56 -0700480
481 /**
482 * Broadcast Action: The local Bluetooth adapter has changed its friendly
483 * Bluetooth name.
484 * <p>This name is visible to remote Bluetooth devices.
485 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
486 * the name.
487 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
488 */
Myles Watson125b5452017-11-27 16:41:47 -0800489 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
490 ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
Nick Pelly005b2282009-09-10 10:21:56 -0700491 /**
492 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
493 * intents to request the local Bluetooth name.
494 */
495 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
496
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700497 /**
498 * Intent used to broadcast the change in connection state of the local
499 * Bluetooth adapter to a profile of the remote device. When the adapter is
500 * not connected to any profiles of any remote devices and it attempts a
Ricardo Loo Forondaf710a232018-01-24 17:49:18 -0800501 * connection to a profile this intent will be sent. Once connected, this intent
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700502 * will not be sent for any more connection attempts to any profiles of any
503 * remote device. When the adapter disconnects from the last profile its
504 * connected to of any remote device, this intent will be sent.
505 *
506 * <p> This intent is useful for applications that are only concerned about
507 * whether the local adapter is connected to any profile of any device and
508 * are not really concerned about which profile. For example, an application
509 * which displays an icon to display whether Bluetooth is connected or not
510 * can use this intent.
511 *
512 * <p>This intent will have 3 extras:
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800513 * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
514 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700515 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
516 *
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800517 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
518 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700519 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
520 *
521 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
522 */
Myles Watson125b5452017-11-27 16:41:47 -0800523 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
524 ACTION_CONNECTION_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700525 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700526
527 /**
528 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
529 *
530 * This extra represents the current connection state.
531 */
532 public static final String EXTRA_CONNECTION_STATE =
Jack Hea355e5e2017-08-22 16:06:54 -0700533 "android.bluetooth.adapter.extra.CONNECTION_STATE";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700534
535 /**
536 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
537 *
538 * This extra represents the previous connection state.
539 */
540 public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
Jack Hea355e5e2017-08-22 16:06:54 -0700541 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700542
Nitin Arorad055adb2015-03-02 15:03:51 -0800543 /**
544 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700545 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800546 * @hide
547 */
Myles Watson125b5452017-11-27 16:41:47 -0800548 @SystemApi public static final String ACTION_BLE_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700549 "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800550
551 /**
Stanley Tngdd749b02017-04-17 22:35:45 -0700552 * Intent used to broadcast the change in the Bluetooth address
553 * of the local Bluetooth adapter.
554 * <p>Always contains the extra field {@link
555 * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
556 *
557 * Note: only system level processes are allowed to send this
558 * defined broadcast.
559 *
560 * @hide
561 */
562 public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700563 "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
Stanley Tngdd749b02017-04-17 22:35:45 -0700564
565 /**
566 * Used as a String extra field in {@link
567 * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
568 * Bluetooth address.
569 *
570 * @hide
571 */
572 public static final String EXTRA_BLUETOOTH_ADDRESS =
Jack Hea355e5e2017-08-22 16:06:54 -0700573 "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
Stanley Tngdd749b02017-04-17 22:35:45 -0700574
575 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800576 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
577 * by BLE Always on enabled application to know the ACL_CONNECTED event
578 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
579 * as Bluetooth LE is the only feature available in STATE_BLE_ON
580 *
581 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
582 * works in Bluetooth state STATE_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700583 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800584 * @hide
585 */
586 public static final String ACTION_BLE_ACL_CONNECTED =
Jack Hea355e5e2017-08-22 16:06:54 -0700587 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800588
589 /**
590 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
591 * by BLE Always on enabled application to know the ACL_DISCONNECTED event
592 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
593 * LE is the only feature available in STATE_BLE_ON
594 *
595 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
596 * works in Bluetooth state STATE_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700597 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800598 * @hide
599 */
600 public static final String ACTION_BLE_ACL_DISCONNECTED =
Jack Hea355e5e2017-08-22 16:06:54 -0700601 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800602
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700603 /** The profile is in disconnected state */
Jack Hebd020a62018-03-02 13:11:27 -0800604 public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700605 /** The profile is in connecting state */
Jack Hebd020a62018-03-02 13:11:27 -0800606 public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700607 /** The profile is in connected state */
Jack Hebd020a62018-03-02 13:11:27 -0800608 public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700609 /** The profile is in disconnecting state */
Jack Hebd020a62018-03-02 13:11:27 -0800610 public static final int STATE_DISCONNECTING =
611 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700612
Nick Pellyf242b7b2009-10-08 00:12:45 +0200613 /** @hide */
fredc0f420372012-04-12 00:02:00 -0700614 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
Nitin Arorad055adb2015-03-02 15:03:51 -0800615 private final IBinder mToken;
Nick Pellyf242b7b2009-10-08 00:12:45 +0200616
Casper Bonde238e0f92015-04-09 09:24:48 +0200617
Jack Hea355e5e2017-08-22 16:06:54 -0700618 /**
619 * When creating a ServerSocket using listenUsingRfcommOn() or
620 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
621 * a ServerSocket that auto assigns a channel number to the first
622 * bluetooth socket.
623 * The channel number assigned to this first Bluetooth Socket will
624 * be stored in the ServerSocket, and reused for subsequent Bluetooth
625 * sockets.
626 *
627 * @hide
628 */
Casper Bonde238e0f92015-04-09 09:24:48 +0200629 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
630
631
Nick Pelly005b2282009-09-10 10:21:56 -0700632 private static final int ADDRESS_LENGTH = 17;
Nick Pellybd022f42009-08-14 18:33:38 -0700633
Nick Pellyf242b7b2009-10-08 00:12:45 +0200634 /**
Jake Hambyf51eada2010-09-21 13:39:53 -0700635 * Lazily initialized singleton. Guaranteed final after first object
Nick Pellyf242b7b2009-10-08 00:12:45 +0200636 * constructed.
637 */
638 private static BluetoothAdapter sAdapter;
639
Wei Wangc3059cc2014-07-23 23:34:00 -0700640 private static BluetoothLeScanner sBluetoothLeScanner;
641 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800642 private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
Wei Wangc3059cc2014-07-23 23:34:00 -0700643
fredc0f420372012-04-12 00:02:00 -0700644 private final IBluetoothManager mManagerService;
Mathew Inwood4dc66d32018-08-01 15:07:20 +0100645 @UnsupportedAppUsage
fredc0f420372012-04-12 00:02:00 -0700646 private IBluetooth mService;
Zach Johnson57e6e902018-12-12 17:11:25 -0800647 private Context mContext;
Myles Watson125b5452017-11-27 16:41:47 -0800648 private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
Nick Pellybd022f42009-08-14 18:33:38 -0700649
Wei Wangf3055892014-03-11 22:22:41 -0700650 private final Object mLock = new Object();
Wei Wangc3059cc2014-07-23 23:34:00 -0700651 private final Map<LeScanCallback, ScanCallback> mLeScanClients;
Ugo Yu4a33b882019-01-08 09:00:09 +0800652 private static final Map<BluetoothDevice, List<Pair<MetadataListener, Handler>>>
653 sMetadataListeners = new HashMap<>();
654
655 /**
656 * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
657 * implementation.
658 */
659 private static final IBluetoothMetadataListener sBluetoothMetadataListener =
660 new IBluetoothMetadataListener.Stub() {
661 @Override
662 public void onMetadataChanged(BluetoothDevice device, int key, String value) {
663 synchronized (sMetadataListeners) {
664 if (sMetadataListeners.containsKey(device)) {
665 List<Pair<MetadataListener, Handler>> list = sMetadataListeners.get(device);
666 for (Pair<MetadataListener, Handler> pair : list) {
667 MetadataListener listener = pair.first;
668 Handler handler = pair.second;
669 handler.post(() -> {
670 listener.onMetadataChanged(device, key, value);
671 });
672 }
673 }
674 }
675 return;
676 }
677 };
Matthew Xie484867a2011-08-25 16:45:58 -0700678
Nick Pellybd022f42009-08-14 18:33:38 -0700679 /**
Nick Pellyf242b7b2009-10-08 00:12:45 +0200680 * Get a handle to the default local Bluetooth adapter.
681 * <p>Currently Android only supports one Bluetooth adapter, but the API
682 * could be extended to support more. This will always return the default
683 * adapter.
Marie Janssen553c8c72017-01-12 16:00:30 -0800684 * </p>
Jack Hea355e5e2017-08-22 16:06:54 -0700685 *
686 * @return the default local adapter, or null if Bluetooth is not supported on this hardware
687 * platform
Nick Pellyf242b7b2009-10-08 00:12:45 +0200688 */
689 public static synchronized BluetoothAdapter getDefaultAdapter() {
690 if (sAdapter == null) {
fredc0f420372012-04-12 00:02:00 -0700691 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200692 if (b != null) {
fredc0f420372012-04-12 00:02:00 -0700693 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
694 sAdapter = new BluetoothAdapter(managerService);
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -0800695 } else {
696 Log.e(TAG, "Bluetooth binder is null");
Nick Pellyf242b7b2009-10-08 00:12:45 +0200697 }
698 }
699 return sAdapter;
700 }
701
702 /**
703 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
Nick Pellybd022f42009-08-14 18:33:38 -0700704 */
fredc0f420372012-04-12 00:02:00 -0700705 BluetoothAdapter(IBluetoothManager managerService) {
706
707 if (managerService == null) {
708 throw new IllegalArgumentException("bluetooth manager service is null");
Nick Pellybd022f42009-08-14 18:33:38 -0700709 }
fredc0f420372012-04-12 00:02:00 -0700710 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700711 mServiceLock.writeLock().lock();
fredc0f420372012-04-12 00:02:00 -0700712 mService = managerService.registerAdapter(mManagerCallback);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700713 } catch (RemoteException e) {
714 Log.e(TAG, "", e);
715 } finally {
716 mServiceLock.writeLock().unlock();
717 }
fredc0f420372012-04-12 00:02:00 -0700718 mManagerService = managerService;
Wei Wangc3059cc2014-07-23 23:34:00 -0700719 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
Nitin Arorad055adb2015-03-02 15:03:51 -0800720 mToken = new Binder();
Nick Pellybd022f42009-08-14 18:33:38 -0700721 }
722
723 /**
Nick Pelly45e27042009-08-19 11:00:00 -0700724 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
725 * address.
726 * <p>Valid Bluetooth hardware addresses must be upper case, in a format
Nick Pelly005b2282009-09-10 10:21:56 -0700727 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
728 * available to validate a Bluetooth address.
Nick Pelly45e27042009-08-19 11:00:00 -0700729 * <p>A {@link BluetoothDevice} will always be returned for a valid
730 * hardware address, even if this adapter has never seen that device.
Nick Pellyde893f52009-09-08 13:15:33 -0700731 *
Nick Pellybd022f42009-08-14 18:33:38 -0700732 * @param address valid Bluetooth MAC address
Nick Pelly45e27042009-08-19 11:00:00 -0700733 * @throws IllegalArgumentException if address is invalid
Nick Pellybd022f42009-08-14 18:33:38 -0700734 */
735 public BluetoothDevice getRemoteDevice(String address) {
736 return new BluetoothDevice(address);
737 }
738
739 /**
Nick Pelly75596b42011-12-07 15:03:55 -0800740 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
741 * address.
742 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
743 * expects the address in network byte order (MSB first).
744 * <p>A {@link BluetoothDevice} will always be returned for a valid
745 * hardware address, even if this adapter has never seen that device.
746 *
747 * @param address Bluetooth MAC address (6 bytes)
748 * @throws IllegalArgumentException if address is invalid
749 */
750 public BluetoothDevice getRemoteDevice(byte[] address) {
751 if (address == null || address.length != 6) {
752 throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
753 }
Myles Watson125b5452017-11-27 16:41:47 -0800754 return new BluetoothDevice(
755 String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1],
756 address[2], address[3], address[4], address[5]));
Nick Pelly75596b42011-12-07 15:03:55 -0800757 }
758
759 /**
Prerepa Viswanadham248edc32014-10-15 16:36:01 -0700760 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
761 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
762 * supported on this device.
Wei Wangc3059cc2014-07-23 23:34:00 -0700763 * <p>
764 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
765 * on this device before calling this method.
Wei Wangadf6aff2014-05-20 06:30:20 +0000766 */
767 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
Myles Watson125b5452017-11-27 16:41:47 -0800768 if (!getLeAccess()) {
769 return null;
770 }
Jack Hea355e5e2017-08-22 16:06:54 -0700771 synchronized (mLock) {
Wei Wangc3059cc2014-07-23 23:34:00 -0700772 if (sBluetoothLeAdvertiser == null) {
773 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
774 }
775 }
776 return sBluetoothLeAdvertiser;
Wei Wangadf6aff2014-05-20 06:30:20 +0000777 }
778
779 /**
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800780 * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
781 * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
782 * Advertising is not supported on this device.
783 * <p>
784 * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
785 * supported on this device before calling this method.
Jack Hea355e5e2017-08-22 16:06:54 -0700786 *
Jakub Pawlowskia537b3f2017-03-29 17:00:44 -0700787 * @hide
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800788 */
789 public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
Jack Hea355e5e2017-08-22 16:06:54 -0700790 if (!getLeAccess()) {
791 return null;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800792 }
Jack Hea355e5e2017-08-22 16:06:54 -0700793
794 if (!isLePeriodicAdvertisingSupported()) {
795 return null;
796 }
797
798 synchronized (mLock) {
799 if (sPeriodicAdvertisingManager == null) {
Myles Watson125b5452017-11-27 16:41:47 -0800800 sPeriodicAdvertisingManager = new PeriodicAdvertisingManager(mManagerService);
Jack Hea355e5e2017-08-22 16:06:54 -0700801 }
802 }
803 return sPeriodicAdvertisingManager;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800804 }
805
806 /**
Wei Wangadf6aff2014-05-20 06:30:20 +0000807 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
808 */
809 public BluetoothLeScanner getBluetoothLeScanner() {
Myles Watson125b5452017-11-27 16:41:47 -0800810 if (!getLeAccess()) {
811 return null;
812 }
Jack Hea355e5e2017-08-22 16:06:54 -0700813 synchronized (mLock) {
Wei Wangc3059cc2014-07-23 23:34:00 -0700814 if (sBluetoothLeScanner == null) {
815 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
816 }
817 }
818 return sBluetoothLeScanner;
Wei Wangadf6aff2014-05-20 06:30:20 +0000819 }
820
821 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700822 * Return true if Bluetooth is currently enabled and ready for use.
823 * <p>Equivalent to:
824 * <code>getBluetoothState() == STATE_ON</code>
Nick Pellybd022f42009-08-14 18:33:38 -0700825 *
Nick Pellyde893f52009-09-08 13:15:33 -0700826 * @return true if the local adapter is turned on
Nick Pellybd022f42009-08-14 18:33:38 -0700827 */
Tor Norbye2d497522015-04-23 17:10:21 -0700828 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -0700829 public boolean isEnabled() {
830 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700831 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -0800832 if (mService != null) {
833 return mService.isEnabled();
834 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700835 } catch (RemoteException e) {
836 Log.e(TAG, "", e);
837 } finally {
838 mServiceLock.readLock().unlock();
839 }
840
Nick Pellybd022f42009-08-14 18:33:38 -0700841 return false;
842 }
843
844 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800845 * Return true if Bluetooth LE(Always BLE On feature) is currently
846 * enabled and ready for use
847 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
848 *
849 * @return true if the local Bluetooth LE adapter is turned on
850 * @hide
851 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700852 @SystemApi
853 public boolean isLeEnabled() {
Jack Hea355e5e2017-08-22 16:06:54 -0700854 final int state = getLeState();
Myles Watson125b5452017-11-27 16:41:47 -0800855 if (DBG) {
856 Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
857 }
Jack Hea355e5e2017-08-22 16:06:54 -0700858 return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
Nitin Arorad055adb2015-03-02 15:03:51 -0800859 }
860
861 /**
Marie Janssen59804562016-12-28 14:13:21 -0800862 * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
Nitin Arorad055adb2015-03-02 15:03:51 -0800863 *
864 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
865 * to STATE_OFF and completely shut-down Bluetooth
866 *
867 * <p> If the Adapter state is STATE_ON, This would unregister the existance of
868 * special Bluetooth LE application and hence the further turning off of Bluetooth
869 * from UI would ensure the complete turn-off of Bluetooth rather than staying back
870 * BLE only state
871 *
872 * <p>This is an asynchronous call: it will return immediately, and
873 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
874 * to be notified of subsequent adapter state changes If this call returns
875 * true, then the adapter state will immediately transition from {@link
876 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
877 * later transition to either {@link #STATE_BLE_ON} or {@link
878 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
879 * If this call returns false then there was an
880 * immediate problem that will prevent the QAdapter from being turned off -
881 * such as the QAadapter already being turned off.
882 *
Jack Hea355e5e2017-08-22 16:06:54 -0700883 * @return true to indicate success, or false on immediate error
Nitin Arorad055adb2015-03-02 15:03:51 -0800884 * @hide
885 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700886 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800887 public boolean disableBLE() {
Myles Watson125b5452017-11-27 16:41:47 -0800888 if (!isBleScanAlwaysAvailable()) {
889 return false;
890 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800891
892 int state = getLeState();
Marie Janssen59804562016-12-28 14:13:21 -0800893 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
894 String packageName = ActivityThread.currentPackageName();
Myles Watson125b5452017-11-27 16:41:47 -0800895 if (DBG) {
896 Log.d(TAG, "disableBLE(): de-registering " + packageName);
897 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800898 try {
Marie Janssen59804562016-12-28 14:13:21 -0800899 mManagerService.updateBleAppCount(mToken, false, packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800900 } catch (RemoteException e) {
901 Log.e(TAG, "", e);
902 }
903 return true;
Nitin Arorad055adb2015-03-02 15:03:51 -0800904 }
905
Myles Watson125b5452017-11-27 16:41:47 -0800906 if (DBG) {
907 Log.d(TAG, "disableBLE(): Already disabled");
908 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800909 return false;
910 }
911
912 /**
Marie Janssen59804562016-12-28 14:13:21 -0800913 * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
Nitin Arorad055adb2015-03-02 15:03:51 -0800914 *
Marie Janssen59804562016-12-28 14:13:21 -0800915 * enableBLE registers the existence of an app using only LE functions.
916 *
917 * enableBLE may enable Bluetooth to an LE only mode so that an app can use
918 * LE related features (BluetoothGatt or BluetoothGattServer classes)
919 *
920 * If the user disables Bluetooth while an app is registered to use LE only features,
921 * Bluetooth will remain on in LE only mode for the app.
922 *
923 * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
924 *
925 * <p>This is an asynchronous call: it returns immediately, and
Nitin Arorad055adb2015-03-02 15:03:51 -0800926 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
Marie Janssen59804562016-12-28 14:13:21 -0800927 * to be notified of adapter state changes.
928 *
929 * If this call returns * true, then the adapter state is either in a mode where
930 * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
931 * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
932 *
933 * If this call returns false then there was an immediate problem that prevents the
934 * adapter from being turned on - such as Airplane mode.
935 *
936 * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
Nitin Arorad055adb2015-03-02 15:03:51 -0800937 * states, It includes all the classic Bluetooth Adapter states along with
938 * internal BLE only states
939 *
Jack Hea355e5e2017-08-22 16:06:54 -0700940 * @return true to indicate Bluetooth LE will be available, or false on immediate error
Nitin Arorad055adb2015-03-02 15:03:51 -0800941 * @hide
942 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700943 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800944 public boolean enableBLE() {
Myles Watson125b5452017-11-27 16:41:47 -0800945 if (!isBleScanAlwaysAvailable()) {
946 return false;
947 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800948
Nitin Arorad055adb2015-03-02 15:03:51 -0800949 try {
Marie Janssen59804562016-12-28 14:13:21 -0800950 String packageName = ActivityThread.currentPackageName();
951 mManagerService.updateBleAppCount(mToken, true, packageName);
Marie Janssen6a383a72016-10-25 10:47:51 -0700952 if (isLeEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -0800953 if (DBG) {
954 Log.d(TAG, "enableBLE(): Bluetooth already enabled");
955 }
Marie Janssen6a383a72016-10-25 10:47:51 -0700956 return true;
957 }
Myles Watson125b5452017-11-27 16:41:47 -0800958 if (DBG) {
959 Log.d(TAG, "enableBLE(): Calling enable");
960 }
Marie Janssen59804562016-12-28 14:13:21 -0800961 return mManagerService.enable(packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800962 } catch (RemoteException e) {
963 Log.e(TAG, "", e);
964 }
965
966 return false;
967 }
968
969 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700970 * Get the current state of the local Bluetooth adapter.
971 * <p>Possible return values are
972 * {@link #STATE_OFF},
973 * {@link #STATE_TURNING_ON},
974 * {@link #STATE_ON},
975 * {@link #STATE_TURNING_OFF}.
Nick Pellybd022f42009-08-14 18:33:38 -0700976 *
Nick Pellyde893f52009-09-08 13:15:33 -0700977 * @return current state of Bluetooth adapter
Nick Pellybd022f42009-08-14 18:33:38 -0700978 */
Tor Norbye2d497522015-04-23 17:10:21 -0700979 @RequiresPermission(Manifest.permission.BLUETOOTH)
980 @AdapterState
Nick Pellyde893f52009-09-08 13:15:33 -0700981 public int getState() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700982 int state = BluetoothAdapter.STATE_OFF;
983
Nick Pellybd022f42009-08-14 18:33:38 -0700984 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700985 mServiceLock.readLock().lock();
986 if (mService != null) {
987 state = mService.getState();
fredc0f420372012-04-12 00:02:00 -0700988 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700989 } catch (RemoteException e) {
990 Log.e(TAG, "", e);
991 } finally {
992 mServiceLock.readLock().unlock();
993 }
994
995 // Consider all internal states as OFF
Myles Watson125b5452017-11-27 16:41:47 -0800996 if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700997 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
998 if (VDBG) {
Myles Watson125b5452017-11-27 16:41:47 -0800999 Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
Jack Hea355e5e2017-08-22 16:06:54 -07001000 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001001 state = BluetoothAdapter.STATE_OFF;
1002 }
Jack Hea355e5e2017-08-22 16:06:54 -07001003 if (VDBG) {
Myles Watson125b5452017-11-27 16:41:47 -08001004 Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(
1005 state));
Jack Hea355e5e2017-08-22 16:06:54 -07001006 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001007 return state;
Nick Pellybd022f42009-08-14 18:33:38 -07001008 }
1009
1010 /**
Nitin Arorad055adb2015-03-02 15:03:51 -08001011 * Get the current state of the local Bluetooth adapter
1012 * <p>This returns current internal state of Adapter including LE ON/OFF
1013 *
1014 * <p>Possible return values are
1015 * {@link #STATE_OFF},
1016 * {@link #STATE_BLE_TURNING_ON},
1017 * {@link #STATE_BLE_ON},
1018 * {@link #STATE_TURNING_ON},
1019 * {@link #STATE_ON},
1020 * {@link #STATE_TURNING_OFF},
1021 * {@link #STATE_BLE_TURNING_OFF}.
Nitin Arorad055adb2015-03-02 15:03:51 -08001022 *
1023 * @return current state of Bluetooth adapter
1024 * @hide
1025 */
Tor Norbye2d497522015-04-23 17:10:21 -07001026 @RequiresPermission(Manifest.permission.BLUETOOTH)
1027 @AdapterState
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001028 @UnsupportedAppUsage
Nitin Arorad055adb2015-03-02 15:03:51 -08001029 public int getLeState() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001030 int state = BluetoothAdapter.STATE_OFF;
1031
Nitin Arorad055adb2015-03-02 15:03:51 -08001032 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001033 mServiceLock.readLock().lock();
1034 if (mService != null) {
1035 state = mService.getState();
Nitin Arorad055adb2015-03-02 15:03:51 -08001036 }
1037 } catch (RemoteException e) {
1038 Log.e(TAG, "", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001039 } finally {
1040 mServiceLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -08001041 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001042
Myles Watson125b5452017-11-27 16:41:47 -08001043 if (VDBG) {
1044 Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state));
1045 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001046 return state;
Nitin Arorad055adb2015-03-02 15:03:51 -08001047 }
1048
1049 boolean getLeAccess() {
Jack Hea355e5e2017-08-22 16:06:54 -07001050 if (getLeState() == STATE_ON) {
Nitin Arorad055adb2015-03-02 15:03:51 -08001051 return true;
Jack Hea355e5e2017-08-22 16:06:54 -07001052 } else if (getLeState() == STATE_BLE_ON) {
Nitin Arorad055adb2015-03-02 15:03:51 -08001053 return true; // TODO: FILTER SYSTEM APPS HERE <--
Jack Hea355e5e2017-08-22 16:06:54 -07001054 }
Nitin Arorad055adb2015-03-02 15:03:51 -08001055
1056 return false;
1057 }
1058
1059 /**
Scott Mained2a70d2009-12-09 16:07:39 -08001060 * Turn on the local Bluetooth adapter&mdash;do not use without explicit
1061 * user action to turn on Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -07001062 * <p>This powers on the underlying Bluetooth hardware, and starts all
1063 * Bluetooth system services.
Scott Mained2a70d2009-12-09 16:07:39 -08001064 * <p class="caution"><strong>Bluetooth should never be enabled without
1065 * direct user consent</strong>. If you want to turn on Bluetooth in order
1066 * to create a wireless connection, you should use the {@link
1067 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
1068 * user permission to turn on Bluetooth. The {@link #enable()} method is
1069 * provided only for applications that include a user interface for changing
1070 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +04001071 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -07001072 * clients should listen for {@link #ACTION_STATE_CHANGED}
1073 * to be notified of subsequent adapter state changes. If this call returns
1074 * true, then the adapter state will immediately transition from {@link
1075 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
1076 * later transition to either {@link #STATE_OFF} or {@link
1077 * #STATE_ON}. If this call returns false then there was an
1078 * immediate problem that will prevent the adapter from being turned on -
1079 * such as Airplane mode, or the adapter is already turned on.
Nick Pellyde893f52009-09-08 13:15:33 -07001080 *
Jack Hea355e5e2017-08-22 16:06:54 -07001081 * @return true to indicate adapter startup has begun, or false on immediate error
Nick Pellybd022f42009-08-14 18:33:38 -07001082 */
Tor Norbye2d497522015-04-23 17:10:21 -07001083 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001084 public boolean enable() {
Marie Janssencb21ad72016-12-13 10:51:02 -08001085 if (isEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -08001086 if (DBG) {
1087 Log.d(TAG, "enable(): BT already enabled!");
1088 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07001089 return true;
1090 }
Nick Pellybd022f42009-08-14 18:33:38 -07001091 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001092 return mManagerService.enable(ActivityThread.currentPackageName());
Jack Hea355e5e2017-08-22 16:06:54 -07001093 } catch (RemoteException e) {
1094 Log.e(TAG, "", e);
1095 }
Nick Pellybd022f42009-08-14 18:33:38 -07001096 return false;
1097 }
1098
1099 /**
Scott Mained2a70d2009-12-09 16:07:39 -08001100 * Turn off the local Bluetooth adapter&mdash;do not use without explicit
1101 * user action to turn off Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -07001102 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
1103 * system services, and powers down the underlying Bluetooth hardware.
Jake Hambyf51eada2010-09-21 13:39:53 -07001104 * <p class="caution"><strong>Bluetooth should never be disabled without
Scott Mained2a70d2009-12-09 16:07:39 -08001105 * direct user consent</strong>. The {@link #disable()} method is
1106 * provided only for applications that include a user interface for changing
1107 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +04001108 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -07001109 * clients should listen for {@link #ACTION_STATE_CHANGED}
1110 * to be notified of subsequent adapter state changes. If this call returns
1111 * true, then the adapter state will immediately transition from {@link
1112 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
1113 * later transition to either {@link #STATE_OFF} or {@link
1114 * #STATE_ON}. If this call returns false then there was an
1115 * immediate problem that will prevent the adapter from being turned off -
1116 * such as the adapter already being turned off.
Nick Pellybd022f42009-08-14 18:33:38 -07001117 *
Jack Hea355e5e2017-08-22 16:06:54 -07001118 * @return true to indicate adapter shutdown has begun, or false on immediate error
Nick Pellybd022f42009-08-14 18:33:38 -07001119 */
Tor Norbye2d497522015-04-23 17:10:21 -07001120 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001121 public boolean disable() {
1122 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001123 return mManagerService.disable(ActivityThread.currentPackageName(), true);
Jack Hea355e5e2017-08-22 16:06:54 -07001124 } catch (RemoteException e) {
1125 Log.e(TAG, "", e);
1126 }
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001127 return false;
1128 }
1129
1130 /**
1131 * Turn off the local Bluetooth adapter and don't persist the setting.
1132 *
1133 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1134 * permission
1135 *
Jack Hea355e5e2017-08-22 16:06:54 -07001136 * @return true to indicate adapter shutdown has begun, or false on immediate error
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001137 * @hide
1138 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001139 @UnsupportedAppUsage
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001140 public boolean disable(boolean persist) {
fredc0f420372012-04-12 00:02:00 -07001141
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001142 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001143 return mManagerService.disable(ActivityThread.currentPackageName(), persist);
Jack Hea355e5e2017-08-22 16:06:54 -07001144 } catch (RemoteException e) {
1145 Log.e(TAG, "", e);
1146 }
Nick Pellybd022f42009-08-14 18:33:38 -07001147 return false;
1148 }
1149
Nick Pellyde893f52009-09-08 13:15:33 -07001150 /**
1151 * Returns the hardware address of the local Bluetooth adapter.
1152 * <p>For example, "00:11:22:AA:BB:CC".
Nick Pellyde893f52009-09-08 13:15:33 -07001153 *
1154 * @return Bluetooth hardware address as string
1155 */
Tor Norbye2d497522015-04-23 17:10:21 -07001156 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001157 public String getAddress() {
1158 try {
fredc0f420372012-04-12 00:02:00 -07001159 return mManagerService.getAddress();
Jack Hea355e5e2017-08-22 16:06:54 -07001160 } catch (RemoteException e) {
1161 Log.e(TAG, "", e);
1162 }
Nick Pellybd022f42009-08-14 18:33:38 -07001163 return null;
1164 }
1165
1166 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001167 * Get the friendly Bluetooth name of the local Bluetooth adapter.
1168 * <p>This name is visible to remote Bluetooth devices.
1169 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -07001170 *
Nick Pellyde893f52009-09-08 13:15:33 -07001171 * @return the Bluetooth name, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07001172 */
1173 public String getName() {
1174 try {
fredc116d1d462012-04-20 14:47:08 -07001175 return mManagerService.getName();
Jack Hea355e5e2017-08-22 16:06:54 -07001176 } catch (RemoteException e) {
1177 Log.e(TAG, "", e);
1178 }
Nick Pellybd022f42009-08-14 18:33:38 -07001179 return null;
1180 }
1181
1182 /**
Ajay Panickercda6e872015-07-28 16:52:09 -07001183 * Factory reset bluetooth settings.
1184 *
1185 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
1186 * permission
1187 *
1188 * @return true to indicate that the config file was successfully cleared
Ajay Panickercda6e872015-07-28 16:52:09 -07001189 * @hide
1190 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001191 @UnsupportedAppUsage
Ajay Panickercda6e872015-07-28 16:52:09 -07001192 public boolean factoryReset() {
1193 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001194 mServiceLock.readLock().lock();
Ajay Panickercda6e872015-07-28 16:52:09 -07001195 if (mService != null) {
1196 return mService.factoryReset();
1197 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001198 SystemProperties.set("persist.bluetooth.factoryreset", "true");
1199 } catch (RemoteException e) {
1200 Log.e(TAG, "", e);
1201 } finally {
1202 mServiceLock.readLock().unlock();
1203 }
Ajay Panickercda6e872015-07-28 16:52:09 -07001204 return false;
1205 }
1206
1207 /**
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001208 * Get the UUIDs supported by the local Bluetooth adapter.
1209 *
1210 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1211 *
1212 * @return the UUIDs supported by the local Bluetooth Adapter.
1213 * @hide
1214 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001215 @UnsupportedAppUsage
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001216 public ParcelUuid[] getUuids() {
Myles Watson125b5452017-11-27 16:41:47 -08001217 if (getState() != STATE_ON) {
1218 return null;
1219 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001220 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001221 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001222 if (mService != null) {
1223 return mService.getUuids();
1224 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001225 } catch (RemoteException e) {
1226 Log.e(TAG, "", e);
1227 } finally {
1228 mServiceLock.readLock().unlock();
1229 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001230 return null;
1231 }
1232
1233 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001234 * Set the friendly Bluetooth name of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001235 * <p>This name is visible to remote Bluetooth devices.
Jake Hamby0f584302010-09-16 18:12:51 -07001236 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1237 * encoding, although many remote devices can only display the first
1238 * 40 characters, and some may be limited to just 20.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001239 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1240 * will return false. After turning on Bluetooth,
1241 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1242 * to get the updated value.
Nick Pellybd022f42009-08-14 18:33:38 -07001243 *
Nick Pellyde893f52009-09-08 13:15:33 -07001244 * @param name a valid Bluetooth name
Jack Hea355e5e2017-08-22 16:06:54 -07001245 * @return true if the name was set, false otherwise
Nick Pellybd022f42009-08-14 18:33:38 -07001246 */
Tor Norbye2d497522015-04-23 17:10:21 -07001247 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001248 public boolean setName(String name) {
Myles Watson125b5452017-11-27 16:41:47 -08001249 if (getState() != STATE_ON) {
1250 return false;
1251 }
Nick Pellybd022f42009-08-14 18:33:38 -07001252 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001253 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001254 if (mService != null) {
1255 return mService.setName(name);
1256 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001257 } catch (RemoteException e) {
1258 Log.e(TAG, "", e);
1259 } finally {
1260 mServiceLock.readLock().unlock();
1261 }
Nick Pellybd022f42009-08-14 18:33:38 -07001262 return false;
1263 }
1264
1265 /**
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001266 * Returns the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1267 * adapter.
1268 *
1269 * @return {@link BluetoothClass} Bluetooth CoD of local Bluetooth device.
1270 *
1271 * @hide
1272 */
1273 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1274 public BluetoothClass getBluetoothClass() {
Myles Watson125b5452017-11-27 16:41:47 -08001275 if (getState() != STATE_ON) {
1276 return null;
1277 }
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001278 try {
1279 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001280 if (mService != null) {
1281 return mService.getBluetoothClass();
1282 }
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001283 } catch (RemoteException e) {
1284 Log.e(TAG, "", e);
1285 } finally {
1286 mServiceLock.readLock().unlock();
1287 }
1288 return null;
1289 }
1290
1291 /**
Pulkit Bhuwalka547853d2017-09-25 17:55:12 -07001292 * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1293 * adapter.
1294 *
1295 * <p>Note: This value persists across system reboot.
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001296 *
1297 * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
1298 * @return true if successful, false if unsuccessful.
1299 *
1300 * @hide
1301 */
1302 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
1303 public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
Myles Watson125b5452017-11-27 16:41:47 -08001304 if (getState() != STATE_ON) {
1305 return false;
1306 }
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001307 try {
1308 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001309 if (mService != null) {
1310 return mService.setBluetoothClass(bluetoothClass);
1311 }
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001312 } catch (RemoteException e) {
1313 Log.e(TAG, "", e);
1314 } finally {
1315 mServiceLock.readLock().unlock();
1316 }
1317 return false;
1318 }
1319
1320 /**
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001321 * Returns the Input/Output capability of the device for classic Bluetooth.
1322 *
1323 * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1324 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1325 * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1326 *
1327 * @hide
1328 */
1329 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001330 @IoCapability
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001331 public int getIoCapability() {
1332 if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1333 try {
1334 mServiceLock.readLock().lock();
1335 if (mService != null) return mService.getIoCapability();
1336 } catch (RemoteException e) {
1337 Log.e(TAG, e.getMessage(), e);
1338 } finally {
1339 mServiceLock.readLock().unlock();
1340 }
1341 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1342 }
1343
1344 /**
1345 * Sets the Input/Output capability of the device for classic Bluetooth.
1346 *
1347 * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1348 * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1349 * and {@link BluetoothAdapter#enable()} to see the changes.
1350 *
1351 * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1352 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1353 * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1354 *
1355 * @hide
1356 */
1357 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001358 public boolean setIoCapability(@IoCapability int capability) {
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001359 if (getState() != STATE_ON) return false;
1360 try {
1361 mServiceLock.readLock().lock();
1362 if (mService != null) return mService.setIoCapability(capability);
1363 } catch (RemoteException e) {
1364 Log.e(TAG, e.getMessage(), e);
1365 } finally {
1366 mServiceLock.readLock().unlock();
1367 }
1368 return false;
1369 }
1370
1371 /**
1372 * Returns the Input/Output capability of the device for BLE operations.
1373 *
1374 * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1375 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1376 * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1377 *
1378 * @hide
1379 */
1380 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001381 @IoCapability
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001382 public int getLeIoCapability() {
1383 if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1384 try {
1385 mServiceLock.readLock().lock();
1386 if (mService != null) return mService.getLeIoCapability();
1387 } catch (RemoteException e) {
1388 Log.e(TAG, e.getMessage(), e);
1389 } finally {
1390 mServiceLock.readLock().unlock();
1391 }
1392 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1393 }
1394
1395 /**
1396 * Sets the Input/Output capability of the device for BLE operations.
1397 *
1398 * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1399 * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1400 * and {@link BluetoothAdapter#enable()} to see the changes.
1401 *
1402 * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1403 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1404 * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1405 *
1406 * @hide
1407 */
1408 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001409 public boolean setLeIoCapability(@IoCapability int capability) {
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001410 if (getState() != STATE_ON) return false;
1411 try {
1412 mServiceLock.readLock().lock();
1413 if (mService != null) return mService.setLeIoCapability(capability);
1414 } catch (RemoteException e) {
1415 Log.e(TAG, e.getMessage(), e);
1416 } finally {
1417 mServiceLock.readLock().unlock();
1418 }
1419 return false;
1420 }
1421
1422 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001423 * Get the current Bluetooth scan mode of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001424 * <p>The Bluetooth scan mode determines if the local adapter is
1425 * connectable and/or discoverable from remote Bluetooth devices.
1426 * <p>Possible values are:
1427 * {@link #SCAN_MODE_NONE},
1428 * {@link #SCAN_MODE_CONNECTABLE},
1429 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001430 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1431 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1432 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1433 * to get the updated value.
Nick Pellyde893f52009-09-08 13:15:33 -07001434 *
1435 * @return scan mode
Nick Pellybd022f42009-08-14 18:33:38 -07001436 */
Tor Norbye2d497522015-04-23 17:10:21 -07001437 @RequiresPermission(Manifest.permission.BLUETOOTH)
1438 @ScanMode
Nick Pellybd022f42009-08-14 18:33:38 -07001439 public int getScanMode() {
Myles Watson125b5452017-11-27 16:41:47 -08001440 if (getState() != STATE_ON) {
1441 return SCAN_MODE_NONE;
1442 }
Nick Pellybd022f42009-08-14 18:33:38 -07001443 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001444 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001445 if (mService != null) {
1446 return mService.getScanMode();
1447 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001448 } catch (RemoteException e) {
1449 Log.e(TAG, "", e);
1450 } finally {
1451 mServiceLock.readLock().unlock();
1452 }
Nick Pellyde893f52009-09-08 13:15:33 -07001453 return SCAN_MODE_NONE;
Nick Pellybd022f42009-08-14 18:33:38 -07001454 }
1455
1456 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001457 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1458 * <p>The Bluetooth scan mode determines if the local adapter is
1459 * connectable and/or discoverable from remote Bluetooth devices.
Nick Pelly12835472009-09-25 15:00:29 -07001460 * <p>For privacy reasons, discoverable mode is automatically turned off
1461 * after <code>duration</code> seconds. For example, 120 seconds should be
1462 * enough for a remote device to initiate and complete its discovery
1463 * process.
Nick Pellyde893f52009-09-08 13:15:33 -07001464 * <p>Valid scan mode values are:
1465 * {@link #SCAN_MODE_NONE},
1466 * {@link #SCAN_MODE_CONNECTABLE},
1467 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001468 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1469 * will return false. After turning on Bluetooth,
1470 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1471 * to get the updated value.
Nick Pelly18b1e792009-09-24 11:14:15 -07001472 * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
1473 * <p>Applications cannot set the scan mode. They should use
1474 * <code>startActivityForResult(
1475 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1476 * </code>instead.
Nick Pellyde893f52009-09-08 13:15:33 -07001477 *
1478 * @param mode valid scan mode
Jack Hea355e5e2017-08-22 16:06:54 -07001479 * @param duration time in seconds to apply scan mode, only used for {@link
1480 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
1481 * @return true if the scan mode was set, false otherwise
Nick Pelly18b1e792009-09-24 11:14:15 -07001482 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07001483 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001484 @UnsupportedAppUsage
Tor Norbye2d497522015-04-23 17:10:21 -07001485 public boolean setScanMode(@ScanMode int mode, int duration) {
Myles Watson125b5452017-11-27 16:41:47 -08001486 if (getState() != STATE_ON) {
1487 return false;
1488 }
Nick Pellybd022f42009-08-14 18:33:38 -07001489 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001490 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001491 if (mService != null) {
1492 return mService.setScanMode(mode, duration);
1493 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001494 } catch (RemoteException e) {
1495 Log.e(TAG, "", e);
1496 } finally {
1497 mServiceLock.readLock().unlock();
1498 }
Nick Pellyde893f52009-09-08 13:15:33 -07001499 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001500 }
1501
Nick Pelly45e27042009-08-19 11:00:00 -07001502 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001503 @UnsupportedAppUsage
Nick Pelly12835472009-09-25 15:00:29 -07001504 public boolean setScanMode(int mode) {
Myles Watson125b5452017-11-27 16:41:47 -08001505 if (getState() != STATE_ON) {
1506 return false;
1507 }
Srikanth Uppala827de2d2012-04-04 03:33:26 -07001508 /* getDiscoverableTimeout() to use the latest from NV than use 0 */
1509 return setScanMode(mode, getDiscoverableTimeout());
Nick Pelly12835472009-09-25 15:00:29 -07001510 }
1511
1512 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001513 @UnsupportedAppUsage
Nick Pellybd022f42009-08-14 18:33:38 -07001514 public int getDiscoverableTimeout() {
Myles Watson125b5452017-11-27 16:41:47 -08001515 if (getState() != STATE_ON) {
1516 return -1;
1517 }
Nick Pellybd022f42009-08-14 18:33:38 -07001518 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001519 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001520 if (mService != null) {
1521 return mService.getDiscoverableTimeout();
1522 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001523 } catch (RemoteException e) {
1524 Log.e(TAG, "", e);
1525 } finally {
1526 mServiceLock.readLock().unlock();
1527 }
Nick Pellybd022f42009-08-14 18:33:38 -07001528 return -1;
1529 }
1530
Nick Pelly45e27042009-08-19 11:00:00 -07001531 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001532 @UnsupportedAppUsage
Nick Pellybd022f42009-08-14 18:33:38 -07001533 public void setDiscoverableTimeout(int timeout) {
Myles Watson125b5452017-11-27 16:41:47 -08001534 if (getState() != STATE_ON) {
1535 return;
1536 }
Nick Pellybd022f42009-08-14 18:33:38 -07001537 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001538 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001539 if (mService != null) {
1540 mService.setDiscoverableTimeout(timeout);
1541 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001542 } catch (RemoteException e) {
1543 Log.e(TAG, "", e);
1544 } finally {
1545 mServiceLock.readLock().unlock();
1546 }
Nick Pellybd022f42009-08-14 18:33:38 -07001547 }
1548
Nick Pelly005b2282009-09-10 10:21:56 -07001549 /**
Marie Janssen23a48332017-01-24 14:09:59 -08001550 * Get the end time of the latest remote device discovery process.
Jack Hea355e5e2017-08-22 16:06:54 -07001551 *
1552 * @return the latest time that the bluetooth adapter was/will be in discovery mode, in
1553 * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has
1554 * been called recently.
Marie Janssen23a48332017-01-24 14:09:59 -08001555 * @hide
1556 */
1557 public long getDiscoveryEndMillis() {
1558 try {
1559 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001560 if (mService != null) {
1561 return mService.getDiscoveryEndMillis();
1562 }
Marie Janssen23a48332017-01-24 14:09:59 -08001563 } catch (RemoteException e) {
1564 Log.e(TAG, "", e);
1565 } finally {
1566 mServiceLock.readLock().unlock();
1567 }
1568 return -1;
1569 }
1570
1571 /**
Zach Johnson57e6e902018-12-12 17:11:25 -08001572 * Set the context for this BluetoothAdapter (only called from BluetoothManager)
1573 * @hide
1574 */
1575 public void setContext(Context context) {
1576 mContext = context;
1577 }
1578
1579 private String getOpPackageName() {
1580 // Workaround for legacy API for getting a BluetoothAdapter not
1581 // passing a context
1582 if (mContext != null) {
1583 return mContext.getOpPackageName();
1584 }
1585 return ActivityThread.currentOpPackageName();
1586 }
1587
1588 /**
Nick Pelly005b2282009-09-10 10:21:56 -07001589 * Start the remote device discovery process.
1590 * <p>The discovery process usually involves an inquiry scan of about 12
1591 * seconds, followed by a page scan of each new device to retrieve its
1592 * Bluetooth name.
1593 * <p>This is an asynchronous call, it will return immediately. Register
1594 * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1595 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1596 * discovery starts and completes. Register for {@link
1597 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1598 * are found.
1599 * <p>Device discovery is a heavyweight procedure. New connections to
1600 * remote Bluetooth devices should not be attempted while discovery is in
1601 * progress, and existing connections will experience limited bandwidth
1602 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
Scott Main6d95fc02009-11-19 17:00:19 -08001603 * discovery. Discovery is not managed by the Activity,
1604 * but is run as a system service, so an application should always call
1605 * {@link BluetoothAdapter#cancelDiscovery()} even if it
1606 * did not directly request a discovery, just to be sure.
Nick Pelly005b2282009-09-10 10:21:56 -07001607 * <p>Device discovery will only find remote devices that are currently
1608 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1609 * not discoverable by default, and need to be entered into a special mode.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001610 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1611 * will return false. After turning on Bluetooth,
1612 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1613 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001614 *
1615 * @return true on success, false on error
1616 */
Tor Norbye2d497522015-04-23 17:10:21 -07001617 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001618 public boolean startDiscovery() {
Myles Watson125b5452017-11-27 16:41:47 -08001619 if (getState() != STATE_ON) {
1620 return false;
1621 }
Nick Pellybd022f42009-08-14 18:33:38 -07001622 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001623 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001624 if (mService != null) {
Zach Johnson57e6e902018-12-12 17:11:25 -08001625 return mService.startDiscovery(getOpPackageName());
Myles Watson125b5452017-11-27 16:41:47 -08001626 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001627 } catch (RemoteException e) {
1628 Log.e(TAG, "", e);
1629 } finally {
1630 mServiceLock.readLock().unlock();
1631 }
Nick Pellybd022f42009-08-14 18:33:38 -07001632 return false;
1633 }
1634
Nick Pelly005b2282009-09-10 10:21:56 -07001635 /**
1636 * Cancel the current device discovery process.
Jake Hamby0f584302010-09-16 18:12:51 -07001637 * <p>Because discovery is a heavyweight procedure for the Bluetooth
Scott Main6d95fc02009-11-19 17:00:19 -08001638 * adapter, this method should always be called before attempting to connect
1639 * to a remote device with {@link
1640 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1641 * the Activity, but is run as a system service, so an application should
1642 * always call cancel discovery even if it did not directly request a
1643 * discovery, just to be sure.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001644 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1645 * will return false. After turning on Bluetooth,
1646 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1647 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001648 *
1649 * @return true on success, false on error
1650 */
Tor Norbye2d497522015-04-23 17:10:21 -07001651 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly005b2282009-09-10 10:21:56 -07001652 public boolean cancelDiscovery() {
Myles Watson125b5452017-11-27 16:41:47 -08001653 if (getState() != STATE_ON) {
1654 return false;
1655 }
Nick Pellybd022f42009-08-14 18:33:38 -07001656 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001657 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001658 if (mService != null) {
1659 return mService.cancelDiscovery();
1660 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001661 } catch (RemoteException e) {
1662 Log.e(TAG, "", e);
1663 } finally {
1664 mServiceLock.readLock().unlock();
1665 }
Nick Pelly005b2282009-09-10 10:21:56 -07001666 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001667 }
1668
Nick Pelly005b2282009-09-10 10:21:56 -07001669 /**
1670 * Return true if the local Bluetooth adapter is currently in the device
1671 * discovery process.
1672 * <p>Device discovery is a heavyweight procedure. New connections to
1673 * remote Bluetooth devices should not be attempted while discovery is in
1674 * progress, and existing connections will experience limited bandwidth
1675 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1676 * discovery.
1677 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1678 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1679 * starts or completes.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001680 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1681 * will return false. After turning on Bluetooth,
1682 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1683 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001684 *
1685 * @return true if discovering
1686 */
Tor Norbye2d497522015-04-23 17:10:21 -07001687 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001688 public boolean isDiscovering() {
Myles Watson125b5452017-11-27 16:41:47 -08001689 if (getState() != STATE_ON) {
1690 return false;
1691 }
Nick Pellybd022f42009-08-14 18:33:38 -07001692 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001693 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001694 if (mService != null) {
1695 return mService.isDiscovering();
1696 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001697 } catch (RemoteException e) {
1698 Log.e(TAG, "", e);
1699 } finally {
1700 mServiceLock.readLock().unlock();
1701 }
Nick Pellybd022f42009-08-14 18:33:38 -07001702 return false;
1703 }
1704
1705 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001706 * Return true if the multi advertisement is supported by the chipset
1707 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001708 * @return true if Multiple Advertisement feature is supported
1709 */
1710 public boolean isMultipleAdvertisementSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001711 if (getState() != STATE_ON) {
1712 return false;
1713 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001714 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001715 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001716 if (mService != null) {
1717 return mService.isMultiAdvertisementSupported();
1718 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001719 } catch (RemoteException e) {
1720 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001721 } finally {
1722 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001723 }
1724 return false;
1725 }
1726
1727 /**
Wei Wangd91f1932015-03-19 15:09:56 -07001728 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1729 *
1730 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1731 * fetch scan results even when Bluetooth is turned off.<p>
1732 *
1733 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1734 *
1735 * @hide
1736 */
1737 @SystemApi
1738 public boolean isBleScanAlwaysAvailable() {
Wei Wang67d84162015-04-26 17:04:29 -07001739 try {
1740 return mManagerService.isBleScanAlwaysAvailable();
1741 } catch (RemoteException e) {
1742 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1743 return false;
1744 }
Wei Wangd91f1932015-03-19 15:09:56 -07001745 }
1746
1747 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001748 * Return true if offloaded filters are supported
1749 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001750 * @return true if chipset supports on-chip filtering
1751 */
1752 public boolean isOffloadedFilteringSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001753 if (!getLeAccess()) {
1754 return false;
1755 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001756 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001757 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001758 if (mService != null) {
1759 return mService.isOffloadedFilteringSupported();
1760 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001761 } catch (RemoteException e) {
1762 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001763 } finally {
1764 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001765 }
1766 return false;
1767 }
1768
1769 /**
1770 * Return true if offloaded scan batching is supported
1771 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001772 * @return true if chipset supports on-chip scan batching
1773 */
1774 public boolean isOffloadedScanBatchingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001775 if (!getLeAccess()) {
1776 return false;
1777 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001778 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001779 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001780 if (mService != null) {
1781 return mService.isOffloadedScanBatchingSupported();
1782 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001783 } catch (RemoteException e) {
1784 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001785 } finally {
1786 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001787 }
1788 return false;
1789 }
1790
1791 /**
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001792 * Return true if LE 2M PHY feature is supported.
1793 *
1794 * @return true if chipset supports LE 2M PHY feature
1795 */
1796 public boolean isLe2MPhySupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001797 if (!getLeAccess()) {
1798 return false;
1799 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001800 try {
1801 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001802 if (mService != null) {
1803 return mService.isLe2MPhySupported();
1804 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001805 } catch (RemoteException e) {
1806 Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
1807 } finally {
1808 mServiceLock.readLock().unlock();
1809 }
1810 return false;
1811 }
1812
1813 /**
1814 * Return true if LE Coded PHY feature is supported.
1815 *
1816 * @return true if chipset supports LE Coded PHY feature
1817 */
1818 public boolean isLeCodedPhySupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001819 if (!getLeAccess()) {
1820 return false;
1821 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001822 try {
1823 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001824 if (mService != null) {
1825 return mService.isLeCodedPhySupported();
1826 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001827 } catch (RemoteException e) {
1828 Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
1829 } finally {
1830 mServiceLock.readLock().unlock();
1831 }
1832 return false;
1833 }
1834
1835 /**
Jakub Pawlowskibc2991e2017-03-10 16:07:59 -08001836 * Return true if LE Extended Advertising feature is supported.
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001837 *
Jakub Pawlowskibc2991e2017-03-10 16:07:59 -08001838 * @return true if chipset supports LE Extended Advertising feature
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001839 */
1840 public boolean isLeExtendedAdvertisingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001841 if (!getLeAccess()) {
1842 return false;
1843 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001844 try {
1845 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001846 if (mService != null) {
1847 return mService.isLeExtendedAdvertisingSupported();
1848 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001849 } catch (RemoteException e) {
1850 Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
1851 } finally {
1852 mServiceLock.readLock().unlock();
1853 }
1854 return false;
1855 }
1856
1857 /**
1858 * Return true if LE Periodic Advertising feature is supported.
1859 *
1860 * @return true if chipset supports LE Periodic Advertising feature
1861 */
1862 public boolean isLePeriodicAdvertisingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001863 if (!getLeAccess()) {
1864 return false;
1865 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001866 try {
1867 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001868 if (mService != null) {
1869 return mService.isLePeriodicAdvertisingSupported();
1870 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001871 } catch (RemoteException e) {
1872 Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
1873 } finally {
1874 mServiceLock.readLock().unlock();
1875 }
1876 return false;
1877 }
1878
1879 /**
Jakub Pawlowski76cceb12017-04-21 04:59:55 -07001880 * Return the maximum LE advertising data length in bytes,
1881 * if LE Extended Advertising feature is supported, 0 otherwise.
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001882 *
1883 * @return the maximum LE advertising data length.
1884 */
1885 public int getLeMaximumAdvertisingDataLength() {
Myles Watson125b5452017-11-27 16:41:47 -08001886 if (!getLeAccess()) {
1887 return 0;
1888 }
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001889 try {
1890 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001891 if (mService != null) {
1892 return mService.getLeMaximumAdvertisingDataLength();
1893 }
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001894 } catch (RemoteException e) {
1895 Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
1896 } finally {
1897 mServiceLock.readLock().unlock();
1898 }
1899 return 0;
1900 }
1901
1902 /**
Stanley Tng61dbd812019-01-13 16:04:31 -08001903 * Return true if Hearing Aid Profile is supported.
1904 *
1905 * @return true if phone supports Hearing Aid Profile
1906 */
1907 private boolean isHearingAidProfileSupported() {
1908 try {
1909 return mManagerService.isHearingAidProfileSupported();
1910 } catch (RemoteException e) {
1911 Log.e(TAG, "remote expection when calling isHearingAidProfileSupported", e);
1912 return false;
1913 }
1914 }
1915
1916 /**
Pavlin Radoslavova5137922018-01-17 02:09:53 -08001917 * Get the maximum number of connected audio devices.
1918 *
1919 * @return the maximum number of connected audio devices
1920 * @hide
1921 */
1922 @RequiresPermission(Manifest.permission.BLUETOOTH)
1923 public int getMaxConnectedAudioDevices() {
1924 try {
1925 mServiceLock.readLock().lock();
1926 if (mService != null) {
1927 return mService.getMaxConnectedAudioDevices();
1928 }
1929 } catch (RemoteException e) {
1930 Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
1931 } finally {
1932 mServiceLock.readLock().unlock();
1933 }
1934 return 1;
1935 }
1936
1937 /**
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001938 * Return true if hardware has entries available for matching beacons
1939 *
1940 * @return true if there are hw entries available for matching beacons
1941 * @hide
1942 */
1943 public boolean isHardwareTrackingFiltersAvailable() {
Myles Watson125b5452017-11-27 16:41:47 -08001944 if (!getLeAccess()) {
1945 return false;
1946 }
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001947 try {
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07001948 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
1949 if (iGatt == null) {
1950 // BLE is not supported
1951 return false;
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001952 }
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07001953 return (iGatt.numHwTrackFiltersAvailable() != 0);
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001954 } catch (RemoteException e) {
1955 Log.e(TAG, "", e);
1956 }
1957 return false;
1958 }
1959
1960 /**
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001961 * Return the record of {@link BluetoothActivityEnergyInfo} object that
1962 * has the activity and energy info. This can be used to ascertain what
1963 * the controller has been up to, since the last sample.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001964 *
Jack Hea355e5e2017-08-22 16:06:54 -07001965 * @param updateType Type of info, cached vs refreshed.
1966 * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or
1967 * unsupported
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001968 * @hide
Jack Hea355e5e2017-08-22 16:06:54 -07001969 * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)}
1970 * instead.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001971 */
Adam Lesinski010bf372016-04-11 12:18:18 -07001972 @Deprecated
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001973 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001974 SynchronousResultReceiver receiver = new SynchronousResultReceiver();
Adam Lesinski991357f2016-05-10 14:00:03 -07001975 requestControllerActivityEnergyInfo(receiver);
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001976 try {
Adam Lesinski010bf372016-04-11 12:18:18 -07001977 SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
1978 if (result.bundle != null) {
1979 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1980 }
1981 } catch (TimeoutException e) {
1982 Log.e(TAG, "getControllerActivityEnergyInfo timed out");
1983 }
1984 return null;
1985 }
1986
1987 /**
1988 * Request the record of {@link BluetoothActivityEnergyInfo} object that
1989 * has the activity and energy info. This can be used to ascertain what
1990 * the controller has been up to, since the last sample.
1991 *
1992 * A null value for the activity info object may be sent if the bluetooth service is
1993 * unreachable or the device does not support reporting such information.
1994 *
Adam Lesinski010bf372016-04-11 12:18:18 -07001995 * @param result The callback to which to send the activity info.
1996 * @hide
1997 */
Adam Lesinski991357f2016-05-10 14:00:03 -07001998 public void requestControllerActivityEnergyInfo(ResultReceiver result) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001999 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002000 mServiceLock.readLock().lock();
2001 if (mService != null) {
2002 mService.requestActivityInfo(result);
2003 result = null;
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002004 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002005 } catch (RemoteException e) {
2006 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
Adam Lesinski991357f2016-05-10 14:00:03 -07002007 } finally {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002008 mServiceLock.readLock().unlock();
Adam Lesinski991357f2016-05-10 14:00:03 -07002009 if (result != null) {
2010 // Only send an immediate result if we failed.
2011 result.send(0, null);
2012 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002013 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002014 }
2015
2016 /**
Nick Pelly005b2282009-09-10 10:21:56 -07002017 * Return the set of {@link BluetoothDevice} objects that are bonded
2018 * (paired) to the local adapter.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002019 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
2020 * will return an empty set. After turning on Bluetooth,
2021 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
2022 * to get the updated value.
Nick Pellybd022f42009-08-14 18:33:38 -07002023 *
Nick Pelly005b2282009-09-10 10:21:56 -07002024 * @return unmodifiable set of {@link BluetoothDevice}, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07002025 */
Tor Norbye2d497522015-04-23 17:10:21 -07002026 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07002027 public Set<BluetoothDevice> getBondedDevices() {
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002028 if (getState() != STATE_ON) {
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08002029 return toDeviceSet(new BluetoothDevice[0]);
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002030 }
Nick Pellybd022f42009-08-14 18:33:38 -07002031 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002032 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002033 if (mService != null) {
2034 return toDeviceSet(mService.getBondedDevices());
2035 }
fredc0f420372012-04-12 00:02:00 -07002036 return toDeviceSet(new BluetoothDevice[0]);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002037 } catch (RemoteException e) {
2038 Log.e(TAG, "", e);
2039 } finally {
2040 mServiceLock.readLock().unlock();
2041 }
Nick Pellybd022f42009-08-14 18:33:38 -07002042 return null;
2043 }
2044
2045 /**
Bryce Leeb1301fa2016-10-09 12:54:42 -07002046 * Gets the currently supported profiles by the adapter.
2047 *
Jack Hea355e5e2017-08-22 16:06:54 -07002048 * <p> This can be used to check whether a profile is supported before attempting
Bryce Leeb1301fa2016-10-09 12:54:42 -07002049 * to connect to its respective proxy.
2050 *
Jack Hea355e5e2017-08-22 16:06:54 -07002051 * @return a list of integers indicating the ids of supported profiles as defined in {@link
2052 * BluetoothProfile}.
Bryce Leeb1301fa2016-10-09 12:54:42 -07002053 * @hide
2054 */
2055 public List<Integer> getSupportedProfiles() {
2056 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
2057
2058 try {
2059 synchronized (mManagerCallback) {
2060 if (mService != null) {
2061 final long supportedProfilesBitMask = mService.getSupportedProfiles();
2062
2063 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
2064 if ((supportedProfilesBitMask & (1 << i)) != 0) {
2065 supportedProfiles.add(i);
2066 }
2067 }
Stanley Tng61dbd812019-01-13 16:04:31 -08002068 } else {
2069 // Bluetooth is disabled. Just fill in known supported Profiles
2070 if (isHearingAidProfileSupported()) {
2071 supportedProfiles.add(BluetoothProfile.HEARING_AID);
2072 }
Bryce Leeb1301fa2016-10-09 12:54:42 -07002073 }
2074 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002075 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -07002076 Log.e(TAG, "getSupportedProfiles:", e);
Marie Janssencb21ad72016-12-13 10:51:02 -08002077 }
Bryce Leeb1301fa2016-10-09 12:54:42 -07002078 return supportedProfiles;
2079 }
2080
2081 /**
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002082 * Get the current connection state of the local Bluetooth adapter.
2083 * This can be used to check whether the local Bluetooth adapter is connected
2084 * to any profile of any other remote Bluetooth Device.
2085 *
2086 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
2087 * intent to get the connection state of the adapter.
2088 *
Jack Hea355e5e2017-08-22 16:06:54 -07002089 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link
2090 * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002091 * @hide
2092 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002093 @UnsupportedAppUsage
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002094 public int getConnectionState() {
Myles Watson125b5452017-11-27 16:41:47 -08002095 if (getState() != STATE_ON) {
2096 return BluetoothAdapter.STATE_DISCONNECTED;
2097 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002098 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002099 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002100 if (mService != null) {
2101 return mService.getAdapterConnectionState();
2102 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002103 } catch (RemoteException e) {
2104 Log.e(TAG, "getConnectionState:", e);
2105 } finally {
2106 mServiceLock.readLock().unlock();
2107 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002108 return BluetoothAdapter.STATE_DISCONNECTED;
2109 }
2110
2111 /**
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002112 * Get the current connection state of a profile.
2113 * This function can be used to check whether the local Bluetooth adapter
2114 * is connected to any remote device for a specific profile.
Jack He6b73b322019-01-03 16:23:41 -08002115 * Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002116 *
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002117 * <p> Return value can be one of
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002118 * {@link BluetoothProfile#STATE_DISCONNECTED},
2119 * {@link BluetoothProfile#STATE_CONNECTING},
2120 * {@link BluetoothProfile#STATE_CONNECTED},
2121 * {@link BluetoothProfile#STATE_DISCONNECTING}
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002122 */
Tor Norbye2d497522015-04-23 17:10:21 -07002123 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002124 public int getProfileConnectionState(int profile) {
Myles Watson125b5452017-11-27 16:41:47 -08002125 if (getState() != STATE_ON) {
2126 return BluetoothProfile.STATE_DISCONNECTED;
2127 }
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002128 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002129 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002130 if (mService != null) {
2131 return mService.getProfileConnectionState(profile);
2132 }
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002133 } catch (RemoteException e) {
2134 Log.e(TAG, "getProfileConnectionState:", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002135 } finally {
2136 mServiceLock.readLock().unlock();
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002137 }
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002138 return BluetoothProfile.STATE_DISCONNECTED;
2139 }
2140
2141 /**
Nick Pelly45e27042009-08-19 11:00:00 -07002142 * Create a listening, secure RFCOMM Bluetooth socket.
2143 * <p>A remote device connecting to this socket will be authenticated and
Nick Pellybd022f42009-08-14 18:33:38 -07002144 * communication on this socket will be encrypted.
Nick Pelly45e27042009-08-19 11:00:00 -07002145 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
Nick Pelly24bb9b82009-10-02 20:34:18 -07002146 * connections from a listening {@link BluetoothServerSocket}.
Nick Pelly45e27042009-08-19 11:00:00 -07002147 * <p>Valid RFCOMM channels are in range 1 to 30.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002148 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Jack Hea355e5e2017-08-22 16:06:54 -07002149 *
Nick Pelly45e27042009-08-19 11:00:00 -07002150 * @param channel RFCOMM channel to listen on
2151 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002152 * @throws IOException on error, for example Bluetooth not available, or insufficient
2153 * permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002154 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002155 */
Nick Pelly45e27042009-08-19 11:00:00 -07002156 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002157 return listenUsingRfcommOn(channel, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02002158 }
2159
2160 /**
2161 * Create a listening, secure RFCOMM Bluetooth socket.
2162 * <p>A remote device connecting to this socket will be authenticated and
2163 * communication on this socket will be encrypted.
2164 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2165 * connections from a listening {@link BluetoothServerSocket}.
2166 * <p>Valid RFCOMM channels are in range 1 to 30.
2167 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
2168 * <p>To auto assign a channel without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002169 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
Jack Hea355e5e2017-08-22 16:06:54 -07002170 *
Casper Bonde23284232015-04-21 13:12:05 +02002171 * @param channel RFCOMM channel to listen on
Jack Hea355e5e2017-08-22 16:06:54 -07002172 * @param mitm enforce man-in-the-middle protection for authentication.
2173 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2174 * connections.
Casper Bonde23284232015-04-21 13:12:05 +02002175 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002176 * @throws IOException on error, for example Bluetooth not available, or insufficient
2177 * permissions, or channel in use.
Casper Bonde23284232015-04-21 13:12:05 +02002178 * @hide
2179 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002180 @UnsupportedAppUsage
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002181 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
Myles Watson125b5452017-11-27 16:41:47 -08002182 boolean min16DigitPin) throws IOException {
2183 BluetoothServerSocket socket =
2184 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm,
2185 min16DigitPin);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002186 int errno = socket.mSocket.bindListen();
Casper Bonde23284232015-04-21 13:12:05 +02002187 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002188 socket.setChannel(socket.mSocket.getPort());
2189 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002190 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07002191 //TODO(BT): Throw the same exception error code
2192 // that the previous code was using.
2193 //socket.mSocket.throwErrnoNative(errno);
2194 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002195 }
2196 return socket;
2197 }
2198
2199 /**
Nick Pelly24bb9b82009-10-02 20:34:18 -07002200 * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
2201 * <p>A remote device connecting to this socket will be authenticated and
2202 * communication on this socket will be encrypted.
2203 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2204 * connections from a listening {@link BluetoothServerSocket}.
2205 * <p>The system will assign an unused RFCOMM channel to listen on.
2206 * <p>The system will also register a Service Discovery
2207 * Protocol (SDP) record with the local SDP server containing the specified
2208 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2209 * can use the same UUID to query our SDP server and discover which channel
2210 * to connect to. This SDP record will be removed when this socket is
2211 * closed, or if this application closes unexpectedly.
Nick Pelly16fb88a2009-10-07 07:44:03 +02002212 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2213 * connect to this socket from another device using the same {@link UUID}.
Jack Hea355e5e2017-08-22 16:06:54 -07002214 *
Nick Pelly24bb9b82009-10-02 20:34:18 -07002215 * @param name service name for SDP record
2216 * @param uuid uuid for SDP record
2217 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002218 * @throws IOException on error, for example Bluetooth not available, or insufficient
2219 * permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002220 */
Tor Norbye2d497522015-04-23 17:10:21 -07002221 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly16fb88a2009-10-07 07:44:03 +02002222 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
Nick Pelly24bb9b82009-10-02 20:34:18 -07002223 throws IOException {
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002224 return createNewRfcommSocketAndRecord(name, uuid, true, true);
2225 }
2226
2227 /**
2228 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002229 * <p>The link key is not required to be authenticated, i.e the communication may be
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002230 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002231 * the link will be encrypted, as encryption is mandartory.
2232 * For legacy devices (pre Bluetooth 2.1 devices) the link will not
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002233 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
2234 * encrypted and authenticated communication channel is desired.
2235 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2236 * connections from a listening {@link BluetoothServerSocket}.
2237 * <p>The system will assign an unused RFCOMM channel to listen on.
2238 * <p>The system will also register a Service Discovery
2239 * Protocol (SDP) record with the local SDP server containing the specified
2240 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2241 * can use the same UUID to query our SDP server and discover which channel
2242 * to connect to. This SDP record will be removed when this socket is
2243 * closed, or if this application closes unexpectedly.
2244 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2245 * connect to this socket from another device using the same {@link UUID}.
Jack Hea355e5e2017-08-22 16:06:54 -07002246 *
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002247 * @param name service name for SDP record
2248 * @param uuid uuid for SDP record
2249 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002250 * @throws IOException on error, for example Bluetooth not available, or insufficient
2251 * permissions, or channel in use.
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002252 */
Tor Norbye2d497522015-04-23 17:10:21 -07002253 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002254 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
2255 throws IOException {
2256 return createNewRfcommSocketAndRecord(name, uuid, false, false);
2257 }
2258
Jack Hea355e5e2017-08-22 16:06:54 -07002259 /**
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002260 * Create a listening, encrypted,
2261 * RFCOMM Bluetooth socket with Service Record.
2262 * <p>The link will be encrypted, but the link key is not required to be authenticated
2263 * i.e the communication is vulnerable to Man In the Middle attacks. Use
2264 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
2265 * <p> Use this socket if authentication of link key is not possible.
2266 * For example, for Bluetooth 2.1 devices, if any of the devices does not have
2267 * an input and output capability or just has the ability to display a numeric key,
2268 * a secure socket connection is not possible and this socket can be used.
2269 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
2270 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
2271 * For more details, refer to the Security Model section 5.2 (vol 3) of
2272 * Bluetooth Core Specification version 2.1 + EDR.
2273 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2274 * connections from a listening {@link BluetoothServerSocket}.
2275 * <p>The system will assign an unused RFCOMM channel to listen on.
2276 * <p>The system will also register a Service Discovery
2277 * Protocol (SDP) record with the local SDP server containing the specified
2278 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2279 * can use the same UUID to query our SDP server and discover which channel
2280 * to connect to. This SDP record will be removed when this socket is
2281 * closed, or if this application closes unexpectedly.
2282 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2283 * connect to this socket from another device using the same {@link UUID}.
2284 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jack Hea355e5e2017-08-22 16:06:54 -07002285 *
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002286 * @param name service name for SDP record
2287 * @param uuid uuid for SDP record
2288 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002289 * @throws IOException on error, for example Bluetooth not available, or insufficient
2290 * permissions, or channel in use.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002291 * @hide
2292 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002293 @UnsupportedAppUsage
Myles Watson125b5452017-11-27 16:41:47 -08002294 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)
2295 throws IOException {
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002296 return createNewRfcommSocketAndRecord(name, uuid, false, true);
2297 }
2298
zzy3b147b72012-04-03 19:48:32 -07002299
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002300 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
2301 boolean auth, boolean encrypt) throws IOException {
Nick Pelly24bb9b82009-10-02 20:34:18 -07002302 BluetoothServerSocket socket;
Myles Watson125b5452017-11-27 16:41:47 -08002303 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, encrypt,
2304 new ParcelUuid(uuid));
zzy3b147b72012-04-03 19:48:32 -07002305 socket.setServiceName(name);
2306 int errno = socket.mSocket.bindListen();
2307 if (errno != 0) {
2308 //TODO(BT): Throw the same exception error code
2309 // that the previous code was using.
2310 //socket.mSocket.throwErrnoNative(errno);
2311 throw new IOException("Error: " + errno);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002312 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002313 return socket;
2314 }
2315
2316 /**
Nick Pellybd022f42009-08-14 18:33:38 -07002317 * Construct an unencrypted, unauthenticated, RFCOMM server socket.
2318 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002319 *
Nick Pellybd022f42009-08-14 18:33:38 -07002320 * @return An RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002321 * @throws IOException On error, for example Bluetooth not available, or insufficient
2322 * permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07002323 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002324 */
2325 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002326 BluetoothServerSocket socket =
2327 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, false, port);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002328 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002329 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002330 socket.setChannel(socket.mSocket.getPort());
2331 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002332 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07002333 //TODO(BT): Throw the same exception error code
2334 // that the previous code was using.
2335 //socket.mSocket.throwErrnoNative(errno);
2336 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002337 }
2338 return socket;
2339 }
2340
Jack Hea355e5e2017-08-22 16:06:54 -07002341 /**
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002342 * Construct an encrypted, RFCOMM server socket.
2343 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002344 *
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002345 * @return An RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002346 * @throws IOException On error, for example Bluetooth not available, or insufficient
2347 * permissions.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002348 * @hide
2349 */
Myles Watson125b5452017-11-27 16:41:47 -08002350 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port) throws IOException {
2351 BluetoothServerSocket socket =
2352 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, true, port);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002353 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002354 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002355 socket.setChannel(socket.mSocket.getPort());
2356 }
zzy3b147b72012-04-03 19:48:32 -07002357 if (errno < 0) {
2358 //TODO(BT): Throw the same exception error code
2359 // that the previous code was using.
2360 //socket.mSocket.throwErrnoNative(errno);
2361 throw new IOException("Error: " + errno);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002362 }
2363 return socket;
2364 }
2365
Nick Pellybd022f42009-08-14 18:33:38 -07002366 /**
2367 * Construct a SCO server socket.
2368 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002369 *
Nick Pellybd022f42009-08-14 18:33:38 -07002370 * @return A SCO BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002371 * @throws IOException On error, for example Bluetooth not available, or insufficient
2372 * permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07002373 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002374 */
2375 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002376 BluetoothServerSocket socket =
2377 new BluetoothServerSocket(BluetoothSocket.TYPE_SCO, false, false, -1);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002378 int errno = socket.mSocket.bindListen();
zzy3b147b72012-04-03 19:48:32 -07002379 if (errno < 0) {
2380 //TODO(BT): Throw the same exception error code
2381 // that the previous code was using.
2382 //socket.mSocket.throwErrnoNative(errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002383 }
2384 return socket;
2385 }
2386
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002387 /**
Casper Bonde238e0f92015-04-09 09:24:48 +02002388 * Construct an encrypted, authenticated, L2CAP server socket.
2389 * Call #accept to retrieve connections to this socket.
Casper Bonde23284232015-04-21 13:12:05 +02002390 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002391 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002392 *
2393 * @param port the PSM to listen on
2394 * @param mitm enforce man-in-the-middle protection for authentication.
2395 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2396 * connections.
Casper Bonde238e0f92015-04-09 09:24:48 +02002397 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002398 * @throws IOException On error, for example Bluetooth not available, or insufficient
2399 * permissions.
Casper Bonde238e0f92015-04-09 09:24:48 +02002400 * @hide
2401 */
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002402 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
2403 throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002404 BluetoothServerSocket socket =
2405 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, true, true, port, mitm,
2406 min16DigitPin);
Casper Bonde238e0f92015-04-09 09:24:48 +02002407 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002408 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Stanley Tnge48468d2017-11-22 16:04:40 -08002409 int assignedChannel = socket.mSocket.getPort();
2410 if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
2411 socket.setChannel(assignedChannel);
Casper Bonde238e0f92015-04-09 09:24:48 +02002412 }
2413 if (errno != 0) {
2414 //TODO(BT): Throw the same exception error code
2415 // that the previous code was using.
2416 //socket.mSocket.throwErrnoNative(errno);
2417 throw new IOException("Error: " + errno);
2418 }
2419 return socket;
2420 }
2421
2422 /**
Casper Bonde23284232015-04-21 13:12:05 +02002423 * Construct an encrypted, authenticated, L2CAP server socket.
2424 * Call #accept to retrieve connections to this socket.
2425 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002426 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002427 *
2428 * @param port the PSM to listen on
Casper Bonde23284232015-04-21 13:12:05 +02002429 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002430 * @throws IOException On error, for example Bluetooth not available, or insufficient
2431 * permissions.
Casper Bonde23284232015-04-21 13:12:05 +02002432 * @hide
2433 */
2434 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002435 return listenUsingL2capOn(port, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02002436 }
2437
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302438
2439 /**
2440 * Construct an insecure L2CAP server socket.
2441 * Call #accept to retrieve connections to this socket.
2442 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002443 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002444 *
2445 * @param port the PSM to listen on
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302446 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002447 * @throws IOException On error, for example Bluetooth not available, or insufficient
2448 * permissions.
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302449 * @hide
2450 */
2451 public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08002452 Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
Myles Watson125b5452017-11-27 16:41:47 -08002453 BluetoothServerSocket socket =
2454 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
Stanley Tnge48468d2017-11-22 16:04:40 -08002455 false);
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302456 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002457 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Stanley Tnge48468d2017-11-22 16:04:40 -08002458 int assignedChannel = socket.mSocket.getPort();
2459 if (DBG) {
2460 Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
2461 + assignedChannel);
2462 }
2463 socket.setChannel(assignedChannel);
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302464 }
2465 if (errno != 0) {
2466 //TODO(BT): Throw the same exception error code
2467 // that the previous code was using.
2468 //socket.mSocket.throwErrnoNative(errno);
2469 throw new IOException("Error: " + errno);
2470 }
2471 return socket;
2472
2473 }
2474
Casper Bonde23284232015-04-21 13:12:05 +02002475 /**
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002476 * Read the local Out of Band Pairing Data
2477 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2478 *
2479 * @return Pair<byte[], byte[]> of Hash and Randomizer
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002480 * @hide
2481 */
2482 public Pair<byte[], byte[]> readOutOfBandData() {
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002483 return null;
2484 }
2485
Scott Main299ae672011-01-19 21:13:18 -08002486 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002487 * Get the profile proxy object associated with the profile.
2488 *
Jack He6b73b322019-01-03 16:23:41 -08002489 * <p>Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP},
Stanley Tng1f5ea662018-11-15 17:11:36 -08002490 * {@link BluetoothProfile#GATT}, {@link BluetoothProfile#HEARING_AID}, or {@link
2491 * BluetoothProfile#GATT_SERVER}. Clients must implement {@link
2492 * BluetoothProfile.ServiceListener} to get notified of the connection status and to get the
2493 * proxy object.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002494 *
2495 * @param context Context of the application
2496 * @param listener The service Listener for connection callbacks.
Jack He6b73b322019-01-03 16:23:41 -08002497 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET},
Stanley Tng1f5ea662018-11-15 17:11:36 -08002498 * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, {@link
2499 * BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#GATT_SERVER}.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002500 * @return true on success, false on error
2501 */
2502 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
Jack Hea355e5e2017-08-22 16:06:54 -07002503 int profile) {
Myles Watson125b5452017-11-27 16:41:47 -08002504 if (context == null || listener == null) {
2505 return false;
2506 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002507
2508 if (profile == BluetoothProfile.HEADSET) {
2509 BluetoothHeadset headset = new BluetoothHeadset(context, listener);
2510 return true;
2511 } else if (profile == BluetoothProfile.A2DP) {
2512 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
2513 return true;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002514 } else if (profile == BluetoothProfile.A2DP_SINK) {
2515 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
2516 return true;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002517 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
2518 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
2519 return true;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002520 } else if (profile == BluetoothProfile.HID_HOST) {
2521 BluetoothHidHost iDev = new BluetoothHidHost(context, listener);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -08002522 return true;
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -08002523 } else if (profile == BluetoothProfile.PAN) {
2524 BluetoothPan pan = new BluetoothPan(context, listener);
2525 return true;
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -07002526 } else if (profile == BluetoothProfile.HEALTH) {
Jack He6b73b322019-01-03 16:23:41 -08002527 Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated");
2528 return false;
Kim Schulz0d376052013-08-22 11:18:02 +02002529 } else if (profile == BluetoothProfile.MAP) {
2530 BluetoothMap map = new BluetoothMap(context, listener);
2531 return true;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002532 } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
2533 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
Hemant Gupta7aca90f2013-08-19 19:03:51 +05302534 return true;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002535 } else if (profile == BluetoothProfile.SAP) {
2536 BluetoothSap sap = new BluetoothSap(context, listener);
2537 return true;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002538 } else if (profile == BluetoothProfile.PBAP_CLIENT) {
2539 BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
2540 return true;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002541 } else if (profile == BluetoothProfile.MAP_CLIENT) {
2542 BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
2543 return true;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002544 } else if (profile == BluetoothProfile.HID_DEVICE) {
2545 BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
Ivan Podogov5297dba2016-12-30 14:35:09 +00002546 return true;
Jakub Pawlowskiea580fa2017-11-22 11:02:34 -08002547 } else if (profile == BluetoothProfile.HEARING_AID) {
Stanley Tng61dbd812019-01-13 16:04:31 -08002548 if (isHearingAidProfileSupported()) {
2549 BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener);
2550 return true;
2551 }
2552 return false;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002553 } else {
2554 return false;
2555 }
2556 }
2557
2558 /**
2559 * Close the connection of the profile proxy to the Service.
2560 *
2561 * <p> Clients should call this when they are no longer using
2562 * the proxy obtained from {@link #getProfileProxy}.
Jack He6b73b322019-01-03 16:23:41 -08002563 * Profile can be one of {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002564 *
2565 * @param profile
2566 * @param proxy Profile proxy object
2567 */
2568 public void closeProfileProxy(int profile, BluetoothProfile proxy) {
Myles Watson125b5452017-11-27 16:41:47 -08002569 if (proxy == null) {
2570 return;
2571 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002572
2573 switch (profile) {
2574 case BluetoothProfile.HEADSET:
Jack Hea355e5e2017-08-22 16:06:54 -07002575 BluetoothHeadset headset = (BluetoothHeadset) proxy;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002576 headset.close();
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002577 break;
2578 case BluetoothProfile.A2DP:
Jack Hea355e5e2017-08-22 16:06:54 -07002579 BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002580 a2dp.close();
2581 break;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002582 case BluetoothProfile.A2DP_SINK:
Jack Hea355e5e2017-08-22 16:06:54 -07002583 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002584 a2dpSink.close();
2585 break;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002586 case BluetoothProfile.AVRCP_CONTROLLER:
Jack Hea355e5e2017-08-22 16:06:54 -07002587 BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002588 avrcp.close();
2589 break;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002590 case BluetoothProfile.HID_HOST:
2591 BluetoothHidHost iDev = (BluetoothHidHost) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002592 iDev.close();
2593 break;
2594 case BluetoothProfile.PAN:
Jack Hea355e5e2017-08-22 16:06:54 -07002595 BluetoothPan pan = (BluetoothPan) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002596 pan.close();
2597 break;
Jack Hea355e5e2017-08-22 16:06:54 -07002598 case BluetoothProfile.GATT:
2599 BluetoothGatt gatt = (BluetoothGatt) proxy;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08002600 gatt.close();
2601 break;
2602 case BluetoothProfile.GATT_SERVER:
Jack Hea355e5e2017-08-22 16:06:54 -07002603 BluetoothGattServer gattServer = (BluetoothGattServer) proxy;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08002604 gattServer.close();
2605 break;
Kim Schulz0d376052013-08-22 11:18:02 +02002606 case BluetoothProfile.MAP:
Jack Hea355e5e2017-08-22 16:06:54 -07002607 BluetoothMap map = (BluetoothMap) proxy;
Kim Schulz0d376052013-08-22 11:18:02 +02002608 map.close();
2609 break;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002610 case BluetoothProfile.HEADSET_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002611 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002612 headsetClient.close();
Hemant Gupta7aca90f2013-08-19 19:03:51 +05302613 break;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002614 case BluetoothProfile.SAP:
Jack Hea355e5e2017-08-22 16:06:54 -07002615 BluetoothSap sap = (BluetoothSap) proxy;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002616 sap.close();
2617 break;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002618 case BluetoothProfile.PBAP_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002619 BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002620 pbapClient.close();
2621 break;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002622 case BluetoothProfile.MAP_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002623 BluetoothMapClient mapClient = (BluetoothMapClient) proxy;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002624 mapClient.close();
2625 break;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002626 case BluetoothProfile.HID_DEVICE:
2627 BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
2628 hidDevice.close();
Ivan Podogov5297dba2016-12-30 14:35:09 +00002629 break;
Jakub Pawlowskiea580fa2017-11-22 11:02:34 -08002630 case BluetoothProfile.HEARING_AID:
2631 BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
2632 hearingAid.close();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002633 }
2634 }
2635
Jack He2992cd02017-08-22 21:21:23 -07002636 private final IBluetoothManagerCallback mManagerCallback =
Jack Hea355e5e2017-08-22 16:06:54 -07002637 new IBluetoothManagerCallback.Stub() {
2638 public void onBluetoothServiceUp(IBluetooth bluetoothService) {
Myles Watson125b5452017-11-27 16:41:47 -08002639 if (DBG) {
2640 Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
2641 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002642
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002643 mServiceLock.writeLock().lock();
Jack Hea355e5e2017-08-22 16:06:54 -07002644 mService = bluetoothService;
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002645 mServiceLock.writeLock().unlock();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002646
Jack Hea355e5e2017-08-22 16:06:54 -07002647 synchronized (mProxyServiceStateCallbacks) {
2648 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2649 try {
2650 if (cb != null) {
2651 cb.onBluetoothServiceUp(bluetoothService);
2652 } else {
2653 Log.d(TAG, "onBluetoothServiceUp: cb is null!");
2654 }
2655 } catch (Exception e) {
2656 Log.e(TAG, "", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002657 }
Matthew Xie60675b22015-02-06 14:09:54 -08002658 }
fredc903ac6f2012-04-24 03:59:57 -07002659 }
Ugo Yu4a33b882019-01-08 09:00:09 +08002660 synchronized (sMetadataListeners) {
2661 sMetadataListeners.forEach((device, pair) -> {
2662 try {
2663 mService.registerMetadataListener(sBluetoothMetadataListener,
2664 device);
2665 } catch (RemoteException e) {
2666 Log.e(TAG, "Failed to register metadata listener", e);
2667 }
2668 });
2669 }
fredc0f420372012-04-12 00:02:00 -07002670 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002671
Jack Hea355e5e2017-08-22 16:06:54 -07002672 public void onBluetoothServiceDown() {
Myles Watson125b5452017-11-27 16:41:47 -08002673 if (DBG) {
2674 Log.d(TAG, "onBluetoothServiceDown: " + mService);
2675 }
Jack Hea355e5e2017-08-22 16:06:54 -07002676
2677 try {
2678 mServiceLock.writeLock().lock();
2679 mService = null;
Myles Watson125b5452017-11-27 16:41:47 -08002680 if (mLeScanClients != null) {
2681 mLeScanClients.clear();
2682 }
2683 if (sBluetoothLeAdvertiser != null) {
2684 sBluetoothLeAdvertiser.cleanup();
2685 }
2686 if (sBluetoothLeScanner != null) {
2687 sBluetoothLeScanner.cleanup();
2688 }
Jack Hea355e5e2017-08-22 16:06:54 -07002689 } finally {
2690 mServiceLock.writeLock().unlock();
2691 }
2692
2693 synchronized (mProxyServiceStateCallbacks) {
2694 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2695 try {
2696 if (cb != null) {
2697 cb.onBluetoothServiceDown();
2698 } else {
2699 Log.d(TAG, "onBluetoothServiceDown: cb is null!");
2700 }
2701 } catch (Exception e) {
2702 Log.e(TAG, "", e);
2703 }
2704 }
2705 }
2706 }
2707
2708 public void onBrEdrDown() {
Myles Watson125b5452017-11-27 16:41:47 -08002709 if (VDBG) {
2710 Log.i(TAG, "onBrEdrDown: " + mService);
2711 }
Jack Hea355e5e2017-08-22 16:06:54 -07002712 }
2713 };
fredc0f420372012-04-12 00:02:00 -07002714
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002715 /**
Martijn Coenen6c614b72012-04-18 13:01:15 -07002716 * Enable the Bluetooth Adapter, but don't auto-connect devices
2717 * and don't persist state. Only for use by system applications.
Jack Hea355e5e2017-08-22 16:06:54 -07002718 *
Martijn Coenen6c614b72012-04-18 13:01:15 -07002719 * @hide
2720 */
Selim Gurun64bd35e2017-10-17 17:01:38 -07002721 @SystemApi
2722 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
Martijn Coenen6c614b72012-04-18 13:01:15 -07002723 public boolean enableNoAutoConnect() {
Jack He2992cd02017-08-22 21:21:23 -07002724 if (isEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -08002725 if (DBG) {
2726 Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
2727 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002728 return true;
2729 }
2730 try {
Marie Janssen59804562016-12-28 14:13:21 -08002731 return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
Jack Hea355e5e2017-08-22 16:06:54 -07002732 } catch (RemoteException e) {
2733 Log.e(TAG, "", e);
2734 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002735 return false;
Martijn Coenen6c614b72012-04-18 13:01:15 -07002736 }
2737
2738 /**
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002739 * Enable control of the Bluetooth Adapter for a single application.
2740 *
2741 * <p>Some applications need to use Bluetooth for short periods of time to
2742 * transfer data but don't want all the associated implications like
2743 * automatic connection to headsets etc.
2744 *
2745 * <p> Multiple applications can call this. This is reference counted and
2746 * Bluetooth disabled only when no one else is using it. There will be no UI
2747 * shown to the user while bluetooth is being enabled. Any user action will
2748 * override this call. For example, if user wants Bluetooth on and the last
2749 * user of this API wanted to disable Bluetooth, Bluetooth will not be
2750 * turned off.
2751 *
2752 * <p> This API is only meant to be used by internal applications. Third
2753 * party applications but use {@link #enable} and {@link #disable} APIs.
2754 *
2755 * <p> If this API returns true, it means the callback will be called.
2756 * The callback will be called with the current state of Bluetooth.
2757 * If the state is not what was requested, an internal error would be the
Jaikumar Ganeshf5fb6c82011-08-03 14:17:22 -07002758 * reason. If Bluetooth is already on and if this function is called to turn
2759 * it on, the api will return true and a callback will be called.
2760 *
2761 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002762 *
2763 * @param on True for on, false for off.
2764 * @param callback The callback to notify changes to the state.
2765 * @hide
2766 */
2767 public boolean changeApplicationBluetoothState(boolean on,
Jack Hea355e5e2017-08-22 16:06:54 -07002768 BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002769 return false;
2770 }
2771
2772 /**
2773 * @hide
2774 */
2775 public interface BluetoothStateChangeCallback {
Myles Watson125b5452017-11-27 16:41:47 -08002776 /**
2777 * @hide
2778 */
2779 void onBluetoothStateChange(boolean on);
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002780 }
2781
2782 /**
2783 * @hide
2784 */
2785 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
2786 private BluetoothStateChangeCallback mCallback;
2787
Myles Watson125b5452017-11-27 16:41:47 -08002788 StateChangeCallbackWrapper(BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002789 mCallback = callback;
2790 }
2791
2792 @Override
2793 public void onBluetoothStateChange(boolean on) {
2794 mCallback.onBluetoothStateChange(on);
2795 }
2796 }
2797
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08002798 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
2799 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
2800 return Collections.unmodifiableSet(deviceSet);
Nick Pellybd022f42009-08-14 18:33:38 -07002801 }
Nick Pelly005b2282009-09-10 10:21:56 -07002802
fredc0f420372012-04-12 00:02:00 -07002803 protected void finalize() throws Throwable {
2804 try {
2805 mManagerService.unregisterAdapter(mManagerCallback);
2806 } catch (RemoteException e) {
2807 Log.e(TAG, "", e);
2808 } finally {
2809 super.finalize();
2810 }
2811 }
2812
2813
Nick Pelly005b2282009-09-10 10:21:56 -07002814 /**
Nick Pelly75596b42011-12-07 15:03:55 -08002815 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
Nick Pelly55e66f12009-09-18 11:37:06 -07002816 * <p>Alphabetic characters must be uppercase to be valid.
Nick Pelly005b2282009-09-10 10:21:56 -07002817 *
2818 * @param address Bluetooth address as string
2819 * @return true if the address is valid, false otherwise
2820 */
2821 public static boolean checkBluetoothAddress(String address) {
2822 if (address == null || address.length() != ADDRESS_LENGTH) {
2823 return false;
2824 }
2825 for (int i = 0; i < ADDRESS_LENGTH; i++) {
2826 char c = address.charAt(i);
2827 switch (i % 3) {
Jack Hea355e5e2017-08-22 16:06:54 -07002828 case 0:
2829 case 1:
2830 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
2831 // hex character, OK
2832 break;
2833 }
2834 return false;
2835 case 2:
2836 if (c == ':') {
2837 break; // OK
2838 }
2839 return false;
Nick Pelly005b2282009-09-10 10:21:56 -07002840 }
2841 }
2842 return true;
2843 }
fredc0f420372012-04-12 00:02:00 -07002844
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002845 @UnsupportedAppUsage
fredc0f420372012-04-12 00:02:00 -07002846 /*package*/ IBluetoothManager getBluetoothManager() {
Jack Hea355e5e2017-08-22 16:06:54 -07002847 return mManagerService;
fredc0f420372012-04-12 00:02:00 -07002848 }
2849
Jack He2992cd02017-08-22 21:21:23 -07002850 private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks =
Jack Hea355e5e2017-08-22 16:06:54 -07002851 new ArrayList<IBluetoothManagerCallback>();
fredcd6883532012-04-25 17:46:13 -07002852
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002853 @UnsupportedAppUsage
fredc903ac6f2012-04-24 03:59:57 -07002854 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08002855 synchronized (mProxyServiceStateCallbacks) {
fredcd6883532012-04-25 17:46:13 -07002856 if (cb == null) {
fredcbf072a72012-05-09 16:52:50 -07002857 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
2858 } else if (!mProxyServiceStateCallbacks.contains(cb)) {
2859 mProxyServiceStateCallbacks.add(cb);
fredc903ac6f2012-04-24 03:59:57 -07002860 }
2861 }
2862 return mService;
2863 }
2864
2865 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08002866 synchronized (mProxyServiceStateCallbacks) {
fredcbf072a72012-05-09 16:52:50 -07002867 mProxyServiceStateCallbacks.remove(cb);
fredc0f420372012-04-12 00:02:00 -07002868 }
2869 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002870
2871 /**
Matthew Xiecdd94e32013-04-11 16:36:26 -07002872 * Callback interface used to deliver LE scan results.
Matthew Xieddf7e472013-03-01 18:41:02 -08002873 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07002874 * @see #startLeScan(LeScanCallback)
2875 * @see #startLeScan(UUID[], LeScanCallback)
Matthew Xieddf7e472013-03-01 18:41:02 -08002876 */
Matthew Xiecdd94e32013-04-11 16:36:26 -07002877 public interface LeScanCallback {
2878 /**
2879 * Callback reporting an LE device found during a device scan initiated
2880 * by the {@link BluetoothAdapter#startLeScan} function.
2881 *
2882 * @param device Identifies the remote device
Jack Hea355e5e2017-08-22 16:06:54 -07002883 * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0
2884 * if no RSSI value is available.
2885 * @param scanRecord The content of the advertisement record offered by the remote device.
Matthew Xiecdd94e32013-04-11 16:36:26 -07002886 */
Myles Watson125b5452017-11-27 16:41:47 -08002887 void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
Matthew Xieddf7e472013-03-01 18:41:02 -08002888 }
2889
2890 /**
2891 * Starts a scan for Bluetooth LE devices.
2892 *
2893 * <p>Results of the scan are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07002894 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08002895 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07002896 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08002897 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07002898 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack Hea355e5e2017-08-22 16:06:54 -07002899 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002900 */
Wei Wangaf74e662014-07-09 14:03:42 -07002901 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002902 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07002903 public boolean startLeScan(LeScanCallback callback) {
2904 return startLeScan(null, callback);
Matthew Xieddf7e472013-03-01 18:41:02 -08002905 }
2906
2907 /**
2908 * Starts a scan for Bluetooth LE devices, looking for devices that
2909 * advertise given services.
2910 *
2911 * <p>Devices which advertise all specified services are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07002912 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08002913 *
Matthew Xieddf7e472013-03-01 18:41:02 -08002914 * @param serviceUuids Array of services to look for
Matthew Xiecdd94e32013-04-11 16:36:26 -07002915 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08002916 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07002917 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack Hea355e5e2017-08-22 16:06:54 -07002918 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002919 */
Wei Wangaf74e662014-07-09 14:03:42 -07002920 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002921 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Wei Wangc3059cc2014-07-23 23:34:00 -07002922 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
Myles Watson125b5452017-11-27 16:41:47 -08002923 if (DBG) {
2924 Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
2925 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07002926 if (callback == null) {
Myles Watson125b5452017-11-27 16:41:47 -08002927 if (DBG) {
2928 Log.e(TAG, "startLeScan: null callback");
2929 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002930 return false;
2931 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002932 BluetoothLeScanner scanner = getBluetoothLeScanner();
2933 if (scanner == null) {
Myles Watson125b5452017-11-27 16:41:47 -08002934 if (DBG) {
2935 Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
2936 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002937 return false;
2938 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002939
Jack Hea355e5e2017-08-22 16:06:54 -07002940 synchronized (mLeScanClients) {
Matthew Xiecdd94e32013-04-11 16:36:26 -07002941 if (mLeScanClients.containsKey(callback)) {
Myles Watson125b5452017-11-27 16:41:47 -08002942 if (DBG) {
2943 Log.e(TAG, "LE Scan has already started");
2944 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07002945 return false;
2946 }
2947
2948 try {
2949 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
Matthew Xie32ab77b2013-05-08 19:26:57 -07002950 if (iGatt == null) {
2951 // BLE is not supported
2952 return false;
2953 }
2954
Wei Wangc3059cc2014-07-23 23:34:00 -07002955 ScanCallback scanCallback = new ScanCallback() {
2956 @Override
2957 public void onScanResult(int callbackType, ScanResult result) {
2958 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
2959 // Should not happen.
2960 Log.e(TAG, "LE Scan has already started");
2961 return;
2962 }
2963 ScanRecord scanRecord = result.getScanRecord();
2964 if (scanRecord == null) {
2965 return;
2966 }
2967 if (serviceUuids != null) {
2968 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
2969 for (UUID uuid : serviceUuids) {
2970 uuids.add(new ParcelUuid(uuid));
2971 }
2972 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
2973 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
Myles Watson125b5452017-11-27 16:41:47 -08002974 if (DBG) {
2975 Log.d(TAG, "uuids does not match");
2976 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002977 return;
2978 }
2979 }
2980 callback.onLeScan(result.getDevice(), result.getRssi(),
2981 scanRecord.getBytes());
2982 }
2983 };
Myles Watson125b5452017-11-27 16:41:47 -08002984 ScanSettings settings = new ScanSettings.Builder().setCallbackType(
2985 ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
2986 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
2987 .build();
Wei Wangc3059cc2014-07-23 23:34:00 -07002988
2989 List<ScanFilter> filters = new ArrayList<ScanFilter>();
2990 if (serviceUuids != null && serviceUuids.length > 0) {
2991 // Note scan filter does not support matching an UUID array so we put one
2992 // UUID to hardware and match the whole array in callback.
Myles Watson125b5452017-11-27 16:41:47 -08002993 ScanFilter filter =
2994 new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuids[0]))
2995 .build();
Wei Wangc3059cc2014-07-23 23:34:00 -07002996 filters.add(filter);
Matthew Xiecdd94e32013-04-11 16:36:26 -07002997 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002998 scanner.startScan(filters, settings, scanCallback);
2999
3000 mLeScanClients.put(callback, scanCallback);
3001 return true;
3002
Matthew Xiecdd94e32013-04-11 16:36:26 -07003003 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -07003004 Log.e(TAG, "", e);
Matthew Xiecdd94e32013-04-11 16:36:26 -07003005 }
3006 }
3007 return false;
Matthew Xieddf7e472013-03-01 18:41:02 -08003008 }
3009
3010 /**
3011 * Stops an ongoing Bluetooth LE device scan.
3012 *
Jack Hea355e5e2017-08-22 16:06:54 -07003013 * @param callback used to identify which scan to stop must be the same handle used to start the
3014 * scan
Wei Wangaf74e662014-07-09 14:03:42 -07003015 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08003016 */
Wei Wangaf74e662014-07-09 14:03:42 -07003017 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07003018 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07003019 public void stopLeScan(LeScanCallback callback) {
Myles Watson125b5452017-11-27 16:41:47 -08003020 if (DBG) {
3021 Log.d(TAG, "stopLeScan()");
3022 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003023 BluetoothLeScanner scanner = getBluetoothLeScanner();
3024 if (scanner == null) {
3025 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08003026 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003027 synchronized (mLeScanClients) {
3028 ScanCallback scanCallback = mLeScanClients.remove(callback);
3029 if (scanCallback == null) {
Myles Watson125b5452017-11-27 16:41:47 -08003030 if (DBG) {
3031 Log.d(TAG, "scan not started yet");
3032 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003033 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08003034 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003035 scanner.stopScan(scanCallback);
Prerepa Viswanadham8f2e74c2014-07-09 12:51:59 -07003036 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07003037 }
Stanley Tnge48468d2017-11-22 16:04:40 -08003038
3039 /**
3040 * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
3041 * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003042 * for incoming connections. The supported Bluetooth transport is LE only.
Stanley Tnge48468d2017-11-22 16:04:40 -08003043 * <p>A remote device connecting to this socket will be authenticated and communication on this
3044 * socket will be encrypted.
3045 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3046 * {@link BluetoothServerSocket}.
3047 * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {#link
3048 * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
3049 * closed, Bluetooth is turned off, or the application exits unexpectedly.
3050 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3051 * defined and performed by the application.
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003052 * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
Stanley Tnge48468d2017-11-22 16:04:40 -08003053 * socket from another Android device that is given the PSM value.
3054 *
Stanley Tnge48468d2017-11-22 16:04:40 -08003055 * @return an L2CAP CoC BluetoothServerSocket
3056 * @throws IOException on error, for example Bluetooth not available, or insufficient
3057 * permissions, or unable to start this CoC
Stanley Tnge48468d2017-11-22 16:04:40 -08003058 */
3059 @RequiresPermission(Manifest.permission.BLUETOOTH)
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003060 public BluetoothServerSocket listenUsingL2capChannel()
Stanley Tnge48468d2017-11-22 16:04:40 -08003061 throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08003062 BluetoothServerSocket socket =
3063 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
3064 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3065 int errno = socket.mSocket.bindListen();
3066 if (errno != 0) {
3067 throw new IOException("Error: " + errno);
3068 }
3069
3070 int assignedPsm = socket.mSocket.getPort();
3071 if (assignedPsm == 0) {
3072 throw new IOException("Error: Unable to assign PSM value");
3073 }
3074 if (DBG) {
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003075 Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
Stanley Tnge48468d2017-11-22 16:04:40 -08003076 + assignedPsm);
3077 }
3078 socket.setChannel(assignedPsm);
3079
3080 return socket;
3081 }
3082
3083 /**
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003084 * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
3085 * API name, listenUsingL2capChannel.
3086 * @hide
3087 */
3088 @RequiresPermission(Manifest.permission.BLUETOOTH)
3089 public BluetoothServerSocket listenUsingL2capCoc(int transport)
3090 throws IOException {
3091 Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel");
3092 return listenUsingL2capChannel();
3093 }
3094
3095 /**
Stanley Tnge48468d2017-11-22 16:04:40 -08003096 * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003097 * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
3098 * supported Bluetooth transport is LE only.
Stanley Tnge48468d2017-11-22 16:04:40 -08003099 * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003100 * to man-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
Stanley Tnge48468d2017-11-22 16:04:40 -08003101 * authenticated communication channel is desired.
3102 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3103 * {@link BluetoothServerSocket}.
3104 * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
3105 * can be read from the {#link BluetoothServerSocket#getPsm()} and this value will be released
3106 * when this server socket is closed, Bluetooth is turned off, or the application exits
3107 * unexpectedly.
3108 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3109 * defined and performed by the application.
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003110 * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
3111 * socket from another Android device that is given the PSM value.
Stanley Tnge48468d2017-11-22 16:04:40 -08003112 *
Stanley Tnge48468d2017-11-22 16:04:40 -08003113 * @return an L2CAP CoC BluetoothServerSocket
3114 * @throws IOException on error, for example Bluetooth not available, or insufficient
3115 * permissions, or unable to start this CoC
Stanley Tnge48468d2017-11-22 16:04:40 -08003116 */
3117 @RequiresPermission(Manifest.permission.BLUETOOTH)
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003118 public BluetoothServerSocket listenUsingInsecureL2capChannel()
Stanley Tnge48468d2017-11-22 16:04:40 -08003119 throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08003120 BluetoothServerSocket socket =
3121 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
3122 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3123 int errno = socket.mSocket.bindListen();
3124 if (errno != 0) {
3125 throw new IOException("Error: " + errno);
3126 }
3127
3128 int assignedPsm = socket.mSocket.getPort();
3129 if (assignedPsm == 0) {
3130 throw new IOException("Error: Unable to assign PSM value");
3131 }
3132 if (DBG) {
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003133 Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
Stanley Tnge48468d2017-11-22 16:04:40 -08003134 + assignedPsm);
3135 }
3136 socket.setChannel(assignedPsm);
3137
3138 return socket;
3139 }
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003140
3141 /**
3142 * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
3143 * API name, listenUsingInsecureL2capChannel.
3144 * @hide
3145 */
3146 @RequiresPermission(Manifest.permission.BLUETOOTH)
3147 public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
3148 throws IOException {
3149 Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, "
3150 + "listenUsingInsecureL2capChannel");
3151 return listenUsingInsecureL2capChannel();
3152 }
Ugo Yu4a33b882019-01-08 09:00:09 +08003153
3154 /**
3155 * Register a {@link #MetadataListener} to receive update about metadata
3156 * changes for this {@link BluetoothDevice}.
3157 * Registration must be done when Bluetooth is ON and will last until
3158 * {@link #unregisterMetadataListener(BluetoothDevice)} is called, even when Bluetooth
3159 * restarted in the middle.
3160 * All input parameters should not be null or {@link NullPointerException} will be triggered.
3161 * The same {@link BluetoothDevice} and {@link #MetadataListener} pair can only be registered
3162 * once, double registration would cause {@link IllegalArgumentException}.
3163 *
3164 * @param device {@link BluetoothDevice} that will be registered
3165 * @param listener {@link #MetadataListener} that will receive asynchronous callbacks
3166 * @param handler the handler for listener callback
3167 * @return true on success, false on error
3168 * @throws NullPointerException If one of {@code listener}, {@code device} or {@code handler}
3169 * is null.
3170 * @throws IllegalArgumentException The same {@link #MetadataListener} and
3171 * {@link BluetoothDevice} are registered twice.
3172 * @hide
3173 */
3174 @SystemApi
3175 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
3176 public boolean registerMetadataListener(BluetoothDevice device, MetadataListener listener,
3177 Handler handler) {
3178 if (DBG) Log.d(TAG, "registerMetdataListener()");
3179
3180 final IBluetooth service = mService;
3181 if (service == null) {
3182 Log.e(TAG, "Bluetooth is not enabled. Cannot register metadata listener");
3183 return false;
3184 }
3185 if (listener == null) {
3186 throw new NullPointerException("listener is null");
3187 }
3188 if (device == null) {
3189 throw new NullPointerException("device is null");
3190 }
3191 if (handler == null) {
3192 throw new NullPointerException("handler is null");
3193 }
3194
3195 synchronized (sMetadataListeners) {
3196 List<Pair<MetadataListener, Handler>> listenerList = sMetadataListeners.get(device);
3197 if (listenerList == null) {
3198 // Create new listener/handler list for registeration
3199 listenerList = new ArrayList<>();
3200 sMetadataListeners.put(device, listenerList);
3201 } else {
3202 // Check whether this device was already registed by the lisenter
3203 if (listenerList.stream().anyMatch((pair) -> (pair.first.equals(listener)))) {
3204 throw new IllegalArgumentException("listener was already regestered"
3205 + " for the device");
3206 }
3207 }
3208
3209 Pair<MetadataListener, Handler> listenerPair = new Pair(listener, handler);
3210 listenerList.add(listenerPair);
3211
3212 boolean ret = false;
3213 try {
3214 ret = service.registerMetadataListener(sBluetoothMetadataListener, device);
3215 } catch (RemoteException e) {
3216 Log.e(TAG, "registerMetadataListener fail", e);
3217 } finally {
3218 if (!ret) {
3219 // Remove listener registered earlier when fail.
3220 listenerList.remove(listenerPair);
3221 if (listenerList.isEmpty()) {
3222 // Remove the device if its listener list is empty
3223 sMetadataListeners.remove(device);
3224 }
3225 }
3226 }
3227 return ret;
3228 }
3229 }
3230
3231 /**
3232 * Unregister all {@link MetadataListener} from this {@link BluetoothDevice}.
3233 * Unregistration can be done when Bluetooth is either ON or OFF.
3234 * {@link #registerMetadataListener(MetadataListener, BluetoothDevice, Handler)} must
3235 * be called before unregisteration.
3236 * Unregistering a device that is not regestered would cause {@link IllegalArgumentException}.
3237 *
3238 * @param device {@link BluetoothDevice} that will be unregistered. it
3239 * should not be null or {@link NullPointerException} will be triggered.
3240 * @return true on success, false on error
3241 * @throws NullPointerException If {@code device} is null.
3242 * @throws IllegalArgumentException If {@code device} has not been registered before.
3243 * @hide
3244 */
3245 @SystemApi
3246 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
3247 public boolean unregisterMetadataListener(BluetoothDevice device) {
3248 if (DBG) Log.d(TAG, "unregisterMetdataListener()");
3249 if (device == null) {
3250 throw new NullPointerException("device is null");
3251 }
3252
3253 synchronized (sMetadataListeners) {
3254 if (sMetadataListeners.containsKey(device)) {
3255 sMetadataListeners.remove(device);
3256 } else {
3257 throw new IllegalArgumentException("device was not registered");
3258 }
3259
3260 final IBluetooth service = mService;
3261 if (service == null) {
3262 // Bluetooth is OFF, do nothing to Bluetooth service.
3263 return true;
3264 }
3265 try {
3266 return service.unregisterMetadataListener(device);
3267 } catch (RemoteException e) {
3268 Log.e(TAG, "unregisterMetadataListener fail", e);
3269 return false;
3270 }
3271 }
3272 }
3273
3274 /**
3275 * This abstract class is used to implement {@link BluetoothAdapter} metadata listener.
3276 * @hide
3277 */
3278 @SystemApi
Ugo Yud9a0a7f2019-01-24 09:13:00 +08003279 public abstract static class MetadataListener {
Ugo Yu4a33b882019-01-08 09:00:09 +08003280 /**
3281 * Callback triggered if the metadata of {@link BluetoothDevice} registered in
3282 * {@link #registerMetadataListener}.
3283 *
3284 * @param device changed {@link BluetoothDevice}.
3285 * @param key changed metadata key, one of BluetoothDevice.METADATA_*.
3286 * @param value the new value of metadata.
3287 */
3288 public void onMetadataChanged(BluetoothDevice device, int key, String value) {
3289 }
3290 }
Nick Pellybd022f42009-08-14 18:33:38 -07003291}