blob: 9d152a7faf44c59b66260920d3a0e535f45cf1b0 [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;
Stanley Tng97341da2019-03-12 10:19:49 -070022import android.annotation.NonNull;
Ugo Yu50e3c082019-03-05 16:20:27 +080023import android.annotation.Nullable;
Tor Norbye2d497522015-04-23 17:10:21 -070024import android.annotation.RequiresPermission;
Nick Pellyde893f52009-09-08 13:15:33 -070025import android.annotation.SdkConstant;
26import android.annotation.SdkConstant.SdkConstantType;
Wei Wangd91f1932015-03-19 15:09:56 -070027import android.annotation.SystemApi;
Mathew Inwood4dc66d32018-08-01 15:07:20 +010028import android.annotation.UnsupportedAppUsage;
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -070029import android.app.ActivityThread;
Wei Wang6d811182014-05-22 12:10:25 -070030import android.bluetooth.le.BluetoothLeAdvertiser;
31import android.bluetooth.le.BluetoothLeScanner;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -080032import android.bluetooth.le.PeriodicAdvertisingManager;
Wei Wangaf74e662014-07-09 14:03:42 -070033import android.bluetooth.le.ScanCallback;
Wei Wangc3059cc2014-07-23 23:34:00 -070034import android.bluetooth.le.ScanFilter;
35import android.bluetooth.le.ScanRecord;
Wei Wang9fb17912014-07-01 15:10:06 -070036import android.bluetooth.le.ScanResult;
Wei Wangaf74e662014-07-09 14:03:42 -070037import android.bluetooth.le.ScanSettings;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070038import android.content.Context;
Adam Lesinski010bf372016-04-11 12:18:18 -070039import android.os.BatteryStats;
Wei Wang46ab7232015-05-07 16:25:33 -070040import android.os.Binder;
Nick Pellyf242b7b2009-10-08 00:12:45 +020041import android.os.IBinder;
Nick Pellyaef439e2009-09-28 12:33:17 -070042import android.os.ParcelUuid;
Nick Pellybd022f42009-08-14 18:33:38 -070043import android.os.RemoteException;
Adam Lesinski010bf372016-04-11 12:18:18 -070044import android.os.ResultReceiver;
Nick Pellyf242b7b2009-10-08 00:12:45 +020045import android.os.ServiceManager;
Adam Lesinski010bf372016-04-11 12:18:18 -070046import android.os.SynchronousResultReceiver;
Ajay Panickerb6e1daf2016-02-29 16:09:14 -080047import android.os.SystemProperties;
Nick Pellybd022f42009-08-14 18:33:38 -070048import android.util.Log;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070049import android.util.Pair;
Wei Wang18c76932013-10-29 21:05:37 -070050
Nick Pellybd022f42009-08-14 18:33:38 -070051import java.io.IOException;
Tor Norbye2d497522015-04-23 17:10:21 -070052import java.lang.annotation.Retention;
53import java.lang.annotation.RetentionPolicy;
fredc903ac6f2012-04-24 03:59:57 -070054import java.util.ArrayList;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070055import java.util.Arrays;
Nick Pellybd022f42009-08-14 18:33:38 -070056import java.util.Collections;
Matthew Xiecdd94e32013-04-11 16:36:26 -070057import java.util.HashMap;
Wei Wang18c76932013-10-29 21:05:37 -070058import java.util.HashSet;
Wei Wang9fb17912014-07-01 15:10:06 -070059import java.util.List;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070060import java.util.Locale;
Matthew Xiecdd94e32013-04-11 16:36:26 -070061import java.util.Map;
Nick Pelly24bb9b82009-10-02 20:34:18 -070062import java.util.Set;
Nick Pelly16fb88a2009-10-07 07:44:03 +020063import java.util.UUID;
Ugo Yu50e3c082019-03-05 16:20:27 +080064import java.util.concurrent.Executor;
Adam Lesinski010bf372016-04-11 12:18:18 -070065import java.util.concurrent.TimeoutException;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -070066import java.util.concurrent.locks.ReentrantReadWriteLock;
Nick Pellybd022f42009-08-14 18:33:38 -070067
68/**
Scott Main9fab0ae2009-11-03 18:17:59 -080069 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
70 * lets you perform fundamental Bluetooth tasks, such as initiate
71 * device discovery, query a list of bonded (paired) devices,
72 * instantiate a {@link BluetoothDevice} using a known MAC address, and create
73 * a {@link BluetoothServerSocket} to listen for connection requests from other
Matthew Xieb30f91e2013-05-29 10:19:06 -070074 * devices, and start a scan for Bluetooth LE devices.
Scott Main9fab0ae2009-11-03 18:17:59 -080075 *
76 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
Marie Janssen553c8c72017-01-12 16:00:30 -080077 * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}.
78 * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter}
79 * method instead.
80 * </p><p>
Scott Main9fab0ae2009-11-03 18:17:59 -080081 * Fundamentally, this is your starting point for all
82 * Bluetooth actions. Once you have the local adapter, you can get a set of
83 * {@link BluetoothDevice} objects representing all paired devices with
84 * {@link #getBondedDevices()}; start device discovery with
85 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
Stanley Tnge48468d2017-11-22 16:04:40 -080086 * listen for incoming RFComm connection requests with {@link
Stanley Tng1bff4ba2018-06-29 14:05:04 -070087 * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
88 * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
Matthew Xieb30f91e2013-05-29 10:19:06 -070089 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
Marie Janssen553c8c72017-01-12 16:00:30 -080090 * </p>
91 * <p>This class is thread safe.</p>
Scott Main9fab0ae2009-11-03 18:17:59 -080092 * <p class="note"><strong>Note:</strong>
93 * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
94 * permission and some also require the
95 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
Marie Janssen553c8c72017-01-12 16:00:30 -080096 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080097 * <div class="special reference">
98 * <h3>Developer Guides</h3>
Hemal Patel65813df2016-08-17 13:18:14 -070099 * <p>
Jack Hea355e5e2017-08-22 16:06:54 -0700100 * For more information about using Bluetooth, read the <a href=
Hemal Patel65813df2016-08-17 13:18:14 -0700101 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
102 * guide.
103 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -0800104 * </div>
105 *
Scott Main9fab0ae2009-11-03 18:17:59 -0800106 * {@see BluetoothDevice}
107 * {@see BluetoothServerSocket}
Nick Pellybd022f42009-08-14 18:33:38 -0700108 */
109public final class BluetoothAdapter {
110 private static final String TAG = "BluetoothAdapter";
fredc0f420372012-04-12 00:02:00 -0700111 private static final boolean DBG = true;
Matthew Xie3b6214f2012-08-29 00:12:29 -0700112 private static final boolean VDBG = false;
Nick Pellybd022f42009-08-14 18:33:38 -0700113
Nick Pellyde893f52009-09-08 13:15:33 -0700114 /**
Svet Ganov408abf72015-05-12 19:13:36 -0700115 * Default MAC address reported to a client that does not have the
116 * android.permission.LOCAL_MAC_ADDRESS permission.
117 *
118 * @hide
119 */
120 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
121
122 /**
Nick Pellyb24e11b2009-09-08 17:40:43 -0700123 * Sentinel error value for this class. Guaranteed to not equal any other
124 * integer constant in this class. Provided as a convenience for functions
125 * that require a sentinel error value, for example:
126 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
127 * BluetoothAdapter.ERROR)</code>
128 */
Nick Pelly005b2282009-09-10 10:21:56 -0700129 public static final int ERROR = Integer.MIN_VALUE;
Nick Pellyb24e11b2009-09-08 17:40:43 -0700130
131 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700132 * Broadcast Action: The state of the local Bluetooth adapter has been
133 * changed.
134 * <p>For example, Bluetooth has been turned on or off.
Nick Pelly005b2282009-09-10 10:21:56 -0700135 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700136 * #EXTRA_PREVIOUS_STATE} containing the new and old states
137 * respectively.
138 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
139 */
Myles Watson125b5452017-11-27 16:41:47 -0800140 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
141 ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
Nick Pellybd022f42009-08-14 18:33:38 -0700142
Nick Pellyde893f52009-09-08 13:15:33 -0700143 /**
144 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
145 * intents to request the current power state. Possible values are:
146 * {@link #STATE_OFF},
147 * {@link #STATE_TURNING_ON},
148 * {@link #STATE_ON},
149 * {@link #STATE_TURNING_OFF},
150 */
Myles Watson125b5452017-11-27 16:41:47 -0800151 public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
Nick Pellyde893f52009-09-08 13:15:33 -0700152 /**
153 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
154 * intents to request the previous power state. Possible values are:
155 * {@link #STATE_OFF},
156 * {@link #STATE_TURNING_ON},
157 * {@link #STATE_ON},
Etan Cohenfd840dd2015-04-23 18:25:08 -0700158 * {@link #STATE_TURNING_OFF}
Nick Pellyde893f52009-09-08 13:15:33 -0700159 */
160 public static final String EXTRA_PREVIOUS_STATE =
Nick Pelly005b2282009-09-10 10:21:56 -0700161 "android.bluetooth.adapter.extra.PREVIOUS_STATE";
Nick Pellybd022f42009-08-14 18:33:38 -0700162
Tor Norbye2d497522015-04-23 17:10:21 -0700163 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700164 @IntDef(prefix = { "STATE_" }, value = {
Myles Watson125b5452017-11-27 16:41:47 -0800165 STATE_OFF,
166 STATE_TURNING_ON,
167 STATE_ON,
168 STATE_TURNING_OFF,
169 STATE_BLE_TURNING_ON,
170 STATE_BLE_ON,
171 STATE_BLE_TURNING_OFF
172 })
Tor Norbye2d497522015-04-23 17:10:21 -0700173 @Retention(RetentionPolicy.SOURCE)
Myles Watson125b5452017-11-27 16:41:47 -0800174 public @interface AdapterState {}
Tor Norbye2d497522015-04-23 17:10:21 -0700175
Nick Pellyde893f52009-09-08 13:15:33 -0700176 /**
177 * Indicates the local Bluetooth adapter is off.
178 */
Nick Pelly005b2282009-09-10 10:21:56 -0700179 public static final int STATE_OFF = 10;
Nick Pellyde893f52009-09-08 13:15:33 -0700180 /**
181 * Indicates the local Bluetooth adapter is turning on. However local
182 * clients should wait for {@link #STATE_ON} before attempting to
183 * use the adapter.
184 */
Nick Pelly005b2282009-09-10 10:21:56 -0700185 public static final int STATE_TURNING_ON = 11;
Nick Pellyde893f52009-09-08 13:15:33 -0700186 /**
187 * Indicates the local Bluetooth adapter is on, and ready for use.
188 */
Nick Pelly005b2282009-09-10 10:21:56 -0700189 public static final int STATE_ON = 12;
Nick Pellyde893f52009-09-08 13:15:33 -0700190 /**
191 * Indicates the local Bluetooth adapter is turning off. Local clients
192 * should immediately attempt graceful disconnection of any remote links.
193 */
Nick Pelly005b2282009-09-10 10:21:56 -0700194 public static final int STATE_TURNING_OFF = 13;
Nick Pellyde893f52009-09-08 13:15:33 -0700195
196 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800197 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
Jack Hea355e5e2017-08-22 16:06:54 -0700198 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800199 * @hide
200 */
201 public static final int STATE_BLE_TURNING_ON = 14;
202
203 /**
204 * Indicates the local Bluetooth adapter is in LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700205 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800206 * @hide
207 */
208 public static final int STATE_BLE_ON = 15;
209
210 /**
211 * Indicates the local Bluetooth adapter is turning off LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700212 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800213 * @hide
214 */
215 public static final int STATE_BLE_TURNING_OFF = 16;
216
217 /**
Stanley Tnge48468d2017-11-22 16:04:40 -0800218 * UUID of the GATT Read Characteristics for LE_PSM value.
219 *
220 * @hide
221 */
222 public static final UUID LE_PSM_CHARACTERISTIC_UUID =
223 UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
224
225 /**
Marie Janssencb21ad72016-12-13 10:51:02 -0800226 * Human-readable string helper for AdapterState
Jack Hea355e5e2017-08-22 16:06:54 -0700227 *
Marie Janssencb21ad72016-12-13 10:51:02 -0800228 * @hide
229 */
230 public static String nameForState(@AdapterState int state) {
Jack Hea355e5e2017-08-22 16:06:54 -0700231 switch (state) {
232 case STATE_OFF:
233 return "OFF";
234 case STATE_TURNING_ON:
235 return "TURNING_ON";
236 case STATE_ON:
237 return "ON";
238 case STATE_TURNING_OFF:
239 return "TURNING_OFF";
240 case STATE_BLE_TURNING_ON:
241 return "BLE_TURNING_ON";
242 case STATE_BLE_ON:
243 return "BLE_ON";
244 case STATE_BLE_TURNING_OFF:
245 return "BLE_TURNING_OFF";
246 default:
247 return "?!?!? (" + state + ")";
Marie Janssencb21ad72016-12-13 10:51:02 -0800248 }
249 }
250
251 /**
Nick Pelly18b1e792009-09-24 11:14:15 -0700252 * Activity Action: Show a system activity that requests discoverable mode.
Scott Main6d95fc02009-11-19 17:00:19 -0800253 * This activity will also request the user to turn on Bluetooth if it
Nick Pelly1acdcc12009-09-28 10:33:55 -0700254 * is not currently enabled.
Nick Pelly18b1e792009-09-24 11:14:15 -0700255 * <p>Discoverable mode is equivalent to {@link
256 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
257 * this Bluetooth adapter when they perform a discovery.
Scott Main6d95fc02009-11-19 17:00:19 -0800258 * <p>For privacy, Android is not discoverable by default.
259 * <p>The sender of this Intent can optionally use extra field {@link
Nick Pelly18b1e792009-09-24 11:14:15 -0700260 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
261 * discoverability. Currently the default duration is 120 seconds, and
262 * maximum duration is capped at 300 seconds for each request.
263 * <p>Notification of the result of this activity is posted using the
264 * {@link android.app.Activity#onActivityResult} callback. The
265 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800266 * will be the duration (in seconds) of discoverability or
267 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
268 * discoverability or an error has occurred.
Nick Pelly18b1e792009-09-24 11:14:15 -0700269 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
Scott Main6d95fc02009-11-19 17:00:19 -0800270 * for global notification whenever the scan mode changes. For example, an
271 * application can be notified when the device has ended discoverability.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700272 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pelly18b1e792009-09-24 11:14:15 -0700273 */
Myles Watson125b5452017-11-27 16:41:47 -0800274 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
275 ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
Nick Pelly18b1e792009-09-24 11:14:15 -0700276
277 /**
278 * Used as an optional int extra field in {@link
279 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
280 * for discoverability in seconds. The current default is 120 seconds, and
281 * requests over 300 seconds will be capped. These values could change.
282 */
283 public static final String EXTRA_DISCOVERABLE_DURATION =
284 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
285
286 /**
Nick Pelly1acdcc12009-09-28 10:33:55 -0700287 * Activity Action: Show a system activity that allows the user to turn on
288 * Bluetooth.
289 * <p>This system activity will return once Bluetooth has completed turning
290 * on, or the user has decided not to turn Bluetooth on.
291 * <p>Notification of the result of this activity is posted using the
292 * {@link android.app.Activity#onActivityResult} callback. The
293 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800294 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
295 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
296 * has rejected the request or an error has occurred.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700297 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
298 * for global notification whenever Bluetooth is turned on or off.
299 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
300 */
Myles Watson125b5452017-11-27 16:41:47 -0800301 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
302 ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
Nick Pelly1acdcc12009-09-28 10:33:55 -0700303
304 /**
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700305 * Activity Action: Show a system activity that allows the user to turn off
306 * Bluetooth. This is used only if permission review is enabled which is for
307 * apps targeting API less than 23 require a permission review before any of
308 * the app's components can run.
309 * <p>This system activity will return once Bluetooth has completed turning
310 * off, or the user has decided not to turn Bluetooth off.
311 * <p>Notification of the result of this activity is posted using the
312 * {@link android.app.Activity#onActivityResult} callback. The
313 * <code>resultCode</code>
314 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
315 * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
316 * has rejected the request or an error has occurred.
317 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
318 * for global notification whenever Bluetooth is turned on or off.
319 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
320 *
321 * @hide
322 */
Myles Watson125b5452017-11-27 16:41:47 -0800323 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
324 ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE";
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700325
326 /**
Wei Wangd91f1932015-03-19 15:09:56 -0700327 * Activity Action: Show a system activity that allows user to enable BLE scans even when
328 * Bluetooth is turned off.<p>
329 *
330 * Notification of result of this activity is posted using
331 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
332 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
333 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
334 * error occurred.
335 *
336 * @hide
337 */
338 @SystemApi
339 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
340 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
341 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
342
343 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700344 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
345 * has changed.
Nick Pelly005b2282009-09-10 10:21:56 -0700346 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700347 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
348 * respectively.
349 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
350 */
Myles Watson125b5452017-11-27 16:41:47 -0800351 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
352 ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
Nick Pellyde893f52009-09-08 13:15:33 -0700353
354 /**
355 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
356 * intents to request the current scan mode. Possible values are:
357 * {@link #SCAN_MODE_NONE},
358 * {@link #SCAN_MODE_CONNECTABLE},
359 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
360 */
Nick Pelly005b2282009-09-10 10:21:56 -0700361 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700362 /**
363 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
364 * intents to request the previous scan mode. Possible values are:
365 * {@link #SCAN_MODE_NONE},
366 * {@link #SCAN_MODE_CONNECTABLE},
367 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
368 */
369 public static final String EXTRA_PREVIOUS_SCAN_MODE =
Nick Pelly005b2282009-09-10 10:21:56 -0700370 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700371
Tor Norbye2d497522015-04-23 17:10:21 -0700372 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700373 @IntDef(prefix = { "SCAN_" }, value = {
374 SCAN_MODE_NONE,
375 SCAN_MODE_CONNECTABLE,
376 SCAN_MODE_CONNECTABLE_DISCOVERABLE
377 })
Tor Norbye2d497522015-04-23 17:10:21 -0700378 @Retention(RetentionPolicy.SOURCE)
Myles Watson125b5452017-11-27 16:41:47 -0800379 public @interface ScanMode {}
Tor Norbye2d497522015-04-23 17:10:21 -0700380
Nick Pellyde893f52009-09-08 13:15:33 -0700381 /**
382 * Indicates that both inquiry scan and page scan are disabled on the local
383 * Bluetooth adapter. Therefore this device is neither discoverable
384 * nor connectable from remote Bluetooth devices.
385 */
Nick Pelly005b2282009-09-10 10:21:56 -0700386 public static final int SCAN_MODE_NONE = 20;
Nick Pellyde893f52009-09-08 13:15:33 -0700387 /**
388 * Indicates that inquiry scan is disabled, but page scan is enabled on the
389 * local Bluetooth adapter. Therefore this device is not discoverable from
390 * remote Bluetooth devices, but is connectable from remote devices that
391 * have previously discovered this device.
392 */
Nick Pelly005b2282009-09-10 10:21:56 -0700393 public static final int SCAN_MODE_CONNECTABLE = 21;
Nick Pellyde893f52009-09-08 13:15:33 -0700394 /**
395 * Indicates that both inquiry scan and page scan are enabled on the local
396 * Bluetooth adapter. Therefore this device is both discoverable and
397 * connectable from remote Bluetooth devices.
398 */
Nick Pelly005b2282009-09-10 10:21:56 -0700399 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
Nick Pellybd022f42009-08-14 18:33:38 -0700400
Nick Pelly005b2282009-09-10 10:21:56 -0700401 /**
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -0700402 * Device only has a display.
403 *
404 * @hide
405 */
406 public static final int IO_CAPABILITY_OUT = 0;
407
408 /**
409 * Device has a display and the ability to input Yes/No.
410 *
411 * @hide
412 */
413 public static final int IO_CAPABILITY_IO = 1;
414
415 /**
416 * Device only has a keyboard for entry but no display.
417 *
418 * @hide
419 */
420 public static final int IO_CAPABILITY_IN = 2;
421
422 /**
423 * Device has no Input or Output capability.
424 *
425 * @hide
426 */
427 public static final int IO_CAPABILITY_NONE = 3;
428
429 /**
430 * Device has a display and a full keyboard.
431 *
432 * @hide
433 */
434 public static final int IO_CAPABILITY_KBDISP = 4;
435
436 /**
437 * Maximum range value for Input/Output capabilities.
438 *
439 * <p>This should be updated when adding a new Input/Output capability. Other code
440 * like validation depends on this being accurate.
441 *
442 * @hide
443 */
444 public static final int IO_CAPABILITY_MAX = 5;
445
446 /**
447 * The Input/Output capability of the device is unknown.
448 *
449 * @hide
450 */
451 public static final int IO_CAPABILITY_UNKNOWN = 255;
452
Pulkit Bhuwalka80238142018-04-20 16:56:53 -0700453 /** @hide */
454 @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE,
455 IO_CAPABILITY_KBDISP})
456 @Retention(RetentionPolicy.SOURCE)
457 public @interface IoCapability {}
458
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -0700459 /**
Nick Pelly005b2282009-09-10 10:21:56 -0700460 * Broadcast Action: The local Bluetooth adapter has started the remote
461 * device discovery process.
462 * <p>This usually involves an inquiry scan of about 12 seconds, followed
463 * by a page scan of each new device to retrieve its Bluetooth name.
464 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
465 * remote Bluetooth devices are found.
466 * <p>Device discovery is a heavyweight procedure. New connections to
467 * remote Bluetooth devices should not be attempted while discovery is in
468 * progress, and existing connections will experience limited bandwidth
469 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
470 * discovery.
471 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
472 */
Myles Watson125b5452017-11-27 16:41:47 -0800473 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
474 ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
Nick Pelly005b2282009-09-10 10:21:56 -0700475 /**
476 * Broadcast Action: The local Bluetooth adapter has finished the device
477 * discovery process.
478 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
479 */
Myles Watson125b5452017-11-27 16:41:47 -0800480 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
481 ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
Nick Pelly005b2282009-09-10 10:21:56 -0700482
483 /**
484 * Broadcast Action: The local Bluetooth adapter has changed its friendly
485 * Bluetooth name.
486 * <p>This name is visible to remote Bluetooth devices.
487 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
488 * the name.
489 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
490 */
Myles Watson125b5452017-11-27 16:41:47 -0800491 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
492 ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
Nick Pelly005b2282009-09-10 10:21:56 -0700493 /**
494 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
495 * intents to request the local Bluetooth name.
496 */
497 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
498
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700499 /**
500 * Intent used to broadcast the change in connection state of the local
501 * Bluetooth adapter to a profile of the remote device. When the adapter is
502 * not connected to any profiles of any remote devices and it attempts a
Ricardo Loo Forondaf710a232018-01-24 17:49:18 -0800503 * connection to a profile this intent will be sent. Once connected, this intent
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700504 * will not be sent for any more connection attempts to any profiles of any
505 * remote device. When the adapter disconnects from the last profile its
506 * connected to of any remote device, this intent will be sent.
507 *
508 * <p> This intent is useful for applications that are only concerned about
509 * whether the local adapter is connected to any profile of any device and
510 * are not really concerned about which profile. For example, an application
511 * which displays an icon to display whether Bluetooth is connected or not
512 * can use this intent.
513 *
514 * <p>This intent will have 3 extras:
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800515 * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
516 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700517 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
518 *
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800519 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
520 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700521 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
522 *
523 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
524 */
Myles Watson125b5452017-11-27 16:41:47 -0800525 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
526 ACTION_CONNECTION_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700527 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700528
529 /**
530 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
531 *
532 * This extra represents the current connection state.
533 */
534 public static final String EXTRA_CONNECTION_STATE =
Jack Hea355e5e2017-08-22 16:06:54 -0700535 "android.bluetooth.adapter.extra.CONNECTION_STATE";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700536
537 /**
538 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
539 *
540 * This extra represents the previous connection state.
541 */
542 public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
Jack Hea355e5e2017-08-22 16:06:54 -0700543 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700544
Nitin Arorad055adb2015-03-02 15:03:51 -0800545 /**
546 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700547 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800548 * @hide
549 */
Myles Watson125b5452017-11-27 16:41:47 -0800550 @SystemApi public static final String ACTION_BLE_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700551 "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800552
553 /**
Stanley Tngdd749b02017-04-17 22:35:45 -0700554 * Intent used to broadcast the change in the Bluetooth address
555 * of the local Bluetooth adapter.
556 * <p>Always contains the extra field {@link
557 * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
558 *
559 * Note: only system level processes are allowed to send this
560 * defined broadcast.
561 *
562 * @hide
563 */
564 public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700565 "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
Stanley Tngdd749b02017-04-17 22:35:45 -0700566
567 /**
568 * Used as a String extra field in {@link
569 * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
570 * Bluetooth address.
571 *
572 * @hide
573 */
574 public static final String EXTRA_BLUETOOTH_ADDRESS =
Jack Hea355e5e2017-08-22 16:06:54 -0700575 "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
Stanley Tngdd749b02017-04-17 22:35:45 -0700576
577 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800578 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
579 * by BLE Always on enabled application to know the ACL_CONNECTED event
580 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
581 * as Bluetooth LE is the only feature available in STATE_BLE_ON
582 *
583 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
584 * works in Bluetooth state STATE_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700585 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800586 * @hide
587 */
588 public static final String ACTION_BLE_ACL_CONNECTED =
Jack Hea355e5e2017-08-22 16:06:54 -0700589 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800590
591 /**
592 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
593 * by BLE Always on enabled application to know the ACL_DISCONNECTED event
594 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
595 * LE is the only feature available in STATE_BLE_ON
596 *
597 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
598 * works in Bluetooth state STATE_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700599 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800600 * @hide
601 */
602 public static final String ACTION_BLE_ACL_DISCONNECTED =
Jack Hea355e5e2017-08-22 16:06:54 -0700603 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800604
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700605 /** The profile is in disconnected state */
Jack Hebd020a62018-03-02 13:11:27 -0800606 public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700607 /** The profile is in connecting state */
Jack Hebd020a62018-03-02 13:11:27 -0800608 public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700609 /** The profile is in connected state */
Jack Hebd020a62018-03-02 13:11:27 -0800610 public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700611 /** The profile is in disconnecting state */
Jack Hebd020a62018-03-02 13:11:27 -0800612 public static final int STATE_DISCONNECTING =
613 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700614
Nick Pellyf242b7b2009-10-08 00:12:45 +0200615 /** @hide */
fredc0f420372012-04-12 00:02:00 -0700616 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
Nitin Arorad055adb2015-03-02 15:03:51 -0800617 private final IBinder mToken;
Nick Pellyf242b7b2009-10-08 00:12:45 +0200618
Casper Bonde238e0f92015-04-09 09:24:48 +0200619
Jack Hea355e5e2017-08-22 16:06:54 -0700620 /**
621 * When creating a ServerSocket using listenUsingRfcommOn() or
622 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
623 * a ServerSocket that auto assigns a channel number to the first
624 * bluetooth socket.
625 * The channel number assigned to this first Bluetooth Socket will
626 * be stored in the ServerSocket, and reused for subsequent Bluetooth
627 * sockets.
628 *
629 * @hide
630 */
Casper Bonde238e0f92015-04-09 09:24:48 +0200631 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
632
633
Nick Pelly005b2282009-09-10 10:21:56 -0700634 private static final int ADDRESS_LENGTH = 17;
Nick Pellybd022f42009-08-14 18:33:38 -0700635
Nick Pellyf242b7b2009-10-08 00:12:45 +0200636 /**
Jake Hambyf51eada2010-09-21 13:39:53 -0700637 * Lazily initialized singleton. Guaranteed final after first object
Nick Pellyf242b7b2009-10-08 00:12:45 +0200638 * constructed.
639 */
640 private static BluetoothAdapter sAdapter;
641
Wei Wangc3059cc2014-07-23 23:34:00 -0700642 private static BluetoothLeScanner sBluetoothLeScanner;
643 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800644 private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
Wei Wangc3059cc2014-07-23 23:34:00 -0700645
fredc0f420372012-04-12 00:02:00 -0700646 private final IBluetoothManager mManagerService;
Mathew Inwood4dc66d32018-08-01 15:07:20 +0100647 @UnsupportedAppUsage
fredc0f420372012-04-12 00:02:00 -0700648 private IBluetooth mService;
Zach Johnson57e6e902018-12-12 17:11:25 -0800649 private Context mContext;
Myles Watson125b5452017-11-27 16:41:47 -0800650 private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
Nick Pellybd022f42009-08-14 18:33:38 -0700651
Wei Wangf3055892014-03-11 22:22:41 -0700652 private final Object mLock = new Object();
Wei Wangc3059cc2014-07-23 23:34:00 -0700653 private final Map<LeScanCallback, ScanCallback> mLeScanClients;
Ugo Yu50e3c082019-03-05 16:20:27 +0800654 private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
Ugo Yu4a33b882019-01-08 09:00:09 +0800655 sMetadataListeners = new HashMap<>();
656
657 /**
658 * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
659 * implementation.
660 */
661 private static final IBluetoothMetadataListener sBluetoothMetadataListener =
662 new IBluetoothMetadataListener.Stub() {
663 @Override
Ugo Yu50e3c082019-03-05 16:20:27 +0800664 public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) {
Ugo Yu4a33b882019-01-08 09:00:09 +0800665 synchronized (sMetadataListeners) {
666 if (sMetadataListeners.containsKey(device)) {
Ugo Yu50e3c082019-03-05 16:20:27 +0800667 List<Pair<OnMetadataChangedListener, Executor>> list =
668 sMetadataListeners.get(device);
669 for (Pair<OnMetadataChangedListener, Executor> pair : list) {
670 OnMetadataChangedListener listener = pair.first;
671 Executor executor = pair.second;
672 executor.execute(() -> {
Ugo Yu4a33b882019-01-08 09:00:09 +0800673 listener.onMetadataChanged(device, key, value);
674 });
675 }
676 }
677 }
678 return;
679 }
680 };
Matthew Xie484867a2011-08-25 16:45:58 -0700681
Nick Pellybd022f42009-08-14 18:33:38 -0700682 /**
Nick Pellyf242b7b2009-10-08 00:12:45 +0200683 * Get a handle to the default local Bluetooth adapter.
684 * <p>Currently Android only supports one Bluetooth adapter, but the API
685 * could be extended to support more. This will always return the default
686 * adapter.
Marie Janssen553c8c72017-01-12 16:00:30 -0800687 * </p>
Jack Hea355e5e2017-08-22 16:06:54 -0700688 *
689 * @return the default local adapter, or null if Bluetooth is not supported on this hardware
690 * platform
Nick Pellyf242b7b2009-10-08 00:12:45 +0200691 */
692 public static synchronized BluetoothAdapter getDefaultAdapter() {
693 if (sAdapter == null) {
fredc0f420372012-04-12 00:02:00 -0700694 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200695 if (b != null) {
fredc0f420372012-04-12 00:02:00 -0700696 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
697 sAdapter = new BluetoothAdapter(managerService);
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -0800698 } else {
699 Log.e(TAG, "Bluetooth binder is null");
Nick Pellyf242b7b2009-10-08 00:12:45 +0200700 }
701 }
702 return sAdapter;
703 }
704
705 /**
706 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
Nick Pellybd022f42009-08-14 18:33:38 -0700707 */
fredc0f420372012-04-12 00:02:00 -0700708 BluetoothAdapter(IBluetoothManager managerService) {
709
710 if (managerService == null) {
711 throw new IllegalArgumentException("bluetooth manager service is null");
Nick Pellybd022f42009-08-14 18:33:38 -0700712 }
fredc0f420372012-04-12 00:02:00 -0700713 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700714 mServiceLock.writeLock().lock();
fredc0f420372012-04-12 00:02:00 -0700715 mService = managerService.registerAdapter(mManagerCallback);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700716 } catch (RemoteException e) {
717 Log.e(TAG, "", e);
718 } finally {
719 mServiceLock.writeLock().unlock();
720 }
fredc0f420372012-04-12 00:02:00 -0700721 mManagerService = managerService;
Wei Wangc3059cc2014-07-23 23:34:00 -0700722 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
Nitin Arorad055adb2015-03-02 15:03:51 -0800723 mToken = new Binder();
Nick Pellybd022f42009-08-14 18:33:38 -0700724 }
725
726 /**
Nick Pelly45e27042009-08-19 11:00:00 -0700727 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
728 * address.
729 * <p>Valid Bluetooth hardware addresses must be upper case, in a format
Nick Pelly005b2282009-09-10 10:21:56 -0700730 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
731 * available to validate a Bluetooth address.
Nick Pelly45e27042009-08-19 11:00:00 -0700732 * <p>A {@link BluetoothDevice} will always be returned for a valid
733 * hardware address, even if this adapter has never seen that device.
Nick Pellyde893f52009-09-08 13:15:33 -0700734 *
Nick Pellybd022f42009-08-14 18:33:38 -0700735 * @param address valid Bluetooth MAC address
Nick Pelly45e27042009-08-19 11:00:00 -0700736 * @throws IllegalArgumentException if address is invalid
Nick Pellybd022f42009-08-14 18:33:38 -0700737 */
738 public BluetoothDevice getRemoteDevice(String address) {
739 return new BluetoothDevice(address);
740 }
741
742 /**
Nick Pelly75596b42011-12-07 15:03:55 -0800743 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
744 * address.
745 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
746 * expects the address in network byte order (MSB first).
747 * <p>A {@link BluetoothDevice} will always be returned for a valid
748 * hardware address, even if this adapter has never seen that device.
749 *
750 * @param address Bluetooth MAC address (6 bytes)
751 * @throws IllegalArgumentException if address is invalid
752 */
753 public BluetoothDevice getRemoteDevice(byte[] address) {
754 if (address == null || address.length != 6) {
755 throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
756 }
Myles Watson125b5452017-11-27 16:41:47 -0800757 return new BluetoothDevice(
758 String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1],
759 address[2], address[3], address[4], address[5]));
Nick Pelly75596b42011-12-07 15:03:55 -0800760 }
761
762 /**
Prerepa Viswanadham248edc32014-10-15 16:36:01 -0700763 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
764 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
765 * supported on this device.
Wei Wangc3059cc2014-07-23 23:34:00 -0700766 * <p>
767 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
768 * on this device before calling this method.
Wei Wangadf6aff2014-05-20 06:30:20 +0000769 */
770 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
Myles Watson125b5452017-11-27 16:41:47 -0800771 if (!getLeAccess()) {
772 return null;
773 }
Jack Hea355e5e2017-08-22 16:06:54 -0700774 synchronized (mLock) {
Wei Wangc3059cc2014-07-23 23:34:00 -0700775 if (sBluetoothLeAdvertiser == null) {
776 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
777 }
778 }
779 return sBluetoothLeAdvertiser;
Wei Wangadf6aff2014-05-20 06:30:20 +0000780 }
781
782 /**
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800783 * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
784 * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
785 * Advertising is not supported on this device.
786 * <p>
787 * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
788 * supported on this device before calling this method.
Jack Hea355e5e2017-08-22 16:06:54 -0700789 *
Jakub Pawlowskia537b3f2017-03-29 17:00:44 -0700790 * @hide
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800791 */
792 public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
Jack Hea355e5e2017-08-22 16:06:54 -0700793 if (!getLeAccess()) {
794 return null;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800795 }
Jack Hea355e5e2017-08-22 16:06:54 -0700796
797 if (!isLePeriodicAdvertisingSupported()) {
798 return null;
799 }
800
801 synchronized (mLock) {
802 if (sPeriodicAdvertisingManager == null) {
Myles Watson125b5452017-11-27 16:41:47 -0800803 sPeriodicAdvertisingManager = new PeriodicAdvertisingManager(mManagerService);
Jack Hea355e5e2017-08-22 16:06:54 -0700804 }
805 }
806 return sPeriodicAdvertisingManager;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800807 }
808
809 /**
Wei Wangadf6aff2014-05-20 06:30:20 +0000810 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
811 */
812 public BluetoothLeScanner getBluetoothLeScanner() {
Myles Watson125b5452017-11-27 16:41:47 -0800813 if (!getLeAccess()) {
814 return null;
815 }
Jack Hea355e5e2017-08-22 16:06:54 -0700816 synchronized (mLock) {
Wei Wangc3059cc2014-07-23 23:34:00 -0700817 if (sBluetoothLeScanner == null) {
818 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
819 }
820 }
821 return sBluetoothLeScanner;
Wei Wangadf6aff2014-05-20 06:30:20 +0000822 }
823
824 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700825 * Return true if Bluetooth is currently enabled and ready for use.
826 * <p>Equivalent to:
827 * <code>getBluetoothState() == STATE_ON</code>
Nick Pellybd022f42009-08-14 18:33:38 -0700828 *
Nick Pellyde893f52009-09-08 13:15:33 -0700829 * @return true if the local adapter is turned on
Nick Pellybd022f42009-08-14 18:33:38 -0700830 */
Tor Norbye2d497522015-04-23 17:10:21 -0700831 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -0700832 public boolean isEnabled() {
833 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700834 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -0800835 if (mService != null) {
836 return mService.isEnabled();
837 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700838 } catch (RemoteException e) {
839 Log.e(TAG, "", e);
840 } finally {
841 mServiceLock.readLock().unlock();
842 }
843
Nick Pellybd022f42009-08-14 18:33:38 -0700844 return false;
845 }
846
847 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800848 * Return true if Bluetooth LE(Always BLE On feature) is currently
849 * enabled and ready for use
850 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
851 *
852 * @return true if the local Bluetooth LE adapter is turned on
853 * @hide
854 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700855 @SystemApi
856 public boolean isLeEnabled() {
Jack Hea355e5e2017-08-22 16:06:54 -0700857 final int state = getLeState();
Myles Watson125b5452017-11-27 16:41:47 -0800858 if (DBG) {
859 Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
860 }
Dan Harms2d7e1872019-08-06 09:18:02 -0700861 return (state == BluetoothAdapter.STATE_ON
862 || state == BluetoothAdapter.STATE_BLE_ON
863 || state == BluetoothAdapter.STATE_TURNING_ON
864 || state == BluetoothAdapter.STATE_TURNING_OFF);
Nitin Arorad055adb2015-03-02 15:03:51 -0800865 }
866
867 /**
Marie Janssen59804562016-12-28 14:13:21 -0800868 * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
Nitin Arorad055adb2015-03-02 15:03:51 -0800869 *
870 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
871 * to STATE_OFF and completely shut-down Bluetooth
872 *
873 * <p> If the Adapter state is STATE_ON, This would unregister the existance of
874 * special Bluetooth LE application and hence the further turning off of Bluetooth
875 * from UI would ensure the complete turn-off of Bluetooth rather than staying back
876 * BLE only state
877 *
878 * <p>This is an asynchronous call: it will return immediately, and
879 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
880 * to be notified of subsequent adapter state changes If this call returns
881 * true, then the adapter state will immediately transition from {@link
882 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
883 * later transition to either {@link #STATE_BLE_ON} or {@link
884 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
885 * If this call returns false then there was an
886 * immediate problem that will prevent the QAdapter from being turned off -
887 * such as the QAadapter already being turned off.
888 *
Jack Hea355e5e2017-08-22 16:06:54 -0700889 * @return true to indicate success, or false on immediate error
Nitin Arorad055adb2015-03-02 15:03:51 -0800890 * @hide
891 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700892 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800893 public boolean disableBLE() {
Myles Watson125b5452017-11-27 16:41:47 -0800894 if (!isBleScanAlwaysAvailable()) {
895 return false;
896 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800897
898 int state = getLeState();
Marie Janssen59804562016-12-28 14:13:21 -0800899 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
900 String packageName = ActivityThread.currentPackageName();
Myles Watson125b5452017-11-27 16:41:47 -0800901 if (DBG) {
902 Log.d(TAG, "disableBLE(): de-registering " + packageName);
903 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800904 try {
Marie Janssen59804562016-12-28 14:13:21 -0800905 mManagerService.updateBleAppCount(mToken, false, packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800906 } catch (RemoteException e) {
907 Log.e(TAG, "", e);
908 }
909 return true;
Nitin Arorad055adb2015-03-02 15:03:51 -0800910 }
911
Myles Watson125b5452017-11-27 16:41:47 -0800912 if (DBG) {
913 Log.d(TAG, "disableBLE(): Already disabled");
914 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800915 return false;
916 }
917
918 /**
Marie Janssen59804562016-12-28 14:13:21 -0800919 * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
Nitin Arorad055adb2015-03-02 15:03:51 -0800920 *
Marie Janssen59804562016-12-28 14:13:21 -0800921 * enableBLE registers the existence of an app using only LE functions.
922 *
923 * enableBLE may enable Bluetooth to an LE only mode so that an app can use
924 * LE related features (BluetoothGatt or BluetoothGattServer classes)
925 *
926 * If the user disables Bluetooth while an app is registered to use LE only features,
927 * Bluetooth will remain on in LE only mode for the app.
928 *
929 * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
930 *
931 * <p>This is an asynchronous call: it returns immediately, and
Nitin Arorad055adb2015-03-02 15:03:51 -0800932 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
Marie Janssen59804562016-12-28 14:13:21 -0800933 * to be notified of adapter state changes.
934 *
935 * If this call returns * true, then the adapter state is either in a mode where
936 * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
937 * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
938 *
939 * If this call returns false then there was an immediate problem that prevents the
940 * adapter from being turned on - such as Airplane mode.
941 *
942 * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
Nitin Arorad055adb2015-03-02 15:03:51 -0800943 * states, It includes all the classic Bluetooth Adapter states along with
944 * internal BLE only states
945 *
Jack Hea355e5e2017-08-22 16:06:54 -0700946 * @return true to indicate Bluetooth LE will be available, or false on immediate error
Nitin Arorad055adb2015-03-02 15:03:51 -0800947 * @hide
948 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700949 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800950 public boolean enableBLE() {
Myles Watson125b5452017-11-27 16:41:47 -0800951 if (!isBleScanAlwaysAvailable()) {
952 return false;
953 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800954
Nitin Arorad055adb2015-03-02 15:03:51 -0800955 try {
Marie Janssen59804562016-12-28 14:13:21 -0800956 String packageName = ActivityThread.currentPackageName();
957 mManagerService.updateBleAppCount(mToken, true, packageName);
Marie Janssen6a383a72016-10-25 10:47:51 -0700958 if (isLeEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -0800959 if (DBG) {
960 Log.d(TAG, "enableBLE(): Bluetooth already enabled");
961 }
Marie Janssen6a383a72016-10-25 10:47:51 -0700962 return true;
963 }
Myles Watson125b5452017-11-27 16:41:47 -0800964 if (DBG) {
965 Log.d(TAG, "enableBLE(): Calling enable");
966 }
Marie Janssen59804562016-12-28 14:13:21 -0800967 return mManagerService.enable(packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800968 } catch (RemoteException e) {
969 Log.e(TAG, "", e);
970 }
971
972 return false;
973 }
974
975 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700976 * Get the current state of the local Bluetooth adapter.
977 * <p>Possible return values are
978 * {@link #STATE_OFF},
979 * {@link #STATE_TURNING_ON},
980 * {@link #STATE_ON},
981 * {@link #STATE_TURNING_OFF}.
Nick Pellybd022f42009-08-14 18:33:38 -0700982 *
Nick Pellyde893f52009-09-08 13:15:33 -0700983 * @return current state of Bluetooth adapter
Nick Pellybd022f42009-08-14 18:33:38 -0700984 */
Tor Norbye2d497522015-04-23 17:10:21 -0700985 @RequiresPermission(Manifest.permission.BLUETOOTH)
986 @AdapterState
Nick Pellyde893f52009-09-08 13:15:33 -0700987 public int getState() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700988 int state = BluetoothAdapter.STATE_OFF;
989
Nick Pellybd022f42009-08-14 18:33:38 -0700990 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700991 mServiceLock.readLock().lock();
992 if (mService != null) {
993 state = mService.getState();
fredc0f420372012-04-12 00:02:00 -0700994 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700995 } catch (RemoteException e) {
996 Log.e(TAG, "", e);
997 } finally {
998 mServiceLock.readLock().unlock();
999 }
1000
1001 // Consider all internal states as OFF
Myles Watson125b5452017-11-27 16:41:47 -08001002 if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON
Jack Hea355e5e2017-08-22 16:06:54 -07001003 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
1004 if (VDBG) {
Myles Watson125b5452017-11-27 16:41:47 -08001005 Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
Jack Hea355e5e2017-08-22 16:06:54 -07001006 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001007 state = BluetoothAdapter.STATE_OFF;
1008 }
Jack Hea355e5e2017-08-22 16:06:54 -07001009 if (VDBG) {
Myles Watson125b5452017-11-27 16:41:47 -08001010 Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(
1011 state));
Jack Hea355e5e2017-08-22 16:06:54 -07001012 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001013 return state;
Nick Pellybd022f42009-08-14 18:33:38 -07001014 }
1015
1016 /**
Nitin Arorad055adb2015-03-02 15:03:51 -08001017 * Get the current state of the local Bluetooth adapter
1018 * <p>This returns current internal state of Adapter including LE ON/OFF
1019 *
1020 * <p>Possible return values are
1021 * {@link #STATE_OFF},
1022 * {@link #STATE_BLE_TURNING_ON},
1023 * {@link #STATE_BLE_ON},
1024 * {@link #STATE_TURNING_ON},
1025 * {@link #STATE_ON},
1026 * {@link #STATE_TURNING_OFF},
1027 * {@link #STATE_BLE_TURNING_OFF}.
Nitin Arorad055adb2015-03-02 15:03:51 -08001028 *
1029 * @return current state of Bluetooth adapter
1030 * @hide
1031 */
Tor Norbye2d497522015-04-23 17:10:21 -07001032 @RequiresPermission(Manifest.permission.BLUETOOTH)
1033 @AdapterState
Andrei Oneaf950c082019-06-17 11:26:14 +01001034 @UnsupportedAppUsage(publicAlternatives = "Use {@link #getState()} instead to determine "
1035 + "whether you can use BLE & BT classic.")
Nitin Arorad055adb2015-03-02 15:03:51 -08001036 public int getLeState() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001037 int state = BluetoothAdapter.STATE_OFF;
1038
Nitin Arorad055adb2015-03-02 15:03:51 -08001039 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001040 mServiceLock.readLock().lock();
1041 if (mService != null) {
1042 state = mService.getState();
Nitin Arorad055adb2015-03-02 15:03:51 -08001043 }
1044 } catch (RemoteException e) {
1045 Log.e(TAG, "", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001046 } finally {
1047 mServiceLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -08001048 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001049
Myles Watson125b5452017-11-27 16:41:47 -08001050 if (VDBG) {
1051 Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state));
1052 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001053 return state;
Nitin Arorad055adb2015-03-02 15:03:51 -08001054 }
1055
1056 boolean getLeAccess() {
Jack Hea355e5e2017-08-22 16:06:54 -07001057 if (getLeState() == STATE_ON) {
Nitin Arorad055adb2015-03-02 15:03:51 -08001058 return true;
Jack Hea355e5e2017-08-22 16:06:54 -07001059 } else if (getLeState() == STATE_BLE_ON) {
Nitin Arorad055adb2015-03-02 15:03:51 -08001060 return true; // TODO: FILTER SYSTEM APPS HERE <--
Jack Hea355e5e2017-08-22 16:06:54 -07001061 }
Nitin Arorad055adb2015-03-02 15:03:51 -08001062
1063 return false;
1064 }
1065
1066 /**
Scott Mained2a70d2009-12-09 16:07:39 -08001067 * Turn on the local Bluetooth adapter&mdash;do not use without explicit
1068 * user action to turn on Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -07001069 * <p>This powers on the underlying Bluetooth hardware, and starts all
1070 * Bluetooth system services.
Scott Mained2a70d2009-12-09 16:07:39 -08001071 * <p class="caution"><strong>Bluetooth should never be enabled without
1072 * direct user consent</strong>. If you want to turn on Bluetooth in order
1073 * to create a wireless connection, you should use the {@link
1074 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
1075 * user permission to turn on Bluetooth. The {@link #enable()} method is
1076 * provided only for applications that include a user interface for changing
1077 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +04001078 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -07001079 * clients should listen for {@link #ACTION_STATE_CHANGED}
1080 * to be notified of subsequent adapter state changes. If this call returns
1081 * true, then the adapter state will immediately transition from {@link
1082 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
1083 * later transition to either {@link #STATE_OFF} or {@link
1084 * #STATE_ON}. If this call returns false then there was an
1085 * immediate problem that will prevent the adapter from being turned on -
1086 * such as Airplane mode, or the adapter is already turned on.
Nick Pellyde893f52009-09-08 13:15:33 -07001087 *
Jack Hea355e5e2017-08-22 16:06:54 -07001088 * @return true to indicate adapter startup has begun, or false on immediate error
Nick Pellybd022f42009-08-14 18:33:38 -07001089 */
Tor Norbye2d497522015-04-23 17:10:21 -07001090 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001091 public boolean enable() {
Marie Janssencb21ad72016-12-13 10:51:02 -08001092 if (isEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -08001093 if (DBG) {
1094 Log.d(TAG, "enable(): BT already enabled!");
1095 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07001096 return true;
1097 }
Nick Pellybd022f42009-08-14 18:33:38 -07001098 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001099 return mManagerService.enable(ActivityThread.currentPackageName());
Jack Hea355e5e2017-08-22 16:06:54 -07001100 } catch (RemoteException e) {
1101 Log.e(TAG, "", e);
1102 }
Nick Pellybd022f42009-08-14 18:33:38 -07001103 return false;
1104 }
1105
1106 /**
Scott Mained2a70d2009-12-09 16:07:39 -08001107 * Turn off the local Bluetooth adapter&mdash;do not use without explicit
1108 * user action to turn off Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -07001109 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
1110 * system services, and powers down the underlying Bluetooth hardware.
Jake Hambyf51eada2010-09-21 13:39:53 -07001111 * <p class="caution"><strong>Bluetooth should never be disabled without
Scott Mained2a70d2009-12-09 16:07:39 -08001112 * direct user consent</strong>. The {@link #disable()} method is
1113 * provided only for applications that include a user interface for changing
1114 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +04001115 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -07001116 * clients should listen for {@link #ACTION_STATE_CHANGED}
1117 * to be notified of subsequent adapter state changes. If this call returns
1118 * true, then the adapter state will immediately transition from {@link
1119 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
1120 * later transition to either {@link #STATE_OFF} or {@link
1121 * #STATE_ON}. If this call returns false then there was an
1122 * immediate problem that will prevent the adapter from being turned off -
1123 * such as the adapter already being turned off.
Nick Pellybd022f42009-08-14 18:33:38 -07001124 *
Jack Hea355e5e2017-08-22 16:06:54 -07001125 * @return true to indicate adapter shutdown has begun, or false on immediate error
Nick Pellybd022f42009-08-14 18:33:38 -07001126 */
Tor Norbye2d497522015-04-23 17:10:21 -07001127 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001128 public boolean disable() {
1129 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001130 return mManagerService.disable(ActivityThread.currentPackageName(), true);
Jack Hea355e5e2017-08-22 16:06:54 -07001131 } catch (RemoteException e) {
1132 Log.e(TAG, "", e);
1133 }
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001134 return false;
1135 }
1136
1137 /**
1138 * Turn off the local Bluetooth adapter and don't persist the setting.
1139 *
1140 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1141 * permission
1142 *
Jack Hea355e5e2017-08-22 16:06:54 -07001143 * @return true to indicate adapter shutdown has begun, or false on immediate error
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001144 * @hide
1145 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001146 @UnsupportedAppUsage
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001147 public boolean disable(boolean persist) {
fredc0f420372012-04-12 00:02:00 -07001148
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001149 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001150 return mManagerService.disable(ActivityThread.currentPackageName(), persist);
Jack Hea355e5e2017-08-22 16:06:54 -07001151 } catch (RemoteException e) {
1152 Log.e(TAG, "", e);
1153 }
Nick Pellybd022f42009-08-14 18:33:38 -07001154 return false;
1155 }
1156
Nick Pellyde893f52009-09-08 13:15:33 -07001157 /**
1158 * Returns the hardware address of the local Bluetooth adapter.
1159 * <p>For example, "00:11:22:AA:BB:CC".
Nick Pellyde893f52009-09-08 13:15:33 -07001160 *
1161 * @return Bluetooth hardware address as string
1162 */
Tor Norbye2d497522015-04-23 17:10:21 -07001163 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001164 public String getAddress() {
1165 try {
fredc0f420372012-04-12 00:02:00 -07001166 return mManagerService.getAddress();
Jack Hea355e5e2017-08-22 16:06:54 -07001167 } catch (RemoteException e) {
1168 Log.e(TAG, "", e);
1169 }
Nick Pellybd022f42009-08-14 18:33:38 -07001170 return null;
1171 }
1172
1173 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001174 * Get the friendly Bluetooth name of the local Bluetooth adapter.
1175 * <p>This name is visible to remote Bluetooth devices.
1176 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -07001177 *
Nick Pellyde893f52009-09-08 13:15:33 -07001178 * @return the Bluetooth name, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07001179 */
1180 public String getName() {
1181 try {
fredc116d1d462012-04-20 14:47:08 -07001182 return mManagerService.getName();
Jack Hea355e5e2017-08-22 16:06:54 -07001183 } catch (RemoteException e) {
1184 Log.e(TAG, "", e);
1185 }
Nick Pellybd022f42009-08-14 18:33:38 -07001186 return null;
1187 }
1188
1189 /**
Ajay Panickercda6e872015-07-28 16:52:09 -07001190 * Factory reset bluetooth settings.
1191 *
Ajay Panickercda6e872015-07-28 16:52:09 -07001192 * @return true to indicate that the config file was successfully cleared
Ajay Panickercda6e872015-07-28 16:52:09 -07001193 * @hide
1194 */
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001195 @SystemApi
1196 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Ajay Panickercda6e872015-07-28 16:52:09 -07001197 public boolean factoryReset() {
1198 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001199 mServiceLock.readLock().lock();
Ajay Panickercda6e872015-07-28 16:52:09 -07001200 if (mService != null) {
1201 return mService.factoryReset();
1202 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001203 SystemProperties.set("persist.bluetooth.factoryreset", "true");
1204 } catch (RemoteException e) {
1205 Log.e(TAG, "", e);
1206 } finally {
1207 mServiceLock.readLock().unlock();
1208 }
Ajay Panickercda6e872015-07-28 16:52:09 -07001209 return false;
1210 }
1211
1212 /**
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001213 * Get the UUIDs supported by the local Bluetooth adapter.
1214 *
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001215 * @return the UUIDs supported by the local Bluetooth Adapter.
1216 * @hide
1217 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001218 @UnsupportedAppUsage
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001219 @RequiresPermission(Manifest.permission.BLUETOOTH)
1220 public @NonNull ParcelUuid[] getUuids() {
Myles Watson125b5452017-11-27 16:41:47 -08001221 if (getState() != STATE_ON) {
1222 return null;
1223 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001224 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001225 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001226 if (mService != null) {
1227 return mService.getUuids();
1228 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001229 } catch (RemoteException e) {
1230 Log.e(TAG, "", e);
1231 } finally {
1232 mServiceLock.readLock().unlock();
1233 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001234 return null;
1235 }
1236
1237 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001238 * Set the friendly Bluetooth name of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001239 * <p>This name is visible to remote Bluetooth devices.
Jake Hamby0f584302010-09-16 18:12:51 -07001240 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1241 * encoding, although many remote devices can only display the first
1242 * 40 characters, and some may be limited to just 20.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001243 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1244 * will return false. After turning on Bluetooth,
1245 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1246 * to get the updated value.
Nick Pellybd022f42009-08-14 18:33:38 -07001247 *
Nick Pellyde893f52009-09-08 13:15:33 -07001248 * @param name a valid Bluetooth name
Jack Hea355e5e2017-08-22 16:06:54 -07001249 * @return true if the name was set, false otherwise
Nick Pellybd022f42009-08-14 18:33:38 -07001250 */
Tor Norbye2d497522015-04-23 17:10:21 -07001251 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001252 public boolean setName(String name) {
Myles Watson125b5452017-11-27 16:41:47 -08001253 if (getState() != STATE_ON) {
1254 return false;
1255 }
Nick Pellybd022f42009-08-14 18:33:38 -07001256 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001257 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001258 if (mService != null) {
1259 return mService.setName(name);
1260 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001261 } catch (RemoteException e) {
1262 Log.e(TAG, "", e);
1263 } finally {
1264 mServiceLock.readLock().unlock();
1265 }
Nick Pellybd022f42009-08-14 18:33:38 -07001266 return false;
1267 }
1268
1269 /**
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001270 * Returns the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1271 * adapter.
1272 *
1273 * @return {@link BluetoothClass} Bluetooth CoD of local Bluetooth device.
1274 *
1275 * @hide
1276 */
1277 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1278 public BluetoothClass getBluetoothClass() {
Myles Watson125b5452017-11-27 16:41:47 -08001279 if (getState() != STATE_ON) {
1280 return null;
1281 }
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001282 try {
1283 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001284 if (mService != null) {
1285 return mService.getBluetoothClass();
1286 }
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001287 } catch (RemoteException e) {
1288 Log.e(TAG, "", e);
1289 } finally {
1290 mServiceLock.readLock().unlock();
1291 }
1292 return null;
1293 }
1294
1295 /**
Pulkit Bhuwalka547853d2017-09-25 17:55:12 -07001296 * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1297 * adapter.
1298 *
1299 * <p>Note: This value persists across system reboot.
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001300 *
1301 * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
1302 * @return true if successful, false if unsuccessful.
1303 *
1304 * @hide
1305 */
1306 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
1307 public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
Myles Watson125b5452017-11-27 16:41:47 -08001308 if (getState() != STATE_ON) {
1309 return false;
1310 }
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001311 try {
1312 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001313 if (mService != null) {
1314 return mService.setBluetoothClass(bluetoothClass);
1315 }
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001316 } catch (RemoteException e) {
1317 Log.e(TAG, "", e);
1318 } finally {
1319 mServiceLock.readLock().unlock();
1320 }
1321 return false;
1322 }
1323
1324 /**
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001325 * Returns the Input/Output capability of the device for classic Bluetooth.
1326 *
1327 * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1328 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1329 * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1330 *
1331 * @hide
1332 */
1333 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001334 @IoCapability
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001335 public int getIoCapability() {
1336 if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1337 try {
1338 mServiceLock.readLock().lock();
1339 if (mService != null) return mService.getIoCapability();
1340 } catch (RemoteException e) {
1341 Log.e(TAG, e.getMessage(), e);
1342 } finally {
1343 mServiceLock.readLock().unlock();
1344 }
1345 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1346 }
1347
1348 /**
1349 * Sets the Input/Output capability of the device for classic Bluetooth.
1350 *
1351 * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1352 * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1353 * and {@link BluetoothAdapter#enable()} to see the changes.
1354 *
1355 * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1356 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1357 * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1358 *
1359 * @hide
1360 */
1361 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001362 public boolean setIoCapability(@IoCapability int capability) {
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001363 if (getState() != STATE_ON) return false;
1364 try {
1365 mServiceLock.readLock().lock();
1366 if (mService != null) return mService.setIoCapability(capability);
1367 } catch (RemoteException e) {
1368 Log.e(TAG, e.getMessage(), e);
1369 } finally {
1370 mServiceLock.readLock().unlock();
1371 }
1372 return false;
1373 }
1374
1375 /**
1376 * Returns the Input/Output capability of the device for BLE operations.
1377 *
1378 * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1379 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1380 * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1381 *
1382 * @hide
1383 */
1384 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001385 @IoCapability
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001386 public int getLeIoCapability() {
1387 if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1388 try {
1389 mServiceLock.readLock().lock();
1390 if (mService != null) return mService.getLeIoCapability();
1391 } catch (RemoteException e) {
1392 Log.e(TAG, e.getMessage(), e);
1393 } finally {
1394 mServiceLock.readLock().unlock();
1395 }
1396 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1397 }
1398
1399 /**
1400 * Sets the Input/Output capability of the device for BLE operations.
1401 *
1402 * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1403 * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1404 * and {@link BluetoothAdapter#enable()} to see the changes.
1405 *
1406 * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1407 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1408 * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1409 *
1410 * @hide
1411 */
1412 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001413 public boolean setLeIoCapability(@IoCapability int capability) {
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001414 if (getState() != STATE_ON) return false;
1415 try {
1416 mServiceLock.readLock().lock();
1417 if (mService != null) return mService.setLeIoCapability(capability);
1418 } catch (RemoteException e) {
1419 Log.e(TAG, e.getMessage(), e);
1420 } finally {
1421 mServiceLock.readLock().unlock();
1422 }
1423 return false;
1424 }
1425
1426 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001427 * Get the current Bluetooth scan mode of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001428 * <p>The Bluetooth scan mode determines if the local adapter is
1429 * connectable and/or discoverable from remote Bluetooth devices.
1430 * <p>Possible values are:
1431 * {@link #SCAN_MODE_NONE},
1432 * {@link #SCAN_MODE_CONNECTABLE},
1433 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001434 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1435 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1436 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1437 * to get the updated value.
Nick Pellyde893f52009-09-08 13:15:33 -07001438 *
1439 * @return scan mode
Nick Pellybd022f42009-08-14 18:33:38 -07001440 */
Tor Norbye2d497522015-04-23 17:10:21 -07001441 @RequiresPermission(Manifest.permission.BLUETOOTH)
1442 @ScanMode
Nick Pellybd022f42009-08-14 18:33:38 -07001443 public int getScanMode() {
Myles Watson125b5452017-11-27 16:41:47 -08001444 if (getState() != STATE_ON) {
1445 return SCAN_MODE_NONE;
1446 }
Nick Pellybd022f42009-08-14 18:33:38 -07001447 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001448 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001449 if (mService != null) {
1450 return mService.getScanMode();
1451 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001452 } catch (RemoteException e) {
1453 Log.e(TAG, "", e);
1454 } finally {
1455 mServiceLock.readLock().unlock();
1456 }
Nick Pellyde893f52009-09-08 13:15:33 -07001457 return SCAN_MODE_NONE;
Nick Pellybd022f42009-08-14 18:33:38 -07001458 }
1459
1460 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001461 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1462 * <p>The Bluetooth scan mode determines if the local adapter is
1463 * connectable and/or discoverable from remote Bluetooth devices.
Nick Pelly12835472009-09-25 15:00:29 -07001464 * <p>For privacy reasons, discoverable mode is automatically turned off
1465 * after <code>duration</code> seconds. For example, 120 seconds should be
1466 * enough for a remote device to initiate and complete its discovery
1467 * process.
Nick Pellyde893f52009-09-08 13:15:33 -07001468 * <p>Valid scan mode values are:
1469 * {@link #SCAN_MODE_NONE},
1470 * {@link #SCAN_MODE_CONNECTABLE},
1471 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001472 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1473 * will return false. After turning on Bluetooth,
1474 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1475 * to get the updated value.
Nick Pelly18b1e792009-09-24 11:14:15 -07001476 * <p>Applications cannot set the scan mode. They should use
1477 * <code>startActivityForResult(
1478 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1479 * </code>instead.
Nick Pellyde893f52009-09-08 13:15:33 -07001480 *
1481 * @param mode valid scan mode
Jack Hea355e5e2017-08-22 16:06:54 -07001482 * @param duration time in seconds to apply scan mode, only used for {@link
1483 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
1484 * @return true if the scan mode was set, false otherwise
Nick Pelly18b1e792009-09-24 11:14:15 -07001485 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07001486 */
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001487 @SystemApi
1488 @RequiresPermission(Manifest.permission.BLUETOOTH)
Tor Norbye2d497522015-04-23 17:10:21 -07001489 public boolean setScanMode(@ScanMode int mode, int duration) {
Myles Watson125b5452017-11-27 16:41:47 -08001490 if (getState() != STATE_ON) {
1491 return false;
1492 }
Nick Pellybd022f42009-08-14 18:33:38 -07001493 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001494 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001495 if (mService != null) {
1496 return mService.setScanMode(mode, duration);
1497 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001498 } catch (RemoteException e) {
1499 Log.e(TAG, "", e);
1500 } finally {
1501 mServiceLock.readLock().unlock();
1502 }
Nick Pellyde893f52009-09-08 13:15:33 -07001503 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001504 }
1505
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001506 /**
1507 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1508 * <p>The Bluetooth scan mode determines if the local adapter is
1509 * connectable and/or discoverable from remote Bluetooth devices.
1510 * <p>For privacy reasons, discoverable mode is automatically turned off
1511 * after <code>duration</code> seconds. For example, 120 seconds should be
1512 * enough for a remote device to initiate and complete its discovery
1513 * process.
1514 * <p>Valid scan mode values are:
1515 * {@link #SCAN_MODE_NONE},
1516 * {@link #SCAN_MODE_CONNECTABLE},
1517 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
1518 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1519 * will return false. After turning on Bluetooth,
1520 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1521 * to get the updated value.
1522 * <p>Applications cannot set the scan mode. They should use
1523 * <code>startActivityForResult(
1524 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1525 * </code>instead.
1526 *
1527 * @param mode valid scan mode
1528 * @return true if the scan mode was set, false otherwise
1529 * @hide
1530 */
1531 @SystemApi
1532 @RequiresPermission(Manifest.permission.BLUETOOTH)
1533 public boolean setScanMode(@ScanMode int mode) {
Myles Watson125b5452017-11-27 16:41:47 -08001534 if (getState() != STATE_ON) {
1535 return false;
1536 }
Srikanth Uppala827de2d2012-04-04 03:33:26 -07001537 /* getDiscoverableTimeout() to use the latest from NV than use 0 */
1538 return setScanMode(mode, getDiscoverableTimeout());
Nick Pelly12835472009-09-25 15:00:29 -07001539 }
1540
1541 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001542 @UnsupportedAppUsage
Nick Pellybd022f42009-08-14 18:33:38 -07001543 public int getDiscoverableTimeout() {
Myles Watson125b5452017-11-27 16:41:47 -08001544 if (getState() != STATE_ON) {
1545 return -1;
1546 }
Nick Pellybd022f42009-08-14 18:33:38 -07001547 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001548 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001549 if (mService != null) {
1550 return mService.getDiscoverableTimeout();
1551 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001552 } catch (RemoteException e) {
1553 Log.e(TAG, "", e);
1554 } finally {
1555 mServiceLock.readLock().unlock();
1556 }
Nick Pellybd022f42009-08-14 18:33:38 -07001557 return -1;
1558 }
1559
Nick Pelly45e27042009-08-19 11:00:00 -07001560 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001561 @UnsupportedAppUsage
Nick Pellybd022f42009-08-14 18:33:38 -07001562 public void setDiscoverableTimeout(int timeout) {
Myles Watson125b5452017-11-27 16:41:47 -08001563 if (getState() != STATE_ON) {
1564 return;
1565 }
Nick Pellybd022f42009-08-14 18:33:38 -07001566 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001567 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001568 if (mService != null) {
1569 mService.setDiscoverableTimeout(timeout);
1570 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001571 } catch (RemoteException e) {
1572 Log.e(TAG, "", e);
1573 } finally {
1574 mServiceLock.readLock().unlock();
1575 }
Nick Pellybd022f42009-08-14 18:33:38 -07001576 }
1577
Nick Pelly005b2282009-09-10 10:21:56 -07001578 /**
Marie Janssen23a48332017-01-24 14:09:59 -08001579 * Get the end time of the latest remote device discovery process.
Jack Hea355e5e2017-08-22 16:06:54 -07001580 *
1581 * @return the latest time that the bluetooth adapter was/will be in discovery mode, in
1582 * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has
1583 * been called recently.
Marie Janssen23a48332017-01-24 14:09:59 -08001584 * @hide
1585 */
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001586 @SystemApi
1587 @RequiresPermission(Manifest.permission.BLUETOOTH)
Marie Janssen23a48332017-01-24 14:09:59 -08001588 public long getDiscoveryEndMillis() {
1589 try {
1590 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001591 if (mService != null) {
1592 return mService.getDiscoveryEndMillis();
1593 }
Marie Janssen23a48332017-01-24 14:09:59 -08001594 } catch (RemoteException e) {
1595 Log.e(TAG, "", e);
1596 } finally {
1597 mServiceLock.readLock().unlock();
1598 }
1599 return -1;
1600 }
1601
1602 /**
Zach Johnson57e6e902018-12-12 17:11:25 -08001603 * Set the context for this BluetoothAdapter (only called from BluetoothManager)
1604 * @hide
1605 */
1606 public void setContext(Context context) {
1607 mContext = context;
1608 }
1609
1610 private String getOpPackageName() {
1611 // Workaround for legacy API for getting a BluetoothAdapter not
1612 // passing a context
1613 if (mContext != null) {
1614 return mContext.getOpPackageName();
1615 }
1616 return ActivityThread.currentOpPackageName();
1617 }
1618
1619 /**
Nick Pelly005b2282009-09-10 10:21:56 -07001620 * Start the remote device discovery process.
1621 * <p>The discovery process usually involves an inquiry scan of about 12
1622 * seconds, followed by a page scan of each new device to retrieve its
1623 * Bluetooth name.
1624 * <p>This is an asynchronous call, it will return immediately. Register
1625 * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1626 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1627 * discovery starts and completes. Register for {@link
1628 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1629 * are found.
1630 * <p>Device discovery is a heavyweight procedure. New connections to
1631 * remote Bluetooth devices should not be attempted while discovery is in
1632 * progress, and existing connections will experience limited bandwidth
1633 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
Scott Main6d95fc02009-11-19 17:00:19 -08001634 * discovery. Discovery is not managed by the Activity,
1635 * but is run as a system service, so an application should always call
1636 * {@link BluetoothAdapter#cancelDiscovery()} even if it
1637 * did not directly request a discovery, just to be sure.
Nick Pelly005b2282009-09-10 10:21:56 -07001638 * <p>Device discovery will only find remote devices that are currently
1639 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1640 * not discoverable by default, and need to be entered into a special mode.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001641 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1642 * will return false. After turning on Bluetooth,
1643 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1644 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001645 *
1646 * @return true on success, false on error
1647 */
Tor Norbye2d497522015-04-23 17:10:21 -07001648 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001649 public boolean startDiscovery() {
Myles Watson125b5452017-11-27 16:41:47 -08001650 if (getState() != STATE_ON) {
1651 return false;
1652 }
Nick Pellybd022f42009-08-14 18:33:38 -07001653 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001654 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001655 if (mService != null) {
Zach Johnson57e6e902018-12-12 17:11:25 -08001656 return mService.startDiscovery(getOpPackageName());
Myles Watson125b5452017-11-27 16:41:47 -08001657 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001658 } catch (RemoteException e) {
1659 Log.e(TAG, "", e);
1660 } finally {
1661 mServiceLock.readLock().unlock();
1662 }
Nick Pellybd022f42009-08-14 18:33:38 -07001663 return false;
1664 }
1665
Nick Pelly005b2282009-09-10 10:21:56 -07001666 /**
1667 * Cancel the current device discovery process.
Jake Hamby0f584302010-09-16 18:12:51 -07001668 * <p>Because discovery is a heavyweight procedure for the Bluetooth
Scott Main6d95fc02009-11-19 17:00:19 -08001669 * adapter, this method should always be called before attempting to connect
1670 * to a remote device with {@link
1671 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1672 * the Activity, but is run as a system service, so an application should
1673 * always call cancel discovery even if it did not directly request a
1674 * discovery, just to be sure.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001675 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1676 * will return false. After turning on Bluetooth,
1677 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1678 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001679 *
1680 * @return true on success, false on error
1681 */
Tor Norbye2d497522015-04-23 17:10:21 -07001682 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly005b2282009-09-10 10:21:56 -07001683 public boolean cancelDiscovery() {
Myles Watson125b5452017-11-27 16:41:47 -08001684 if (getState() != STATE_ON) {
1685 return false;
1686 }
Nick Pellybd022f42009-08-14 18:33:38 -07001687 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001688 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001689 if (mService != null) {
1690 return mService.cancelDiscovery();
1691 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001692 } catch (RemoteException e) {
1693 Log.e(TAG, "", e);
1694 } finally {
1695 mServiceLock.readLock().unlock();
1696 }
Nick Pelly005b2282009-09-10 10:21:56 -07001697 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001698 }
1699
Nick Pelly005b2282009-09-10 10:21:56 -07001700 /**
1701 * Return true if the local Bluetooth adapter is currently in the device
1702 * discovery process.
1703 * <p>Device discovery is a heavyweight procedure. New connections to
1704 * remote Bluetooth devices should not be attempted while discovery is in
1705 * progress, and existing connections will experience limited bandwidth
1706 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1707 * discovery.
1708 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1709 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1710 * starts or completes.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001711 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1712 * will return false. After turning on Bluetooth,
1713 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1714 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001715 *
1716 * @return true if discovering
1717 */
Tor Norbye2d497522015-04-23 17:10:21 -07001718 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001719 public boolean isDiscovering() {
Myles Watson125b5452017-11-27 16:41:47 -08001720 if (getState() != STATE_ON) {
1721 return false;
1722 }
Nick Pellybd022f42009-08-14 18:33:38 -07001723 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001724 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001725 if (mService != null) {
1726 return mService.isDiscovering();
1727 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001728 } catch (RemoteException e) {
1729 Log.e(TAG, "", e);
1730 } finally {
1731 mServiceLock.readLock().unlock();
1732 }
Nick Pellybd022f42009-08-14 18:33:38 -07001733 return false;
1734 }
1735
1736 /**
Rahul Sabnis0d33ef92019-11-13 16:21:12 -08001737 * Connects all enabled and supported bluetooth profiles between the local and remote device
1738 *
1739 * @param device is the remote device with which to connect these profiles
1740 * @return true if all profiles successfully connected, false if an error occurred
1741 *
1742 * @hide
1743 */
1744 @SystemApi
1745 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1746 public boolean connectAllEnabledProfiles(@NonNull BluetoothDevice device) {
1747 try {
1748 mServiceLock.readLock().lock();
1749 if (mService != null) {
1750 return mService.connectAllEnabledProfiles(device);
1751 }
1752 } catch (RemoteException e) {
1753 Log.e(TAG, "", e);
1754 } finally {
1755 mServiceLock.readLock().unlock();
1756 }
1757
1758 return false;
1759 }
1760
1761 /**
1762 * Disconnects all enabled and supported bluetooth profiles between the local and remote device
1763 *
1764 * @param device is the remote device with which to disconnect these profiles
1765 * @return true if all profiles successfully disconnected, false if an error occurred
1766 *
1767 * @hide
1768 */
1769 @SystemApi
1770 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1771 public boolean disconnectAllEnabledProfiles(@NonNull BluetoothDevice device) {
1772 try {
1773 mServiceLock.readLock().lock();
1774 if (mService != null) {
1775 return mService.disconnectAllEnabledProfiles(device);
1776 }
1777 } catch (RemoteException e) {
1778 Log.e(TAG, "", e);
1779 } finally {
1780 mServiceLock.readLock().unlock();
1781 }
1782
1783 return false;
1784 }
1785
1786 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001787 * Return true if the multi advertisement is supported by the chipset
1788 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001789 * @return true if Multiple Advertisement feature is supported
1790 */
1791 public boolean isMultipleAdvertisementSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001792 if (getState() != STATE_ON) {
1793 return false;
1794 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001795 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001796 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001797 if (mService != null) {
1798 return mService.isMultiAdvertisementSupported();
1799 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001800 } catch (RemoteException e) {
1801 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001802 } finally {
1803 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001804 }
1805 return false;
1806 }
1807
1808 /**
Wei Wangd91f1932015-03-19 15:09:56 -07001809 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1810 *
1811 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1812 * fetch scan results even when Bluetooth is turned off.<p>
1813 *
1814 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1815 *
1816 * @hide
1817 */
1818 @SystemApi
1819 public boolean isBleScanAlwaysAvailable() {
Wei Wang67d84162015-04-26 17:04:29 -07001820 try {
1821 return mManagerService.isBleScanAlwaysAvailable();
1822 } catch (RemoteException e) {
1823 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1824 return false;
1825 }
Wei Wangd91f1932015-03-19 15:09:56 -07001826 }
1827
1828 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001829 * Return true if offloaded filters are supported
1830 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001831 * @return true if chipset supports on-chip filtering
1832 */
1833 public boolean isOffloadedFilteringSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001834 if (!getLeAccess()) {
1835 return false;
1836 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001837 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001838 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001839 if (mService != null) {
1840 return mService.isOffloadedFilteringSupported();
1841 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001842 } catch (RemoteException e) {
1843 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001844 } finally {
1845 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001846 }
1847 return false;
1848 }
1849
1850 /**
1851 * Return true if offloaded scan batching is supported
1852 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001853 * @return true if chipset supports on-chip scan batching
1854 */
1855 public boolean isOffloadedScanBatchingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001856 if (!getLeAccess()) {
1857 return false;
1858 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001859 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001860 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001861 if (mService != null) {
1862 return mService.isOffloadedScanBatchingSupported();
1863 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001864 } catch (RemoteException e) {
1865 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001866 } finally {
1867 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001868 }
1869 return false;
1870 }
1871
1872 /**
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001873 * Return true if LE 2M PHY feature is supported.
1874 *
1875 * @return true if chipset supports LE 2M PHY feature
1876 */
1877 public boolean isLe2MPhySupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001878 if (!getLeAccess()) {
1879 return false;
1880 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001881 try {
1882 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001883 if (mService != null) {
1884 return mService.isLe2MPhySupported();
1885 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001886 } catch (RemoteException e) {
1887 Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
1888 } finally {
1889 mServiceLock.readLock().unlock();
1890 }
1891 return false;
1892 }
1893
1894 /**
1895 * Return true if LE Coded PHY feature is supported.
1896 *
1897 * @return true if chipset supports LE Coded PHY feature
1898 */
1899 public boolean isLeCodedPhySupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001900 if (!getLeAccess()) {
1901 return false;
1902 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001903 try {
1904 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001905 if (mService != null) {
1906 return mService.isLeCodedPhySupported();
1907 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001908 } catch (RemoteException e) {
1909 Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
1910 } finally {
1911 mServiceLock.readLock().unlock();
1912 }
1913 return false;
1914 }
1915
1916 /**
Jakub Pawlowskibc2991e2017-03-10 16:07:59 -08001917 * Return true if LE Extended Advertising feature is supported.
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001918 *
Jakub Pawlowskibc2991e2017-03-10 16:07:59 -08001919 * @return true if chipset supports LE Extended Advertising feature
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001920 */
1921 public boolean isLeExtendedAdvertisingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001922 if (!getLeAccess()) {
1923 return false;
1924 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001925 try {
1926 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001927 if (mService != null) {
1928 return mService.isLeExtendedAdvertisingSupported();
1929 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001930 } catch (RemoteException e) {
1931 Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
1932 } finally {
1933 mServiceLock.readLock().unlock();
1934 }
1935 return false;
1936 }
1937
1938 /**
1939 * Return true if LE Periodic Advertising feature is supported.
1940 *
1941 * @return true if chipset supports LE Periodic Advertising feature
1942 */
1943 public boolean isLePeriodicAdvertisingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001944 if (!getLeAccess()) {
1945 return false;
1946 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001947 try {
1948 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001949 if (mService != null) {
1950 return mService.isLePeriodicAdvertisingSupported();
1951 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001952 } catch (RemoteException e) {
1953 Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
1954 } finally {
1955 mServiceLock.readLock().unlock();
1956 }
1957 return false;
1958 }
1959
1960 /**
Jakub Pawlowski76cceb12017-04-21 04:59:55 -07001961 * Return the maximum LE advertising data length in bytes,
1962 * if LE Extended Advertising feature is supported, 0 otherwise.
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001963 *
1964 * @return the maximum LE advertising data length.
1965 */
1966 public int getLeMaximumAdvertisingDataLength() {
Myles Watson125b5452017-11-27 16:41:47 -08001967 if (!getLeAccess()) {
1968 return 0;
1969 }
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001970 try {
1971 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001972 if (mService != null) {
1973 return mService.getLeMaximumAdvertisingDataLength();
1974 }
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001975 } catch (RemoteException e) {
1976 Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
1977 } finally {
1978 mServiceLock.readLock().unlock();
1979 }
1980 return 0;
1981 }
1982
1983 /**
Stanley Tng61dbd812019-01-13 16:04:31 -08001984 * Return true if Hearing Aid Profile is supported.
1985 *
1986 * @return true if phone supports Hearing Aid Profile
1987 */
1988 private boolean isHearingAidProfileSupported() {
1989 try {
1990 return mManagerService.isHearingAidProfileSupported();
1991 } catch (RemoteException e) {
1992 Log.e(TAG, "remote expection when calling isHearingAidProfileSupported", e);
1993 return false;
1994 }
1995 }
1996
1997 /**
Pavlin Radoslavova5137922018-01-17 02:09:53 -08001998 * Get the maximum number of connected audio devices.
1999 *
2000 * @return the maximum number of connected audio devices
2001 * @hide
2002 */
2003 @RequiresPermission(Manifest.permission.BLUETOOTH)
2004 public int getMaxConnectedAudioDevices() {
2005 try {
2006 mServiceLock.readLock().lock();
2007 if (mService != null) {
2008 return mService.getMaxConnectedAudioDevices();
2009 }
2010 } catch (RemoteException e) {
2011 Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
2012 } finally {
2013 mServiceLock.readLock().unlock();
2014 }
2015 return 1;
2016 }
2017
2018 /**
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07002019 * Return true if hardware has entries available for matching beacons
2020 *
2021 * @return true if there are hw entries available for matching beacons
2022 * @hide
2023 */
2024 public boolean isHardwareTrackingFiltersAvailable() {
Myles Watson125b5452017-11-27 16:41:47 -08002025 if (!getLeAccess()) {
2026 return false;
2027 }
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07002028 try {
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07002029 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
2030 if (iGatt == null) {
2031 // BLE is not supported
2032 return false;
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07002033 }
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07002034 return (iGatt.numHwTrackFiltersAvailable() != 0);
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07002035 } catch (RemoteException e) {
2036 Log.e(TAG, "", e);
2037 }
2038 return false;
2039 }
2040
2041 /**
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002042 * Return the record of {@link BluetoothActivityEnergyInfo} object that
2043 * has the activity and energy info. This can be used to ascertain what
2044 * the controller has been up to, since the last sample.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002045 *
Jack Hea355e5e2017-08-22 16:06:54 -07002046 * @param updateType Type of info, cached vs refreshed.
2047 * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or
2048 * unsupported
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002049 * @hide
Jack Hea355e5e2017-08-22 16:06:54 -07002050 * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)}
2051 * instead.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002052 */
Adam Lesinski010bf372016-04-11 12:18:18 -07002053 @Deprecated
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002054 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
Adam Lesinski010bf372016-04-11 12:18:18 -07002055 SynchronousResultReceiver receiver = new SynchronousResultReceiver();
Adam Lesinski991357f2016-05-10 14:00:03 -07002056 requestControllerActivityEnergyInfo(receiver);
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002057 try {
Adam Lesinski010bf372016-04-11 12:18:18 -07002058 SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
2059 if (result.bundle != null) {
2060 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
2061 }
2062 } catch (TimeoutException e) {
2063 Log.e(TAG, "getControllerActivityEnergyInfo timed out");
2064 }
2065 return null;
2066 }
2067
2068 /**
2069 * Request the record of {@link BluetoothActivityEnergyInfo} object that
2070 * has the activity and energy info. This can be used to ascertain what
2071 * the controller has been up to, since the last sample.
2072 *
2073 * A null value for the activity info object may be sent if the bluetooth service is
2074 * unreachable or the device does not support reporting such information.
2075 *
Adam Lesinski010bf372016-04-11 12:18:18 -07002076 * @param result The callback to which to send the activity info.
2077 * @hide
2078 */
Adam Lesinski991357f2016-05-10 14:00:03 -07002079 public void requestControllerActivityEnergyInfo(ResultReceiver result) {
Adam Lesinski010bf372016-04-11 12:18:18 -07002080 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002081 mServiceLock.readLock().lock();
2082 if (mService != null) {
2083 mService.requestActivityInfo(result);
2084 result = null;
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002085 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002086 } catch (RemoteException e) {
2087 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
Adam Lesinski991357f2016-05-10 14:00:03 -07002088 } finally {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002089 mServiceLock.readLock().unlock();
Adam Lesinski991357f2016-05-10 14:00:03 -07002090 if (result != null) {
2091 // Only send an immediate result if we failed.
2092 result.send(0, null);
2093 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002094 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002095 }
2096
2097 /**
Nick Pelly005b2282009-09-10 10:21:56 -07002098 * Return the set of {@link BluetoothDevice} objects that are bonded
2099 * (paired) to the local adapter.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002100 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
2101 * will return an empty set. After turning on Bluetooth,
2102 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
2103 * to get the updated value.
Nick Pellybd022f42009-08-14 18:33:38 -07002104 *
Nick Pelly005b2282009-09-10 10:21:56 -07002105 * @return unmodifiable set of {@link BluetoothDevice}, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07002106 */
Tor Norbye2d497522015-04-23 17:10:21 -07002107 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07002108 public Set<BluetoothDevice> getBondedDevices() {
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002109 if (getState() != STATE_ON) {
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08002110 return toDeviceSet(new BluetoothDevice[0]);
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002111 }
Nick Pellybd022f42009-08-14 18:33:38 -07002112 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002113 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002114 if (mService != null) {
2115 return toDeviceSet(mService.getBondedDevices());
2116 }
fredc0f420372012-04-12 00:02:00 -07002117 return toDeviceSet(new BluetoothDevice[0]);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002118 } catch (RemoteException e) {
2119 Log.e(TAG, "", e);
2120 } finally {
2121 mServiceLock.readLock().unlock();
2122 }
Nick Pellybd022f42009-08-14 18:33:38 -07002123 return null;
2124 }
2125
2126 /**
Bryce Leeb1301fa2016-10-09 12:54:42 -07002127 * Gets the currently supported profiles by the adapter.
2128 *
Jack Hea355e5e2017-08-22 16:06:54 -07002129 * <p> This can be used to check whether a profile is supported before attempting
Bryce Leeb1301fa2016-10-09 12:54:42 -07002130 * to connect to its respective proxy.
2131 *
Jack Hea355e5e2017-08-22 16:06:54 -07002132 * @return a list of integers indicating the ids of supported profiles as defined in {@link
2133 * BluetoothProfile}.
Bryce Leeb1301fa2016-10-09 12:54:42 -07002134 * @hide
2135 */
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07002136 public @NonNull List<Integer> getSupportedProfiles() {
Bryce Leeb1301fa2016-10-09 12:54:42 -07002137 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
2138
2139 try {
2140 synchronized (mManagerCallback) {
2141 if (mService != null) {
2142 final long supportedProfilesBitMask = mService.getSupportedProfiles();
2143
2144 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
2145 if ((supportedProfilesBitMask & (1 << i)) != 0) {
2146 supportedProfiles.add(i);
2147 }
2148 }
Stanley Tng61dbd812019-01-13 16:04:31 -08002149 } else {
2150 // Bluetooth is disabled. Just fill in known supported Profiles
2151 if (isHearingAidProfileSupported()) {
2152 supportedProfiles.add(BluetoothProfile.HEARING_AID);
2153 }
Bryce Leeb1301fa2016-10-09 12:54:42 -07002154 }
2155 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002156 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -07002157 Log.e(TAG, "getSupportedProfiles:", e);
Marie Janssencb21ad72016-12-13 10:51:02 -08002158 }
Bryce Leeb1301fa2016-10-09 12:54:42 -07002159 return supportedProfiles;
2160 }
2161
2162 /**
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002163 * Get the current connection state of the local Bluetooth adapter.
2164 * This can be used to check whether the local Bluetooth adapter is connected
2165 * to any profile of any other remote Bluetooth Device.
2166 *
2167 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
2168 * intent to get the connection state of the adapter.
2169 *
Jack Hea355e5e2017-08-22 16:06:54 -07002170 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link
2171 * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002172 * @hide
2173 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002174 @UnsupportedAppUsage
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002175 public int getConnectionState() {
Myles Watson125b5452017-11-27 16:41:47 -08002176 if (getState() != STATE_ON) {
2177 return BluetoothAdapter.STATE_DISCONNECTED;
2178 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002179 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002180 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002181 if (mService != null) {
2182 return mService.getAdapterConnectionState();
2183 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002184 } catch (RemoteException e) {
2185 Log.e(TAG, "getConnectionState:", e);
2186 } finally {
2187 mServiceLock.readLock().unlock();
2188 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002189 return BluetoothAdapter.STATE_DISCONNECTED;
2190 }
2191
2192 /**
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002193 * Get the current connection state of a profile.
2194 * This function can be used to check whether the local Bluetooth adapter
2195 * is connected to any remote device for a specific profile.
Jack He6b73b322019-01-03 16:23:41 -08002196 * Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002197 *
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002198 * <p> Return value can be one of
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002199 * {@link BluetoothProfile#STATE_DISCONNECTED},
2200 * {@link BluetoothProfile#STATE_CONNECTING},
2201 * {@link BluetoothProfile#STATE_CONNECTED},
2202 * {@link BluetoothProfile#STATE_DISCONNECTING}
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002203 */
Tor Norbye2d497522015-04-23 17:10:21 -07002204 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002205 public int getProfileConnectionState(int profile) {
Myles Watson125b5452017-11-27 16:41:47 -08002206 if (getState() != STATE_ON) {
2207 return BluetoothProfile.STATE_DISCONNECTED;
2208 }
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002209 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002210 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002211 if (mService != null) {
2212 return mService.getProfileConnectionState(profile);
2213 }
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002214 } catch (RemoteException e) {
2215 Log.e(TAG, "getProfileConnectionState:", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002216 } finally {
2217 mServiceLock.readLock().unlock();
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002218 }
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002219 return BluetoothProfile.STATE_DISCONNECTED;
2220 }
2221
2222 /**
Nick Pelly45e27042009-08-19 11:00:00 -07002223 * Create a listening, secure RFCOMM Bluetooth socket.
2224 * <p>A remote device connecting to this socket will be authenticated and
Nick Pellybd022f42009-08-14 18:33:38 -07002225 * communication on this socket will be encrypted.
Nick Pelly45e27042009-08-19 11:00:00 -07002226 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
Nick Pelly24bb9b82009-10-02 20:34:18 -07002227 * connections from a listening {@link BluetoothServerSocket}.
Nick Pelly45e27042009-08-19 11:00:00 -07002228 * <p>Valid RFCOMM channels are in range 1 to 30.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002229 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Jack Hea355e5e2017-08-22 16:06:54 -07002230 *
Nick Pelly45e27042009-08-19 11:00:00 -07002231 * @param channel RFCOMM channel to listen on
2232 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002233 * @throws IOException on error, for example Bluetooth not available, or insufficient
2234 * permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002235 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002236 */
Nick Pelly45e27042009-08-19 11:00:00 -07002237 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002238 return listenUsingRfcommOn(channel, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02002239 }
2240
2241 /**
2242 * Create a listening, secure RFCOMM Bluetooth socket.
2243 * <p>A remote device connecting to this socket will be authenticated and
2244 * communication on this socket will be encrypted.
2245 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2246 * connections from a listening {@link BluetoothServerSocket}.
2247 * <p>Valid RFCOMM channels are in range 1 to 30.
2248 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
2249 * <p>To auto assign a channel without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002250 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
Jack Hea355e5e2017-08-22 16:06:54 -07002251 *
Casper Bonde23284232015-04-21 13:12:05 +02002252 * @param channel RFCOMM channel to listen on
Jack Hea355e5e2017-08-22 16:06:54 -07002253 * @param mitm enforce man-in-the-middle protection for authentication.
2254 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2255 * connections.
Casper Bonde23284232015-04-21 13:12:05 +02002256 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002257 * @throws IOException on error, for example Bluetooth not available, or insufficient
2258 * permissions, or channel in use.
Casper Bonde23284232015-04-21 13:12:05 +02002259 * @hide
2260 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002261 @UnsupportedAppUsage
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002262 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
Myles Watson125b5452017-11-27 16:41:47 -08002263 boolean min16DigitPin) throws IOException {
2264 BluetoothServerSocket socket =
2265 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm,
2266 min16DigitPin);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002267 int errno = socket.mSocket.bindListen();
Casper Bonde23284232015-04-21 13:12:05 +02002268 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002269 socket.setChannel(socket.mSocket.getPort());
2270 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002271 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07002272 //TODO(BT): Throw the same exception error code
2273 // that the previous code was using.
2274 //socket.mSocket.throwErrnoNative(errno);
2275 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002276 }
2277 return socket;
2278 }
2279
2280 /**
Nick Pelly24bb9b82009-10-02 20:34:18 -07002281 * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
2282 * <p>A remote device connecting to this socket will be authenticated and
2283 * communication on this socket will be encrypted.
2284 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2285 * connections from a listening {@link BluetoothServerSocket}.
2286 * <p>The system will assign an unused RFCOMM channel to listen on.
2287 * <p>The system will also register a Service Discovery
2288 * Protocol (SDP) record with the local SDP server containing the specified
2289 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2290 * can use the same UUID to query our SDP server and discover which channel
2291 * to connect to. This SDP record will be removed when this socket is
2292 * closed, or if this application closes unexpectedly.
Nick Pelly16fb88a2009-10-07 07:44:03 +02002293 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2294 * connect to this socket from another device using the same {@link UUID}.
Jack Hea355e5e2017-08-22 16:06:54 -07002295 *
Nick Pelly24bb9b82009-10-02 20:34:18 -07002296 * @param name service name for SDP record
2297 * @param uuid uuid for SDP record
2298 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002299 * @throws IOException on error, for example Bluetooth not available, or insufficient
2300 * permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002301 */
Tor Norbye2d497522015-04-23 17:10:21 -07002302 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly16fb88a2009-10-07 07:44:03 +02002303 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
Nick Pelly24bb9b82009-10-02 20:34:18 -07002304 throws IOException {
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002305 return createNewRfcommSocketAndRecord(name, uuid, true, true);
2306 }
2307
2308 /**
2309 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002310 * <p>The link key is not required to be authenticated, i.e the communication may be
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002311 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002312 * the link will be encrypted, as encryption is mandartory.
2313 * For legacy devices (pre Bluetooth 2.1 devices) the link will not
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002314 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
2315 * encrypted and authenticated communication channel is desired.
2316 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2317 * connections from a listening {@link BluetoothServerSocket}.
2318 * <p>The system will assign an unused RFCOMM channel to listen on.
2319 * <p>The system will also register a Service Discovery
2320 * Protocol (SDP) record with the local SDP server containing the specified
2321 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2322 * can use the same UUID to query our SDP server and discover which channel
2323 * to connect to. This SDP record will be removed when this socket is
2324 * closed, or if this application closes unexpectedly.
2325 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2326 * connect to this socket from another device using the same {@link UUID}.
Jack Hea355e5e2017-08-22 16:06:54 -07002327 *
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002328 * @param name service name for SDP record
2329 * @param uuid uuid for SDP record
2330 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002331 * @throws IOException on error, for example Bluetooth not available, or insufficient
2332 * permissions, or channel in use.
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002333 */
Tor Norbye2d497522015-04-23 17:10:21 -07002334 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002335 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
2336 throws IOException {
2337 return createNewRfcommSocketAndRecord(name, uuid, false, false);
2338 }
2339
Jack Hea355e5e2017-08-22 16:06:54 -07002340 /**
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002341 * Create a listening, encrypted,
2342 * RFCOMM Bluetooth socket with Service Record.
2343 * <p>The link will be encrypted, but the link key is not required to be authenticated
2344 * i.e the communication is vulnerable to Man In the Middle attacks. Use
2345 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
2346 * <p> Use this socket if authentication of link key is not possible.
2347 * For example, for Bluetooth 2.1 devices, if any of the devices does not have
2348 * an input and output capability or just has the ability to display a numeric key,
2349 * a secure socket connection is not possible and this socket can be used.
2350 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
2351 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
2352 * For more details, refer to the Security Model section 5.2 (vol 3) of
2353 * Bluetooth Core Specification version 2.1 + EDR.
2354 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2355 * connections from a listening {@link BluetoothServerSocket}.
2356 * <p>The system will assign an unused RFCOMM channel to listen on.
2357 * <p>The system will also register a Service Discovery
2358 * Protocol (SDP) record with the local SDP server containing the specified
2359 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2360 * can use the same UUID to query our SDP server and discover which channel
2361 * to connect to. This SDP record will be removed when this socket is
2362 * closed, or if this application closes unexpectedly.
2363 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2364 * connect to this socket from another device using the same {@link UUID}.
2365 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jack Hea355e5e2017-08-22 16:06:54 -07002366 *
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002367 * @param name service name for SDP record
2368 * @param uuid uuid for SDP record
2369 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002370 * @throws IOException on error, for example Bluetooth not available, or insufficient
2371 * permissions, or channel in use.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002372 * @hide
2373 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002374 @UnsupportedAppUsage
Myles Watson125b5452017-11-27 16:41:47 -08002375 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)
2376 throws IOException {
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002377 return createNewRfcommSocketAndRecord(name, uuid, false, true);
2378 }
2379
zzy3b147b72012-04-03 19:48:32 -07002380
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002381 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
2382 boolean auth, boolean encrypt) throws IOException {
Nick Pelly24bb9b82009-10-02 20:34:18 -07002383 BluetoothServerSocket socket;
Myles Watson125b5452017-11-27 16:41:47 -08002384 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, encrypt,
2385 new ParcelUuid(uuid));
zzy3b147b72012-04-03 19:48:32 -07002386 socket.setServiceName(name);
2387 int errno = socket.mSocket.bindListen();
2388 if (errno != 0) {
2389 //TODO(BT): Throw the same exception error code
2390 // that the previous code was using.
2391 //socket.mSocket.throwErrnoNative(errno);
2392 throw new IOException("Error: " + errno);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002393 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002394 return socket;
2395 }
2396
2397 /**
Nick Pellybd022f42009-08-14 18:33:38 -07002398 * Construct an unencrypted, unauthenticated, RFCOMM server socket.
2399 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002400 *
Nick Pellybd022f42009-08-14 18:33:38 -07002401 * @return An RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002402 * @throws IOException On error, for example Bluetooth not available, or insufficient
2403 * permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07002404 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002405 */
2406 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002407 BluetoothServerSocket socket =
2408 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, false, port);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002409 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002410 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002411 socket.setChannel(socket.mSocket.getPort());
2412 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002413 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07002414 //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);
Nick Pellybd022f42009-08-14 18:33:38 -07002418 }
2419 return socket;
2420 }
2421
Jack Hea355e5e2017-08-22 16:06:54 -07002422 /**
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002423 * Construct an encrypted, RFCOMM server socket.
2424 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002425 *
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002426 * @return An RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002427 * @throws IOException On error, for example Bluetooth not available, or insufficient
2428 * permissions.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002429 * @hide
2430 */
Myles Watson125b5452017-11-27 16:41:47 -08002431 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port) throws IOException {
2432 BluetoothServerSocket socket =
2433 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, true, port);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002434 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002435 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002436 socket.setChannel(socket.mSocket.getPort());
2437 }
zzy3b147b72012-04-03 19:48:32 -07002438 if (errno < 0) {
2439 //TODO(BT): Throw the same exception error code
2440 // that the previous code was using.
2441 //socket.mSocket.throwErrnoNative(errno);
2442 throw new IOException("Error: " + errno);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002443 }
2444 return socket;
2445 }
2446
Nick Pellybd022f42009-08-14 18:33:38 -07002447 /**
2448 * Construct a SCO server socket.
2449 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002450 *
Nick Pellybd022f42009-08-14 18:33:38 -07002451 * @return A SCO BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002452 * @throws IOException On error, for example Bluetooth not available, or insufficient
2453 * permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07002454 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002455 */
2456 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002457 BluetoothServerSocket socket =
2458 new BluetoothServerSocket(BluetoothSocket.TYPE_SCO, false, false, -1);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002459 int errno = socket.mSocket.bindListen();
zzy3b147b72012-04-03 19:48:32 -07002460 if (errno < 0) {
2461 //TODO(BT): Throw the same exception error code
2462 // that the previous code was using.
2463 //socket.mSocket.throwErrnoNative(errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002464 }
2465 return socket;
2466 }
2467
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002468 /**
Casper Bonde238e0f92015-04-09 09:24:48 +02002469 * Construct an encrypted, authenticated, L2CAP server socket.
2470 * Call #accept to retrieve connections to this socket.
Casper Bonde23284232015-04-21 13:12:05 +02002471 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002472 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002473 *
2474 * @param port the PSM to listen on
2475 * @param mitm enforce man-in-the-middle protection for authentication.
2476 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2477 * connections.
Casper Bonde238e0f92015-04-09 09:24:48 +02002478 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002479 * @throws IOException On error, for example Bluetooth not available, or insufficient
2480 * permissions.
Casper Bonde238e0f92015-04-09 09:24:48 +02002481 * @hide
2482 */
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002483 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
2484 throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002485 BluetoothServerSocket socket =
2486 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, true, true, port, mitm,
2487 min16DigitPin);
Casper Bonde238e0f92015-04-09 09:24:48 +02002488 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002489 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Stanley Tnge48468d2017-11-22 16:04:40 -08002490 int assignedChannel = socket.mSocket.getPort();
2491 if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
2492 socket.setChannel(assignedChannel);
Casper Bonde238e0f92015-04-09 09:24:48 +02002493 }
2494 if (errno != 0) {
2495 //TODO(BT): Throw the same exception error code
2496 // that the previous code was using.
2497 //socket.mSocket.throwErrnoNative(errno);
2498 throw new IOException("Error: " + errno);
2499 }
2500 return socket;
2501 }
2502
2503 /**
Casper Bonde23284232015-04-21 13:12:05 +02002504 * Construct an encrypted, authenticated, L2CAP server socket.
2505 * Call #accept to retrieve connections to this socket.
2506 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002507 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002508 *
2509 * @param port the PSM to listen on
Casper Bonde23284232015-04-21 13:12:05 +02002510 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002511 * @throws IOException On error, for example Bluetooth not available, or insufficient
2512 * permissions.
Casper Bonde23284232015-04-21 13:12:05 +02002513 * @hide
2514 */
2515 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002516 return listenUsingL2capOn(port, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02002517 }
2518
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302519
2520 /**
2521 * Construct an insecure L2CAP server socket.
2522 * Call #accept to retrieve connections to this socket.
2523 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002524 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002525 *
2526 * @param port the PSM to listen on
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302527 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002528 * @throws IOException On error, for example Bluetooth not available, or insufficient
2529 * permissions.
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302530 * @hide
2531 */
2532 public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08002533 Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
Myles Watson125b5452017-11-27 16:41:47 -08002534 BluetoothServerSocket socket =
2535 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
Stanley Tnge48468d2017-11-22 16:04:40 -08002536 false);
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302537 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002538 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Stanley Tnge48468d2017-11-22 16:04:40 -08002539 int assignedChannel = socket.mSocket.getPort();
2540 if (DBG) {
2541 Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
2542 + assignedChannel);
2543 }
2544 socket.setChannel(assignedChannel);
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302545 }
2546 if (errno != 0) {
2547 //TODO(BT): Throw the same exception error code
2548 // that the previous code was using.
2549 //socket.mSocket.throwErrnoNative(errno);
2550 throw new IOException("Error: " + errno);
2551 }
2552 return socket;
2553
2554 }
2555
Casper Bonde23284232015-04-21 13:12:05 +02002556 /**
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002557 * Read the local Out of Band Pairing Data
2558 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2559 *
2560 * @return Pair<byte[], byte[]> of Hash and Randomizer
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002561 * @hide
2562 */
2563 public Pair<byte[], byte[]> readOutOfBandData() {
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002564 return null;
2565 }
2566
Scott Main299ae672011-01-19 21:13:18 -08002567 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002568 * Get the profile proxy object associated with the profile.
2569 *
Jack He6b73b322019-01-03 16:23:41 -08002570 * <p>Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP},
Stanley Tng1f5ea662018-11-15 17:11:36 -08002571 * {@link BluetoothProfile#GATT}, {@link BluetoothProfile#HEARING_AID}, or {@link
2572 * BluetoothProfile#GATT_SERVER}. Clients must implement {@link
2573 * BluetoothProfile.ServiceListener} to get notified of the connection status and to get the
2574 * proxy object.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002575 *
2576 * @param context Context of the application
2577 * @param listener The service Listener for connection callbacks.
Jack He6b73b322019-01-03 16:23:41 -08002578 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET},
Stanley Tng1f5ea662018-11-15 17:11:36 -08002579 * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, {@link
2580 * BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#GATT_SERVER}.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002581 * @return true on success, false on error
2582 */
2583 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
Jack Hea355e5e2017-08-22 16:06:54 -07002584 int profile) {
Myles Watson125b5452017-11-27 16:41:47 -08002585 if (context == null || listener == null) {
2586 return false;
2587 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002588
2589 if (profile == BluetoothProfile.HEADSET) {
2590 BluetoothHeadset headset = new BluetoothHeadset(context, listener);
2591 return true;
2592 } else if (profile == BluetoothProfile.A2DP) {
2593 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
2594 return true;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002595 } else if (profile == BluetoothProfile.A2DP_SINK) {
2596 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
2597 return true;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002598 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
2599 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
2600 return true;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002601 } else if (profile == BluetoothProfile.HID_HOST) {
2602 BluetoothHidHost iDev = new BluetoothHidHost(context, listener);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -08002603 return true;
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -08002604 } else if (profile == BluetoothProfile.PAN) {
2605 BluetoothPan pan = new BluetoothPan(context, listener);
2606 return true;
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -07002607 } else if (profile == BluetoothProfile.HEALTH) {
Jack He6b73b322019-01-03 16:23:41 -08002608 Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated");
2609 return false;
Kim Schulz0d376052013-08-22 11:18:02 +02002610 } else if (profile == BluetoothProfile.MAP) {
2611 BluetoothMap map = new BluetoothMap(context, listener);
2612 return true;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002613 } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
2614 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
Hemant Gupta7aca90f2013-08-19 19:03:51 +05302615 return true;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002616 } else if (profile == BluetoothProfile.SAP) {
2617 BluetoothSap sap = new BluetoothSap(context, listener);
2618 return true;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002619 } else if (profile == BluetoothProfile.PBAP_CLIENT) {
2620 BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
2621 return true;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002622 } else if (profile == BluetoothProfile.MAP_CLIENT) {
2623 BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
2624 return true;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002625 } else if (profile == BluetoothProfile.HID_DEVICE) {
2626 BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
Ivan Podogov5297dba2016-12-30 14:35:09 +00002627 return true;
Jakub Pawlowskiea580fa2017-11-22 11:02:34 -08002628 } else if (profile == BluetoothProfile.HEARING_AID) {
Stanley Tng61dbd812019-01-13 16:04:31 -08002629 if (isHearingAidProfileSupported()) {
2630 BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener);
2631 return true;
2632 }
2633 return false;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002634 } else {
2635 return false;
2636 }
2637 }
2638
2639 /**
2640 * Close the connection of the profile proxy to the Service.
2641 *
2642 * <p> Clients should call this when they are no longer using
2643 * the proxy obtained from {@link #getProfileProxy}.
Jack He6b73b322019-01-03 16:23:41 -08002644 * Profile can be one of {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002645 *
2646 * @param profile
2647 * @param proxy Profile proxy object
2648 */
2649 public void closeProfileProxy(int profile, BluetoothProfile proxy) {
Myles Watson125b5452017-11-27 16:41:47 -08002650 if (proxy == null) {
2651 return;
2652 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002653
2654 switch (profile) {
2655 case BluetoothProfile.HEADSET:
Jack Hea355e5e2017-08-22 16:06:54 -07002656 BluetoothHeadset headset = (BluetoothHeadset) proxy;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002657 headset.close();
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002658 break;
2659 case BluetoothProfile.A2DP:
Jack Hea355e5e2017-08-22 16:06:54 -07002660 BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002661 a2dp.close();
2662 break;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002663 case BluetoothProfile.A2DP_SINK:
Jack Hea355e5e2017-08-22 16:06:54 -07002664 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002665 a2dpSink.close();
2666 break;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002667 case BluetoothProfile.AVRCP_CONTROLLER:
Jack Hea355e5e2017-08-22 16:06:54 -07002668 BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002669 avrcp.close();
2670 break;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002671 case BluetoothProfile.HID_HOST:
2672 BluetoothHidHost iDev = (BluetoothHidHost) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002673 iDev.close();
2674 break;
2675 case BluetoothProfile.PAN:
Jack Hea355e5e2017-08-22 16:06:54 -07002676 BluetoothPan pan = (BluetoothPan) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002677 pan.close();
2678 break;
Jack Hea355e5e2017-08-22 16:06:54 -07002679 case BluetoothProfile.GATT:
2680 BluetoothGatt gatt = (BluetoothGatt) proxy;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08002681 gatt.close();
2682 break;
2683 case BluetoothProfile.GATT_SERVER:
Jack Hea355e5e2017-08-22 16:06:54 -07002684 BluetoothGattServer gattServer = (BluetoothGattServer) proxy;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08002685 gattServer.close();
2686 break;
Kim Schulz0d376052013-08-22 11:18:02 +02002687 case BluetoothProfile.MAP:
Jack Hea355e5e2017-08-22 16:06:54 -07002688 BluetoothMap map = (BluetoothMap) proxy;
Kim Schulz0d376052013-08-22 11:18:02 +02002689 map.close();
2690 break;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002691 case BluetoothProfile.HEADSET_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002692 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002693 headsetClient.close();
Hemant Gupta7aca90f2013-08-19 19:03:51 +05302694 break;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002695 case BluetoothProfile.SAP:
Jack Hea355e5e2017-08-22 16:06:54 -07002696 BluetoothSap sap = (BluetoothSap) proxy;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002697 sap.close();
2698 break;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002699 case BluetoothProfile.PBAP_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002700 BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002701 pbapClient.close();
2702 break;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002703 case BluetoothProfile.MAP_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002704 BluetoothMapClient mapClient = (BluetoothMapClient) proxy;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002705 mapClient.close();
2706 break;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002707 case BluetoothProfile.HID_DEVICE:
2708 BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
2709 hidDevice.close();
Ivan Podogov5297dba2016-12-30 14:35:09 +00002710 break;
Jakub Pawlowskiea580fa2017-11-22 11:02:34 -08002711 case BluetoothProfile.HEARING_AID:
2712 BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
2713 hearingAid.close();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002714 }
2715 }
2716
Jack He2992cd02017-08-22 21:21:23 -07002717 private final IBluetoothManagerCallback mManagerCallback =
Jack Hea355e5e2017-08-22 16:06:54 -07002718 new IBluetoothManagerCallback.Stub() {
2719 public void onBluetoothServiceUp(IBluetooth bluetoothService) {
Myles Watson125b5452017-11-27 16:41:47 -08002720 if (DBG) {
2721 Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
2722 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002723
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002724 mServiceLock.writeLock().lock();
Jack Hea355e5e2017-08-22 16:06:54 -07002725 mService = bluetoothService;
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002726 mServiceLock.writeLock().unlock();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002727
Jack Hea355e5e2017-08-22 16:06:54 -07002728 synchronized (mProxyServiceStateCallbacks) {
2729 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2730 try {
2731 if (cb != null) {
2732 cb.onBluetoothServiceUp(bluetoothService);
2733 } else {
2734 Log.d(TAG, "onBluetoothServiceUp: cb is null!");
2735 }
2736 } catch (Exception e) {
2737 Log.e(TAG, "", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002738 }
Matthew Xie60675b22015-02-06 14:09:54 -08002739 }
fredc903ac6f2012-04-24 03:59:57 -07002740 }
Ugo Yu4a33b882019-01-08 09:00:09 +08002741 synchronized (sMetadataListeners) {
2742 sMetadataListeners.forEach((device, pair) -> {
2743 try {
2744 mService.registerMetadataListener(sBluetoothMetadataListener,
2745 device);
2746 } catch (RemoteException e) {
2747 Log.e(TAG, "Failed to register metadata listener", e);
2748 }
2749 });
2750 }
fredc0f420372012-04-12 00:02:00 -07002751 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002752
Jack Hea355e5e2017-08-22 16:06:54 -07002753 public void onBluetoothServiceDown() {
Myles Watson125b5452017-11-27 16:41:47 -08002754 if (DBG) {
2755 Log.d(TAG, "onBluetoothServiceDown: " + mService);
2756 }
Jack Hea355e5e2017-08-22 16:06:54 -07002757
2758 try {
2759 mServiceLock.writeLock().lock();
2760 mService = null;
Myles Watson125b5452017-11-27 16:41:47 -08002761 if (mLeScanClients != null) {
2762 mLeScanClients.clear();
2763 }
2764 if (sBluetoothLeAdvertiser != null) {
2765 sBluetoothLeAdvertiser.cleanup();
2766 }
2767 if (sBluetoothLeScanner != null) {
2768 sBluetoothLeScanner.cleanup();
2769 }
Jack Hea355e5e2017-08-22 16:06:54 -07002770 } finally {
2771 mServiceLock.writeLock().unlock();
2772 }
2773
2774 synchronized (mProxyServiceStateCallbacks) {
2775 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2776 try {
2777 if (cb != null) {
2778 cb.onBluetoothServiceDown();
2779 } else {
2780 Log.d(TAG, "onBluetoothServiceDown: cb is null!");
2781 }
2782 } catch (Exception e) {
2783 Log.e(TAG, "", e);
2784 }
2785 }
2786 }
2787 }
2788
2789 public void onBrEdrDown() {
Myles Watson125b5452017-11-27 16:41:47 -08002790 if (VDBG) {
2791 Log.i(TAG, "onBrEdrDown: " + mService);
2792 }
Jack Hea355e5e2017-08-22 16:06:54 -07002793 }
2794 };
fredc0f420372012-04-12 00:02:00 -07002795
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002796 /**
Martijn Coenen6c614b72012-04-18 13:01:15 -07002797 * Enable the Bluetooth Adapter, but don't auto-connect devices
2798 * and don't persist state. Only for use by system applications.
Jack Hea355e5e2017-08-22 16:06:54 -07002799 *
Martijn Coenen6c614b72012-04-18 13:01:15 -07002800 * @hide
2801 */
Selim Gurun64bd35e2017-10-17 17:01:38 -07002802 @SystemApi
2803 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
Martijn Coenen6c614b72012-04-18 13:01:15 -07002804 public boolean enableNoAutoConnect() {
Jack He2992cd02017-08-22 21:21:23 -07002805 if (isEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -08002806 if (DBG) {
2807 Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
2808 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002809 return true;
2810 }
2811 try {
Marie Janssen59804562016-12-28 14:13:21 -08002812 return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
Jack Hea355e5e2017-08-22 16:06:54 -07002813 } catch (RemoteException e) {
2814 Log.e(TAG, "", e);
2815 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002816 return false;
Martijn Coenen6c614b72012-04-18 13:01:15 -07002817 }
2818
2819 /**
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002820 * Enable control of the Bluetooth Adapter for a single application.
2821 *
2822 * <p>Some applications need to use Bluetooth for short periods of time to
2823 * transfer data but don't want all the associated implications like
2824 * automatic connection to headsets etc.
2825 *
2826 * <p> Multiple applications can call this. This is reference counted and
2827 * Bluetooth disabled only when no one else is using it. There will be no UI
2828 * shown to the user while bluetooth is being enabled. Any user action will
2829 * override this call. For example, if user wants Bluetooth on and the last
2830 * user of this API wanted to disable Bluetooth, Bluetooth will not be
2831 * turned off.
2832 *
2833 * <p> This API is only meant to be used by internal applications. Third
2834 * party applications but use {@link #enable} and {@link #disable} APIs.
2835 *
2836 * <p> If this API returns true, it means the callback will be called.
2837 * The callback will be called with the current state of Bluetooth.
2838 * If the state is not what was requested, an internal error would be the
Jaikumar Ganeshf5fb6c82011-08-03 14:17:22 -07002839 * reason. If Bluetooth is already on and if this function is called to turn
2840 * it on, the api will return true and a callback will be called.
2841 *
2842 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002843 *
2844 * @param on True for on, false for off.
2845 * @param callback The callback to notify changes to the state.
2846 * @hide
2847 */
2848 public boolean changeApplicationBluetoothState(boolean on,
Jack Hea355e5e2017-08-22 16:06:54 -07002849 BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002850 return false;
2851 }
2852
2853 /**
2854 * @hide
2855 */
2856 public interface BluetoothStateChangeCallback {
Myles Watson125b5452017-11-27 16:41:47 -08002857 /**
2858 * @hide
2859 */
2860 void onBluetoothStateChange(boolean on);
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002861 }
2862
2863 /**
2864 * @hide
2865 */
2866 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
2867 private BluetoothStateChangeCallback mCallback;
2868
Myles Watson125b5452017-11-27 16:41:47 -08002869 StateChangeCallbackWrapper(BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002870 mCallback = callback;
2871 }
2872
2873 @Override
2874 public void onBluetoothStateChange(boolean on) {
2875 mCallback.onBluetoothStateChange(on);
2876 }
2877 }
2878
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08002879 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
2880 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
2881 return Collections.unmodifiableSet(deviceSet);
Nick Pellybd022f42009-08-14 18:33:38 -07002882 }
Nick Pelly005b2282009-09-10 10:21:56 -07002883
fredc0f420372012-04-12 00:02:00 -07002884 protected void finalize() throws Throwable {
2885 try {
2886 mManagerService.unregisterAdapter(mManagerCallback);
2887 } catch (RemoteException e) {
2888 Log.e(TAG, "", e);
2889 } finally {
2890 super.finalize();
2891 }
2892 }
2893
2894
Nick Pelly005b2282009-09-10 10:21:56 -07002895 /**
Nick Pelly75596b42011-12-07 15:03:55 -08002896 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
Nick Pelly55e66f12009-09-18 11:37:06 -07002897 * <p>Alphabetic characters must be uppercase to be valid.
Nick Pelly005b2282009-09-10 10:21:56 -07002898 *
2899 * @param address Bluetooth address as string
2900 * @return true if the address is valid, false otherwise
2901 */
2902 public static boolean checkBluetoothAddress(String address) {
2903 if (address == null || address.length() != ADDRESS_LENGTH) {
2904 return false;
2905 }
2906 for (int i = 0; i < ADDRESS_LENGTH; i++) {
2907 char c = address.charAt(i);
2908 switch (i % 3) {
Jack Hea355e5e2017-08-22 16:06:54 -07002909 case 0:
2910 case 1:
2911 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
2912 // hex character, OK
2913 break;
2914 }
2915 return false;
2916 case 2:
2917 if (c == ':') {
2918 break; // OK
2919 }
2920 return false;
Nick Pelly005b2282009-09-10 10:21:56 -07002921 }
2922 }
2923 return true;
2924 }
fredc0f420372012-04-12 00:02:00 -07002925
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002926 @UnsupportedAppUsage
fredc0f420372012-04-12 00:02:00 -07002927 /*package*/ IBluetoothManager getBluetoothManager() {
Jack Hea355e5e2017-08-22 16:06:54 -07002928 return mManagerService;
fredc0f420372012-04-12 00:02:00 -07002929 }
2930
Jack He2992cd02017-08-22 21:21:23 -07002931 private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks =
Jack Hea355e5e2017-08-22 16:06:54 -07002932 new ArrayList<IBluetoothManagerCallback>();
fredcd6883532012-04-25 17:46:13 -07002933
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002934 @UnsupportedAppUsage
fredc903ac6f2012-04-24 03:59:57 -07002935 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08002936 synchronized (mProxyServiceStateCallbacks) {
fredcd6883532012-04-25 17:46:13 -07002937 if (cb == null) {
fredcbf072a72012-05-09 16:52:50 -07002938 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
2939 } else if (!mProxyServiceStateCallbacks.contains(cb)) {
2940 mProxyServiceStateCallbacks.add(cb);
fredc903ac6f2012-04-24 03:59:57 -07002941 }
2942 }
2943 return mService;
2944 }
2945
2946 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08002947 synchronized (mProxyServiceStateCallbacks) {
fredcbf072a72012-05-09 16:52:50 -07002948 mProxyServiceStateCallbacks.remove(cb);
fredc0f420372012-04-12 00:02:00 -07002949 }
2950 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002951
2952 /**
Matthew Xiecdd94e32013-04-11 16:36:26 -07002953 * Callback interface used to deliver LE scan results.
Matthew Xieddf7e472013-03-01 18:41:02 -08002954 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07002955 * @see #startLeScan(LeScanCallback)
2956 * @see #startLeScan(UUID[], LeScanCallback)
Matthew Xieddf7e472013-03-01 18:41:02 -08002957 */
Matthew Xiecdd94e32013-04-11 16:36:26 -07002958 public interface LeScanCallback {
2959 /**
2960 * Callback reporting an LE device found during a device scan initiated
2961 * by the {@link BluetoothAdapter#startLeScan} function.
2962 *
2963 * @param device Identifies the remote device
Jack Hea355e5e2017-08-22 16:06:54 -07002964 * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0
2965 * if no RSSI value is available.
2966 * @param scanRecord The content of the advertisement record offered by the remote device.
Matthew Xiecdd94e32013-04-11 16:36:26 -07002967 */
Myles Watson125b5452017-11-27 16:41:47 -08002968 void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
Matthew Xieddf7e472013-03-01 18:41:02 -08002969 }
2970
2971 /**
2972 * Starts a scan for Bluetooth LE devices.
2973 *
2974 * <p>Results of the scan are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07002975 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08002976 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07002977 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08002978 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07002979 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack Hea355e5e2017-08-22 16:06:54 -07002980 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002981 */
Wei Wangaf74e662014-07-09 14:03:42 -07002982 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002983 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07002984 public boolean startLeScan(LeScanCallback callback) {
2985 return startLeScan(null, callback);
Matthew Xieddf7e472013-03-01 18:41:02 -08002986 }
2987
2988 /**
2989 * Starts a scan for Bluetooth LE devices, looking for devices that
2990 * advertise given services.
2991 *
2992 * <p>Devices which advertise all specified services are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07002993 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08002994 *
Matthew Xieddf7e472013-03-01 18:41:02 -08002995 * @param serviceUuids Array of services to look for
Matthew Xiecdd94e32013-04-11 16:36:26 -07002996 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08002997 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07002998 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack Hea355e5e2017-08-22 16:06:54 -07002999 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08003000 */
Wei Wangaf74e662014-07-09 14:03:42 -07003001 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07003002 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Wei Wangc3059cc2014-07-23 23:34:00 -07003003 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
Myles Watson125b5452017-11-27 16:41:47 -08003004 if (DBG) {
3005 Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
3006 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07003007 if (callback == null) {
Myles Watson125b5452017-11-27 16:41:47 -08003008 if (DBG) {
3009 Log.e(TAG, "startLeScan: null callback");
3010 }
Matthew Xieddf7e472013-03-01 18:41:02 -08003011 return false;
3012 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003013 BluetoothLeScanner scanner = getBluetoothLeScanner();
3014 if (scanner == null) {
Myles Watson125b5452017-11-27 16:41:47 -08003015 if (DBG) {
3016 Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
3017 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003018 return false;
3019 }
Matthew Xieddf7e472013-03-01 18:41:02 -08003020
Jack Hea355e5e2017-08-22 16:06:54 -07003021 synchronized (mLeScanClients) {
Matthew Xiecdd94e32013-04-11 16:36:26 -07003022 if (mLeScanClients.containsKey(callback)) {
Myles Watson125b5452017-11-27 16:41:47 -08003023 if (DBG) {
3024 Log.e(TAG, "LE Scan has already started");
3025 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07003026 return false;
3027 }
3028
3029 try {
3030 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
Matthew Xie32ab77b2013-05-08 19:26:57 -07003031 if (iGatt == null) {
3032 // BLE is not supported
3033 return false;
3034 }
3035
Wei Wangc3059cc2014-07-23 23:34:00 -07003036 ScanCallback scanCallback = new ScanCallback() {
3037 @Override
3038 public void onScanResult(int callbackType, ScanResult result) {
3039 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
3040 // Should not happen.
3041 Log.e(TAG, "LE Scan has already started");
3042 return;
3043 }
3044 ScanRecord scanRecord = result.getScanRecord();
3045 if (scanRecord == null) {
3046 return;
3047 }
3048 if (serviceUuids != null) {
3049 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
3050 for (UUID uuid : serviceUuids) {
3051 uuids.add(new ParcelUuid(uuid));
3052 }
3053 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
3054 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
Myles Watson125b5452017-11-27 16:41:47 -08003055 if (DBG) {
3056 Log.d(TAG, "uuids does not match");
3057 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003058 return;
3059 }
3060 }
3061 callback.onLeScan(result.getDevice(), result.getRssi(),
3062 scanRecord.getBytes());
3063 }
3064 };
Myles Watson125b5452017-11-27 16:41:47 -08003065 ScanSettings settings = new ScanSettings.Builder().setCallbackType(
3066 ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
3067 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
3068 .build();
Wei Wangc3059cc2014-07-23 23:34:00 -07003069
3070 List<ScanFilter> filters = new ArrayList<ScanFilter>();
3071 if (serviceUuids != null && serviceUuids.length > 0) {
3072 // Note scan filter does not support matching an UUID array so we put one
3073 // UUID to hardware and match the whole array in callback.
Myles Watson125b5452017-11-27 16:41:47 -08003074 ScanFilter filter =
3075 new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuids[0]))
3076 .build();
Wei Wangc3059cc2014-07-23 23:34:00 -07003077 filters.add(filter);
Matthew Xiecdd94e32013-04-11 16:36:26 -07003078 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003079 scanner.startScan(filters, settings, scanCallback);
3080
3081 mLeScanClients.put(callback, scanCallback);
3082 return true;
3083
Matthew Xiecdd94e32013-04-11 16:36:26 -07003084 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -07003085 Log.e(TAG, "", e);
Matthew Xiecdd94e32013-04-11 16:36:26 -07003086 }
3087 }
3088 return false;
Matthew Xieddf7e472013-03-01 18:41:02 -08003089 }
3090
3091 /**
3092 * Stops an ongoing Bluetooth LE device scan.
3093 *
Jack Hea355e5e2017-08-22 16:06:54 -07003094 * @param callback used to identify which scan to stop must be the same handle used to start the
3095 * scan
Wei Wangaf74e662014-07-09 14:03:42 -07003096 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08003097 */
Wei Wangaf74e662014-07-09 14:03:42 -07003098 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07003099 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07003100 public void stopLeScan(LeScanCallback callback) {
Myles Watson125b5452017-11-27 16:41:47 -08003101 if (DBG) {
3102 Log.d(TAG, "stopLeScan()");
3103 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003104 BluetoothLeScanner scanner = getBluetoothLeScanner();
3105 if (scanner == null) {
3106 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08003107 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003108 synchronized (mLeScanClients) {
3109 ScanCallback scanCallback = mLeScanClients.remove(callback);
3110 if (scanCallback == null) {
Myles Watson125b5452017-11-27 16:41:47 -08003111 if (DBG) {
3112 Log.d(TAG, "scan not started yet");
3113 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003114 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08003115 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003116 scanner.stopScan(scanCallback);
Prerepa Viswanadham8f2e74c2014-07-09 12:51:59 -07003117 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07003118 }
Stanley Tnge48468d2017-11-22 16:04:40 -08003119
3120 /**
3121 * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
3122 * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003123 * for incoming connections. The supported Bluetooth transport is LE only.
Stanley Tnge48468d2017-11-22 16:04:40 -08003124 * <p>A remote device connecting to this socket will be authenticated and communication on this
3125 * socket will be encrypted.
3126 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3127 * {@link BluetoothServerSocket}.
Andrew Solovaya44f2c072018-10-02 14:14:42 -07003128 * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {@link
Stanley Tnge48468d2017-11-22 16:04:40 -08003129 * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
3130 * closed, Bluetooth is turned off, or the application exits unexpectedly.
3131 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3132 * defined and performed by the application.
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003133 * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
Stanley Tnge48468d2017-11-22 16:04:40 -08003134 * socket from another Android device that is given the PSM value.
3135 *
Stanley Tnge48468d2017-11-22 16:04:40 -08003136 * @return an L2CAP CoC BluetoothServerSocket
3137 * @throws IOException on error, for example Bluetooth not available, or insufficient
3138 * permissions, or unable to start this CoC
Stanley Tnge48468d2017-11-22 16:04:40 -08003139 */
3140 @RequiresPermission(Manifest.permission.BLUETOOTH)
Stanley Tng97341da2019-03-12 10:19:49 -07003141 public @NonNull BluetoothServerSocket listenUsingL2capChannel()
Stanley Tnge48468d2017-11-22 16:04:40 -08003142 throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08003143 BluetoothServerSocket socket =
3144 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
3145 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3146 int errno = socket.mSocket.bindListen();
3147 if (errno != 0) {
3148 throw new IOException("Error: " + errno);
3149 }
3150
3151 int assignedPsm = socket.mSocket.getPort();
3152 if (assignedPsm == 0) {
3153 throw new IOException("Error: Unable to assign PSM value");
3154 }
3155 if (DBG) {
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003156 Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
Stanley Tnge48468d2017-11-22 16:04:40 -08003157 + assignedPsm);
3158 }
3159 socket.setChannel(assignedPsm);
3160
3161 return socket;
3162 }
3163
3164 /**
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003165 * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
3166 * API name, listenUsingL2capChannel.
3167 * @hide
3168 */
3169 @RequiresPermission(Manifest.permission.BLUETOOTH)
3170 public BluetoothServerSocket listenUsingL2capCoc(int transport)
3171 throws IOException {
3172 Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel");
3173 return listenUsingL2capChannel();
3174 }
3175
3176 /**
Stanley Tnge48468d2017-11-22 16:04:40 -08003177 * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003178 * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
3179 * supported Bluetooth transport is LE only.
Stanley Tnge48468d2017-11-22 16:04:40 -08003180 * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003181 * to man-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
Stanley Tnge48468d2017-11-22 16:04:40 -08003182 * authenticated communication channel is desired.
3183 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3184 * {@link BluetoothServerSocket}.
3185 * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
Andrew Solovaya44f2c072018-10-02 14:14:42 -07003186 * can be read from the {@link BluetoothServerSocket#getPsm()} and this value will be released
Stanley Tnge48468d2017-11-22 16:04:40 -08003187 * when this server socket is closed, Bluetooth is turned off, or the application exits
3188 * unexpectedly.
3189 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3190 * defined and performed by the application.
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003191 * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
3192 * socket from another Android device that is given the PSM value.
Stanley Tnge48468d2017-11-22 16:04:40 -08003193 *
Stanley Tnge48468d2017-11-22 16:04:40 -08003194 * @return an L2CAP CoC BluetoothServerSocket
3195 * @throws IOException on error, for example Bluetooth not available, or insufficient
3196 * permissions, or unable to start this CoC
Stanley Tnge48468d2017-11-22 16:04:40 -08003197 */
3198 @RequiresPermission(Manifest.permission.BLUETOOTH)
Stanley Tng97341da2019-03-12 10:19:49 -07003199 public @NonNull BluetoothServerSocket listenUsingInsecureL2capChannel()
Stanley Tnge48468d2017-11-22 16:04:40 -08003200 throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08003201 BluetoothServerSocket socket =
3202 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
3203 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3204 int errno = socket.mSocket.bindListen();
3205 if (errno != 0) {
3206 throw new IOException("Error: " + errno);
3207 }
3208
3209 int assignedPsm = socket.mSocket.getPort();
3210 if (assignedPsm == 0) {
3211 throw new IOException("Error: Unable to assign PSM value");
3212 }
3213 if (DBG) {
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003214 Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
Stanley Tnge48468d2017-11-22 16:04:40 -08003215 + assignedPsm);
3216 }
3217 socket.setChannel(assignedPsm);
3218
3219 return socket;
3220 }
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003221
3222 /**
3223 * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
3224 * API name, listenUsingInsecureL2capChannel.
3225 * @hide
3226 */
3227 @RequiresPermission(Manifest.permission.BLUETOOTH)
3228 public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
3229 throws IOException {
3230 Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, "
3231 + "listenUsingInsecureL2capChannel");
3232 return listenUsingInsecureL2capChannel();
3233 }
Ugo Yu4a33b882019-01-08 09:00:09 +08003234
3235 /**
Ugo Yu50e3c082019-03-05 16:20:27 +08003236 * Register a {@link #OnMetadataChangedListener} to receive update about metadata
Ugo Yu4a33b882019-01-08 09:00:09 +08003237 * changes for this {@link BluetoothDevice}.
3238 * Registration must be done when Bluetooth is ON and will last until
Ugo Yu50e3c082019-03-05 16:20:27 +08003239 * {@link #removeOnMetadataChangedListener(BluetoothDevice)} is called, even when Bluetooth
Ugo Yu4a33b882019-01-08 09:00:09 +08003240 * restarted in the middle.
3241 * All input parameters should not be null or {@link NullPointerException} will be triggered.
Ugo Yu50e3c082019-03-05 16:20:27 +08003242 * The same {@link BluetoothDevice} and {@link #OnMetadataChangedListener} pair can only be
3243 * registered once, double registration would cause {@link IllegalArgumentException}.
Ugo Yu4a33b882019-01-08 09:00:09 +08003244 *
3245 * @param device {@link BluetoothDevice} that will be registered
Ugo Yu50e3c082019-03-05 16:20:27 +08003246 * @param executor the executor for listener callback
3247 * @param listener {@link #OnMetadataChangedListener} that will receive asynchronous callbacks
Ugo Yu4a33b882019-01-08 09:00:09 +08003248 * @return true on success, false on error
Ugo Yu50e3c082019-03-05 16:20:27 +08003249 * @throws NullPointerException If one of {@code listener}, {@code device} or {@code executor}
Ugo Yu4a33b882019-01-08 09:00:09 +08003250 * is null.
Ugo Yu50e3c082019-03-05 16:20:27 +08003251 * @throws IllegalArgumentException The same {@link #OnMetadataChangedListener} and
Ugo Yu4a33b882019-01-08 09:00:09 +08003252 * {@link BluetoothDevice} are registered twice.
3253 * @hide
3254 */
3255 @SystemApi
3256 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Ugo Yu50e3c082019-03-05 16:20:27 +08003257 public boolean addOnMetadataChangedListener(@NonNull BluetoothDevice device,
3258 @NonNull Executor executor, @NonNull OnMetadataChangedListener listener) {
3259 if (DBG) Log.d(TAG, "addOnMetadataChangedListener()");
Ugo Yu4a33b882019-01-08 09:00:09 +08003260
3261 final IBluetooth service = mService;
3262 if (service == null) {
3263 Log.e(TAG, "Bluetooth is not enabled. Cannot register metadata listener");
3264 return false;
3265 }
3266 if (listener == null) {
3267 throw new NullPointerException("listener is null");
3268 }
3269 if (device == null) {
3270 throw new NullPointerException("device is null");
3271 }
Ugo Yu50e3c082019-03-05 16:20:27 +08003272 if (executor == null) {
3273 throw new NullPointerException("executor is null");
Ugo Yu4a33b882019-01-08 09:00:09 +08003274 }
3275
3276 synchronized (sMetadataListeners) {
Ugo Yu50e3c082019-03-05 16:20:27 +08003277 List<Pair<OnMetadataChangedListener, Executor>> listenerList =
3278 sMetadataListeners.get(device);
Ugo Yu4a33b882019-01-08 09:00:09 +08003279 if (listenerList == null) {
Ugo Yu50e3c082019-03-05 16:20:27 +08003280 // Create new listener/executor list for registeration
Ugo Yu4a33b882019-01-08 09:00:09 +08003281 listenerList = new ArrayList<>();
3282 sMetadataListeners.put(device, listenerList);
3283 } else {
3284 // Check whether this device was already registed by the lisenter
3285 if (listenerList.stream().anyMatch((pair) -> (pair.first.equals(listener)))) {
3286 throw new IllegalArgumentException("listener was already regestered"
3287 + " for the device");
3288 }
3289 }
3290
Ugo Yu50e3c082019-03-05 16:20:27 +08003291 Pair<OnMetadataChangedListener, Executor> listenerPair = new Pair(listener, executor);
Ugo Yu4a33b882019-01-08 09:00:09 +08003292 listenerList.add(listenerPair);
3293
3294 boolean ret = false;
3295 try {
3296 ret = service.registerMetadataListener(sBluetoothMetadataListener, device);
3297 } catch (RemoteException e) {
3298 Log.e(TAG, "registerMetadataListener fail", e);
3299 } finally {
3300 if (!ret) {
3301 // Remove listener registered earlier when fail.
3302 listenerList.remove(listenerPair);
3303 if (listenerList.isEmpty()) {
3304 // Remove the device if its listener list is empty
3305 sMetadataListeners.remove(device);
3306 }
3307 }
3308 }
3309 return ret;
3310 }
3311 }
3312
3313 /**
Ugo Yu50e3c082019-03-05 16:20:27 +08003314 * Unregister a {@link #OnMetadataChangedListener} from a registered {@link BluetoothDevice}.
Ugo Yu4a33b882019-01-08 09:00:09 +08003315 * Unregistration can be done when Bluetooth is either ON or OFF.
Ugo Yu50e3c082019-03-05 16:20:27 +08003316 * {@link #addOnMetadataChangedListener(OnMetadataChangedListener, BluetoothDevice, Executor)}
3317 * must be called before unregisteration.
Ugo Yu4a33b882019-01-08 09:00:09 +08003318 *
Ugo Yu50e3c082019-03-05 16:20:27 +08003319 * @param device {@link BluetoothDevice} that will be unregistered. It
3320 * should not be null or {@link NullPointerException} will be triggered.
3321 * @param listener {@link OnMetadataChangedListener} that will be unregistered. It
Ugo Yu4a33b882019-01-08 09:00:09 +08003322 * should not be null or {@link NullPointerException} will be triggered.
3323 * @return true on success, false on error
Ugo Yu50e3c082019-03-05 16:20:27 +08003324 * @throws NullPointerException If {@code listener} or {@code device} is null.
Ugo Yu4a33b882019-01-08 09:00:09 +08003325 * @throws IllegalArgumentException If {@code device} has not been registered before.
3326 * @hide
3327 */
3328 @SystemApi
3329 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Ugo Yu50e3c082019-03-05 16:20:27 +08003330 public boolean removeOnMetadataChangedListener(@NonNull BluetoothDevice device,
3331 @NonNull OnMetadataChangedListener listener) {
3332 if (DBG) Log.d(TAG, "removeOnMetadataChangedListener()");
Ugo Yu4a33b882019-01-08 09:00:09 +08003333 if (device == null) {
3334 throw new NullPointerException("device is null");
3335 }
Ugo Yu50e3c082019-03-05 16:20:27 +08003336 if (listener == null) {
3337 throw new NullPointerException("listener is null");
3338 }
Ugo Yu4a33b882019-01-08 09:00:09 +08003339
3340 synchronized (sMetadataListeners) {
Ugo Yu50e3c082019-03-05 16:20:27 +08003341 if (!sMetadataListeners.containsKey(device)) {
Ugo Yu4a33b882019-01-08 09:00:09 +08003342 throw new IllegalArgumentException("device was not registered");
3343 }
Ugo Yu50e3c082019-03-05 16:20:27 +08003344 // Remove issued listener from the registered device
3345 sMetadataListeners.get(device).removeIf((pair) -> (pair.first.equals(listener)));
Ugo Yu4a33b882019-01-08 09:00:09 +08003346
Ugo Yu50e3c082019-03-05 16:20:27 +08003347 if (sMetadataListeners.get(device).isEmpty()) {
3348 // Unregister to Bluetooth service if all listeners are removed from
3349 // the registered device
3350 sMetadataListeners.remove(device);
3351 final IBluetooth service = mService;
3352 if (service == null) {
3353 // Bluetooth is OFF, do nothing to Bluetooth service.
3354 return true;
3355 }
3356 try {
3357 return service.unregisterMetadataListener(device);
3358 } catch (RemoteException e) {
3359 Log.e(TAG, "unregisterMetadataListener fail", e);
3360 return false;
3361 }
Ugo Yu4a33b882019-01-08 09:00:09 +08003362 }
3363 }
Ugo Yu50e3c082019-03-05 16:20:27 +08003364 return true;
Ugo Yu4a33b882019-01-08 09:00:09 +08003365 }
3366
3367 /**
Ugo Yu50e3c082019-03-05 16:20:27 +08003368 * This interface is used to implement {@link BluetoothAdapter} metadata listener.
Ugo Yu4a33b882019-01-08 09:00:09 +08003369 * @hide
3370 */
3371 @SystemApi
Ugo Yu50e3c082019-03-05 16:20:27 +08003372 public interface OnMetadataChangedListener {
Ugo Yu4a33b882019-01-08 09:00:09 +08003373 /**
3374 * Callback triggered if the metadata of {@link BluetoothDevice} registered in
Ugo Yu50e3c082019-03-05 16:20:27 +08003375 * {@link #addOnMetadataChangedListener}.
Ugo Yu4a33b882019-01-08 09:00:09 +08003376 *
3377 * @param device changed {@link BluetoothDevice}.
3378 * @param key changed metadata key, one of BluetoothDevice.METADATA_*.
Ugo Yu50e3c082019-03-05 16:20:27 +08003379 * @param value the new value of metadata as byte array.
Ugo Yu4a33b882019-01-08 09:00:09 +08003380 */
Ugo Yu50e3c082019-03-05 16:20:27 +08003381 void onMetadataChanged(@NonNull BluetoothDevice device, int key,
3382 @Nullable byte[] value);
Ugo Yu4a33b882019-01-08 09:00:09 +08003383 }
Nick Pellybd022f42009-08-14 18:33:38 -07003384}