blob: 608b563bfc76e33cf69ba7215d372fe9bad2f561 [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;
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -070028import android.app.ActivityThread;
Lee Shombert38265342019-12-30 10:57:12 -080029import android.app.PropertyInvalidatedCache;
Rahul Sabnisdf1ef4a2019-11-27 18:09:33 -080030import android.bluetooth.BluetoothProfile.ConnectionPolicy;
Wei Wang6d811182014-05-22 12:10:25 -070031import android.bluetooth.le.BluetoothLeAdvertiser;
32import android.bluetooth.le.BluetoothLeScanner;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -080033import android.bluetooth.le.PeriodicAdvertisingManager;
Wei Wangaf74e662014-07-09 14:03:42 -070034import android.bluetooth.le.ScanCallback;
Wei Wangc3059cc2014-07-23 23:34:00 -070035import android.bluetooth.le.ScanFilter;
36import android.bluetooth.le.ScanRecord;
Wei Wang9fb17912014-07-01 15:10:06 -070037import android.bluetooth.le.ScanResult;
Wei Wangaf74e662014-07-09 14:03:42 -070038import android.bluetooth.le.ScanSettings;
Artur Satayeve23a0eb2019-12-10 17:47:52 +000039import android.compat.annotation.UnsupportedAppUsage;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070040import android.content.Context;
Adam Lesinski010bf372016-04-11 12:18:18 -070041import android.os.BatteryStats;
Wei Wang46ab7232015-05-07 16:25:33 -070042import android.os.Binder;
Nick Pellyf242b7b2009-10-08 00:12:45 +020043import android.os.IBinder;
Nick Pellyaef439e2009-09-28 12:33:17 -070044import android.os.ParcelUuid;
Nick Pellybd022f42009-08-14 18:33:38 -070045import android.os.RemoteException;
Adam Lesinski010bf372016-04-11 12:18:18 -070046import android.os.ResultReceiver;
Nick Pellyf242b7b2009-10-08 00:12:45 +020047import android.os.ServiceManager;
Adam Lesinski010bf372016-04-11 12:18:18 -070048import android.os.SynchronousResultReceiver;
Ajay Panickerb6e1daf2016-02-29 16:09:14 -080049import android.os.SystemProperties;
Nick Pellybd022f42009-08-14 18:33:38 -070050import android.util.Log;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070051import android.util.Pair;
Wei Wang18c76932013-10-29 21:05:37 -070052
Nick Pellybd022f42009-08-14 18:33:38 -070053import java.io.IOException;
Tor Norbye2d497522015-04-23 17:10:21 -070054import java.lang.annotation.Retention;
55import java.lang.annotation.RetentionPolicy;
fredc903ac6f2012-04-24 03:59:57 -070056import java.util.ArrayList;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070057import java.util.Arrays;
Nick Pellybd022f42009-08-14 18:33:38 -070058import java.util.Collections;
Matthew Xiecdd94e32013-04-11 16:36:26 -070059import java.util.HashMap;
Wei Wang18c76932013-10-29 21:05:37 -070060import java.util.HashSet;
Wei Wang9fb17912014-07-01 15:10:06 -070061import java.util.List;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070062import java.util.Locale;
Matthew Xiecdd94e32013-04-11 16:36:26 -070063import java.util.Map;
Nick Pelly24bb9b82009-10-02 20:34:18 -070064import java.util.Set;
Nick Pelly16fb88a2009-10-07 07:44:03 +020065import java.util.UUID;
Ugo Yu50e3c082019-03-05 16:20:27 +080066import java.util.concurrent.Executor;
Adam Lesinski010bf372016-04-11 12:18:18 -070067import java.util.concurrent.TimeoutException;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -070068import java.util.concurrent.locks.ReentrantReadWriteLock;
Nick Pellybd022f42009-08-14 18:33:38 -070069
70/**
Scott Main9fab0ae2009-11-03 18:17:59 -080071 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
72 * lets you perform fundamental Bluetooth tasks, such as initiate
73 * device discovery, query a list of bonded (paired) devices,
74 * instantiate a {@link BluetoothDevice} using a known MAC address, and create
75 * a {@link BluetoothServerSocket} to listen for connection requests from other
Matthew Xieb30f91e2013-05-29 10:19:06 -070076 * devices, and start a scan for Bluetooth LE devices.
Scott Main9fab0ae2009-11-03 18:17:59 -080077 *
78 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
Marie Janssen553c8c72017-01-12 16:00:30 -080079 * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}.
80 * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter}
81 * method instead.
82 * </p><p>
Scott Main9fab0ae2009-11-03 18:17:59 -080083 * Fundamentally, this is your starting point for all
84 * Bluetooth actions. Once you have the local adapter, you can get a set of
85 * {@link BluetoothDevice} objects representing all paired devices with
86 * {@link #getBondedDevices()}; start device discovery with
87 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
Stanley Tnge48468d2017-11-22 16:04:40 -080088 * listen for incoming RFComm connection requests with {@link
Stanley Tng1bff4ba2018-06-29 14:05:04 -070089 * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
90 * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
Matthew Xieb30f91e2013-05-29 10:19:06 -070091 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
Marie Janssen553c8c72017-01-12 16:00:30 -080092 * </p>
93 * <p>This class is thread safe.</p>
Scott Main9fab0ae2009-11-03 18:17:59 -080094 * <p class="note"><strong>Note:</strong>
95 * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
96 * permission and some also require the
97 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
Marie Janssen553c8c72017-01-12 16:00:30 -080098 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080099 * <div class="special reference">
100 * <h3>Developer Guides</h3>
Hemal Patel65813df2016-08-17 13:18:14 -0700101 * <p>
Jack Hea355e5e2017-08-22 16:06:54 -0700102 * For more information about using Bluetooth, read the <a href=
Hemal Patel65813df2016-08-17 13:18:14 -0700103 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
104 * guide.
105 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -0800106 * </div>
107 *
Scott Main9fab0ae2009-11-03 18:17:59 -0800108 * {@see BluetoothDevice}
109 * {@see BluetoothServerSocket}
Nick Pellybd022f42009-08-14 18:33:38 -0700110 */
111public final class BluetoothAdapter {
112 private static final String TAG = "BluetoothAdapter";
fredc0f420372012-04-12 00:02:00 -0700113 private static final boolean DBG = true;
Matthew Xie3b6214f2012-08-29 00:12:29 -0700114 private static final boolean VDBG = false;
Nick Pellybd022f42009-08-14 18:33:38 -0700115
Nick Pellyde893f52009-09-08 13:15:33 -0700116 /**
Svet Ganov408abf72015-05-12 19:13:36 -0700117 * Default MAC address reported to a client that does not have the
118 * android.permission.LOCAL_MAC_ADDRESS permission.
119 *
120 * @hide
121 */
122 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
123
124 /**
Nick Pellyb24e11b2009-09-08 17:40:43 -0700125 * Sentinel error value for this class. Guaranteed to not equal any other
126 * integer constant in this class. Provided as a convenience for functions
127 * that require a sentinel error value, for example:
128 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
129 * BluetoothAdapter.ERROR)</code>
130 */
Nick Pelly005b2282009-09-10 10:21:56 -0700131 public static final int ERROR = Integer.MIN_VALUE;
Nick Pellyb24e11b2009-09-08 17:40:43 -0700132
133 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700134 * Broadcast Action: The state of the local Bluetooth adapter has been
135 * changed.
136 * <p>For example, Bluetooth has been turned on or off.
Nick Pelly005b2282009-09-10 10:21:56 -0700137 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700138 * #EXTRA_PREVIOUS_STATE} containing the new and old states
139 * respectively.
140 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
141 */
Myles Watson125b5452017-11-27 16:41:47 -0800142 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
143 ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
Nick Pellybd022f42009-08-14 18:33:38 -0700144
Nick Pellyde893f52009-09-08 13:15:33 -0700145 /**
146 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
147 * intents to request the current power state. Possible values are:
148 * {@link #STATE_OFF},
149 * {@link #STATE_TURNING_ON},
150 * {@link #STATE_ON},
151 * {@link #STATE_TURNING_OFF},
152 */
Myles Watson125b5452017-11-27 16:41:47 -0800153 public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
Nick Pellyde893f52009-09-08 13:15:33 -0700154 /**
155 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
156 * intents to request the previous power state. Possible values are:
157 * {@link #STATE_OFF},
158 * {@link #STATE_TURNING_ON},
159 * {@link #STATE_ON},
Etan Cohenfd840dd2015-04-23 18:25:08 -0700160 * {@link #STATE_TURNING_OFF}
Nick Pellyde893f52009-09-08 13:15:33 -0700161 */
162 public static final String EXTRA_PREVIOUS_STATE =
Nick Pelly005b2282009-09-10 10:21:56 -0700163 "android.bluetooth.adapter.extra.PREVIOUS_STATE";
Nick Pellybd022f42009-08-14 18:33:38 -0700164
Tor Norbye2d497522015-04-23 17:10:21 -0700165 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700166 @IntDef(prefix = { "STATE_" }, value = {
Myles Watson125b5452017-11-27 16:41:47 -0800167 STATE_OFF,
168 STATE_TURNING_ON,
169 STATE_ON,
170 STATE_TURNING_OFF,
171 STATE_BLE_TURNING_ON,
172 STATE_BLE_ON,
173 STATE_BLE_TURNING_OFF
174 })
Tor Norbye2d497522015-04-23 17:10:21 -0700175 @Retention(RetentionPolicy.SOURCE)
Myles Watson125b5452017-11-27 16:41:47 -0800176 public @interface AdapterState {}
Tor Norbye2d497522015-04-23 17:10:21 -0700177
Nick Pellyde893f52009-09-08 13:15:33 -0700178 /**
179 * Indicates the local Bluetooth adapter is off.
180 */
Nick Pelly005b2282009-09-10 10:21:56 -0700181 public static final int STATE_OFF = 10;
Nick Pellyde893f52009-09-08 13:15:33 -0700182 /**
183 * Indicates the local Bluetooth adapter is turning on. However local
184 * clients should wait for {@link #STATE_ON} before attempting to
185 * use the adapter.
186 */
Nick Pelly005b2282009-09-10 10:21:56 -0700187 public static final int STATE_TURNING_ON = 11;
Nick Pellyde893f52009-09-08 13:15:33 -0700188 /**
189 * Indicates the local Bluetooth adapter is on, and ready for use.
190 */
Nick Pelly005b2282009-09-10 10:21:56 -0700191 public static final int STATE_ON = 12;
Nick Pellyde893f52009-09-08 13:15:33 -0700192 /**
193 * Indicates the local Bluetooth adapter is turning off. Local clients
194 * should immediately attempt graceful disconnection of any remote links.
195 */
Nick Pelly005b2282009-09-10 10:21:56 -0700196 public static final int STATE_TURNING_OFF = 13;
Nick Pellyde893f52009-09-08 13:15:33 -0700197
198 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800199 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
Jack Hea355e5e2017-08-22 16:06:54 -0700200 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800201 * @hide
202 */
203 public static final int STATE_BLE_TURNING_ON = 14;
204
205 /**
206 * Indicates the local Bluetooth adapter is in LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700207 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800208 * @hide
209 */
210 public static final int STATE_BLE_ON = 15;
211
212 /**
213 * Indicates the local Bluetooth adapter is turning off LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700214 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800215 * @hide
216 */
217 public static final int STATE_BLE_TURNING_OFF = 16;
218
219 /**
Stanley Tnge48468d2017-11-22 16:04:40 -0800220 * UUID of the GATT Read Characteristics for LE_PSM value.
221 *
222 * @hide
223 */
224 public static final UUID LE_PSM_CHARACTERISTIC_UUID =
225 UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
226
227 /**
Marie Janssencb21ad72016-12-13 10:51:02 -0800228 * Human-readable string helper for AdapterState
Jack Hea355e5e2017-08-22 16:06:54 -0700229 *
Marie Janssencb21ad72016-12-13 10:51:02 -0800230 * @hide
231 */
232 public static String nameForState(@AdapterState int state) {
Jack Hea355e5e2017-08-22 16:06:54 -0700233 switch (state) {
234 case STATE_OFF:
235 return "OFF";
236 case STATE_TURNING_ON:
237 return "TURNING_ON";
238 case STATE_ON:
239 return "ON";
240 case STATE_TURNING_OFF:
241 return "TURNING_OFF";
242 case STATE_BLE_TURNING_ON:
243 return "BLE_TURNING_ON";
244 case STATE_BLE_ON:
245 return "BLE_ON";
246 case STATE_BLE_TURNING_OFF:
247 return "BLE_TURNING_OFF";
248 default:
249 return "?!?!? (" + state + ")";
Marie Janssencb21ad72016-12-13 10:51:02 -0800250 }
251 }
252
253 /**
Nick Pelly18b1e792009-09-24 11:14:15 -0700254 * Activity Action: Show a system activity that requests discoverable mode.
Scott Main6d95fc02009-11-19 17:00:19 -0800255 * This activity will also request the user to turn on Bluetooth if it
Nick Pelly1acdcc12009-09-28 10:33:55 -0700256 * is not currently enabled.
Nick Pelly18b1e792009-09-24 11:14:15 -0700257 * <p>Discoverable mode is equivalent to {@link
258 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
259 * this Bluetooth adapter when they perform a discovery.
Scott Main6d95fc02009-11-19 17:00:19 -0800260 * <p>For privacy, Android is not discoverable by default.
261 * <p>The sender of this Intent can optionally use extra field {@link
Nick Pelly18b1e792009-09-24 11:14:15 -0700262 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
263 * discoverability. Currently the default duration is 120 seconds, and
264 * maximum duration is capped at 300 seconds for each request.
265 * <p>Notification of the result of this activity is posted using the
266 * {@link android.app.Activity#onActivityResult} callback. The
267 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800268 * will be the duration (in seconds) of discoverability or
269 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
270 * discoverability or an error has occurred.
Nick Pelly18b1e792009-09-24 11:14:15 -0700271 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
Scott Main6d95fc02009-11-19 17:00:19 -0800272 * for global notification whenever the scan mode changes. For example, an
273 * application can be notified when the device has ended discoverability.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700274 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pelly18b1e792009-09-24 11:14:15 -0700275 */
Myles Watson125b5452017-11-27 16:41:47 -0800276 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
277 ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
Nick Pelly18b1e792009-09-24 11:14:15 -0700278
279 /**
280 * Used as an optional int extra field in {@link
281 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
282 * for discoverability in seconds. The current default is 120 seconds, and
283 * requests over 300 seconds will be capped. These values could change.
284 */
285 public static final String EXTRA_DISCOVERABLE_DURATION =
286 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
287
288 /**
Nick Pelly1acdcc12009-09-28 10:33:55 -0700289 * Activity Action: Show a system activity that allows the user to turn on
290 * Bluetooth.
291 * <p>This system activity will return once Bluetooth has completed turning
292 * on, or the user has decided not to turn Bluetooth on.
293 * <p>Notification of the result of this activity is posted using the
294 * {@link android.app.Activity#onActivityResult} callback. The
295 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800296 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
297 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
298 * has rejected the request or an error has occurred.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700299 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
300 * for global notification whenever Bluetooth is turned on or off.
301 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
302 */
Myles Watson125b5452017-11-27 16:41:47 -0800303 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
304 ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
Nick Pelly1acdcc12009-09-28 10:33:55 -0700305
306 /**
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700307 * Activity Action: Show a system activity that allows the user to turn off
308 * Bluetooth. This is used only if permission review is enabled which is for
309 * apps targeting API less than 23 require a permission review before any of
310 * the app's components can run.
311 * <p>This system activity will return once Bluetooth has completed turning
312 * off, or the user has decided not to turn Bluetooth off.
313 * <p>Notification of the result of this activity is posted using the
314 * {@link android.app.Activity#onActivityResult} callback. The
315 * <code>resultCode</code>
316 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
317 * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
318 * has rejected the request or an error has occurred.
319 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
320 * for global notification whenever Bluetooth is turned on or off.
321 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
322 *
323 * @hide
324 */
Myles Watson125b5452017-11-27 16:41:47 -0800325 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
326 ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE";
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700327
328 /**
Wei Wangd91f1932015-03-19 15:09:56 -0700329 * Activity Action: Show a system activity that allows user to enable BLE scans even when
330 * Bluetooth is turned off.<p>
331 *
332 * Notification of result of this activity is posted using
333 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
334 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
335 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
336 * error occurred.
337 *
338 * @hide
339 */
340 @SystemApi
341 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
342 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
343 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
344
345 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700346 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
347 * has changed.
Nick Pelly005b2282009-09-10 10:21:56 -0700348 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700349 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
350 * respectively.
351 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
352 */
Myles Watson125b5452017-11-27 16:41:47 -0800353 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
354 ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
Nick Pellyde893f52009-09-08 13:15:33 -0700355
356 /**
357 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
358 * intents to request the current scan mode. Possible values are:
359 * {@link #SCAN_MODE_NONE},
360 * {@link #SCAN_MODE_CONNECTABLE},
361 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
362 */
Nick Pelly005b2282009-09-10 10:21:56 -0700363 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700364 /**
365 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
366 * intents to request the previous scan mode. Possible values are:
367 * {@link #SCAN_MODE_NONE},
368 * {@link #SCAN_MODE_CONNECTABLE},
369 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
370 */
371 public static final String EXTRA_PREVIOUS_SCAN_MODE =
Nick Pelly005b2282009-09-10 10:21:56 -0700372 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700373
Tor Norbye2d497522015-04-23 17:10:21 -0700374 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700375 @IntDef(prefix = { "SCAN_" }, value = {
376 SCAN_MODE_NONE,
377 SCAN_MODE_CONNECTABLE,
378 SCAN_MODE_CONNECTABLE_DISCOVERABLE
379 })
Tor Norbye2d497522015-04-23 17:10:21 -0700380 @Retention(RetentionPolicy.SOURCE)
Myles Watson125b5452017-11-27 16:41:47 -0800381 public @interface ScanMode {}
Tor Norbye2d497522015-04-23 17:10:21 -0700382
Nick Pellyde893f52009-09-08 13:15:33 -0700383 /**
384 * Indicates that both inquiry scan and page scan are disabled on the local
385 * Bluetooth adapter. Therefore this device is neither discoverable
386 * nor connectable from remote Bluetooth devices.
387 */
Nick Pelly005b2282009-09-10 10:21:56 -0700388 public static final int SCAN_MODE_NONE = 20;
Nick Pellyde893f52009-09-08 13:15:33 -0700389 /**
390 * Indicates that inquiry scan is disabled, but page scan is enabled on the
391 * local Bluetooth adapter. Therefore this device is not discoverable from
392 * remote Bluetooth devices, but is connectable from remote devices that
393 * have previously discovered this device.
394 */
Nick Pelly005b2282009-09-10 10:21:56 -0700395 public static final int SCAN_MODE_CONNECTABLE = 21;
Nick Pellyde893f52009-09-08 13:15:33 -0700396 /**
397 * Indicates that both inquiry scan and page scan are enabled on the local
398 * Bluetooth adapter. Therefore this device is both discoverable and
399 * connectable from remote Bluetooth devices.
400 */
Nick Pelly005b2282009-09-10 10:21:56 -0700401 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
Nick Pellybd022f42009-08-14 18:33:38 -0700402
Nick Pelly005b2282009-09-10 10:21:56 -0700403 /**
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -0700404 * Device only has a display.
405 *
406 * @hide
407 */
408 public static final int IO_CAPABILITY_OUT = 0;
409
410 /**
411 * Device has a display and the ability to input Yes/No.
412 *
413 * @hide
414 */
415 public static final int IO_CAPABILITY_IO = 1;
416
417 /**
418 * Device only has a keyboard for entry but no display.
419 *
420 * @hide
421 */
422 public static final int IO_CAPABILITY_IN = 2;
423
424 /**
425 * Device has no Input or Output capability.
426 *
427 * @hide
428 */
429 public static final int IO_CAPABILITY_NONE = 3;
430
431 /**
432 * Device has a display and a full keyboard.
433 *
434 * @hide
435 */
436 public static final int IO_CAPABILITY_KBDISP = 4;
437
438 /**
439 * Maximum range value for Input/Output capabilities.
440 *
441 * <p>This should be updated when adding a new Input/Output capability. Other code
442 * like validation depends on this being accurate.
443 *
444 * @hide
445 */
446 public static final int IO_CAPABILITY_MAX = 5;
447
448 /**
449 * The Input/Output capability of the device is unknown.
450 *
451 * @hide
452 */
453 public static final int IO_CAPABILITY_UNKNOWN = 255;
454
Pulkit Bhuwalka80238142018-04-20 16:56:53 -0700455 /** @hide */
456 @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE,
457 IO_CAPABILITY_KBDISP})
458 @Retention(RetentionPolicy.SOURCE)
459 public @interface IoCapability {}
460
Rahul Sabnisc4526972019-11-25 11:16:10 -0800461 /** @hide */
462 @IntDef(prefix = "ACTIVE_DEVICE_", value = {ACTIVE_DEVICE_AUDIO,
463 ACTIVE_DEVICE_PHONE_CALL, ACTIVE_DEVICE_ALL})
464 @Retention(RetentionPolicy.SOURCE)
465 public @interface ActiveDeviceUse {}
466
467 /**
468 * Use the specified device for audio (a2dp and hearing aid profile)
469 *
470 * @hide
471 */
472 @SystemApi
473 public static final int ACTIVE_DEVICE_AUDIO = 0;
474
475 /**
476 * Use the specified device for phone calls (headset profile and hearing
477 * aid profile)
478 *
479 * @hide
480 */
481 @SystemApi
482 public static final int ACTIVE_DEVICE_PHONE_CALL = 1;
483
484 /**
485 * Use the specified device for a2dp, hearing aid profile, and headset profile
486 *
487 * @hide
488 */
489 @SystemApi
490 public static final int ACTIVE_DEVICE_ALL = 2;
491
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -0700492 /**
Nick Pelly005b2282009-09-10 10:21:56 -0700493 * Broadcast Action: The local Bluetooth adapter has started the remote
494 * device discovery process.
495 * <p>This usually involves an inquiry scan of about 12 seconds, followed
496 * by a page scan of each new device to retrieve its Bluetooth name.
497 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
498 * remote Bluetooth devices are found.
499 * <p>Device discovery is a heavyweight procedure. New connections to
500 * remote Bluetooth devices should not be attempted while discovery is in
501 * progress, and existing connections will experience limited bandwidth
502 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
503 * discovery.
504 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
505 */
Myles Watson125b5452017-11-27 16:41:47 -0800506 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
507 ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
Nick Pelly005b2282009-09-10 10:21:56 -0700508 /**
509 * Broadcast Action: The local Bluetooth adapter has finished the device
510 * discovery process.
511 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
512 */
Myles Watson125b5452017-11-27 16:41:47 -0800513 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
514 ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
Nick Pelly005b2282009-09-10 10:21:56 -0700515
516 /**
517 * Broadcast Action: The local Bluetooth adapter has changed its friendly
518 * Bluetooth name.
519 * <p>This name is visible to remote Bluetooth devices.
520 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
521 * the name.
522 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
523 */
Myles Watson125b5452017-11-27 16:41:47 -0800524 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
525 ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
Nick Pelly005b2282009-09-10 10:21:56 -0700526 /**
527 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
528 * intents to request the local Bluetooth name.
529 */
530 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
531
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700532 /**
533 * Intent used to broadcast the change in connection state of the local
534 * Bluetooth adapter to a profile of the remote device. When the adapter is
535 * not connected to any profiles of any remote devices and it attempts a
Ricardo Loo Forondaf710a232018-01-24 17:49:18 -0800536 * connection to a profile this intent will be sent. Once connected, this intent
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700537 * will not be sent for any more connection attempts to any profiles of any
538 * remote device. When the adapter disconnects from the last profile its
539 * connected to of any remote device, this intent will be sent.
540 *
541 * <p> This intent is useful for applications that are only concerned about
542 * whether the local adapter is connected to any profile of any device and
543 * are not really concerned about which profile. For example, an application
544 * which displays an icon to display whether Bluetooth is connected or not
545 * can use this intent.
546 *
547 * <p>This intent will have 3 extras:
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800548 * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
549 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700550 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
551 *
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800552 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
553 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700554 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
555 *
556 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
557 */
Myles Watson125b5452017-11-27 16:41:47 -0800558 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
559 ACTION_CONNECTION_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700560 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700561
562 /**
563 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
564 *
565 * This extra represents the current connection state.
566 */
567 public static final String EXTRA_CONNECTION_STATE =
Jack Hea355e5e2017-08-22 16:06:54 -0700568 "android.bluetooth.adapter.extra.CONNECTION_STATE";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700569
570 /**
571 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
572 *
573 * This extra represents the previous connection state.
574 */
575 public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
Jack Hea355e5e2017-08-22 16:06:54 -0700576 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700577
Nitin Arorad055adb2015-03-02 15:03:51 -0800578 /**
579 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700580 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800581 * @hide
582 */
Myles Watson125b5452017-11-27 16:41:47 -0800583 @SystemApi public static final String ACTION_BLE_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700584 "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800585
586 /**
Stanley Tngdd749b02017-04-17 22:35:45 -0700587 * Intent used to broadcast the change in the Bluetooth address
588 * of the local Bluetooth adapter.
589 * <p>Always contains the extra field {@link
590 * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
591 *
592 * Note: only system level processes are allowed to send this
593 * defined broadcast.
594 *
595 * @hide
596 */
597 public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700598 "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
Stanley Tngdd749b02017-04-17 22:35:45 -0700599
600 /**
601 * Used as a String extra field in {@link
602 * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
603 * Bluetooth address.
604 *
605 * @hide
606 */
607 public static final String EXTRA_BLUETOOTH_ADDRESS =
Jack Hea355e5e2017-08-22 16:06:54 -0700608 "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
Stanley Tngdd749b02017-04-17 22:35:45 -0700609
610 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800611 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
612 * by BLE Always on enabled application to know the ACL_CONNECTED event
613 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
614 * as Bluetooth LE is the only feature available in STATE_BLE_ON
615 *
616 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
617 * works in Bluetooth state STATE_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700618 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800619 * @hide
620 */
621 public static final String ACTION_BLE_ACL_CONNECTED =
Jack Hea355e5e2017-08-22 16:06:54 -0700622 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800623
624 /**
625 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
626 * by BLE Always on enabled application to know the ACL_DISCONNECTED event
627 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
628 * LE is the only feature available in STATE_BLE_ON
629 *
630 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
631 * works in Bluetooth state STATE_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700632 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800633 * @hide
634 */
635 public static final String ACTION_BLE_ACL_DISCONNECTED =
Jack Hea355e5e2017-08-22 16:06:54 -0700636 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800637
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700638 /** The profile is in disconnected state */
Jack Hebd020a62018-03-02 13:11:27 -0800639 public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700640 /** The profile is in connecting state */
Jack Hebd020a62018-03-02 13:11:27 -0800641 public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700642 /** The profile is in connected state */
Jack Hebd020a62018-03-02 13:11:27 -0800643 public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700644 /** The profile is in disconnecting state */
Jack Hebd020a62018-03-02 13:11:27 -0800645 public static final int STATE_DISCONNECTING =
646 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700647
Nick Pellyf242b7b2009-10-08 00:12:45 +0200648 /** @hide */
fredc0f420372012-04-12 00:02:00 -0700649 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
Nitin Arorad055adb2015-03-02 15:03:51 -0800650 private final IBinder mToken;
Nick Pellyf242b7b2009-10-08 00:12:45 +0200651
Casper Bonde238e0f92015-04-09 09:24:48 +0200652
Jack Hea355e5e2017-08-22 16:06:54 -0700653 /**
654 * When creating a ServerSocket using listenUsingRfcommOn() or
655 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
656 * a ServerSocket that auto assigns a channel number to the first
657 * bluetooth socket.
658 * The channel number assigned to this first Bluetooth Socket will
659 * be stored in the ServerSocket, and reused for subsequent Bluetooth
660 * sockets.
661 *
662 * @hide
663 */
Casper Bonde238e0f92015-04-09 09:24:48 +0200664 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
665
666
Nick Pelly005b2282009-09-10 10:21:56 -0700667 private static final int ADDRESS_LENGTH = 17;
Nick Pellybd022f42009-08-14 18:33:38 -0700668
Nick Pellyf242b7b2009-10-08 00:12:45 +0200669 /**
Jake Hambyf51eada2010-09-21 13:39:53 -0700670 * Lazily initialized singleton. Guaranteed final after first object
Nick Pellyf242b7b2009-10-08 00:12:45 +0200671 * constructed.
672 */
673 private static BluetoothAdapter sAdapter;
674
Wei Wangc3059cc2014-07-23 23:34:00 -0700675 private static BluetoothLeScanner sBluetoothLeScanner;
676 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800677 private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
Wei Wangc3059cc2014-07-23 23:34:00 -0700678
fredc0f420372012-04-12 00:02:00 -0700679 private final IBluetoothManager mManagerService;
Mathew Inwood4dc66d32018-08-01 15:07:20 +0100680 @UnsupportedAppUsage
fredc0f420372012-04-12 00:02:00 -0700681 private IBluetooth mService;
Zach Johnson57e6e902018-12-12 17:11:25 -0800682 private Context mContext;
Myles Watson125b5452017-11-27 16:41:47 -0800683 private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
Nick Pellybd022f42009-08-14 18:33:38 -0700684
Wei Wangf3055892014-03-11 22:22:41 -0700685 private final Object mLock = new Object();
Wei Wangc3059cc2014-07-23 23:34:00 -0700686 private final Map<LeScanCallback, ScanCallback> mLeScanClients;
Ugo Yu50e3c082019-03-05 16:20:27 +0800687 private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
Ugo Yu4a33b882019-01-08 09:00:09 +0800688 sMetadataListeners = new HashMap<>();
689
690 /**
691 * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
692 * implementation.
693 */
694 private static final IBluetoothMetadataListener sBluetoothMetadataListener =
695 new IBluetoothMetadataListener.Stub() {
696 @Override
Ugo Yu50e3c082019-03-05 16:20:27 +0800697 public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) {
Ugo Yu4a33b882019-01-08 09:00:09 +0800698 synchronized (sMetadataListeners) {
699 if (sMetadataListeners.containsKey(device)) {
Ugo Yu50e3c082019-03-05 16:20:27 +0800700 List<Pair<OnMetadataChangedListener, Executor>> list =
701 sMetadataListeners.get(device);
702 for (Pair<OnMetadataChangedListener, Executor> pair : list) {
703 OnMetadataChangedListener listener = pair.first;
704 Executor executor = pair.second;
705 executor.execute(() -> {
Ugo Yu4a33b882019-01-08 09:00:09 +0800706 listener.onMetadataChanged(device, key, value);
707 });
708 }
709 }
710 }
711 return;
712 }
713 };
Matthew Xie484867a2011-08-25 16:45:58 -0700714
Nick Pellybd022f42009-08-14 18:33:38 -0700715 /**
Nick Pellyf242b7b2009-10-08 00:12:45 +0200716 * Get a handle to the default local Bluetooth adapter.
717 * <p>Currently Android only supports one Bluetooth adapter, but the API
718 * could be extended to support more. This will always return the default
719 * adapter.
Marie Janssen553c8c72017-01-12 16:00:30 -0800720 * </p>
Jack Hea355e5e2017-08-22 16:06:54 -0700721 *
722 * @return the default local adapter, or null if Bluetooth is not supported on this hardware
723 * platform
Nick Pellyf242b7b2009-10-08 00:12:45 +0200724 */
725 public static synchronized BluetoothAdapter getDefaultAdapter() {
726 if (sAdapter == null) {
fredc0f420372012-04-12 00:02:00 -0700727 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200728 if (b != null) {
fredc0f420372012-04-12 00:02:00 -0700729 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
730 sAdapter = new BluetoothAdapter(managerService);
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -0800731 } else {
732 Log.e(TAG, "Bluetooth binder is null");
Nick Pellyf242b7b2009-10-08 00:12:45 +0200733 }
734 }
735 return sAdapter;
736 }
737
738 /**
739 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
Nick Pellybd022f42009-08-14 18:33:38 -0700740 */
fredc0f420372012-04-12 00:02:00 -0700741 BluetoothAdapter(IBluetoothManager managerService) {
742
743 if (managerService == null) {
744 throw new IllegalArgumentException("bluetooth manager service is null");
Nick Pellybd022f42009-08-14 18:33:38 -0700745 }
fredc0f420372012-04-12 00:02:00 -0700746 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700747 mServiceLock.writeLock().lock();
fredc0f420372012-04-12 00:02:00 -0700748 mService = managerService.registerAdapter(mManagerCallback);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700749 } catch (RemoteException e) {
750 Log.e(TAG, "", e);
751 } finally {
752 mServiceLock.writeLock().unlock();
753 }
fredc0f420372012-04-12 00:02:00 -0700754 mManagerService = managerService;
Wei Wangc3059cc2014-07-23 23:34:00 -0700755 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
Nitin Arorad055adb2015-03-02 15:03:51 -0800756 mToken = new Binder();
Nick Pellybd022f42009-08-14 18:33:38 -0700757 }
758
759 /**
Nick Pelly45e27042009-08-19 11:00:00 -0700760 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
761 * address.
762 * <p>Valid Bluetooth hardware addresses must be upper case, in a format
Nick Pelly005b2282009-09-10 10:21:56 -0700763 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
764 * available to validate a Bluetooth address.
Nick Pelly45e27042009-08-19 11:00:00 -0700765 * <p>A {@link BluetoothDevice} will always be returned for a valid
766 * hardware address, even if this adapter has never seen that device.
Nick Pellyde893f52009-09-08 13:15:33 -0700767 *
Nick Pellybd022f42009-08-14 18:33:38 -0700768 * @param address valid Bluetooth MAC address
Nick Pelly45e27042009-08-19 11:00:00 -0700769 * @throws IllegalArgumentException if address is invalid
Nick Pellybd022f42009-08-14 18:33:38 -0700770 */
771 public BluetoothDevice getRemoteDevice(String address) {
772 return new BluetoothDevice(address);
773 }
774
775 /**
Nick Pelly75596b42011-12-07 15:03:55 -0800776 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
777 * address.
778 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
779 * expects the address in network byte order (MSB first).
780 * <p>A {@link BluetoothDevice} will always be returned for a valid
781 * hardware address, even if this adapter has never seen that device.
782 *
783 * @param address Bluetooth MAC address (6 bytes)
784 * @throws IllegalArgumentException if address is invalid
785 */
786 public BluetoothDevice getRemoteDevice(byte[] address) {
787 if (address == null || address.length != 6) {
788 throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
789 }
Myles Watson125b5452017-11-27 16:41:47 -0800790 return new BluetoothDevice(
791 String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1],
792 address[2], address[3], address[4], address[5]));
Nick Pelly75596b42011-12-07 15:03:55 -0800793 }
794
795 /**
Prerepa Viswanadham248edc32014-10-15 16:36:01 -0700796 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
797 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
798 * supported on this device.
Wei Wangc3059cc2014-07-23 23:34:00 -0700799 * <p>
800 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
801 * on this device before calling this method.
Wei Wangadf6aff2014-05-20 06:30:20 +0000802 */
803 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
Myles Watson125b5452017-11-27 16:41:47 -0800804 if (!getLeAccess()) {
805 return null;
806 }
Jack Hea355e5e2017-08-22 16:06:54 -0700807 synchronized (mLock) {
Wei Wangc3059cc2014-07-23 23:34:00 -0700808 if (sBluetoothLeAdvertiser == null) {
809 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
810 }
811 }
812 return sBluetoothLeAdvertiser;
Wei Wangadf6aff2014-05-20 06:30:20 +0000813 }
814
815 /**
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800816 * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
817 * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
818 * Advertising is not supported on this device.
819 * <p>
820 * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
821 * supported on this device before calling this method.
Jack Hea355e5e2017-08-22 16:06:54 -0700822 *
Jakub Pawlowskia537b3f2017-03-29 17:00:44 -0700823 * @hide
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800824 */
825 public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
Jack Hea355e5e2017-08-22 16:06:54 -0700826 if (!getLeAccess()) {
827 return null;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800828 }
Jack Hea355e5e2017-08-22 16:06:54 -0700829
830 if (!isLePeriodicAdvertisingSupported()) {
831 return null;
832 }
833
834 synchronized (mLock) {
835 if (sPeriodicAdvertisingManager == null) {
Myles Watson125b5452017-11-27 16:41:47 -0800836 sPeriodicAdvertisingManager = new PeriodicAdvertisingManager(mManagerService);
Jack Hea355e5e2017-08-22 16:06:54 -0700837 }
838 }
839 return sPeriodicAdvertisingManager;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800840 }
841
842 /**
Wei Wangadf6aff2014-05-20 06:30:20 +0000843 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
844 */
845 public BluetoothLeScanner getBluetoothLeScanner() {
Myles Watson125b5452017-11-27 16:41:47 -0800846 if (!getLeAccess()) {
847 return null;
848 }
Jack Hea355e5e2017-08-22 16:06:54 -0700849 synchronized (mLock) {
Wei Wangc3059cc2014-07-23 23:34:00 -0700850 if (sBluetoothLeScanner == null) {
Philip P. Moltmann22209942019-11-15 12:41:09 -0800851 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService, getOpPackageName(),
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800852 getAttributionTag());
Wei Wangc3059cc2014-07-23 23:34:00 -0700853 }
854 }
855 return sBluetoothLeScanner;
Wei Wangadf6aff2014-05-20 06:30:20 +0000856 }
857
858 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700859 * Return true if Bluetooth is currently enabled and ready for use.
860 * <p>Equivalent to:
861 * <code>getBluetoothState() == STATE_ON</code>
Nick Pellybd022f42009-08-14 18:33:38 -0700862 *
Nick Pellyde893f52009-09-08 13:15:33 -0700863 * @return true if the local adapter is turned on
Nick Pellybd022f42009-08-14 18:33:38 -0700864 */
Tor Norbye2d497522015-04-23 17:10:21 -0700865 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -0700866 public boolean isEnabled() {
Zach Johnson76236d72019-11-26 21:30:07 -0800867 return getState() == BluetoothAdapter.STATE_ON;
Nick Pellybd022f42009-08-14 18:33:38 -0700868 }
869
870 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800871 * Return true if Bluetooth LE(Always BLE On feature) is currently
872 * enabled and ready for use
873 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
874 *
875 * @return true if the local Bluetooth LE adapter is turned on
876 * @hide
877 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700878 @SystemApi
879 public boolean isLeEnabled() {
Jack Hea355e5e2017-08-22 16:06:54 -0700880 final int state = getLeState();
Myles Watson125b5452017-11-27 16:41:47 -0800881 if (DBG) {
882 Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
883 }
Dan Harms2d7e1872019-08-06 09:18:02 -0700884 return (state == BluetoothAdapter.STATE_ON
885 || state == BluetoothAdapter.STATE_BLE_ON
886 || state == BluetoothAdapter.STATE_TURNING_ON
887 || state == BluetoothAdapter.STATE_TURNING_OFF);
Nitin Arorad055adb2015-03-02 15:03:51 -0800888 }
889
890 /**
Marie Janssen59804562016-12-28 14:13:21 -0800891 * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
Nitin Arorad055adb2015-03-02 15:03:51 -0800892 *
893 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
894 * to STATE_OFF and completely shut-down Bluetooth
895 *
896 * <p> If the Adapter state is STATE_ON, This would unregister the existance of
897 * special Bluetooth LE application and hence the further turning off of Bluetooth
898 * from UI would ensure the complete turn-off of Bluetooth rather than staying back
899 * BLE only state
900 *
901 * <p>This is an asynchronous call: it will return immediately, and
902 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
903 * to be notified of subsequent adapter state changes If this call returns
904 * true, then the adapter state will immediately transition from {@link
905 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
906 * later transition to either {@link #STATE_BLE_ON} or {@link
907 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
908 * If this call returns false then there was an
909 * immediate problem that will prevent the QAdapter from being turned off -
910 * such as the QAadapter already being turned off.
911 *
Jack Hea355e5e2017-08-22 16:06:54 -0700912 * @return true to indicate success, or false on immediate error
Nitin Arorad055adb2015-03-02 15:03:51 -0800913 * @hide
914 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700915 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800916 public boolean disableBLE() {
Myles Watson125b5452017-11-27 16:41:47 -0800917 if (!isBleScanAlwaysAvailable()) {
918 return false;
919 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800920
921 int state = getLeState();
Marie Janssen59804562016-12-28 14:13:21 -0800922 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
923 String packageName = ActivityThread.currentPackageName();
Myles Watson125b5452017-11-27 16:41:47 -0800924 if (DBG) {
925 Log.d(TAG, "disableBLE(): de-registering " + packageName);
926 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800927 try {
Marie Janssen59804562016-12-28 14:13:21 -0800928 mManagerService.updateBleAppCount(mToken, false, packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800929 } catch (RemoteException e) {
930 Log.e(TAG, "", e);
931 }
932 return true;
Nitin Arorad055adb2015-03-02 15:03:51 -0800933 }
934
Myles Watson125b5452017-11-27 16:41:47 -0800935 if (DBG) {
936 Log.d(TAG, "disableBLE(): Already disabled");
937 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800938 return false;
939 }
940
941 /**
Marie Janssen59804562016-12-28 14:13:21 -0800942 * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
Nitin Arorad055adb2015-03-02 15:03:51 -0800943 *
Marie Janssen59804562016-12-28 14:13:21 -0800944 * enableBLE registers the existence of an app using only LE functions.
945 *
946 * enableBLE may enable Bluetooth to an LE only mode so that an app can use
947 * LE related features (BluetoothGatt or BluetoothGattServer classes)
948 *
949 * If the user disables Bluetooth while an app is registered to use LE only features,
950 * Bluetooth will remain on in LE only mode for the app.
951 *
952 * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
953 *
954 * <p>This is an asynchronous call: it returns immediately, and
Nitin Arorad055adb2015-03-02 15:03:51 -0800955 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
Marie Janssen59804562016-12-28 14:13:21 -0800956 * to be notified of adapter state changes.
957 *
958 * If this call returns * true, then the adapter state is either in a mode where
959 * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
960 * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
961 *
962 * If this call returns false then there was an immediate problem that prevents the
963 * adapter from being turned on - such as Airplane mode.
964 *
965 * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
Nitin Arorad055adb2015-03-02 15:03:51 -0800966 * states, It includes all the classic Bluetooth Adapter states along with
967 * internal BLE only states
968 *
Jack Hea355e5e2017-08-22 16:06:54 -0700969 * @return true to indicate Bluetooth LE will be available, or false on immediate error
Nitin Arorad055adb2015-03-02 15:03:51 -0800970 * @hide
971 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700972 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800973 public boolean enableBLE() {
Myles Watson125b5452017-11-27 16:41:47 -0800974 if (!isBleScanAlwaysAvailable()) {
975 return false;
976 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800977
Nitin Arorad055adb2015-03-02 15:03:51 -0800978 try {
Marie Janssen59804562016-12-28 14:13:21 -0800979 String packageName = ActivityThread.currentPackageName();
980 mManagerService.updateBleAppCount(mToken, true, packageName);
Marie Janssen6a383a72016-10-25 10:47:51 -0700981 if (isLeEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -0800982 if (DBG) {
983 Log.d(TAG, "enableBLE(): Bluetooth already enabled");
984 }
Marie Janssen6a383a72016-10-25 10:47:51 -0700985 return true;
986 }
Myles Watson125b5452017-11-27 16:41:47 -0800987 if (DBG) {
988 Log.d(TAG, "enableBLE(): Calling enable");
989 }
Marie Janssen59804562016-12-28 14:13:21 -0800990 return mManagerService.enable(packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800991 } catch (RemoteException e) {
992 Log.e(TAG, "", e);
993 }
994
995 return false;
996 }
997
Lee Shombert38265342019-12-30 10:57:12 -0800998 private static final String BLUETOOTH_GET_STATE_CACHE_PROPERTY = "cache_key.bluetooth.get_state";
999
1000 private final PropertyInvalidatedCache<Void, Integer> mBluetoothGetStateCache =
1001 new PropertyInvalidatedCache<Void, Integer>(
1002 8, BLUETOOTH_GET_STATE_CACHE_PROPERTY) {
1003 @Override
1004 protected Integer recompute(Void query) {
1005 try {
1006 mServiceLock.readLock().lock();
1007 if (mService != null) {
1008 return mService.getState();
1009 }
1010 } catch (RemoteException e) {
1011 Log.e(TAG, "", e);
1012 } finally {
1013 mServiceLock.readLock().unlock();
1014 }
1015 return BluetoothAdapter.STATE_OFF;
1016 }
1017 };
1018
1019 /** @hide */
1020 public void disableBluetoothGetStateCache() {
1021 mBluetoothGetStateCache.disableLocal();
1022 }
1023
1024 /** @hide */
1025 public static void invalidateBluetoothGetStateCache() {
1026 PropertyInvalidatedCache.invalidateCache(BLUETOOTH_GET_STATE_CACHE_PROPERTY);
1027 }
1028
Nitin Arorad055adb2015-03-02 15:03:51 -08001029 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001030 * Get the current state of the local Bluetooth adapter.
1031 * <p>Possible return values are
1032 * {@link #STATE_OFF},
1033 * {@link #STATE_TURNING_ON},
1034 * {@link #STATE_ON},
1035 * {@link #STATE_TURNING_OFF}.
Nick Pellybd022f42009-08-14 18:33:38 -07001036 *
Nick Pellyde893f52009-09-08 13:15:33 -07001037 * @return current state of Bluetooth adapter
Nick Pellybd022f42009-08-14 18:33:38 -07001038 */
Tor Norbye2d497522015-04-23 17:10:21 -07001039 @RequiresPermission(Manifest.permission.BLUETOOTH)
1040 @AdapterState
Nick Pellyde893f52009-09-08 13:15:33 -07001041 public int getState() {
Lee Shombert38265342019-12-30 10:57:12 -08001042 int state = mBluetoothGetStateCache.query(null);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001043
1044 // Consider all internal states as OFF
Myles Watson125b5452017-11-27 16:41:47 -08001045 if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON
Jack Hea355e5e2017-08-22 16:06:54 -07001046 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
1047 if (VDBG) {
Myles Watson125b5452017-11-27 16:41:47 -08001048 Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
Jack Hea355e5e2017-08-22 16:06:54 -07001049 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001050 state = BluetoothAdapter.STATE_OFF;
1051 }
Jack Hea355e5e2017-08-22 16:06:54 -07001052 if (VDBG) {
Myles Watson125b5452017-11-27 16:41:47 -08001053 Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(
1054 state));
Jack Hea355e5e2017-08-22 16:06:54 -07001055 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001056 return state;
Nick Pellybd022f42009-08-14 18:33:38 -07001057 }
1058
1059 /**
Nitin Arorad055adb2015-03-02 15:03:51 -08001060 * Get the current state of the local Bluetooth adapter
1061 * <p>This returns current internal state of Adapter including LE ON/OFF
1062 *
1063 * <p>Possible return values are
1064 * {@link #STATE_OFF},
1065 * {@link #STATE_BLE_TURNING_ON},
1066 * {@link #STATE_BLE_ON},
1067 * {@link #STATE_TURNING_ON},
1068 * {@link #STATE_ON},
1069 * {@link #STATE_TURNING_OFF},
1070 * {@link #STATE_BLE_TURNING_OFF}.
Nitin Arorad055adb2015-03-02 15:03:51 -08001071 *
1072 * @return current state of Bluetooth adapter
1073 * @hide
1074 */
Tor Norbye2d497522015-04-23 17:10:21 -07001075 @RequiresPermission(Manifest.permission.BLUETOOTH)
1076 @AdapterState
Andrei Oneaf950c082019-06-17 11:26:14 +01001077 @UnsupportedAppUsage(publicAlternatives = "Use {@link #getState()} instead to determine "
1078 + "whether you can use BLE & BT classic.")
Nitin Arorad055adb2015-03-02 15:03:51 -08001079 public int getLeState() {
Lee Shombert38265342019-12-30 10:57:12 -08001080 int state = mBluetoothGetStateCache.query(null);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001081
Myles Watson125b5452017-11-27 16:41:47 -08001082 if (VDBG) {
1083 Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state));
1084 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001085 return state;
Nitin Arorad055adb2015-03-02 15:03:51 -08001086 }
1087
1088 boolean getLeAccess() {
Jack Hea355e5e2017-08-22 16:06:54 -07001089 if (getLeState() == STATE_ON) {
Nitin Arorad055adb2015-03-02 15:03:51 -08001090 return true;
Jack Hea355e5e2017-08-22 16:06:54 -07001091 } else if (getLeState() == STATE_BLE_ON) {
Nitin Arorad055adb2015-03-02 15:03:51 -08001092 return true; // TODO: FILTER SYSTEM APPS HERE <--
Jack Hea355e5e2017-08-22 16:06:54 -07001093 }
Nitin Arorad055adb2015-03-02 15:03:51 -08001094
1095 return false;
1096 }
1097
1098 /**
Scott Mained2a70d2009-12-09 16:07:39 -08001099 * Turn on the local Bluetooth adapter&mdash;do not use without explicit
1100 * user action to turn on Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -07001101 * <p>This powers on the underlying Bluetooth hardware, and starts all
1102 * Bluetooth system services.
Scott Mained2a70d2009-12-09 16:07:39 -08001103 * <p class="caution"><strong>Bluetooth should never be enabled without
1104 * direct user consent</strong>. If you want to turn on Bluetooth in order
1105 * to create a wireless connection, you should use the {@link
1106 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
1107 * user permission to turn on Bluetooth. The {@link #enable()} method is
1108 * provided only for applications that include a user interface for changing
1109 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +04001110 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -07001111 * clients should listen for {@link #ACTION_STATE_CHANGED}
1112 * to be notified of subsequent adapter state changes. If this call returns
1113 * true, then the adapter state will immediately transition from {@link
1114 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
1115 * later transition to either {@link #STATE_OFF} or {@link
1116 * #STATE_ON}. If this call returns false then there was an
1117 * immediate problem that will prevent the adapter from being turned on -
1118 * such as Airplane mode, or the adapter is already turned on.
Nick Pellyde893f52009-09-08 13:15:33 -07001119 *
Jack Hea355e5e2017-08-22 16:06:54 -07001120 * @return true to indicate adapter startup has begun, or false on immediate error
Nick Pellybd022f42009-08-14 18:33:38 -07001121 */
Tor Norbye2d497522015-04-23 17:10:21 -07001122 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001123 public boolean enable() {
Marie Janssencb21ad72016-12-13 10:51:02 -08001124 if (isEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -08001125 if (DBG) {
1126 Log.d(TAG, "enable(): BT already enabled!");
1127 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07001128 return true;
1129 }
Nick Pellybd022f42009-08-14 18:33:38 -07001130 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001131 return mManagerService.enable(ActivityThread.currentPackageName());
Jack Hea355e5e2017-08-22 16:06:54 -07001132 } catch (RemoteException e) {
1133 Log.e(TAG, "", e);
1134 }
Nick Pellybd022f42009-08-14 18:33:38 -07001135 return false;
1136 }
1137
1138 /**
Scott Mained2a70d2009-12-09 16:07:39 -08001139 * Turn off the local Bluetooth adapter&mdash;do not use without explicit
1140 * user action to turn off Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -07001141 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
1142 * system services, and powers down the underlying Bluetooth hardware.
Jake Hambyf51eada2010-09-21 13:39:53 -07001143 * <p class="caution"><strong>Bluetooth should never be disabled without
Scott Mained2a70d2009-12-09 16:07:39 -08001144 * direct user consent</strong>. The {@link #disable()} method is
1145 * provided only for applications that include a user interface for changing
1146 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +04001147 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -07001148 * clients should listen for {@link #ACTION_STATE_CHANGED}
1149 * to be notified of subsequent adapter state changes. If this call returns
1150 * true, then the adapter state will immediately transition from {@link
1151 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
1152 * later transition to either {@link #STATE_OFF} or {@link
1153 * #STATE_ON}. If this call returns false then there was an
1154 * immediate problem that will prevent the adapter from being turned off -
1155 * such as the adapter already being turned off.
Nick Pellybd022f42009-08-14 18:33:38 -07001156 *
Jack Hea355e5e2017-08-22 16:06:54 -07001157 * @return true to indicate adapter shutdown has begun, or false on immediate error
Nick Pellybd022f42009-08-14 18:33:38 -07001158 */
Tor Norbye2d497522015-04-23 17:10:21 -07001159 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001160 public boolean disable() {
1161 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001162 return mManagerService.disable(ActivityThread.currentPackageName(), true);
Jack Hea355e5e2017-08-22 16:06:54 -07001163 } catch (RemoteException e) {
1164 Log.e(TAG, "", e);
1165 }
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001166 return false;
1167 }
1168
1169 /**
1170 * Turn off the local Bluetooth adapter and don't persist the setting.
1171 *
1172 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1173 * permission
1174 *
Jack Hea355e5e2017-08-22 16:06:54 -07001175 * @return true to indicate adapter shutdown has begun, or false on immediate error
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001176 * @hide
1177 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001178 @UnsupportedAppUsage
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001179 public boolean disable(boolean persist) {
fredc0f420372012-04-12 00:02:00 -07001180
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001181 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001182 return mManagerService.disable(ActivityThread.currentPackageName(), persist);
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 false;
1187 }
1188
Nick Pellyde893f52009-09-08 13:15:33 -07001189 /**
1190 * Returns the hardware address of the local Bluetooth adapter.
1191 * <p>For example, "00:11:22:AA:BB:CC".
Nick Pellyde893f52009-09-08 13:15:33 -07001192 *
1193 * @return Bluetooth hardware address as string
1194 */
Tor Norbye2d497522015-04-23 17:10:21 -07001195 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001196 public String getAddress() {
1197 try {
fredc0f420372012-04-12 00:02:00 -07001198 return mManagerService.getAddress();
Jack Hea355e5e2017-08-22 16:06:54 -07001199 } catch (RemoteException e) {
1200 Log.e(TAG, "", e);
1201 }
Nick Pellybd022f42009-08-14 18:33:38 -07001202 return null;
1203 }
1204
1205 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001206 * Get the friendly Bluetooth name of the local Bluetooth adapter.
1207 * <p>This name is visible to remote Bluetooth devices.
1208 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -07001209 *
Nick Pellyde893f52009-09-08 13:15:33 -07001210 * @return the Bluetooth name, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07001211 */
1212 public String getName() {
1213 try {
fredc116d1d462012-04-20 14:47:08 -07001214 return mManagerService.getName();
Jack Hea355e5e2017-08-22 16:06:54 -07001215 } catch (RemoteException e) {
1216 Log.e(TAG, "", e);
1217 }
Nick Pellybd022f42009-08-14 18:33:38 -07001218 return null;
1219 }
1220
1221 /**
Ajay Panickercda6e872015-07-28 16:52:09 -07001222 * Factory reset bluetooth settings.
1223 *
Ajay Panickercda6e872015-07-28 16:52:09 -07001224 * @return true to indicate that the config file was successfully cleared
Ajay Panickercda6e872015-07-28 16:52:09 -07001225 * @hide
1226 */
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001227 @SystemApi
1228 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Ajay Panickercda6e872015-07-28 16:52:09 -07001229 public boolean factoryReset() {
1230 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001231 mServiceLock.readLock().lock();
weichinwenge5470732020-03-05 10:37:44 +08001232 if (mService != null && mService.factoryReset()
1233 && mManagerService != null && mManagerService.onFactoryReset()) {
1234 return true;
Ajay Panickercda6e872015-07-28 16:52:09 -07001235 }
weichinwenge5470732020-03-05 10:37:44 +08001236 Log.e(TAG, "factoryReset(): Setting persist.bluetooth.factoryreset to retry later");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001237 SystemProperties.set("persist.bluetooth.factoryreset", "true");
1238 } catch (RemoteException e) {
1239 Log.e(TAG, "", e);
1240 } finally {
1241 mServiceLock.readLock().unlock();
1242 }
Ajay Panickercda6e872015-07-28 16:52:09 -07001243 return false;
1244 }
1245
1246 /**
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001247 * Get the UUIDs supported by the local Bluetooth adapter.
1248 *
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001249 * @return the UUIDs supported by the local Bluetooth Adapter.
1250 * @hide
1251 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001252 @UnsupportedAppUsage
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001253 @RequiresPermission(Manifest.permission.BLUETOOTH)
Rahul Sabnisd3dd0112020-01-17 15:09:44 -08001254 public @Nullable ParcelUuid[] getUuids() {
Myles Watson125b5452017-11-27 16:41:47 -08001255 if (getState() != STATE_ON) {
1256 return null;
1257 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001258 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001259 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001260 if (mService != null) {
1261 return mService.getUuids();
1262 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001263 } catch (RemoteException e) {
1264 Log.e(TAG, "", e);
1265 } finally {
1266 mServiceLock.readLock().unlock();
1267 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001268 return null;
1269 }
1270
1271 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001272 * Set the friendly Bluetooth name of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001273 * <p>This name is visible to remote Bluetooth devices.
Jake Hamby0f584302010-09-16 18:12:51 -07001274 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1275 * encoding, although many remote devices can only display the first
1276 * 40 characters, and some may be limited to just 20.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001277 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1278 * will return false. After turning on Bluetooth,
1279 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1280 * to get the updated value.
Nick Pellybd022f42009-08-14 18:33:38 -07001281 *
Nick Pellyde893f52009-09-08 13:15:33 -07001282 * @param name a valid Bluetooth name
Jack Hea355e5e2017-08-22 16:06:54 -07001283 * @return true if the name was set, false otherwise
Nick Pellybd022f42009-08-14 18:33:38 -07001284 */
Tor Norbye2d497522015-04-23 17:10:21 -07001285 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001286 public boolean setName(String name) {
Myles Watson125b5452017-11-27 16:41:47 -08001287 if (getState() != STATE_ON) {
1288 return false;
1289 }
Nick Pellybd022f42009-08-14 18:33:38 -07001290 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001291 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001292 if (mService != null) {
1293 return mService.setName(name);
1294 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001295 } catch (RemoteException e) {
1296 Log.e(TAG, "", e);
1297 } finally {
1298 mServiceLock.readLock().unlock();
1299 }
Nick Pellybd022f42009-08-14 18:33:38 -07001300 return false;
1301 }
1302
1303 /**
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001304 * Returns the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1305 * adapter.
1306 *
1307 * @return {@link BluetoothClass} Bluetooth CoD of local Bluetooth device.
1308 *
1309 * @hide
1310 */
1311 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1312 public BluetoothClass getBluetoothClass() {
Myles Watson125b5452017-11-27 16:41:47 -08001313 if (getState() != STATE_ON) {
1314 return null;
1315 }
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001316 try {
1317 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001318 if (mService != null) {
1319 return mService.getBluetoothClass();
1320 }
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001321 } catch (RemoteException e) {
1322 Log.e(TAG, "", e);
1323 } finally {
1324 mServiceLock.readLock().unlock();
1325 }
1326 return null;
1327 }
1328
1329 /**
Pulkit Bhuwalka547853d2017-09-25 17:55:12 -07001330 * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1331 * adapter.
1332 *
1333 * <p>Note: This value persists across system reboot.
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001334 *
1335 * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
1336 * @return true if successful, false if unsuccessful.
1337 *
1338 * @hide
1339 */
1340 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
1341 public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
Myles Watson125b5452017-11-27 16:41:47 -08001342 if (getState() != STATE_ON) {
1343 return false;
1344 }
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001345 try {
1346 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001347 if (mService != null) {
1348 return mService.setBluetoothClass(bluetoothClass);
1349 }
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001350 } catch (RemoteException e) {
1351 Log.e(TAG, "", e);
1352 } finally {
1353 mServiceLock.readLock().unlock();
1354 }
1355 return false;
1356 }
1357
1358 /**
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001359 * Returns the Input/Output capability of the device for classic Bluetooth.
1360 *
1361 * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1362 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1363 * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1364 *
1365 * @hide
1366 */
1367 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001368 @IoCapability
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001369 public int getIoCapability() {
1370 if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1371 try {
1372 mServiceLock.readLock().lock();
1373 if (mService != null) return mService.getIoCapability();
1374 } catch (RemoteException e) {
1375 Log.e(TAG, e.getMessage(), e);
1376 } finally {
1377 mServiceLock.readLock().unlock();
1378 }
1379 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1380 }
1381
1382 /**
1383 * Sets the Input/Output capability of the device for classic Bluetooth.
1384 *
1385 * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1386 * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1387 * and {@link BluetoothAdapter#enable()} to see the changes.
1388 *
1389 * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1390 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1391 * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1392 *
1393 * @hide
1394 */
1395 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001396 public boolean setIoCapability(@IoCapability int capability) {
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001397 if (getState() != STATE_ON) return false;
1398 try {
1399 mServiceLock.readLock().lock();
1400 if (mService != null) return mService.setIoCapability(capability);
1401 } catch (RemoteException e) {
1402 Log.e(TAG, e.getMessage(), e);
1403 } finally {
1404 mServiceLock.readLock().unlock();
1405 }
1406 return false;
1407 }
1408
1409 /**
1410 * Returns the Input/Output capability of the device for BLE operations.
1411 *
1412 * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1413 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1414 * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1415 *
1416 * @hide
1417 */
1418 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001419 @IoCapability
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001420 public int getLeIoCapability() {
1421 if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1422 try {
1423 mServiceLock.readLock().lock();
1424 if (mService != null) return mService.getLeIoCapability();
1425 } catch (RemoteException e) {
1426 Log.e(TAG, e.getMessage(), e);
1427 } finally {
1428 mServiceLock.readLock().unlock();
1429 }
1430 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1431 }
1432
1433 /**
1434 * Sets the Input/Output capability of the device for BLE operations.
1435 *
1436 * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1437 * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1438 * and {@link BluetoothAdapter#enable()} to see the changes.
1439 *
1440 * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1441 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1442 * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1443 *
1444 * @hide
1445 */
1446 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001447 public boolean setLeIoCapability(@IoCapability int capability) {
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001448 if (getState() != STATE_ON) return false;
1449 try {
1450 mServiceLock.readLock().lock();
1451 if (mService != null) return mService.setLeIoCapability(capability);
1452 } catch (RemoteException e) {
1453 Log.e(TAG, e.getMessage(), e);
1454 } finally {
1455 mServiceLock.readLock().unlock();
1456 }
1457 return false;
1458 }
1459
1460 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001461 * Get the current Bluetooth scan mode of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001462 * <p>The Bluetooth scan mode determines if the local adapter is
1463 * connectable and/or discoverable from remote Bluetooth devices.
1464 * <p>Possible values are:
1465 * {@link #SCAN_MODE_NONE},
1466 * {@link #SCAN_MODE_CONNECTABLE},
1467 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001468 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1469 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1470 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1471 * to get the updated value.
Nick Pellyde893f52009-09-08 13:15:33 -07001472 *
1473 * @return scan mode
Nick Pellybd022f42009-08-14 18:33:38 -07001474 */
Tor Norbye2d497522015-04-23 17:10:21 -07001475 @RequiresPermission(Manifest.permission.BLUETOOTH)
1476 @ScanMode
Nick Pellybd022f42009-08-14 18:33:38 -07001477 public int getScanMode() {
Myles Watson125b5452017-11-27 16:41:47 -08001478 if (getState() != STATE_ON) {
1479 return SCAN_MODE_NONE;
1480 }
Nick Pellybd022f42009-08-14 18:33:38 -07001481 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001482 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001483 if (mService != null) {
1484 return mService.getScanMode();
1485 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001486 } catch (RemoteException e) {
1487 Log.e(TAG, "", e);
1488 } finally {
1489 mServiceLock.readLock().unlock();
1490 }
Nick Pellyde893f52009-09-08 13:15:33 -07001491 return SCAN_MODE_NONE;
Nick Pellybd022f42009-08-14 18:33:38 -07001492 }
1493
1494 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001495 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1496 * <p>The Bluetooth scan mode determines if the local adapter is
1497 * connectable and/or discoverable from remote Bluetooth devices.
Nick Pelly12835472009-09-25 15:00:29 -07001498 * <p>For privacy reasons, discoverable mode is automatically turned off
Rahul Sabnis99507b52020-01-31 11:40:15 -08001499 * after <code>durationMillis</code> milliseconds. For example, 120000 milliseconds should be
1500 * enough for a remote device to initiate and complete its discovery process.
Nick Pellyde893f52009-09-08 13:15:33 -07001501 * <p>Valid scan mode values are:
1502 * {@link #SCAN_MODE_NONE},
1503 * {@link #SCAN_MODE_CONNECTABLE},
1504 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001505 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1506 * will return false. After turning on Bluetooth,
1507 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1508 * to get the updated value.
Nick Pelly18b1e792009-09-24 11:14:15 -07001509 * <p>Applications cannot set the scan mode. They should use
1510 * <code>startActivityForResult(
1511 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1512 * </code>instead.
Nick Pellyde893f52009-09-08 13:15:33 -07001513 *
1514 * @param mode valid scan mode
Rahul Sabnis99507b52020-01-31 11:40:15 -08001515 * @param durationMillis time in milliseconds to apply scan mode, only used for {@link
Jack Hea355e5e2017-08-22 16:06:54 -07001516 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
1517 * @return true if the scan mode was set, false otherwise
Nick Pelly18b1e792009-09-24 11:14:15 -07001518 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07001519 */
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001520 @SystemApi
Rahul Sabnis99507b52020-01-31 11:40:15 -08001521 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
1522 public boolean setScanMode(@ScanMode int mode, long durationMillis) {
Myles Watson125b5452017-11-27 16:41:47 -08001523 if (getState() != STATE_ON) {
1524 return false;
1525 }
Nick Pellybd022f42009-08-14 18:33:38 -07001526 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001527 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001528 if (mService != null) {
Rahul Sabnis99507b52020-01-31 11:40:15 -08001529 int durationSeconds = Math.toIntExact(durationMillis / 1000);
1530 return mService.setScanMode(mode, durationSeconds);
Myles Watson125b5452017-11-27 16:41:47 -08001531 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001532 } catch (RemoteException e) {
1533 Log.e(TAG, "", e);
Rahul Sabnis99507b52020-01-31 11:40:15 -08001534 } catch (ArithmeticException ex) {
1535 Log.e(TAG, "setScanMode: Duration in seconds outside of the bounds of an int");
1536 throw new IllegalArgumentException("Duration not in bounds. In seconds, the "
1537 + "durationMillis must be in the range of an int");
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001538 } finally {
1539 mServiceLock.readLock().unlock();
1540 }
Nick Pellyde893f52009-09-08 13:15:33 -07001541 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001542 }
1543
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001544 /**
1545 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1546 * <p>The Bluetooth scan mode determines if the local adapter is
1547 * connectable and/or discoverable from remote Bluetooth devices.
1548 * <p>For privacy reasons, discoverable mode is automatically turned off
1549 * after <code>duration</code> seconds. For example, 120 seconds should be
1550 * enough for a remote device to initiate and complete its discovery
1551 * process.
1552 * <p>Valid scan mode values are:
1553 * {@link #SCAN_MODE_NONE},
1554 * {@link #SCAN_MODE_CONNECTABLE},
1555 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
1556 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1557 * will return false. After turning on Bluetooth,
1558 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1559 * to get the updated value.
1560 * <p>Applications cannot set the scan mode. They should use
1561 * <code>startActivityForResult(
1562 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1563 * </code>instead.
1564 *
1565 * @param mode valid scan mode
1566 * @return true if the scan mode was set, false otherwise
1567 * @hide
1568 */
1569 @SystemApi
Rahul Sabnis99507b52020-01-31 11:40:15 -08001570 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001571 public boolean setScanMode(@ScanMode int mode) {
Myles Watson125b5452017-11-27 16:41:47 -08001572 if (getState() != STATE_ON) {
1573 return false;
1574 }
Rahul Sabnis99507b52020-01-31 11:40:15 -08001575 try {
1576 mServiceLock.readLock().lock();
1577 if (mService != null) {
1578 return mService.setScanMode(mode, getDiscoverableTimeout());
1579 }
1580 } catch (RemoteException e) {
1581 Log.e(TAG, "", e);
1582 } finally {
1583 mServiceLock.readLock().unlock();
1584 }
1585 return false;
Nick Pelly12835472009-09-25 15:00:29 -07001586 }
1587
1588 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001589 @UnsupportedAppUsage
Nick Pellybd022f42009-08-14 18:33:38 -07001590 public int getDiscoverableTimeout() {
Myles Watson125b5452017-11-27 16:41:47 -08001591 if (getState() != STATE_ON) {
1592 return -1;
1593 }
Nick Pellybd022f42009-08-14 18:33:38 -07001594 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001595 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001596 if (mService != null) {
1597 return mService.getDiscoverableTimeout();
1598 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001599 } catch (RemoteException e) {
1600 Log.e(TAG, "", e);
1601 } finally {
1602 mServiceLock.readLock().unlock();
1603 }
Nick Pellybd022f42009-08-14 18:33:38 -07001604 return -1;
1605 }
1606
Nick Pelly45e27042009-08-19 11:00:00 -07001607 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001608 @UnsupportedAppUsage
Nick Pellybd022f42009-08-14 18:33:38 -07001609 public void setDiscoverableTimeout(int timeout) {
Myles Watson125b5452017-11-27 16:41:47 -08001610 if (getState() != STATE_ON) {
1611 return;
1612 }
Nick Pellybd022f42009-08-14 18:33:38 -07001613 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001614 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001615 if (mService != null) {
1616 mService.setDiscoverableTimeout(timeout);
1617 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001618 } catch (RemoteException e) {
1619 Log.e(TAG, "", e);
1620 } finally {
1621 mServiceLock.readLock().unlock();
1622 }
Nick Pellybd022f42009-08-14 18:33:38 -07001623 }
1624
Nick Pelly005b2282009-09-10 10:21:56 -07001625 /**
Marie Janssen23a48332017-01-24 14:09:59 -08001626 * Get the end time of the latest remote device discovery process.
Jack Hea355e5e2017-08-22 16:06:54 -07001627 *
1628 * @return the latest time that the bluetooth adapter was/will be in discovery mode, in
1629 * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has
1630 * been called recently.
Marie Janssen23a48332017-01-24 14:09:59 -08001631 * @hide
1632 */
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07001633 @SystemApi
1634 @RequiresPermission(Manifest.permission.BLUETOOTH)
Marie Janssen23a48332017-01-24 14:09:59 -08001635 public long getDiscoveryEndMillis() {
1636 try {
1637 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001638 if (mService != null) {
1639 return mService.getDiscoveryEndMillis();
1640 }
Marie Janssen23a48332017-01-24 14:09:59 -08001641 } catch (RemoteException e) {
1642 Log.e(TAG, "", e);
1643 } finally {
1644 mServiceLock.readLock().unlock();
1645 }
1646 return -1;
1647 }
1648
1649 /**
Zach Johnson57e6e902018-12-12 17:11:25 -08001650 * Set the context for this BluetoothAdapter (only called from BluetoothManager)
1651 * @hide
1652 */
1653 public void setContext(Context context) {
1654 mContext = context;
1655 }
1656
1657 private String getOpPackageName() {
1658 // Workaround for legacy API for getting a BluetoothAdapter not
1659 // passing a context
1660 if (mContext != null) {
1661 return mContext.getOpPackageName();
1662 }
1663 return ActivityThread.currentOpPackageName();
1664 }
1665
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -08001666 private String getAttributionTag() {
Philip P. Moltmann22209942019-11-15 12:41:09 -08001667 // Workaround for legacy API for getting a BluetoothAdapter not
1668 // passing a context
1669 if (mContext != null) {
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -08001670 return mContext.getAttributionTag();
Philip P. Moltmann22209942019-11-15 12:41:09 -08001671 }
1672 return null;
1673 }
1674
Zach Johnson57e6e902018-12-12 17:11:25 -08001675 /**
Nick Pelly005b2282009-09-10 10:21:56 -07001676 * Start the remote device discovery process.
1677 * <p>The discovery process usually involves an inquiry scan of about 12
1678 * seconds, followed by a page scan of each new device to retrieve its
1679 * Bluetooth name.
1680 * <p>This is an asynchronous call, it will return immediately. Register
1681 * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1682 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1683 * discovery starts and completes. Register for {@link
1684 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1685 * are found.
1686 * <p>Device discovery is a heavyweight procedure. New connections to
1687 * remote Bluetooth devices should not be attempted while discovery is in
1688 * progress, and existing connections will experience limited bandwidth
1689 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
Scott Main6d95fc02009-11-19 17:00:19 -08001690 * discovery. Discovery is not managed by the Activity,
1691 * but is run as a system service, so an application should always call
1692 * {@link BluetoothAdapter#cancelDiscovery()} even if it
1693 * did not directly request a discovery, just to be sure.
Nick Pelly005b2282009-09-10 10:21:56 -07001694 * <p>Device discovery will only find remote devices that are currently
1695 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1696 * not discoverable by default, and need to be entered into a special mode.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001697 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1698 * will return false. After turning on Bluetooth,
1699 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1700 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001701 *
1702 * @return true on success, false on error
1703 */
Tor Norbye2d497522015-04-23 17:10:21 -07001704 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001705 public boolean startDiscovery() {
Myles Watson125b5452017-11-27 16:41:47 -08001706 if (getState() != STATE_ON) {
1707 return false;
1708 }
Nick Pellybd022f42009-08-14 18:33:38 -07001709 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001710 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001711 if (mService != null) {
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -08001712 return mService.startDiscovery(getOpPackageName(), getAttributionTag());
Myles Watson125b5452017-11-27 16:41:47 -08001713 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001714 } catch (RemoteException e) {
1715 Log.e(TAG, "", e);
1716 } finally {
1717 mServiceLock.readLock().unlock();
1718 }
Nick Pellybd022f42009-08-14 18:33:38 -07001719 return false;
1720 }
1721
Nick Pelly005b2282009-09-10 10:21:56 -07001722 /**
1723 * Cancel the current device discovery process.
Jake Hamby0f584302010-09-16 18:12:51 -07001724 * <p>Because discovery is a heavyweight procedure for the Bluetooth
Scott Main6d95fc02009-11-19 17:00:19 -08001725 * adapter, this method should always be called before attempting to connect
1726 * to a remote device with {@link
1727 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1728 * the Activity, but is run as a system service, so an application should
1729 * always call cancel discovery even if it did not directly request a
1730 * discovery, just to be sure.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001731 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1732 * will return false. After turning on Bluetooth,
1733 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1734 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001735 *
1736 * @return true on success, false on error
1737 */
Tor Norbye2d497522015-04-23 17:10:21 -07001738 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly005b2282009-09-10 10:21:56 -07001739 public boolean cancelDiscovery() {
Myles Watson125b5452017-11-27 16:41:47 -08001740 if (getState() != STATE_ON) {
1741 return false;
1742 }
Nick Pellybd022f42009-08-14 18:33:38 -07001743 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001744 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001745 if (mService != null) {
1746 return mService.cancelDiscovery();
1747 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001748 } catch (RemoteException e) {
1749 Log.e(TAG, "", e);
1750 } finally {
1751 mServiceLock.readLock().unlock();
1752 }
Nick Pelly005b2282009-09-10 10:21:56 -07001753 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001754 }
1755
Nick Pelly005b2282009-09-10 10:21:56 -07001756 /**
1757 * Return true if the local Bluetooth adapter is currently in the device
1758 * discovery process.
1759 * <p>Device discovery is a heavyweight procedure. New connections to
1760 * remote Bluetooth devices should not be attempted while discovery is in
1761 * progress, and existing connections will experience limited bandwidth
1762 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1763 * discovery.
1764 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1765 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1766 * starts or completes.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001767 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1768 * will return false. After turning on Bluetooth,
1769 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1770 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001771 *
1772 * @return true if discovering
1773 */
Tor Norbye2d497522015-04-23 17:10:21 -07001774 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001775 public boolean isDiscovering() {
Myles Watson125b5452017-11-27 16:41:47 -08001776 if (getState() != STATE_ON) {
1777 return false;
1778 }
Nick Pellybd022f42009-08-14 18:33:38 -07001779 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001780 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001781 if (mService != null) {
1782 return mService.isDiscovering();
1783 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001784 } catch (RemoteException e) {
1785 Log.e(TAG, "", e);
1786 } finally {
1787 mServiceLock.readLock().unlock();
1788 }
Nick Pellybd022f42009-08-14 18:33:38 -07001789 return false;
1790 }
1791
1792 /**
Rahul Sabnise6f17152020-01-30 16:59:02 -08001793 * Removes the active device for the grouping of @ActiveDeviceUse specified
1794 *
1795 * @param profiles represents the purpose for which we are setting this as the active device.
1796 * Possible values are:
1797 * {@link BluetoothAdapter#ACTIVE_DEVICE_AUDIO},
1798 * {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL},
1799 * {@link BluetoothAdapter#ACTIVE_DEVICE_ALL}
1800 * @return false on immediate error, true otherwise
1801 * @throws IllegalArgumentException if device is null or profiles is not one of
1802 * {@link ActiveDeviceUse}
1803 * @hide
1804 */
1805 @SystemApi
1806 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
1807 public boolean removeActiveDevice(@ActiveDeviceUse int profiles) {
1808 if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
1809 && profiles != ACTIVE_DEVICE_ALL) {
1810 Log.e(TAG, "Invalid profiles param value in removeActiveDevice");
1811 throw new IllegalArgumentException("Profiles must be one of "
1812 + "BluetoothAdapter.ACTIVE_DEVICE_AUDIO, "
1813 + "BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL, or "
1814 + "BluetoothAdapter.ACTIVE_DEVICE_ALL");
1815 }
1816 try {
1817 mServiceLock.readLock().lock();
1818 if (mService != null) {
1819 return mService.removeActiveDevice(profiles);
1820 }
1821 } catch (RemoteException e) {
1822 Log.e(TAG, "", e);
1823 } finally {
1824 mServiceLock.readLock().unlock();
1825 }
1826
1827 return false;
1828 }
1829
1830 /**
1831 * Sets device as the active devices for the profiles passed into the function
Rahul Sabnisc4526972019-11-25 11:16:10 -08001832 *
1833 * @param device is the remote bluetooth device
1834 * @param profiles represents the purpose for which we are setting this as the active device.
1835 * Possible values are:
1836 * {@link BluetoothAdapter#ACTIVE_DEVICE_AUDIO},
1837 * {@link BluetoothAdapter#ACTIVE_DEVICE_PHONE_CALL},
1838 * {@link BluetoothAdapter#ACTIVE_DEVICE_ALL}
1839 * @return false on immediate error, true otherwise
Rahul Sabnise6f17152020-01-30 16:59:02 -08001840 * @throws IllegalArgumentException if device is null or profiles is not one of
1841 * {@link ActiveDeviceUse}
Rahul Sabnisc4526972019-11-25 11:16:10 -08001842 * @hide
1843 */
1844 @SystemApi
Rahul Sabnise6f17152020-01-30 16:59:02 -08001845 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
1846 public boolean setActiveDevice(@NonNull BluetoothDevice device,
Rahul Sabnisc4526972019-11-25 11:16:10 -08001847 @ActiveDeviceUse int profiles) {
Rahul Sabnise6f17152020-01-30 16:59:02 -08001848 if (device == null) {
1849 Log.e(TAG, "setActiveDevice: Null device passed as parameter");
1850 throw new IllegalArgumentException("device cannot be null");
1851 }
Rahul Sabnisc4526972019-11-25 11:16:10 -08001852 if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
1853 && profiles != ACTIVE_DEVICE_ALL) {
1854 Log.e(TAG, "Invalid profiles param value in setActiveDevice");
Rahul Sabnise6f17152020-01-30 16:59:02 -08001855 throw new IllegalArgumentException("Profiles must be one of "
1856 + "BluetoothAdapter.ACTIVE_DEVICE_AUDIO, "
1857 + "BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL, or "
1858 + "BluetoothAdapter.ACTIVE_DEVICE_ALL");
Rahul Sabnisc4526972019-11-25 11:16:10 -08001859 }
Rahul Sabnisc4526972019-11-25 11:16:10 -08001860 try {
1861 mServiceLock.readLock().lock();
1862 if (mService != null) {
1863 return mService.setActiveDevice(device, profiles);
1864 }
1865 } catch (RemoteException e) {
1866 Log.e(TAG, "", e);
1867 } finally {
1868 mServiceLock.readLock().unlock();
1869 }
1870
1871 return false;
1872 }
1873
1874 /**
Rahul Sabnis966cef372020-02-05 14:03:19 -08001875 * Connects all enabled and supported bluetooth profiles between the local and remote device.
1876 * Connection is asynchronous and you should listen to each profile's broadcast intent
1877 * ACTION_CONNECTION_STATE_CHANGED to verify whether connection was successful. For example,
1878 * to verify a2dp is connected, you would listen for
1879 * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
Rahul Sabnis0d33ef92019-11-13 16:21:12 -08001880 *
1881 * @param device is the remote device with which to connect these profiles
Rahul Sabnis966cef372020-02-05 14:03:19 -08001882 * @return true if message sent to try to connect all profiles, false if an error occurred
Rahul Sabnis0d33ef92019-11-13 16:21:12 -08001883 *
1884 * @hide
1885 */
1886 @SystemApi
Rahul Sabnis966cef372020-02-05 14:03:19 -08001887 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Rahul Sabnis0d33ef92019-11-13 16:21:12 -08001888 public boolean connectAllEnabledProfiles(@NonNull BluetoothDevice device) {
1889 try {
1890 mServiceLock.readLock().lock();
1891 if (mService != null) {
1892 return mService.connectAllEnabledProfiles(device);
1893 }
1894 } catch (RemoteException e) {
1895 Log.e(TAG, "", e);
1896 } finally {
1897 mServiceLock.readLock().unlock();
1898 }
1899
1900 return false;
1901 }
1902
1903 /**
Rahul Sabnis966cef372020-02-05 14:03:19 -08001904 * Disconnects all enabled and supported bluetooth profiles between the local and remote device.
1905 * Disconnection is asynchronous and you should listen to each profile's broadcast intent
1906 * ACTION_CONNECTION_STATE_CHANGED to verify whether disconnection was successful. For example,
1907 * to verify a2dp is disconnected, you would listen for
1908 * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
Rahul Sabnis0d33ef92019-11-13 16:21:12 -08001909 *
1910 * @param device is the remote device with which to disconnect these profiles
Rahul Sabnis966cef372020-02-05 14:03:19 -08001911 * @return true if message sent to try to disconnect all profiles, false if an error occurred
Rahul Sabnis0d33ef92019-11-13 16:21:12 -08001912 *
1913 * @hide
1914 */
1915 @SystemApi
Rahul Sabnis966cef372020-02-05 14:03:19 -08001916 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Rahul Sabnis0d33ef92019-11-13 16:21:12 -08001917 public boolean disconnectAllEnabledProfiles(@NonNull BluetoothDevice device) {
1918 try {
1919 mServiceLock.readLock().lock();
1920 if (mService != null) {
1921 return mService.disconnectAllEnabledProfiles(device);
1922 }
1923 } catch (RemoteException e) {
1924 Log.e(TAG, "", e);
1925 } finally {
1926 mServiceLock.readLock().unlock();
1927 }
1928
1929 return false;
1930 }
1931
1932 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001933 * Return true if the multi advertisement is supported by the chipset
1934 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001935 * @return true if Multiple Advertisement feature is supported
1936 */
1937 public boolean isMultipleAdvertisementSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001938 if (getState() != STATE_ON) {
1939 return false;
1940 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001941 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001942 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001943 if (mService != null) {
1944 return mService.isMultiAdvertisementSupported();
1945 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001946 } catch (RemoteException e) {
1947 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001948 } finally {
1949 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001950 }
1951 return false;
1952 }
1953
1954 /**
Wei Wangd91f1932015-03-19 15:09:56 -07001955 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1956 *
1957 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1958 * fetch scan results even when Bluetooth is turned off.<p>
1959 *
1960 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1961 *
1962 * @hide
1963 */
1964 @SystemApi
1965 public boolean isBleScanAlwaysAvailable() {
Wei Wang67d84162015-04-26 17:04:29 -07001966 try {
1967 return mManagerService.isBleScanAlwaysAvailable();
1968 } catch (RemoteException e) {
1969 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1970 return false;
1971 }
Wei Wangd91f1932015-03-19 15:09:56 -07001972 }
1973
Lee Shomberta6574302019-12-30 11:54:37 -08001974 private static final String BLUETOOTH_FILTERING_CACHE_PROPERTY =
1975 "cache_key.bluetooth.is_offloaded_filtering_supported";
1976 private final PropertyInvalidatedCache<Void, Boolean> mBluetoothFilteringCache =
1977 new PropertyInvalidatedCache<Void, Boolean>(
1978 8, BLUETOOTH_FILTERING_CACHE_PROPERTY) {
1979 @Override
1980 protected Boolean recompute(Void query) {
1981 try {
1982 mServiceLock.readLock().lock();
1983 if (mService != null) {
1984 return mService.isOffloadedFilteringSupported();
1985 }
1986 } catch (RemoteException e) {
1987 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
1988 } finally {
1989 mServiceLock.readLock().unlock();
1990 }
1991 return false;
1992
1993 }
1994 };
1995
1996 /** @hide */
1997 public void disableIsOffloadedFilteringSupportedCache() {
1998 mBluetoothFilteringCache.disableLocal();
1999 }
2000
2001 /** @hide */
2002 public static void invalidateIsOffloadedFilteringSupportedCache() {
2003 PropertyInvalidatedCache.invalidateCache(BLUETOOTH_FILTERING_CACHE_PROPERTY);
2004 }
2005
Wei Wangd91f1932015-03-19 15:09:56 -07002006 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07002007 * Return true if offloaded filters are supported
2008 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07002009 * @return true if chipset supports on-chip filtering
2010 */
2011 public boolean isOffloadedFilteringSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08002012 if (!getLeAccess()) {
2013 return false;
2014 }
Lee Shomberta6574302019-12-30 11:54:37 -08002015 return mBluetoothFilteringCache.query(null);
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07002016 }
2017
2018 /**
2019 * Return true if offloaded scan batching is supported
2020 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07002021 * @return true if chipset supports on-chip scan batching
2022 */
2023 public boolean isOffloadedScanBatchingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08002024 if (!getLeAccess()) {
2025 return false;
2026 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07002027 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002028 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002029 if (mService != null) {
2030 return mService.isOffloadedScanBatchingSupported();
2031 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07002032 } catch (RemoteException e) {
2033 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002034 } finally {
2035 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07002036 }
2037 return false;
2038 }
2039
2040 /**
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002041 * Return true if LE 2M PHY feature is supported.
2042 *
2043 * @return true if chipset supports LE 2M PHY feature
2044 */
2045 public boolean isLe2MPhySupported() {
Myles Watson125b5452017-11-27 16:41:47 -08002046 if (!getLeAccess()) {
2047 return false;
2048 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002049 try {
2050 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002051 if (mService != null) {
2052 return mService.isLe2MPhySupported();
2053 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002054 } catch (RemoteException e) {
2055 Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
2056 } finally {
2057 mServiceLock.readLock().unlock();
2058 }
2059 return false;
2060 }
2061
2062 /**
2063 * Return true if LE Coded PHY feature is supported.
2064 *
2065 * @return true if chipset supports LE Coded PHY feature
2066 */
2067 public boolean isLeCodedPhySupported() {
Myles Watson125b5452017-11-27 16:41:47 -08002068 if (!getLeAccess()) {
2069 return false;
2070 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002071 try {
2072 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002073 if (mService != null) {
2074 return mService.isLeCodedPhySupported();
2075 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002076 } catch (RemoteException e) {
2077 Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
2078 } finally {
2079 mServiceLock.readLock().unlock();
2080 }
2081 return false;
2082 }
2083
2084 /**
Jakub Pawlowskibc2991e2017-03-10 16:07:59 -08002085 * Return true if LE Extended Advertising feature is supported.
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002086 *
Jakub Pawlowskibc2991e2017-03-10 16:07:59 -08002087 * @return true if chipset supports LE Extended Advertising feature
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002088 */
2089 public boolean isLeExtendedAdvertisingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08002090 if (!getLeAccess()) {
2091 return false;
2092 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002093 try {
2094 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002095 if (mService != null) {
2096 return mService.isLeExtendedAdvertisingSupported();
2097 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002098 } catch (RemoteException e) {
2099 Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
2100 } finally {
2101 mServiceLock.readLock().unlock();
2102 }
2103 return false;
2104 }
2105
2106 /**
2107 * Return true if LE Periodic Advertising feature is supported.
2108 *
2109 * @return true if chipset supports LE Periodic Advertising feature
2110 */
2111 public boolean isLePeriodicAdvertisingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08002112 if (!getLeAccess()) {
2113 return false;
2114 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002115 try {
2116 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002117 if (mService != null) {
2118 return mService.isLePeriodicAdvertisingSupported();
2119 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08002120 } catch (RemoteException e) {
2121 Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
2122 } finally {
2123 mServiceLock.readLock().unlock();
2124 }
2125 return false;
2126 }
2127
2128 /**
Jakub Pawlowski76cceb12017-04-21 04:59:55 -07002129 * Return the maximum LE advertising data length in bytes,
2130 * if LE Extended Advertising feature is supported, 0 otherwise.
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07002131 *
2132 * @return the maximum LE advertising data length.
2133 */
2134 public int getLeMaximumAdvertisingDataLength() {
Myles Watson125b5452017-11-27 16:41:47 -08002135 if (!getLeAccess()) {
2136 return 0;
2137 }
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07002138 try {
2139 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002140 if (mService != null) {
2141 return mService.getLeMaximumAdvertisingDataLength();
2142 }
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07002143 } catch (RemoteException e) {
2144 Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
2145 } finally {
2146 mServiceLock.readLock().unlock();
2147 }
2148 return 0;
2149 }
2150
2151 /**
Stanley Tng61dbd812019-01-13 16:04:31 -08002152 * Return true if Hearing Aid Profile is supported.
2153 *
2154 * @return true if phone supports Hearing Aid Profile
2155 */
2156 private boolean isHearingAidProfileSupported() {
2157 try {
2158 return mManagerService.isHearingAidProfileSupported();
2159 } catch (RemoteException e) {
2160 Log.e(TAG, "remote expection when calling isHearingAidProfileSupported", e);
2161 return false;
2162 }
2163 }
2164
2165 /**
Pavlin Radoslavova5137922018-01-17 02:09:53 -08002166 * Get the maximum number of connected audio devices.
2167 *
2168 * @return the maximum number of connected audio devices
2169 * @hide
2170 */
2171 @RequiresPermission(Manifest.permission.BLUETOOTH)
2172 public int getMaxConnectedAudioDevices() {
2173 try {
2174 mServiceLock.readLock().lock();
2175 if (mService != null) {
2176 return mService.getMaxConnectedAudioDevices();
2177 }
2178 } catch (RemoteException e) {
2179 Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
2180 } finally {
2181 mServiceLock.readLock().unlock();
2182 }
2183 return 1;
2184 }
2185
2186 /**
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07002187 * Return true if hardware has entries available for matching beacons
2188 *
2189 * @return true if there are hw entries available for matching beacons
2190 * @hide
2191 */
2192 public boolean isHardwareTrackingFiltersAvailable() {
Myles Watson125b5452017-11-27 16:41:47 -08002193 if (!getLeAccess()) {
2194 return false;
2195 }
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07002196 try {
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07002197 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
2198 if (iGatt == null) {
2199 // BLE is not supported
2200 return false;
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07002201 }
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07002202 return (iGatt.numHwTrackFiltersAvailable() != 0);
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07002203 } catch (RemoteException e) {
2204 Log.e(TAG, "", e);
2205 }
2206 return false;
2207 }
2208
2209 /**
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002210 * Return the record of {@link BluetoothActivityEnergyInfo} object that
2211 * has the activity and energy info. This can be used to ascertain what
2212 * the controller has been up to, since the last sample.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002213 *
Jack Hea355e5e2017-08-22 16:06:54 -07002214 * @param updateType Type of info, cached vs refreshed.
2215 * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or
2216 * unsupported
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002217 * @hide
Jack Hea355e5e2017-08-22 16:06:54 -07002218 * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)}
2219 * instead.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002220 */
Adam Lesinski010bf372016-04-11 12:18:18 -07002221 @Deprecated
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002222 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
Adam Lesinski010bf372016-04-11 12:18:18 -07002223 SynchronousResultReceiver receiver = new SynchronousResultReceiver();
Adam Lesinski991357f2016-05-10 14:00:03 -07002224 requestControllerActivityEnergyInfo(receiver);
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002225 try {
Adam Lesinski010bf372016-04-11 12:18:18 -07002226 SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
2227 if (result.bundle != null) {
2228 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
2229 }
2230 } catch (TimeoutException e) {
2231 Log.e(TAG, "getControllerActivityEnergyInfo timed out");
2232 }
2233 return null;
2234 }
2235
2236 /**
2237 * Request the record of {@link BluetoothActivityEnergyInfo} object that
2238 * has the activity and energy info. This can be used to ascertain what
2239 * the controller has been up to, since the last sample.
2240 *
2241 * A null value for the activity info object may be sent if the bluetooth service is
2242 * unreachable or the device does not support reporting such information.
2243 *
Adam Lesinski010bf372016-04-11 12:18:18 -07002244 * @param result The callback to which to send the activity info.
2245 * @hide
2246 */
Adam Lesinski991357f2016-05-10 14:00:03 -07002247 public void requestControllerActivityEnergyInfo(ResultReceiver result) {
Adam Lesinski010bf372016-04-11 12:18:18 -07002248 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002249 mServiceLock.readLock().lock();
2250 if (mService != null) {
2251 mService.requestActivityInfo(result);
2252 result = null;
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002253 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002254 } catch (RemoteException e) {
2255 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
Adam Lesinski991357f2016-05-10 14:00:03 -07002256 } finally {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002257 mServiceLock.readLock().unlock();
Adam Lesinski991357f2016-05-10 14:00:03 -07002258 if (result != null) {
2259 // Only send an immediate result if we failed.
2260 result.send(0, null);
2261 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002262 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07002263 }
2264
2265 /**
Rahul Sabnis791dedb2020-01-29 11:53:10 -08002266 * Fetches a list of the most recently connected bluetooth devices ordered by how recently they
2267 * were connected with most recently first and least recently last
2268 *
2269 * @return {@link List} of bonded {@link BluetoothDevice} ordered by how recently they were
2270 * connected
2271 *
2272 * @hide
2273 */
2274 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
2275 public @NonNull List<BluetoothDevice> getMostRecentlyConnectedDevices() {
2276 if (getState() != STATE_ON) {
2277 return new ArrayList<>();
2278 }
2279 try {
2280 mServiceLock.readLock().lock();
2281 if (mService != null) {
2282 return mService.getMostRecentlyConnectedDevices();
2283 }
2284 } catch (RemoteException e) {
2285 Log.e(TAG, "", e);
2286 } finally {
2287 mServiceLock.readLock().unlock();
2288 }
2289 return new ArrayList<>();
2290 }
2291
2292 /**
Nick Pelly005b2282009-09-10 10:21:56 -07002293 * Return the set of {@link BluetoothDevice} objects that are bonded
2294 * (paired) to the local adapter.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002295 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
2296 * will return an empty set. After turning on Bluetooth,
2297 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
2298 * to get the updated value.
Nick Pellybd022f42009-08-14 18:33:38 -07002299 *
Nick Pelly005b2282009-09-10 10:21:56 -07002300 * @return unmodifiable set of {@link BluetoothDevice}, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07002301 */
Tor Norbye2d497522015-04-23 17:10:21 -07002302 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07002303 public Set<BluetoothDevice> getBondedDevices() {
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002304 if (getState() != STATE_ON) {
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08002305 return toDeviceSet(new BluetoothDevice[0]);
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07002306 }
Nick Pellybd022f42009-08-14 18:33:38 -07002307 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002308 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002309 if (mService != null) {
2310 return toDeviceSet(mService.getBondedDevices());
2311 }
fredc0f420372012-04-12 00:02:00 -07002312 return toDeviceSet(new BluetoothDevice[0]);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002313 } catch (RemoteException e) {
2314 Log.e(TAG, "", e);
2315 } finally {
2316 mServiceLock.readLock().unlock();
2317 }
Nick Pellybd022f42009-08-14 18:33:38 -07002318 return null;
2319 }
2320
2321 /**
Bryce Leeb1301fa2016-10-09 12:54:42 -07002322 * Gets the currently supported profiles by the adapter.
2323 *
Jack Hea355e5e2017-08-22 16:06:54 -07002324 * <p> This can be used to check whether a profile is supported before attempting
Bryce Leeb1301fa2016-10-09 12:54:42 -07002325 * to connect to its respective proxy.
2326 *
Jack Hea355e5e2017-08-22 16:06:54 -07002327 * @return a list of integers indicating the ids of supported profiles as defined in {@link
2328 * BluetoothProfile}.
Bryce Leeb1301fa2016-10-09 12:54:42 -07002329 * @hide
2330 */
Rahul Sabnis644d3dd2019-10-25 13:15:12 -07002331 public @NonNull List<Integer> getSupportedProfiles() {
Bryce Leeb1301fa2016-10-09 12:54:42 -07002332 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
2333
2334 try {
2335 synchronized (mManagerCallback) {
2336 if (mService != null) {
2337 final long supportedProfilesBitMask = mService.getSupportedProfiles();
2338
2339 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
2340 if ((supportedProfilesBitMask & (1 << i)) != 0) {
2341 supportedProfiles.add(i);
2342 }
2343 }
Stanley Tng61dbd812019-01-13 16:04:31 -08002344 } else {
2345 // Bluetooth is disabled. Just fill in known supported Profiles
2346 if (isHearingAidProfileSupported()) {
2347 supportedProfiles.add(BluetoothProfile.HEARING_AID);
2348 }
Bryce Leeb1301fa2016-10-09 12:54:42 -07002349 }
2350 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002351 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -07002352 Log.e(TAG, "getSupportedProfiles:", e);
Marie Janssencb21ad72016-12-13 10:51:02 -08002353 }
Bryce Leeb1301fa2016-10-09 12:54:42 -07002354 return supportedProfiles;
2355 }
2356
2357 /**
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002358 * Get the current connection state of the local Bluetooth adapter.
2359 * This can be used to check whether the local Bluetooth adapter is connected
2360 * to any profile of any other remote Bluetooth Device.
2361 *
2362 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
2363 * intent to get the connection state of the adapter.
2364 *
Jack Hea355e5e2017-08-22 16:06:54 -07002365 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link
2366 * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002367 * @hide
2368 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002369 @UnsupportedAppUsage
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002370 public int getConnectionState() {
Myles Watson125b5452017-11-27 16:41:47 -08002371 if (getState() != STATE_ON) {
2372 return BluetoothAdapter.STATE_DISCONNECTED;
2373 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002374 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002375 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002376 if (mService != null) {
2377 return mService.getAdapterConnectionState();
2378 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002379 } catch (RemoteException e) {
2380 Log.e(TAG, "getConnectionState:", e);
2381 } finally {
2382 mServiceLock.readLock().unlock();
2383 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002384 return BluetoothAdapter.STATE_DISCONNECTED;
2385 }
2386
Lee Shomberta6574302019-12-30 11:54:37 -08002387 private static final String BLUETOOTH_PROFILE_CACHE_PROPERTY =
2388 "cache_key.bluetooth.get_profile_connection_state";
2389 private final PropertyInvalidatedCache<Integer, Integer>
2390 mGetProfileConnectionStateCache =
2391 new PropertyInvalidatedCache<Integer, Integer>(
2392 8, BLUETOOTH_PROFILE_CACHE_PROPERTY) {
2393 @Override
2394 protected Integer recompute(Integer query) {
2395 try {
2396 mServiceLock.readLock().lock();
2397 if (mService != null) {
2398 return mService.getProfileConnectionState(query);
2399 }
2400 } catch (RemoteException e) {
2401 Log.e(TAG, "getProfileConnectionState:", e);
2402 } finally {
2403 mServiceLock.readLock().unlock();
2404 }
2405 return BluetoothProfile.STATE_DISCONNECTED;
2406 }
2407 @Override
2408 public String queryToString(Integer query) {
2409 return String.format("getProfileConnectionState(profile=\"%d\")",
2410 query);
2411 }
2412 };
2413
2414 /** @hide */
2415 public void disableGetProfileConnectionStateCache() {
2416 mGetProfileConnectionStateCache.disableLocal();
2417 }
2418
2419 /** @hide */
2420 public static void invalidateGetProfileConnectionStateCache() {
2421 PropertyInvalidatedCache.invalidateCache(BLUETOOTH_PROFILE_CACHE_PROPERTY);
2422 }
2423
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002424 /**
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002425 * Get the current connection state of a profile.
2426 * This function can be used to check whether the local Bluetooth adapter
2427 * is connected to any remote device for a specific profile.
Jack He6b73b322019-01-03 16:23:41 -08002428 * Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002429 *
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002430 * <p> Return value can be one of
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002431 * {@link BluetoothProfile#STATE_DISCONNECTED},
2432 * {@link BluetoothProfile#STATE_CONNECTING},
2433 * {@link BluetoothProfile#STATE_CONNECTED},
2434 * {@link BluetoothProfile#STATE_DISCONNECTING}
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002435 */
Tor Norbye2d497522015-04-23 17:10:21 -07002436 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002437 public int getProfileConnectionState(int profile) {
Myles Watson125b5452017-11-27 16:41:47 -08002438 if (getState() != STATE_ON) {
2439 return BluetoothProfile.STATE_DISCONNECTED;
2440 }
Lee Shomberta6574302019-12-30 11:54:37 -08002441 return mGetProfileConnectionStateCache.query(new Integer(profile));
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002442 }
2443
2444 /**
Nick Pelly45e27042009-08-19 11:00:00 -07002445 * Create a listening, secure RFCOMM Bluetooth socket.
2446 * <p>A remote device connecting to this socket will be authenticated and
Nick Pellybd022f42009-08-14 18:33:38 -07002447 * communication on this socket will be encrypted.
Nick Pelly45e27042009-08-19 11:00:00 -07002448 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
Nick Pelly24bb9b82009-10-02 20:34:18 -07002449 * connections from a listening {@link BluetoothServerSocket}.
Nick Pelly45e27042009-08-19 11:00:00 -07002450 * <p>Valid RFCOMM channels are in range 1 to 30.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002451 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Jack Hea355e5e2017-08-22 16:06:54 -07002452 *
Nick Pelly45e27042009-08-19 11:00:00 -07002453 * @param channel RFCOMM channel to listen on
2454 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002455 * @throws IOException on error, for example Bluetooth not available, or insufficient
2456 * permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002457 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002458 */
Nick Pelly45e27042009-08-19 11:00:00 -07002459 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002460 return listenUsingRfcommOn(channel, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02002461 }
2462
2463 /**
2464 * Create a listening, secure RFCOMM Bluetooth socket.
2465 * <p>A remote device connecting to this socket will be authenticated and
2466 * communication on this socket will be encrypted.
2467 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2468 * connections from a listening {@link BluetoothServerSocket}.
2469 * <p>Valid RFCOMM channels are in range 1 to 30.
2470 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
2471 * <p>To auto assign a channel without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002472 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
Jack Hea355e5e2017-08-22 16:06:54 -07002473 *
Casper Bonde23284232015-04-21 13:12:05 +02002474 * @param channel RFCOMM channel to listen on
Jack Hea355e5e2017-08-22 16:06:54 -07002475 * @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 Bonde23284232015-04-21 13:12:05 +02002478 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002479 * @throws IOException on error, for example Bluetooth not available, or insufficient
2480 * permissions, or channel in use.
Casper Bonde23284232015-04-21 13:12:05 +02002481 * @hide
2482 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002483 @UnsupportedAppUsage
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002484 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
Myles Watson125b5452017-11-27 16:41:47 -08002485 boolean min16DigitPin) throws IOException {
2486 BluetoothServerSocket socket =
2487 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm,
2488 min16DigitPin);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002489 int errno = socket.mSocket.bindListen();
Casper Bonde23284232015-04-21 13:12:05 +02002490 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002491 socket.setChannel(socket.mSocket.getPort());
2492 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002493 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07002494 //TODO(BT): Throw the same exception error code
2495 // that the previous code was using.
2496 //socket.mSocket.throwErrnoNative(errno);
2497 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002498 }
2499 return socket;
2500 }
2501
2502 /**
Nick Pelly24bb9b82009-10-02 20:34:18 -07002503 * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
2504 * <p>A remote device connecting to this socket will be authenticated and
2505 * communication on this socket will be encrypted.
2506 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2507 * connections from a listening {@link BluetoothServerSocket}.
2508 * <p>The system will assign an unused RFCOMM channel to listen on.
2509 * <p>The system will also register a Service Discovery
2510 * Protocol (SDP) record with the local SDP server containing the specified
2511 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2512 * can use the same UUID to query our SDP server and discover which channel
2513 * to connect to. This SDP record will be removed when this socket is
2514 * closed, or if this application closes unexpectedly.
Nick Pelly16fb88a2009-10-07 07:44:03 +02002515 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2516 * connect to this socket from another device using the same {@link UUID}.
Jack Hea355e5e2017-08-22 16:06:54 -07002517 *
Nick Pelly24bb9b82009-10-02 20:34:18 -07002518 * @param name service name for SDP record
2519 * @param uuid uuid for SDP record
2520 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002521 * @throws IOException on error, for example Bluetooth not available, or insufficient
2522 * permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002523 */
Tor Norbye2d497522015-04-23 17:10:21 -07002524 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly16fb88a2009-10-07 07:44:03 +02002525 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
Nick Pelly24bb9b82009-10-02 20:34:18 -07002526 throws IOException {
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002527 return createNewRfcommSocketAndRecord(name, uuid, true, true);
2528 }
2529
2530 /**
2531 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002532 * <p>The link key is not required to be authenticated, i.e the communication may be
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002533 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002534 * the link will be encrypted, as encryption is mandartory.
2535 * For legacy devices (pre Bluetooth 2.1 devices) the link will not
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002536 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
2537 * encrypted and authenticated communication channel is desired.
2538 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2539 * connections from a listening {@link BluetoothServerSocket}.
2540 * <p>The system will assign an unused RFCOMM channel to listen on.
2541 * <p>The system will also register a Service Discovery
2542 * Protocol (SDP) record with the local SDP server containing the specified
2543 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2544 * can use the same UUID to query our SDP server and discover which channel
2545 * to connect to. This SDP record will be removed when this socket is
2546 * closed, or if this application closes unexpectedly.
2547 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2548 * connect to this socket from another device using the same {@link UUID}.
Jack Hea355e5e2017-08-22 16:06:54 -07002549 *
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002550 * @param name service name for SDP record
2551 * @param uuid uuid for SDP record
2552 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002553 * @throws IOException on error, for example Bluetooth not available, or insufficient
2554 * permissions, or channel in use.
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002555 */
Tor Norbye2d497522015-04-23 17:10:21 -07002556 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002557 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
2558 throws IOException {
2559 return createNewRfcommSocketAndRecord(name, uuid, false, false);
2560 }
2561
Jack Hea355e5e2017-08-22 16:06:54 -07002562 /**
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002563 * Create a listening, encrypted,
2564 * RFCOMM Bluetooth socket with Service Record.
2565 * <p>The link will be encrypted, but the link key is not required to be authenticated
2566 * i.e the communication is vulnerable to Man In the Middle attacks. Use
2567 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
2568 * <p> Use this socket if authentication of link key is not possible.
2569 * For example, for Bluetooth 2.1 devices, if any of the devices does not have
2570 * an input and output capability or just has the ability to display a numeric key,
2571 * a secure socket connection is not possible and this socket can be used.
2572 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
2573 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
2574 * For more details, refer to the Security Model section 5.2 (vol 3) of
2575 * Bluetooth Core Specification version 2.1 + EDR.
2576 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2577 * connections from a listening {@link BluetoothServerSocket}.
2578 * <p>The system will assign an unused RFCOMM channel to listen on.
2579 * <p>The system will also register a Service Discovery
2580 * Protocol (SDP) record with the local SDP server containing the specified
2581 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2582 * can use the same UUID to query our SDP server and discover which channel
2583 * to connect to. This SDP record will be removed when this socket is
2584 * closed, or if this application closes unexpectedly.
2585 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2586 * connect to this socket from another device using the same {@link UUID}.
2587 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jack Hea355e5e2017-08-22 16:06:54 -07002588 *
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002589 * @param name service name for SDP record
2590 * @param uuid uuid for SDP record
2591 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002592 * @throws IOException on error, for example Bluetooth not available, or insufficient
2593 * permissions, or channel in use.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002594 * @hide
2595 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002596 @UnsupportedAppUsage
Myles Watson125b5452017-11-27 16:41:47 -08002597 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)
2598 throws IOException {
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002599 return createNewRfcommSocketAndRecord(name, uuid, false, true);
2600 }
2601
zzy3b147b72012-04-03 19:48:32 -07002602
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002603 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
2604 boolean auth, boolean encrypt) throws IOException {
Nick Pelly24bb9b82009-10-02 20:34:18 -07002605 BluetoothServerSocket socket;
Myles Watson125b5452017-11-27 16:41:47 -08002606 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, encrypt,
2607 new ParcelUuid(uuid));
zzy3b147b72012-04-03 19:48:32 -07002608 socket.setServiceName(name);
2609 int errno = socket.mSocket.bindListen();
2610 if (errno != 0) {
2611 //TODO(BT): Throw the same exception error code
2612 // that the previous code was using.
2613 //socket.mSocket.throwErrnoNative(errno);
2614 throw new IOException("Error: " + errno);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002615 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002616 return socket;
2617 }
2618
2619 /**
Nick Pellybd022f42009-08-14 18:33:38 -07002620 * Construct an unencrypted, unauthenticated, RFCOMM server socket.
2621 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002622 *
Nick Pellybd022f42009-08-14 18:33:38 -07002623 * @return An RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002624 * @throws IOException On error, for example Bluetooth not available, or insufficient
2625 * permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07002626 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002627 */
2628 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002629 BluetoothServerSocket socket =
2630 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, false, port);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002631 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002632 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002633 socket.setChannel(socket.mSocket.getPort());
2634 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002635 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07002636 //TODO(BT): Throw the same exception error code
2637 // that the previous code was using.
2638 //socket.mSocket.throwErrnoNative(errno);
2639 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002640 }
2641 return socket;
2642 }
2643
Jack Hea355e5e2017-08-22 16:06:54 -07002644 /**
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002645 * Construct an encrypted, RFCOMM server socket.
2646 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002647 *
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002648 * @return An RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002649 * @throws IOException On error, for example Bluetooth not available, or insufficient
2650 * permissions.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002651 * @hide
2652 */
Myles Watson125b5452017-11-27 16:41:47 -08002653 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port) throws IOException {
2654 BluetoothServerSocket socket =
2655 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, true, port);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002656 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002657 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002658 socket.setChannel(socket.mSocket.getPort());
2659 }
zzy3b147b72012-04-03 19:48:32 -07002660 if (errno < 0) {
2661 //TODO(BT): Throw the same exception error code
2662 // that the previous code was using.
2663 //socket.mSocket.throwErrnoNative(errno);
2664 throw new IOException("Error: " + errno);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002665 }
2666 return socket;
2667 }
2668
Nick Pellybd022f42009-08-14 18:33:38 -07002669 /**
2670 * Construct a SCO server socket.
2671 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002672 *
Nick Pellybd022f42009-08-14 18:33:38 -07002673 * @return A SCO BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002674 * @throws IOException On error, for example Bluetooth not available, or insufficient
2675 * permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07002676 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002677 */
2678 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002679 BluetoothServerSocket socket =
2680 new BluetoothServerSocket(BluetoothSocket.TYPE_SCO, false, false, -1);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002681 int errno = socket.mSocket.bindListen();
zzy3b147b72012-04-03 19:48:32 -07002682 if (errno < 0) {
2683 //TODO(BT): Throw the same exception error code
2684 // that the previous code was using.
2685 //socket.mSocket.throwErrnoNative(errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002686 }
2687 return socket;
2688 }
2689
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002690 /**
Casper Bonde238e0f92015-04-09 09:24:48 +02002691 * Construct an encrypted, authenticated, L2CAP server socket.
2692 * Call #accept to retrieve connections to this socket.
Casper Bonde23284232015-04-21 13:12:05 +02002693 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002694 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002695 *
2696 * @param port the PSM to listen on
2697 * @param mitm enforce man-in-the-middle protection for authentication.
2698 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2699 * connections.
Casper Bonde238e0f92015-04-09 09:24:48 +02002700 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002701 * @throws IOException On error, for example Bluetooth not available, or insufficient
2702 * permissions.
Casper Bonde238e0f92015-04-09 09:24:48 +02002703 * @hide
2704 */
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002705 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
2706 throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002707 BluetoothServerSocket socket =
2708 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, true, true, port, mitm,
2709 min16DigitPin);
Casper Bonde238e0f92015-04-09 09:24:48 +02002710 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002711 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Stanley Tnge48468d2017-11-22 16:04:40 -08002712 int assignedChannel = socket.mSocket.getPort();
2713 if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
2714 socket.setChannel(assignedChannel);
Casper Bonde238e0f92015-04-09 09:24:48 +02002715 }
2716 if (errno != 0) {
2717 //TODO(BT): Throw the same exception error code
2718 // that the previous code was using.
2719 //socket.mSocket.throwErrnoNative(errno);
2720 throw new IOException("Error: " + errno);
2721 }
2722 return socket;
2723 }
2724
2725 /**
Casper Bonde23284232015-04-21 13:12:05 +02002726 * Construct an encrypted, authenticated, L2CAP server socket.
2727 * Call #accept to retrieve connections to this socket.
2728 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002729 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002730 *
2731 * @param port the PSM to listen on
Casper Bonde23284232015-04-21 13:12:05 +02002732 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002733 * @throws IOException On error, for example Bluetooth not available, or insufficient
2734 * permissions.
Casper Bonde23284232015-04-21 13:12:05 +02002735 * @hide
2736 */
2737 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002738 return listenUsingL2capOn(port, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02002739 }
2740
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302741
2742 /**
2743 * Construct an insecure L2CAP server socket.
2744 * Call #accept to retrieve connections to this socket.
2745 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002746 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002747 *
2748 * @param port the PSM to listen on
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302749 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002750 * @throws IOException On error, for example Bluetooth not available, or insufficient
2751 * permissions.
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302752 * @hide
2753 */
2754 public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08002755 Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
Myles Watson125b5452017-11-27 16:41:47 -08002756 BluetoothServerSocket socket =
2757 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
Stanley Tnge48468d2017-11-22 16:04:40 -08002758 false);
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302759 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002760 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Stanley Tnge48468d2017-11-22 16:04:40 -08002761 int assignedChannel = socket.mSocket.getPort();
2762 if (DBG) {
2763 Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
2764 + assignedChannel);
2765 }
2766 socket.setChannel(assignedChannel);
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302767 }
2768 if (errno != 0) {
2769 //TODO(BT): Throw the same exception error code
2770 // that the previous code was using.
2771 //socket.mSocket.throwErrnoNative(errno);
2772 throw new IOException("Error: " + errno);
2773 }
2774 return socket;
2775
2776 }
2777
Casper Bonde23284232015-04-21 13:12:05 +02002778 /**
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002779 * Read the local Out of Band Pairing Data
2780 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2781 *
2782 * @return Pair<byte[], byte[]> of Hash and Randomizer
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002783 * @hide
2784 */
2785 public Pair<byte[], byte[]> readOutOfBandData() {
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002786 return null;
2787 }
2788
Scott Main299ae672011-01-19 21:13:18 -08002789 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002790 * Get the profile proxy object associated with the profile.
2791 *
Jack He6b73b322019-01-03 16:23:41 -08002792 * <p>Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP},
Stanley Tng1f5ea662018-11-15 17:11:36 -08002793 * {@link BluetoothProfile#GATT}, {@link BluetoothProfile#HEARING_AID}, or {@link
2794 * BluetoothProfile#GATT_SERVER}. Clients must implement {@link
2795 * BluetoothProfile.ServiceListener} to get notified of the connection status and to get the
2796 * proxy object.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002797 *
2798 * @param context Context of the application
2799 * @param listener The service Listener for connection callbacks.
Jack He6b73b322019-01-03 16:23:41 -08002800 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET},
Stanley Tng1f5ea662018-11-15 17:11:36 -08002801 * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, {@link
2802 * BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#GATT_SERVER}.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002803 * @return true on success, false on error
2804 */
2805 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
Jack Hea355e5e2017-08-22 16:06:54 -07002806 int profile) {
Myles Watson125b5452017-11-27 16:41:47 -08002807 if (context == null || listener == null) {
2808 return false;
2809 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002810
2811 if (profile == BluetoothProfile.HEADSET) {
2812 BluetoothHeadset headset = new BluetoothHeadset(context, listener);
2813 return true;
2814 } else if (profile == BluetoothProfile.A2DP) {
2815 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
2816 return true;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002817 } else if (profile == BluetoothProfile.A2DP_SINK) {
2818 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
2819 return true;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002820 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
2821 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
2822 return true;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002823 } else if (profile == BluetoothProfile.HID_HOST) {
2824 BluetoothHidHost iDev = new BluetoothHidHost(context, listener);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -08002825 return true;
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -08002826 } else if (profile == BluetoothProfile.PAN) {
2827 BluetoothPan pan = new BluetoothPan(context, listener);
2828 return true;
Chienyuan2fca55d2020-01-08 17:50:08 +08002829 } else if (profile == BluetoothProfile.PBAP) {
2830 BluetoothPbap pbap = new BluetoothPbap(context, listener);
2831 return true;
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -07002832 } else if (profile == BluetoothProfile.HEALTH) {
Jack He6b73b322019-01-03 16:23:41 -08002833 Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated");
2834 return false;
Kim Schulz0d376052013-08-22 11:18:02 +02002835 } else if (profile == BluetoothProfile.MAP) {
2836 BluetoothMap map = new BluetoothMap(context, listener);
2837 return true;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002838 } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
2839 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
Hemant Gupta7aca90f2013-08-19 19:03:51 +05302840 return true;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002841 } else if (profile == BluetoothProfile.SAP) {
2842 BluetoothSap sap = new BluetoothSap(context, listener);
2843 return true;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002844 } else if (profile == BluetoothProfile.PBAP_CLIENT) {
2845 BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
2846 return true;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002847 } else if (profile == BluetoothProfile.MAP_CLIENT) {
2848 BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
2849 return true;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002850 } else if (profile == BluetoothProfile.HID_DEVICE) {
2851 BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
Ivan Podogov5297dba2016-12-30 14:35:09 +00002852 return true;
Jakub Pawlowskiea580fa2017-11-22 11:02:34 -08002853 } else if (profile == BluetoothProfile.HEARING_AID) {
Stanley Tng61dbd812019-01-13 16:04:31 -08002854 if (isHearingAidProfileSupported()) {
2855 BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener);
2856 return true;
2857 }
2858 return false;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002859 } else {
2860 return false;
2861 }
2862 }
2863
2864 /**
2865 * Close the connection of the profile proxy to the Service.
2866 *
2867 * <p> Clients should call this when they are no longer using
2868 * the proxy obtained from {@link #getProfileProxy}.
Jack He6b73b322019-01-03 16:23:41 -08002869 * Profile can be one of {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002870 *
2871 * @param profile
2872 * @param proxy Profile proxy object
2873 */
2874 public void closeProfileProxy(int profile, BluetoothProfile proxy) {
Myles Watson125b5452017-11-27 16:41:47 -08002875 if (proxy == null) {
2876 return;
2877 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002878
2879 switch (profile) {
2880 case BluetoothProfile.HEADSET:
Jack Hea355e5e2017-08-22 16:06:54 -07002881 BluetoothHeadset headset = (BluetoothHeadset) proxy;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002882 headset.close();
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002883 break;
2884 case BluetoothProfile.A2DP:
Jack Hea355e5e2017-08-22 16:06:54 -07002885 BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002886 a2dp.close();
2887 break;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002888 case BluetoothProfile.A2DP_SINK:
Jack Hea355e5e2017-08-22 16:06:54 -07002889 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002890 a2dpSink.close();
2891 break;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002892 case BluetoothProfile.AVRCP_CONTROLLER:
Jack Hea355e5e2017-08-22 16:06:54 -07002893 BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002894 avrcp.close();
2895 break;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002896 case BluetoothProfile.HID_HOST:
2897 BluetoothHidHost iDev = (BluetoothHidHost) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002898 iDev.close();
2899 break;
2900 case BluetoothProfile.PAN:
Jack Hea355e5e2017-08-22 16:06:54 -07002901 BluetoothPan pan = (BluetoothPan) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002902 pan.close();
2903 break;
Chienyuan2fca55d2020-01-08 17:50:08 +08002904 case BluetoothProfile.PBAP:
2905 BluetoothPbap pbap = (BluetoothPbap) proxy;
2906 pbap.close();
2907 break;
Jack Hea355e5e2017-08-22 16:06:54 -07002908 case BluetoothProfile.GATT:
2909 BluetoothGatt gatt = (BluetoothGatt) proxy;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08002910 gatt.close();
2911 break;
2912 case BluetoothProfile.GATT_SERVER:
Jack Hea355e5e2017-08-22 16:06:54 -07002913 BluetoothGattServer gattServer = (BluetoothGattServer) proxy;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08002914 gattServer.close();
2915 break;
Kim Schulz0d376052013-08-22 11:18:02 +02002916 case BluetoothProfile.MAP:
Jack Hea355e5e2017-08-22 16:06:54 -07002917 BluetoothMap map = (BluetoothMap) proxy;
Kim Schulz0d376052013-08-22 11:18:02 +02002918 map.close();
2919 break;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002920 case BluetoothProfile.HEADSET_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002921 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002922 headsetClient.close();
Hemant Gupta7aca90f2013-08-19 19:03:51 +05302923 break;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002924 case BluetoothProfile.SAP:
Jack Hea355e5e2017-08-22 16:06:54 -07002925 BluetoothSap sap = (BluetoothSap) proxy;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002926 sap.close();
2927 break;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002928 case BluetoothProfile.PBAP_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002929 BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002930 pbapClient.close();
2931 break;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002932 case BluetoothProfile.MAP_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002933 BluetoothMapClient mapClient = (BluetoothMapClient) proxy;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002934 mapClient.close();
2935 break;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002936 case BluetoothProfile.HID_DEVICE:
2937 BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
2938 hidDevice.close();
Ivan Podogov5297dba2016-12-30 14:35:09 +00002939 break;
Jakub Pawlowskiea580fa2017-11-22 11:02:34 -08002940 case BluetoothProfile.HEARING_AID:
2941 BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
2942 hearingAid.close();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002943 }
2944 }
2945
Jack He2992cd02017-08-22 21:21:23 -07002946 private final IBluetoothManagerCallback mManagerCallback =
Jack Hea355e5e2017-08-22 16:06:54 -07002947 new IBluetoothManagerCallback.Stub() {
2948 public void onBluetoothServiceUp(IBluetooth bluetoothService) {
Myles Watson125b5452017-11-27 16:41:47 -08002949 if (DBG) {
2950 Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
2951 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002952
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002953 mServiceLock.writeLock().lock();
Jack Hea355e5e2017-08-22 16:06:54 -07002954 mService = bluetoothService;
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002955 mServiceLock.writeLock().unlock();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002956
Jack Hea355e5e2017-08-22 16:06:54 -07002957 synchronized (mProxyServiceStateCallbacks) {
2958 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2959 try {
2960 if (cb != null) {
2961 cb.onBluetoothServiceUp(bluetoothService);
2962 } else {
2963 Log.d(TAG, "onBluetoothServiceUp: cb is null!");
2964 }
2965 } catch (Exception e) {
2966 Log.e(TAG, "", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002967 }
Matthew Xie60675b22015-02-06 14:09:54 -08002968 }
fredc903ac6f2012-04-24 03:59:57 -07002969 }
Ugo Yu4a33b882019-01-08 09:00:09 +08002970 synchronized (sMetadataListeners) {
2971 sMetadataListeners.forEach((device, pair) -> {
2972 try {
2973 mService.registerMetadataListener(sBluetoothMetadataListener,
2974 device);
2975 } catch (RemoteException e) {
2976 Log.e(TAG, "Failed to register metadata listener", e);
2977 }
2978 });
2979 }
fredc0f420372012-04-12 00:02:00 -07002980 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002981
Jack Hea355e5e2017-08-22 16:06:54 -07002982 public void onBluetoothServiceDown() {
Myles Watson125b5452017-11-27 16:41:47 -08002983 if (DBG) {
2984 Log.d(TAG, "onBluetoothServiceDown: " + mService);
2985 }
Jack Hea355e5e2017-08-22 16:06:54 -07002986
2987 try {
2988 mServiceLock.writeLock().lock();
2989 mService = null;
Myles Watson125b5452017-11-27 16:41:47 -08002990 if (mLeScanClients != null) {
2991 mLeScanClients.clear();
2992 }
2993 if (sBluetoothLeAdvertiser != null) {
2994 sBluetoothLeAdvertiser.cleanup();
2995 }
2996 if (sBluetoothLeScanner != null) {
2997 sBluetoothLeScanner.cleanup();
2998 }
Jack Hea355e5e2017-08-22 16:06:54 -07002999 } finally {
3000 mServiceLock.writeLock().unlock();
3001 }
3002
3003 synchronized (mProxyServiceStateCallbacks) {
3004 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
3005 try {
3006 if (cb != null) {
3007 cb.onBluetoothServiceDown();
3008 } else {
3009 Log.d(TAG, "onBluetoothServiceDown: cb is null!");
3010 }
3011 } catch (Exception e) {
3012 Log.e(TAG, "", e);
3013 }
3014 }
3015 }
3016 }
3017
3018 public void onBrEdrDown() {
Myles Watson125b5452017-11-27 16:41:47 -08003019 if (VDBG) {
3020 Log.i(TAG, "onBrEdrDown: " + mService);
3021 }
Jack Hea355e5e2017-08-22 16:06:54 -07003022 }
3023 };
fredc0f420372012-04-12 00:02:00 -07003024
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07003025 /**
Martijn Coenen6c614b72012-04-18 13:01:15 -07003026 * Enable the Bluetooth Adapter, but don't auto-connect devices
3027 * and don't persist state. Only for use by system applications.
Jack Hea355e5e2017-08-22 16:06:54 -07003028 *
Martijn Coenen6c614b72012-04-18 13:01:15 -07003029 * @hide
3030 */
Selim Gurun64bd35e2017-10-17 17:01:38 -07003031 @SystemApi
3032 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
Martijn Coenen6c614b72012-04-18 13:01:15 -07003033 public boolean enableNoAutoConnect() {
Jack He2992cd02017-08-22 21:21:23 -07003034 if (isEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -08003035 if (DBG) {
3036 Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
3037 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07003038 return true;
3039 }
3040 try {
Marie Janssen59804562016-12-28 14:13:21 -08003041 return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
Jack Hea355e5e2017-08-22 16:06:54 -07003042 } catch (RemoteException e) {
3043 Log.e(TAG, "", e);
3044 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07003045 return false;
Martijn Coenen6c614b72012-04-18 13:01:15 -07003046 }
3047
3048 /**
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07003049 * Enable control of the Bluetooth Adapter for a single application.
3050 *
3051 * <p>Some applications need to use Bluetooth for short periods of time to
3052 * transfer data but don't want all the associated implications like
3053 * automatic connection to headsets etc.
3054 *
3055 * <p> Multiple applications can call this. This is reference counted and
3056 * Bluetooth disabled only when no one else is using it. There will be no UI
3057 * shown to the user while bluetooth is being enabled. Any user action will
3058 * override this call. For example, if user wants Bluetooth on and the last
3059 * user of this API wanted to disable Bluetooth, Bluetooth will not be
3060 * turned off.
3061 *
3062 * <p> This API is only meant to be used by internal applications. Third
3063 * party applications but use {@link #enable} and {@link #disable} APIs.
3064 *
3065 * <p> If this API returns true, it means the callback will be called.
3066 * The callback will be called with the current state of Bluetooth.
3067 * If the state is not what was requested, an internal error would be the
Jaikumar Ganeshf5fb6c82011-08-03 14:17:22 -07003068 * reason. If Bluetooth is already on and if this function is called to turn
3069 * it on, the api will return true and a callback will be called.
3070 *
3071 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07003072 *
3073 * @param on True for on, false for off.
3074 * @param callback The callback to notify changes to the state.
3075 * @hide
3076 */
3077 public boolean changeApplicationBluetoothState(boolean on,
Jack Hea355e5e2017-08-22 16:06:54 -07003078 BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07003079 return false;
3080 }
3081
3082 /**
3083 * @hide
3084 */
3085 public interface BluetoothStateChangeCallback {
Myles Watson125b5452017-11-27 16:41:47 -08003086 /**
3087 * @hide
3088 */
3089 void onBluetoothStateChange(boolean on);
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07003090 }
3091
3092 /**
3093 * @hide
3094 */
3095 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
3096 private BluetoothStateChangeCallback mCallback;
3097
Myles Watson125b5452017-11-27 16:41:47 -08003098 StateChangeCallbackWrapper(BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07003099 mCallback = callback;
3100 }
3101
3102 @Override
3103 public void onBluetoothStateChange(boolean on) {
3104 mCallback.onBluetoothStateChange(on);
3105 }
3106 }
3107
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08003108 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
3109 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
3110 return Collections.unmodifiableSet(deviceSet);
Nick Pellybd022f42009-08-14 18:33:38 -07003111 }
Nick Pelly005b2282009-09-10 10:21:56 -07003112
fredc0f420372012-04-12 00:02:00 -07003113 protected void finalize() throws Throwable {
3114 try {
3115 mManagerService.unregisterAdapter(mManagerCallback);
3116 } catch (RemoteException e) {
3117 Log.e(TAG, "", e);
3118 } finally {
3119 super.finalize();
3120 }
3121 }
3122
3123
Nick Pelly005b2282009-09-10 10:21:56 -07003124 /**
Nick Pelly75596b42011-12-07 15:03:55 -08003125 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
Nick Pelly55e66f12009-09-18 11:37:06 -07003126 * <p>Alphabetic characters must be uppercase to be valid.
Nick Pelly005b2282009-09-10 10:21:56 -07003127 *
3128 * @param address Bluetooth address as string
3129 * @return true if the address is valid, false otherwise
3130 */
3131 public static boolean checkBluetoothAddress(String address) {
3132 if (address == null || address.length() != ADDRESS_LENGTH) {
3133 return false;
3134 }
3135 for (int i = 0; i < ADDRESS_LENGTH; i++) {
3136 char c = address.charAt(i);
3137 switch (i % 3) {
Jack Hea355e5e2017-08-22 16:06:54 -07003138 case 0:
3139 case 1:
3140 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
3141 // hex character, OK
3142 break;
3143 }
3144 return false;
3145 case 2:
3146 if (c == ':') {
3147 break; // OK
3148 }
3149 return false;
Nick Pelly005b2282009-09-10 10:21:56 -07003150 }
3151 }
3152 return true;
3153 }
fredc0f420372012-04-12 00:02:00 -07003154
Mathew Inwood4dc66d32018-08-01 15:07:20 +01003155 @UnsupportedAppUsage
fredc0f420372012-04-12 00:02:00 -07003156 /*package*/ IBluetoothManager getBluetoothManager() {
Jack Hea355e5e2017-08-22 16:06:54 -07003157 return mManagerService;
fredc0f420372012-04-12 00:02:00 -07003158 }
3159
Jack He2992cd02017-08-22 21:21:23 -07003160 private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks =
Jack Hea355e5e2017-08-22 16:06:54 -07003161 new ArrayList<IBluetoothManagerCallback>();
fredcd6883532012-04-25 17:46:13 -07003162
Mathew Inwood4dc66d32018-08-01 15:07:20 +01003163 @UnsupportedAppUsage
fredc903ac6f2012-04-24 03:59:57 -07003164 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08003165 synchronized (mProxyServiceStateCallbacks) {
fredcd6883532012-04-25 17:46:13 -07003166 if (cb == null) {
fredcbf072a72012-05-09 16:52:50 -07003167 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
3168 } else if (!mProxyServiceStateCallbacks.contains(cb)) {
3169 mProxyServiceStateCallbacks.add(cb);
fredc903ac6f2012-04-24 03:59:57 -07003170 }
3171 }
3172 return mService;
3173 }
3174
3175 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08003176 synchronized (mProxyServiceStateCallbacks) {
fredcbf072a72012-05-09 16:52:50 -07003177 mProxyServiceStateCallbacks.remove(cb);
fredc0f420372012-04-12 00:02:00 -07003178 }
3179 }
Matthew Xieddf7e472013-03-01 18:41:02 -08003180
3181 /**
Matthew Xiecdd94e32013-04-11 16:36:26 -07003182 * Callback interface used to deliver LE scan results.
Matthew Xieddf7e472013-03-01 18:41:02 -08003183 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07003184 * @see #startLeScan(LeScanCallback)
3185 * @see #startLeScan(UUID[], LeScanCallback)
Matthew Xieddf7e472013-03-01 18:41:02 -08003186 */
Matthew Xiecdd94e32013-04-11 16:36:26 -07003187 public interface LeScanCallback {
3188 /**
3189 * Callback reporting an LE device found during a device scan initiated
3190 * by the {@link BluetoothAdapter#startLeScan} function.
3191 *
3192 * @param device Identifies the remote device
Jack Hea355e5e2017-08-22 16:06:54 -07003193 * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0
3194 * if no RSSI value is available.
3195 * @param scanRecord The content of the advertisement record offered by the remote device.
Matthew Xiecdd94e32013-04-11 16:36:26 -07003196 */
Myles Watson125b5452017-11-27 16:41:47 -08003197 void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
Matthew Xieddf7e472013-03-01 18:41:02 -08003198 }
3199
3200 /**
3201 * Starts a scan for Bluetooth LE devices.
3202 *
3203 * <p>Results of the scan are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07003204 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08003205 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07003206 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08003207 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07003208 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack Hea355e5e2017-08-22 16:06:54 -07003209 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08003210 */
Wei Wangaf74e662014-07-09 14:03:42 -07003211 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07003212 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07003213 public boolean startLeScan(LeScanCallback callback) {
3214 return startLeScan(null, callback);
Matthew Xieddf7e472013-03-01 18:41:02 -08003215 }
3216
3217 /**
3218 * Starts a scan for Bluetooth LE devices, looking for devices that
3219 * advertise given services.
3220 *
3221 * <p>Devices which advertise all specified services are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07003222 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08003223 *
Matthew Xieddf7e472013-03-01 18:41:02 -08003224 * @param serviceUuids Array of services to look for
Matthew Xiecdd94e32013-04-11 16:36:26 -07003225 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08003226 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07003227 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack Hea355e5e2017-08-22 16:06:54 -07003228 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08003229 */
Wei Wangaf74e662014-07-09 14:03:42 -07003230 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07003231 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Wei Wangc3059cc2014-07-23 23:34:00 -07003232 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
Myles Watson125b5452017-11-27 16:41:47 -08003233 if (DBG) {
3234 Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
3235 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07003236 if (callback == null) {
Myles Watson125b5452017-11-27 16:41:47 -08003237 if (DBG) {
3238 Log.e(TAG, "startLeScan: null callback");
3239 }
Matthew Xieddf7e472013-03-01 18:41:02 -08003240 return false;
3241 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003242 BluetoothLeScanner scanner = getBluetoothLeScanner();
3243 if (scanner == null) {
Myles Watson125b5452017-11-27 16:41:47 -08003244 if (DBG) {
3245 Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
3246 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003247 return false;
3248 }
Matthew Xieddf7e472013-03-01 18:41:02 -08003249
Jack Hea355e5e2017-08-22 16:06:54 -07003250 synchronized (mLeScanClients) {
Matthew Xiecdd94e32013-04-11 16:36:26 -07003251 if (mLeScanClients.containsKey(callback)) {
Myles Watson125b5452017-11-27 16:41:47 -08003252 if (DBG) {
3253 Log.e(TAG, "LE Scan has already started");
3254 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07003255 return false;
3256 }
3257
3258 try {
3259 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
Matthew Xie32ab77b2013-05-08 19:26:57 -07003260 if (iGatt == null) {
3261 // BLE is not supported
3262 return false;
3263 }
3264
Wei Wangc3059cc2014-07-23 23:34:00 -07003265 ScanCallback scanCallback = new ScanCallback() {
3266 @Override
3267 public void onScanResult(int callbackType, ScanResult result) {
3268 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
3269 // Should not happen.
3270 Log.e(TAG, "LE Scan has already started");
3271 return;
3272 }
3273 ScanRecord scanRecord = result.getScanRecord();
3274 if (scanRecord == null) {
3275 return;
3276 }
3277 if (serviceUuids != null) {
3278 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
3279 for (UUID uuid : serviceUuids) {
3280 uuids.add(new ParcelUuid(uuid));
3281 }
3282 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
3283 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
Myles Watson125b5452017-11-27 16:41:47 -08003284 if (DBG) {
3285 Log.d(TAG, "uuids does not match");
3286 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003287 return;
3288 }
3289 }
3290 callback.onLeScan(result.getDevice(), result.getRssi(),
3291 scanRecord.getBytes());
3292 }
3293 };
Myles Watson125b5452017-11-27 16:41:47 -08003294 ScanSettings settings = new ScanSettings.Builder().setCallbackType(
3295 ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
3296 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
3297 .build();
Wei Wangc3059cc2014-07-23 23:34:00 -07003298
3299 List<ScanFilter> filters = new ArrayList<ScanFilter>();
3300 if (serviceUuids != null && serviceUuids.length > 0) {
3301 // Note scan filter does not support matching an UUID array so we put one
3302 // UUID to hardware and match the whole array in callback.
Myles Watson125b5452017-11-27 16:41:47 -08003303 ScanFilter filter =
3304 new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuids[0]))
3305 .build();
Wei Wangc3059cc2014-07-23 23:34:00 -07003306 filters.add(filter);
Matthew Xiecdd94e32013-04-11 16:36:26 -07003307 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003308 scanner.startScan(filters, settings, scanCallback);
3309
3310 mLeScanClients.put(callback, scanCallback);
3311 return true;
3312
Matthew Xiecdd94e32013-04-11 16:36:26 -07003313 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -07003314 Log.e(TAG, "", e);
Matthew Xiecdd94e32013-04-11 16:36:26 -07003315 }
3316 }
3317 return false;
Matthew Xieddf7e472013-03-01 18:41:02 -08003318 }
3319
3320 /**
3321 * Stops an ongoing Bluetooth LE device scan.
3322 *
Jack Hea355e5e2017-08-22 16:06:54 -07003323 * @param callback used to identify which scan to stop must be the same handle used to start the
3324 * scan
Wei Wangaf74e662014-07-09 14:03:42 -07003325 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08003326 */
Wei Wangaf74e662014-07-09 14:03:42 -07003327 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07003328 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07003329 public void stopLeScan(LeScanCallback callback) {
Myles Watson125b5452017-11-27 16:41:47 -08003330 if (DBG) {
3331 Log.d(TAG, "stopLeScan()");
3332 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003333 BluetoothLeScanner scanner = getBluetoothLeScanner();
3334 if (scanner == null) {
3335 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08003336 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003337 synchronized (mLeScanClients) {
3338 ScanCallback scanCallback = mLeScanClients.remove(callback);
3339 if (scanCallback == null) {
Myles Watson125b5452017-11-27 16:41:47 -08003340 if (DBG) {
3341 Log.d(TAG, "scan not started yet");
3342 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003343 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08003344 }
Wei Wangc3059cc2014-07-23 23:34:00 -07003345 scanner.stopScan(scanCallback);
Prerepa Viswanadham8f2e74c2014-07-09 12:51:59 -07003346 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07003347 }
Stanley Tnge48468d2017-11-22 16:04:40 -08003348
3349 /**
3350 * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
3351 * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003352 * for incoming connections. The supported Bluetooth transport is LE only.
Stanley Tnge48468d2017-11-22 16:04:40 -08003353 * <p>A remote device connecting to this socket will be authenticated and communication on this
3354 * socket will be encrypted.
3355 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3356 * {@link BluetoothServerSocket}.
Andrew Solovaya44f2c072018-10-02 14:14:42 -07003357 * <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 -08003358 * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
3359 * closed, Bluetooth is turned off, or the application exits unexpectedly.
3360 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3361 * defined and performed by the application.
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003362 * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
Stanley Tnge48468d2017-11-22 16:04:40 -08003363 * socket from another Android device that is given the PSM value.
3364 *
Stanley Tnge48468d2017-11-22 16:04:40 -08003365 * @return an L2CAP CoC BluetoothServerSocket
3366 * @throws IOException on error, for example Bluetooth not available, or insufficient
3367 * permissions, or unable to start this CoC
Stanley Tnge48468d2017-11-22 16:04:40 -08003368 */
3369 @RequiresPermission(Manifest.permission.BLUETOOTH)
Stanley Tng97341da2019-03-12 10:19:49 -07003370 public @NonNull BluetoothServerSocket listenUsingL2capChannel()
Stanley Tnge48468d2017-11-22 16:04:40 -08003371 throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08003372 BluetoothServerSocket socket =
3373 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
3374 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3375 int errno = socket.mSocket.bindListen();
3376 if (errno != 0) {
3377 throw new IOException("Error: " + errno);
3378 }
3379
3380 int assignedPsm = socket.mSocket.getPort();
3381 if (assignedPsm == 0) {
3382 throw new IOException("Error: Unable to assign PSM value");
3383 }
3384 if (DBG) {
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003385 Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
Stanley Tnge48468d2017-11-22 16:04:40 -08003386 + assignedPsm);
3387 }
3388 socket.setChannel(assignedPsm);
3389
3390 return socket;
3391 }
3392
3393 /**
3394 * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003395 * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
3396 * supported Bluetooth transport is LE only.
Stanley Tnge48468d2017-11-22 16:04:40 -08003397 * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003398 * to man-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
Stanley Tnge48468d2017-11-22 16:04:40 -08003399 * authenticated communication channel is desired.
3400 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3401 * {@link BluetoothServerSocket}.
3402 * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
Andrew Solovaya44f2c072018-10-02 14:14:42 -07003403 * can be read from the {@link BluetoothServerSocket#getPsm()} and this value will be released
Stanley Tnge48468d2017-11-22 16:04:40 -08003404 * when this server socket is closed, Bluetooth is turned off, or the application exits
3405 * unexpectedly.
3406 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3407 * defined and performed by the application.
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003408 * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
3409 * socket from another Android device that is given the PSM value.
Stanley Tnge48468d2017-11-22 16:04:40 -08003410 *
Stanley Tnge48468d2017-11-22 16:04:40 -08003411 * @return an L2CAP CoC BluetoothServerSocket
3412 * @throws IOException on error, for example Bluetooth not available, or insufficient
3413 * permissions, or unable to start this CoC
Stanley Tnge48468d2017-11-22 16:04:40 -08003414 */
3415 @RequiresPermission(Manifest.permission.BLUETOOTH)
Stanley Tng97341da2019-03-12 10:19:49 -07003416 public @NonNull BluetoothServerSocket listenUsingInsecureL2capChannel()
Stanley Tnge48468d2017-11-22 16:04:40 -08003417 throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08003418 BluetoothServerSocket socket =
3419 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
3420 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3421 int errno = socket.mSocket.bindListen();
3422 if (errno != 0) {
3423 throw new IOException("Error: " + errno);
3424 }
3425
3426 int assignedPsm = socket.mSocket.getPort();
3427 if (assignedPsm == 0) {
3428 throw new IOException("Error: Unable to assign PSM value");
3429 }
3430 if (DBG) {
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003431 Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
Stanley Tnge48468d2017-11-22 16:04:40 -08003432 + assignedPsm);
3433 }
3434 socket.setChannel(assignedPsm);
3435
3436 return socket;
3437 }
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003438
3439 /**
Ugo Yu50e3c082019-03-05 16:20:27 +08003440 * Register a {@link #OnMetadataChangedListener} to receive update about metadata
Ugo Yu4a33b882019-01-08 09:00:09 +08003441 * changes for this {@link BluetoothDevice}.
3442 * Registration must be done when Bluetooth is ON and will last until
Ugo Yu50e3c082019-03-05 16:20:27 +08003443 * {@link #removeOnMetadataChangedListener(BluetoothDevice)} is called, even when Bluetooth
Ugo Yu4a33b882019-01-08 09:00:09 +08003444 * restarted in the middle.
3445 * All input parameters should not be null or {@link NullPointerException} will be triggered.
Ugo Yu50e3c082019-03-05 16:20:27 +08003446 * The same {@link BluetoothDevice} and {@link #OnMetadataChangedListener} pair can only be
3447 * registered once, double registration would cause {@link IllegalArgumentException}.
Ugo Yu4a33b882019-01-08 09:00:09 +08003448 *
3449 * @param device {@link BluetoothDevice} that will be registered
Ugo Yu50e3c082019-03-05 16:20:27 +08003450 * @param executor the executor for listener callback
3451 * @param listener {@link #OnMetadataChangedListener} that will receive asynchronous callbacks
Ugo Yu4a33b882019-01-08 09:00:09 +08003452 * @return true on success, false on error
Ugo Yu50e3c082019-03-05 16:20:27 +08003453 * @throws NullPointerException If one of {@code listener}, {@code device} or {@code executor}
Ugo Yu4a33b882019-01-08 09:00:09 +08003454 * is null.
Ugo Yu50e3c082019-03-05 16:20:27 +08003455 * @throws IllegalArgumentException The same {@link #OnMetadataChangedListener} and
Ugo Yu4a33b882019-01-08 09:00:09 +08003456 * {@link BluetoothDevice} are registered twice.
3457 * @hide
3458 */
3459 @SystemApi
3460 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Ugo Yu50e3c082019-03-05 16:20:27 +08003461 public boolean addOnMetadataChangedListener(@NonNull BluetoothDevice device,
3462 @NonNull Executor executor, @NonNull OnMetadataChangedListener listener) {
3463 if (DBG) Log.d(TAG, "addOnMetadataChangedListener()");
Ugo Yu4a33b882019-01-08 09:00:09 +08003464
3465 final IBluetooth service = mService;
3466 if (service == null) {
3467 Log.e(TAG, "Bluetooth is not enabled. Cannot register metadata listener");
3468 return false;
3469 }
3470 if (listener == null) {
3471 throw new NullPointerException("listener is null");
3472 }
3473 if (device == null) {
3474 throw new NullPointerException("device is null");
3475 }
Ugo Yu50e3c082019-03-05 16:20:27 +08003476 if (executor == null) {
3477 throw new NullPointerException("executor is null");
Ugo Yu4a33b882019-01-08 09:00:09 +08003478 }
3479
3480 synchronized (sMetadataListeners) {
Ugo Yu50e3c082019-03-05 16:20:27 +08003481 List<Pair<OnMetadataChangedListener, Executor>> listenerList =
3482 sMetadataListeners.get(device);
Ugo Yu4a33b882019-01-08 09:00:09 +08003483 if (listenerList == null) {
Ugo Yu50e3c082019-03-05 16:20:27 +08003484 // Create new listener/executor list for registeration
Ugo Yu4a33b882019-01-08 09:00:09 +08003485 listenerList = new ArrayList<>();
3486 sMetadataListeners.put(device, listenerList);
3487 } else {
3488 // Check whether this device was already registed by the lisenter
3489 if (listenerList.stream().anyMatch((pair) -> (pair.first.equals(listener)))) {
3490 throw new IllegalArgumentException("listener was already regestered"
3491 + " for the device");
3492 }
3493 }
3494
Ugo Yu50e3c082019-03-05 16:20:27 +08003495 Pair<OnMetadataChangedListener, Executor> listenerPair = new Pair(listener, executor);
Ugo Yu4a33b882019-01-08 09:00:09 +08003496 listenerList.add(listenerPair);
3497
3498 boolean ret = false;
3499 try {
3500 ret = service.registerMetadataListener(sBluetoothMetadataListener, device);
3501 } catch (RemoteException e) {
3502 Log.e(TAG, "registerMetadataListener fail", e);
3503 } finally {
3504 if (!ret) {
3505 // Remove listener registered earlier when fail.
3506 listenerList.remove(listenerPair);
3507 if (listenerList.isEmpty()) {
3508 // Remove the device if its listener list is empty
3509 sMetadataListeners.remove(device);
3510 }
3511 }
3512 }
3513 return ret;
3514 }
3515 }
3516
3517 /**
Ugo Yu50e3c082019-03-05 16:20:27 +08003518 * Unregister a {@link #OnMetadataChangedListener} from a registered {@link BluetoothDevice}.
Ugo Yu4a33b882019-01-08 09:00:09 +08003519 * Unregistration can be done when Bluetooth is either ON or OFF.
Ugo Yu50e3c082019-03-05 16:20:27 +08003520 * {@link #addOnMetadataChangedListener(OnMetadataChangedListener, BluetoothDevice, Executor)}
3521 * must be called before unregisteration.
Ugo Yu4a33b882019-01-08 09:00:09 +08003522 *
Ugo Yu50e3c082019-03-05 16:20:27 +08003523 * @param device {@link BluetoothDevice} that will be unregistered. It
3524 * should not be null or {@link NullPointerException} will be triggered.
3525 * @param listener {@link OnMetadataChangedListener} that will be unregistered. It
Ugo Yu4a33b882019-01-08 09:00:09 +08003526 * should not be null or {@link NullPointerException} will be triggered.
3527 * @return true on success, false on error
Ugo Yu50e3c082019-03-05 16:20:27 +08003528 * @throws NullPointerException If {@code listener} or {@code device} is null.
Ugo Yu4a33b882019-01-08 09:00:09 +08003529 * @throws IllegalArgumentException If {@code device} has not been registered before.
3530 * @hide
3531 */
3532 @SystemApi
3533 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Ugo Yu50e3c082019-03-05 16:20:27 +08003534 public boolean removeOnMetadataChangedListener(@NonNull BluetoothDevice device,
3535 @NonNull OnMetadataChangedListener listener) {
3536 if (DBG) Log.d(TAG, "removeOnMetadataChangedListener()");
Ugo Yu4a33b882019-01-08 09:00:09 +08003537 if (device == null) {
3538 throw new NullPointerException("device is null");
3539 }
Ugo Yu50e3c082019-03-05 16:20:27 +08003540 if (listener == null) {
3541 throw new NullPointerException("listener is null");
3542 }
Ugo Yu4a33b882019-01-08 09:00:09 +08003543
3544 synchronized (sMetadataListeners) {
Ugo Yu50e3c082019-03-05 16:20:27 +08003545 if (!sMetadataListeners.containsKey(device)) {
Ugo Yu4a33b882019-01-08 09:00:09 +08003546 throw new IllegalArgumentException("device was not registered");
3547 }
Ugo Yu50e3c082019-03-05 16:20:27 +08003548 // Remove issued listener from the registered device
3549 sMetadataListeners.get(device).removeIf((pair) -> (pair.first.equals(listener)));
Ugo Yu4a33b882019-01-08 09:00:09 +08003550
Ugo Yu50e3c082019-03-05 16:20:27 +08003551 if (sMetadataListeners.get(device).isEmpty()) {
3552 // Unregister to Bluetooth service if all listeners are removed from
3553 // the registered device
3554 sMetadataListeners.remove(device);
3555 final IBluetooth service = mService;
3556 if (service == null) {
3557 // Bluetooth is OFF, do nothing to Bluetooth service.
3558 return true;
3559 }
3560 try {
3561 return service.unregisterMetadataListener(device);
3562 } catch (RemoteException e) {
3563 Log.e(TAG, "unregisterMetadataListener fail", e);
3564 return false;
3565 }
Ugo Yu4a33b882019-01-08 09:00:09 +08003566 }
3567 }
Ugo Yu50e3c082019-03-05 16:20:27 +08003568 return true;
Ugo Yu4a33b882019-01-08 09:00:09 +08003569 }
3570
3571 /**
Ugo Yu50e3c082019-03-05 16:20:27 +08003572 * This interface is used to implement {@link BluetoothAdapter} metadata listener.
Ugo Yu4a33b882019-01-08 09:00:09 +08003573 * @hide
3574 */
3575 @SystemApi
Ugo Yu50e3c082019-03-05 16:20:27 +08003576 public interface OnMetadataChangedListener {
Ugo Yu4a33b882019-01-08 09:00:09 +08003577 /**
3578 * Callback triggered if the metadata of {@link BluetoothDevice} registered in
Ugo Yu50e3c082019-03-05 16:20:27 +08003579 * {@link #addOnMetadataChangedListener}.
Ugo Yu4a33b882019-01-08 09:00:09 +08003580 *
3581 * @param device changed {@link BluetoothDevice}.
3582 * @param key changed metadata key, one of BluetoothDevice.METADATA_*.
Ugo Yu50e3c082019-03-05 16:20:27 +08003583 * @param value the new value of metadata as byte array.
Ugo Yu4a33b882019-01-08 09:00:09 +08003584 */
Ugo Yu50e3c082019-03-05 16:20:27 +08003585 void onMetadataChanged(@NonNull BluetoothDevice device, int key,
3586 @Nullable byte[] value);
Ugo Yu4a33b882019-01-08 09:00:09 +08003587 }
Rahul Sabnisdf1ef4a2019-11-27 18:09:33 -08003588
3589 /**
3590 * Converts old constant of priority to the new for connection policy
3591 *
3592 * @param priority is the priority to convert to connection policy
3593 * @return the equivalent connection policy constant to the priority
3594 *
3595 * @hide
3596 */
3597 public static @ConnectionPolicy int priorityToConnectionPolicy(int priority) {
3598 switch(priority) {
3599 case BluetoothProfile.PRIORITY_AUTO_CONNECT:
3600 return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
3601 case BluetoothProfile.PRIORITY_ON:
3602 return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
3603 case BluetoothProfile.PRIORITY_OFF:
3604 return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
3605 case BluetoothProfile.PRIORITY_UNDEFINED:
3606 return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
3607 default:
3608 Log.e(TAG, "setPriority: Invalid priority: " + priority);
3609 return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
3610 }
3611 }
3612
3613 /**
3614 * Converts new constant of connection policy to the old for priority
3615 *
3616 * @param connectionPolicy is the connection policy to convert to priority
3617 * @return the equivalent priority constant to the connectionPolicy
3618 *
3619 * @hide
3620 */
3621 public static int connectionPolicyToPriority(@ConnectionPolicy int connectionPolicy) {
3622 switch(connectionPolicy) {
3623 case BluetoothProfile.CONNECTION_POLICY_ALLOWED:
3624 return BluetoothProfile.PRIORITY_ON;
3625 case BluetoothProfile.CONNECTION_POLICY_FORBIDDEN:
3626 return BluetoothProfile.PRIORITY_OFF;
3627 case BluetoothProfile.CONNECTION_POLICY_UNKNOWN:
3628 return BluetoothProfile.PRIORITY_UNDEFINED;
3629 }
3630 return BluetoothProfile.PRIORITY_UNDEFINED;
3631 }
Nick Pellybd022f42009-08-14 18:33:38 -07003632}