blob: 38245fb2ad24e9c06df514f00db10eca13cd9f2b [file] [log] [blame]
Nick Pellybd022f42009-08-14 18:33:38 -07001/*
Myles Watson125b5452017-11-27 16:41:47 -08002 * Copyright 2009-2016 The Android Open Source Project
3 * Copyright 2015 Samsung LSI
Nick Pellybd022f42009-08-14 18:33:38 -07004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package android.bluetooth;
19
Tor Norbye2d497522015-04-23 17:10:21 -070020import android.Manifest;
21import android.annotation.IntDef;
22import android.annotation.RequiresPermission;
Nick Pellyde893f52009-09-08 13:15:33 -070023import android.annotation.SdkConstant;
24import android.annotation.SdkConstant.SdkConstantType;
Wei Wangd91f1932015-03-19 15:09:56 -070025import android.annotation.SystemApi;
Mathew Inwood4dc66d32018-08-01 15:07:20 +010026import android.annotation.UnsupportedAppUsage;
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -070027import android.app.ActivityThread;
Wei Wang6d811182014-05-22 12:10:25 -070028import android.bluetooth.le.BluetoothLeAdvertiser;
29import android.bluetooth.le.BluetoothLeScanner;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -080030import android.bluetooth.le.PeriodicAdvertisingManager;
Wei Wangaf74e662014-07-09 14:03:42 -070031import android.bluetooth.le.ScanCallback;
Wei Wangc3059cc2014-07-23 23:34:00 -070032import android.bluetooth.le.ScanFilter;
33import android.bluetooth.le.ScanRecord;
Wei Wang9fb17912014-07-01 15:10:06 -070034import android.bluetooth.le.ScanResult;
Wei Wangaf74e662014-07-09 14:03:42 -070035import android.bluetooth.le.ScanSettings;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -070036import android.content.Context;
Adam Lesinski010bf372016-04-11 12:18:18 -070037import android.os.BatteryStats;
Wei Wang46ab7232015-05-07 16:25:33 -070038import android.os.Binder;
Nick Pellyf242b7b2009-10-08 00:12:45 +020039import android.os.IBinder;
Nick Pellyaef439e2009-09-28 12:33:17 -070040import android.os.ParcelUuid;
Nick Pellybd022f42009-08-14 18:33:38 -070041import android.os.RemoteException;
Adam Lesinski010bf372016-04-11 12:18:18 -070042import android.os.ResultReceiver;
Nick Pellyf242b7b2009-10-08 00:12:45 +020043import android.os.ServiceManager;
Adam Lesinski010bf372016-04-11 12:18:18 -070044import android.os.SynchronousResultReceiver;
Ajay Panickerb6e1daf2016-02-29 16:09:14 -080045import android.os.SystemProperties;
Nick Pellybd022f42009-08-14 18:33:38 -070046import android.util.Log;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070047import android.util.Pair;
Wei Wang18c76932013-10-29 21:05:37 -070048
Nick Pellybd022f42009-08-14 18:33:38 -070049import java.io.IOException;
Tor Norbye2d497522015-04-23 17:10:21 -070050import java.lang.annotation.Retention;
51import java.lang.annotation.RetentionPolicy;
fredc903ac6f2012-04-24 03:59:57 -070052import java.util.ArrayList;
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -070053import java.util.Arrays;
Nick Pellybd022f42009-08-14 18:33:38 -070054import java.util.Collections;
Matthew Xiecdd94e32013-04-11 16:36:26 -070055import java.util.HashMap;
Wei Wang18c76932013-10-29 21:05:37 -070056import java.util.HashSet;
Wei Wang9fb17912014-07-01 15:10:06 -070057import java.util.List;
Jeff Sharkeyfea17de2013-06-11 14:13:09 -070058import java.util.Locale;
Matthew Xiecdd94e32013-04-11 16:36:26 -070059import java.util.Map;
Nick Pelly24bb9b82009-10-02 20:34:18 -070060import java.util.Set;
Nick Pelly16fb88a2009-10-07 07:44:03 +020061import java.util.UUID;
Adam Lesinski010bf372016-04-11 12:18:18 -070062import java.util.concurrent.TimeoutException;
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -070063import java.util.concurrent.locks.ReentrantReadWriteLock;
Nick Pellybd022f42009-08-14 18:33:38 -070064
65/**
Scott Main9fab0ae2009-11-03 18:17:59 -080066 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
67 * lets you perform fundamental Bluetooth tasks, such as initiate
68 * device discovery, query a list of bonded (paired) devices,
69 * instantiate a {@link BluetoothDevice} using a known MAC address, and create
70 * a {@link BluetoothServerSocket} to listen for connection requests from other
Matthew Xieb30f91e2013-05-29 10:19:06 -070071 * devices, and start a scan for Bluetooth LE devices.
Scott Main9fab0ae2009-11-03 18:17:59 -080072 *
73 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
Marie Janssen553c8c72017-01-12 16:00:30 -080074 * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}.
75 * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter}
76 * method instead.
77 * </p><p>
Scott Main9fab0ae2009-11-03 18:17:59 -080078 * Fundamentally, this is your starting point for all
79 * Bluetooth actions. Once you have the local adapter, you can get a set of
80 * {@link BluetoothDevice} objects representing all paired devices with
81 * {@link #getBondedDevices()}; start device discovery with
82 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
Stanley Tnge48468d2017-11-22 16:04:40 -080083 * listen for incoming RFComm connection requests with {@link
Stanley Tng1bff4ba2018-06-29 14:05:04 -070084 * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
85 * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
Matthew Xieb30f91e2013-05-29 10:19:06 -070086 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
Marie Janssen553c8c72017-01-12 16:00:30 -080087 * </p>
88 * <p>This class is thread safe.</p>
Scott Main9fab0ae2009-11-03 18:17:59 -080089 * <p class="note"><strong>Note:</strong>
90 * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
91 * permission and some also require the
92 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
Marie Janssen553c8c72017-01-12 16:00:30 -080093 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -080094 * <div class="special reference">
95 * <h3>Developer Guides</h3>
Hemal Patel65813df2016-08-17 13:18:14 -070096 * <p>
Jack Hea355e5e2017-08-22 16:06:54 -070097 * For more information about using Bluetooth, read the <a href=
Hemal Patel65813df2016-08-17 13:18:14 -070098 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
99 * guide.
100 * </p>
Joe Fernandez3aef8e1d2011-12-20 10:38:34 -0800101 * </div>
102 *
Scott Main9fab0ae2009-11-03 18:17:59 -0800103 * {@see BluetoothDevice}
104 * {@see BluetoothServerSocket}
Nick Pellybd022f42009-08-14 18:33:38 -0700105 */
106public final class BluetoothAdapter {
107 private static final String TAG = "BluetoothAdapter";
fredc0f420372012-04-12 00:02:00 -0700108 private static final boolean DBG = true;
Matthew Xie3b6214f2012-08-29 00:12:29 -0700109 private static final boolean VDBG = false;
Nick Pellybd022f42009-08-14 18:33:38 -0700110
Nick Pellyde893f52009-09-08 13:15:33 -0700111 /**
Svet Ganov408abf72015-05-12 19:13:36 -0700112 * Default MAC address reported to a client that does not have the
113 * android.permission.LOCAL_MAC_ADDRESS permission.
114 *
115 * @hide
116 */
117 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
118
119 /**
Nick Pellyb24e11b2009-09-08 17:40:43 -0700120 * Sentinel error value for this class. Guaranteed to not equal any other
121 * integer constant in this class. Provided as a convenience for functions
122 * that require a sentinel error value, for example:
123 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
124 * BluetoothAdapter.ERROR)</code>
125 */
Nick Pelly005b2282009-09-10 10:21:56 -0700126 public static final int ERROR = Integer.MIN_VALUE;
Nick Pellyb24e11b2009-09-08 17:40:43 -0700127
128 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700129 * Broadcast Action: The state of the local Bluetooth adapter has been
130 * changed.
131 * <p>For example, Bluetooth has been turned on or off.
Nick Pelly005b2282009-09-10 10:21:56 -0700132 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700133 * #EXTRA_PREVIOUS_STATE} containing the new and old states
134 * respectively.
135 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
136 */
Myles Watson125b5452017-11-27 16:41:47 -0800137 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
138 ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
Nick Pellybd022f42009-08-14 18:33:38 -0700139
Nick Pellyde893f52009-09-08 13:15:33 -0700140 /**
141 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
142 * intents to request the current power state. Possible values are:
143 * {@link #STATE_OFF},
144 * {@link #STATE_TURNING_ON},
145 * {@link #STATE_ON},
146 * {@link #STATE_TURNING_OFF},
147 */
Myles Watson125b5452017-11-27 16:41:47 -0800148 public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
Nick Pellyde893f52009-09-08 13:15:33 -0700149 /**
150 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
151 * intents to request the previous power state. Possible values are:
152 * {@link #STATE_OFF},
153 * {@link #STATE_TURNING_ON},
154 * {@link #STATE_ON},
Etan Cohenfd840dd2015-04-23 18:25:08 -0700155 * {@link #STATE_TURNING_OFF}
Nick Pellyde893f52009-09-08 13:15:33 -0700156 */
157 public static final String EXTRA_PREVIOUS_STATE =
Nick Pelly005b2282009-09-10 10:21:56 -0700158 "android.bluetooth.adapter.extra.PREVIOUS_STATE";
Nick Pellybd022f42009-08-14 18:33:38 -0700159
Tor Norbye2d497522015-04-23 17:10:21 -0700160 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700161 @IntDef(prefix = { "STATE_" }, value = {
Myles Watson125b5452017-11-27 16:41:47 -0800162 STATE_OFF,
163 STATE_TURNING_ON,
164 STATE_ON,
165 STATE_TURNING_OFF,
166 STATE_BLE_TURNING_ON,
167 STATE_BLE_ON,
168 STATE_BLE_TURNING_OFF
169 })
Tor Norbye2d497522015-04-23 17:10:21 -0700170 @Retention(RetentionPolicy.SOURCE)
Myles Watson125b5452017-11-27 16:41:47 -0800171 public @interface AdapterState {}
Tor Norbye2d497522015-04-23 17:10:21 -0700172
Nick Pellyde893f52009-09-08 13:15:33 -0700173 /**
174 * Indicates the local Bluetooth adapter is off.
175 */
Nick Pelly005b2282009-09-10 10:21:56 -0700176 public static final int STATE_OFF = 10;
Nick Pellyde893f52009-09-08 13:15:33 -0700177 /**
178 * Indicates the local Bluetooth adapter is turning on. However local
179 * clients should wait for {@link #STATE_ON} before attempting to
180 * use the adapter.
181 */
Nick Pelly005b2282009-09-10 10:21:56 -0700182 public static final int STATE_TURNING_ON = 11;
Nick Pellyde893f52009-09-08 13:15:33 -0700183 /**
184 * Indicates the local Bluetooth adapter is on, and ready for use.
185 */
Nick Pelly005b2282009-09-10 10:21:56 -0700186 public static final int STATE_ON = 12;
Nick Pellyde893f52009-09-08 13:15:33 -0700187 /**
188 * Indicates the local Bluetooth adapter is turning off. Local clients
189 * should immediately attempt graceful disconnection of any remote links.
190 */
Nick Pelly005b2282009-09-10 10:21:56 -0700191 public static final int STATE_TURNING_OFF = 13;
Nick Pellyde893f52009-09-08 13:15:33 -0700192
193 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800194 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
Jack Hea355e5e2017-08-22 16:06:54 -0700195 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800196 * @hide
197 */
198 public static final int STATE_BLE_TURNING_ON = 14;
199
200 /**
201 * Indicates the local Bluetooth adapter is in LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700202 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800203 * @hide
204 */
205 public static final int STATE_BLE_ON = 15;
206
207 /**
208 * Indicates the local Bluetooth adapter is turning off LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700209 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800210 * @hide
211 */
212 public static final int STATE_BLE_TURNING_OFF = 16;
213
214 /**
Stanley Tnge48468d2017-11-22 16:04:40 -0800215 * UUID of the GATT Read Characteristics for LE_PSM value.
216 *
217 * @hide
218 */
219 public static final UUID LE_PSM_CHARACTERISTIC_UUID =
220 UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
221
222 /**
Marie Janssencb21ad72016-12-13 10:51:02 -0800223 * Human-readable string helper for AdapterState
Jack Hea355e5e2017-08-22 16:06:54 -0700224 *
Marie Janssencb21ad72016-12-13 10:51:02 -0800225 * @hide
226 */
227 public static String nameForState(@AdapterState int state) {
Jack Hea355e5e2017-08-22 16:06:54 -0700228 switch (state) {
229 case STATE_OFF:
230 return "OFF";
231 case STATE_TURNING_ON:
232 return "TURNING_ON";
233 case STATE_ON:
234 return "ON";
235 case STATE_TURNING_OFF:
236 return "TURNING_OFF";
237 case STATE_BLE_TURNING_ON:
238 return "BLE_TURNING_ON";
239 case STATE_BLE_ON:
240 return "BLE_ON";
241 case STATE_BLE_TURNING_OFF:
242 return "BLE_TURNING_OFF";
243 default:
244 return "?!?!? (" + state + ")";
Marie Janssencb21ad72016-12-13 10:51:02 -0800245 }
246 }
247
248 /**
Nick Pelly18b1e792009-09-24 11:14:15 -0700249 * Activity Action: Show a system activity that requests discoverable mode.
Scott Main6d95fc02009-11-19 17:00:19 -0800250 * This activity will also request the user to turn on Bluetooth if it
Nick Pelly1acdcc12009-09-28 10:33:55 -0700251 * is not currently enabled.
Nick Pelly18b1e792009-09-24 11:14:15 -0700252 * <p>Discoverable mode is equivalent to {@link
253 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
254 * this Bluetooth adapter when they perform a discovery.
Scott Main6d95fc02009-11-19 17:00:19 -0800255 * <p>For privacy, Android is not discoverable by default.
256 * <p>The sender of this Intent can optionally use extra field {@link
Nick Pelly18b1e792009-09-24 11:14:15 -0700257 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
258 * discoverability. Currently the default duration is 120 seconds, and
259 * maximum duration is capped at 300 seconds for each request.
260 * <p>Notification of the result of this activity is posted using the
261 * {@link android.app.Activity#onActivityResult} callback. The
262 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800263 * will be the duration (in seconds) of discoverability or
264 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
265 * discoverability or an error has occurred.
Nick Pelly18b1e792009-09-24 11:14:15 -0700266 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
Scott Main6d95fc02009-11-19 17:00:19 -0800267 * for global notification whenever the scan mode changes. For example, an
268 * application can be notified when the device has ended discoverability.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700269 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pelly18b1e792009-09-24 11:14:15 -0700270 */
Myles Watson125b5452017-11-27 16:41:47 -0800271 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
272 ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
Nick Pelly18b1e792009-09-24 11:14:15 -0700273
274 /**
275 * Used as an optional int extra field in {@link
276 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
277 * for discoverability in seconds. The current default is 120 seconds, and
278 * requests over 300 seconds will be capped. These values could change.
279 */
280 public static final String EXTRA_DISCOVERABLE_DURATION =
281 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
282
283 /**
Nick Pelly1acdcc12009-09-28 10:33:55 -0700284 * Activity Action: Show a system activity that allows the user to turn on
285 * Bluetooth.
286 * <p>This system activity will return once Bluetooth has completed turning
287 * on, or the user has decided not to turn Bluetooth on.
288 * <p>Notification of the result of this activity is posted using the
289 * {@link android.app.Activity#onActivityResult} callback. The
290 * <code>resultCode</code>
Michael Chancdd28642009-11-05 18:29:01 -0800291 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
292 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
293 * has rejected the request or an error has occurred.
Nick Pelly1acdcc12009-09-28 10:33:55 -0700294 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
295 * for global notification whenever Bluetooth is turned on or off.
296 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
297 */
Myles Watson125b5452017-11-27 16:41:47 -0800298 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
299 ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
Nick Pelly1acdcc12009-09-28 10:33:55 -0700300
301 /**
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700302 * Activity Action: Show a system activity that allows the user to turn off
303 * Bluetooth. This is used only if permission review is enabled which is for
304 * apps targeting API less than 23 require a permission review before any of
305 * the app's components can run.
306 * <p>This system activity will return once Bluetooth has completed turning
307 * off, or the user has decided not to turn Bluetooth off.
308 * <p>Notification of the result of this activity is posted using the
309 * {@link android.app.Activity#onActivityResult} callback. The
310 * <code>resultCode</code>
311 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
312 * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
313 * has rejected the request or an error has occurred.
314 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
315 * for global notification whenever Bluetooth is turned on or off.
316 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
317 *
318 * @hide
319 */
Myles Watson125b5452017-11-27 16:41:47 -0800320 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
321 ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE";
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -0700322
323 /**
Wei Wangd91f1932015-03-19 15:09:56 -0700324 * Activity Action: Show a system activity that allows user to enable BLE scans even when
325 * Bluetooth is turned off.<p>
326 *
327 * Notification of result of this activity is posted using
328 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
329 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
330 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
331 * error occurred.
332 *
333 * @hide
334 */
335 @SystemApi
336 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
337 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
338 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
339
340 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700341 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
342 * has changed.
Nick Pelly005b2282009-09-10 10:21:56 -0700343 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
Nick Pellyde893f52009-09-08 13:15:33 -0700344 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
345 * respectively.
346 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
347 */
Myles Watson125b5452017-11-27 16:41:47 -0800348 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
349 ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
Nick Pellyde893f52009-09-08 13:15:33 -0700350
351 /**
352 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
353 * intents to request the current scan mode. Possible values are:
354 * {@link #SCAN_MODE_NONE},
355 * {@link #SCAN_MODE_CONNECTABLE},
356 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
357 */
Nick Pelly005b2282009-09-10 10:21:56 -0700358 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700359 /**
360 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
361 * intents to request the previous scan mode. Possible values are:
362 * {@link #SCAN_MODE_NONE},
363 * {@link #SCAN_MODE_CONNECTABLE},
364 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
365 */
366 public static final String EXTRA_PREVIOUS_SCAN_MODE =
Nick Pelly005b2282009-09-10 10:21:56 -0700367 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
Nick Pellyde893f52009-09-08 13:15:33 -0700368
Tor Norbye2d497522015-04-23 17:10:21 -0700369 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700370 @IntDef(prefix = { "SCAN_" }, value = {
371 SCAN_MODE_NONE,
372 SCAN_MODE_CONNECTABLE,
373 SCAN_MODE_CONNECTABLE_DISCOVERABLE
374 })
Tor Norbye2d497522015-04-23 17:10:21 -0700375 @Retention(RetentionPolicy.SOURCE)
Myles Watson125b5452017-11-27 16:41:47 -0800376 public @interface ScanMode {}
Tor Norbye2d497522015-04-23 17:10:21 -0700377
Nick Pellyde893f52009-09-08 13:15:33 -0700378 /**
379 * Indicates that both inquiry scan and page scan are disabled on the local
380 * Bluetooth adapter. Therefore this device is neither discoverable
381 * nor connectable from remote Bluetooth devices.
382 */
Nick Pelly005b2282009-09-10 10:21:56 -0700383 public static final int SCAN_MODE_NONE = 20;
Nick Pellyde893f52009-09-08 13:15:33 -0700384 /**
385 * Indicates that inquiry scan is disabled, but page scan is enabled on the
386 * local Bluetooth adapter. Therefore this device is not discoverable from
387 * remote Bluetooth devices, but is connectable from remote devices that
388 * have previously discovered this device.
389 */
Nick Pelly005b2282009-09-10 10:21:56 -0700390 public static final int SCAN_MODE_CONNECTABLE = 21;
Nick Pellyde893f52009-09-08 13:15:33 -0700391 /**
392 * Indicates that both inquiry scan and page scan are enabled on the local
393 * Bluetooth adapter. Therefore this device is both discoverable and
394 * connectable from remote Bluetooth devices.
395 */
Nick Pelly005b2282009-09-10 10:21:56 -0700396 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
Nick Pellybd022f42009-08-14 18:33:38 -0700397
Nick Pelly005b2282009-09-10 10:21:56 -0700398 /**
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -0700399 * Device only has a display.
400 *
401 * @hide
402 */
403 public static final int IO_CAPABILITY_OUT = 0;
404
405 /**
406 * Device has a display and the ability to input Yes/No.
407 *
408 * @hide
409 */
410 public static final int IO_CAPABILITY_IO = 1;
411
412 /**
413 * Device only has a keyboard for entry but no display.
414 *
415 * @hide
416 */
417 public static final int IO_CAPABILITY_IN = 2;
418
419 /**
420 * Device has no Input or Output capability.
421 *
422 * @hide
423 */
424 public static final int IO_CAPABILITY_NONE = 3;
425
426 /**
427 * Device has a display and a full keyboard.
428 *
429 * @hide
430 */
431 public static final int IO_CAPABILITY_KBDISP = 4;
432
433 /**
434 * Maximum range value for Input/Output capabilities.
435 *
436 * <p>This should be updated when adding a new Input/Output capability. Other code
437 * like validation depends on this being accurate.
438 *
439 * @hide
440 */
441 public static final int IO_CAPABILITY_MAX = 5;
442
443 /**
444 * The Input/Output capability of the device is unknown.
445 *
446 * @hide
447 */
448 public static final int IO_CAPABILITY_UNKNOWN = 255;
449
Pulkit Bhuwalka80238142018-04-20 16:56:53 -0700450 /** @hide */
451 @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE,
452 IO_CAPABILITY_KBDISP})
453 @Retention(RetentionPolicy.SOURCE)
454 public @interface IoCapability {}
455
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -0700456 /**
Nick Pelly005b2282009-09-10 10:21:56 -0700457 * Broadcast Action: The local Bluetooth adapter has started the remote
458 * device discovery process.
459 * <p>This usually involves an inquiry scan of about 12 seconds, followed
460 * by a page scan of each new device to retrieve its Bluetooth name.
461 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
462 * remote Bluetooth devices are found.
463 * <p>Device discovery is a heavyweight procedure. New connections to
464 * remote Bluetooth devices should not be attempted while discovery is in
465 * progress, and existing connections will experience limited bandwidth
466 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
467 * discovery.
468 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
469 */
Myles Watson125b5452017-11-27 16:41:47 -0800470 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
471 ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
Nick Pelly005b2282009-09-10 10:21:56 -0700472 /**
473 * Broadcast Action: The local Bluetooth adapter has finished the device
474 * discovery process.
475 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
476 */
Myles Watson125b5452017-11-27 16:41:47 -0800477 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
478 ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
Nick Pelly005b2282009-09-10 10:21:56 -0700479
480 /**
481 * Broadcast Action: The local Bluetooth adapter has changed its friendly
482 * Bluetooth name.
483 * <p>This name is visible to remote Bluetooth devices.
484 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
485 * the name.
486 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
487 */
Myles Watson125b5452017-11-27 16:41:47 -0800488 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
489 ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
Nick Pelly005b2282009-09-10 10:21:56 -0700490 /**
491 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
492 * intents to request the local Bluetooth name.
493 */
494 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
495
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700496 /**
497 * Intent used to broadcast the change in connection state of the local
498 * Bluetooth adapter to a profile of the remote device. When the adapter is
499 * not connected to any profiles of any remote devices and it attempts a
Ricardo Loo Forondaf710a232018-01-24 17:49:18 -0800500 * connection to a profile this intent will be sent. Once connected, this intent
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700501 * will not be sent for any more connection attempts to any profiles of any
502 * remote device. When the adapter disconnects from the last profile its
503 * connected to of any remote device, this intent will be sent.
504 *
505 * <p> This intent is useful for applications that are only concerned about
506 * whether the local adapter is connected to any profile of any device and
507 * are not really concerned about which profile. For example, an application
508 * which displays an icon to display whether Bluetooth is connected or not
509 * can use this intent.
510 *
511 * <p>This intent will have 3 extras:
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800512 * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
513 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700514 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
515 *
Jaikumar Ganesh0b5b35f2011-02-01 16:47:11 -0800516 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
517 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700518 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
519 *
520 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
521 */
Myles Watson125b5452017-11-27 16:41:47 -0800522 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
523 ACTION_CONNECTION_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700524 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700525
526 /**
527 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
528 *
529 * This extra represents the current connection state.
530 */
531 public static final String EXTRA_CONNECTION_STATE =
Jack Hea355e5e2017-08-22 16:06:54 -0700532 "android.bluetooth.adapter.extra.CONNECTION_STATE";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700533
534 /**
535 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
536 *
537 * This extra represents the previous connection state.
538 */
539 public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
Jack Hea355e5e2017-08-22 16:06:54 -0700540 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700541
Nitin Arorad055adb2015-03-02 15:03:51 -0800542 /**
543 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
Jack Hea355e5e2017-08-22 16:06:54 -0700544 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800545 * @hide
546 */
Myles Watson125b5452017-11-27 16:41:47 -0800547 @SystemApi public static final String ACTION_BLE_STATE_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700548 "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800549
550 /**
Stanley Tngdd749b02017-04-17 22:35:45 -0700551 * Intent used to broadcast the change in the Bluetooth address
552 * of the local Bluetooth adapter.
553 * <p>Always contains the extra field {@link
554 * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
555 *
556 * Note: only system level processes are allowed to send this
557 * defined broadcast.
558 *
559 * @hide
560 */
561 public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
Jack Hea355e5e2017-08-22 16:06:54 -0700562 "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
Stanley Tngdd749b02017-04-17 22:35:45 -0700563
564 /**
565 * Used as a String extra field in {@link
566 * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
567 * Bluetooth address.
568 *
569 * @hide
570 */
571 public static final String EXTRA_BLUETOOTH_ADDRESS =
Jack Hea355e5e2017-08-22 16:06:54 -0700572 "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
Stanley Tngdd749b02017-04-17 22:35:45 -0700573
574 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800575 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
576 * by BLE Always on enabled application to know the ACL_CONNECTED event
577 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
578 * as Bluetooth LE is the only feature available in STATE_BLE_ON
579 *
580 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
581 * works in Bluetooth state STATE_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700582 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800583 * @hide
584 */
585 public static final String ACTION_BLE_ACL_CONNECTED =
Jack Hea355e5e2017-08-22 16:06:54 -0700586 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800587
588 /**
589 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
590 * by BLE Always on enabled application to know the ACL_DISCONNECTED event
591 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
592 * LE is the only feature available in STATE_BLE_ON
593 *
594 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
595 * works in Bluetooth state STATE_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700596 *
Nitin Arorad055adb2015-03-02 15:03:51 -0800597 * @hide
598 */
599 public static final String ACTION_BLE_ACL_DISCONNECTED =
Jack Hea355e5e2017-08-22 16:06:54 -0700600 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
Nitin Arorad055adb2015-03-02 15:03:51 -0800601
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700602 /** The profile is in disconnected state */
Jack Hebd020a62018-03-02 13:11:27 -0800603 public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700604 /** The profile is in connecting state */
Jack Hebd020a62018-03-02 13:11:27 -0800605 public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700606 /** The profile is in connected state */
Jack Hebd020a62018-03-02 13:11:27 -0800607 public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700608 /** The profile is in disconnecting state */
Jack Hebd020a62018-03-02 13:11:27 -0800609 public static final int STATE_DISCONNECTING =
610 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -0700611
Nick Pellyf242b7b2009-10-08 00:12:45 +0200612 /** @hide */
fredc0f420372012-04-12 00:02:00 -0700613 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
Nitin Arorad055adb2015-03-02 15:03:51 -0800614 private final IBinder mToken;
Nick Pellyf242b7b2009-10-08 00:12:45 +0200615
Casper Bonde238e0f92015-04-09 09:24:48 +0200616
Jack Hea355e5e2017-08-22 16:06:54 -0700617 /**
618 * When creating a ServerSocket using listenUsingRfcommOn() or
619 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
620 * a ServerSocket that auto assigns a channel number to the first
621 * bluetooth socket.
622 * The channel number assigned to this first Bluetooth Socket will
623 * be stored in the ServerSocket, and reused for subsequent Bluetooth
624 * sockets.
625 *
626 * @hide
627 */
Casper Bonde238e0f92015-04-09 09:24:48 +0200628 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
629
630
Nick Pelly005b2282009-09-10 10:21:56 -0700631 private static final int ADDRESS_LENGTH = 17;
Nick Pellybd022f42009-08-14 18:33:38 -0700632
Nick Pellyf242b7b2009-10-08 00:12:45 +0200633 /**
Jake Hambyf51eada2010-09-21 13:39:53 -0700634 * Lazily initialized singleton. Guaranteed final after first object
Nick Pellyf242b7b2009-10-08 00:12:45 +0200635 * constructed.
636 */
637 private static BluetoothAdapter sAdapter;
638
Wei Wangc3059cc2014-07-23 23:34:00 -0700639 private static BluetoothLeScanner sBluetoothLeScanner;
640 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800641 private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
Wei Wangc3059cc2014-07-23 23:34:00 -0700642
fredc0f420372012-04-12 00:02:00 -0700643 private final IBluetoothManager mManagerService;
Mathew Inwood4dc66d32018-08-01 15:07:20 +0100644 @UnsupportedAppUsage
fredc0f420372012-04-12 00:02:00 -0700645 private IBluetooth mService;
Zach Johnson57e6e902018-12-12 17:11:25 -0800646 private Context mContext;
Myles Watson125b5452017-11-27 16:41:47 -0800647 private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
Nick Pellybd022f42009-08-14 18:33:38 -0700648
Wei Wangf3055892014-03-11 22:22:41 -0700649 private final Object mLock = new Object();
Wei Wangc3059cc2014-07-23 23:34:00 -0700650 private final Map<LeScanCallback, ScanCallback> mLeScanClients;
Matthew Xie484867a2011-08-25 16:45:58 -0700651
Nick Pellybd022f42009-08-14 18:33:38 -0700652 /**
Nick Pellyf242b7b2009-10-08 00:12:45 +0200653 * Get a handle to the default local Bluetooth adapter.
654 * <p>Currently Android only supports one Bluetooth adapter, but the API
655 * could be extended to support more. This will always return the default
656 * adapter.
Marie Janssen553c8c72017-01-12 16:00:30 -0800657 * </p>
Jack Hea355e5e2017-08-22 16:06:54 -0700658 *
659 * @return the default local adapter, or null if Bluetooth is not supported on this hardware
660 * platform
Nick Pellyf242b7b2009-10-08 00:12:45 +0200661 */
662 public static synchronized BluetoothAdapter getDefaultAdapter() {
663 if (sAdapter == null) {
fredc0f420372012-04-12 00:02:00 -0700664 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
Nick Pellyf242b7b2009-10-08 00:12:45 +0200665 if (b != null) {
fredc0f420372012-04-12 00:02:00 -0700666 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
667 sAdapter = new BluetoothAdapter(managerService);
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -0800668 } else {
669 Log.e(TAG, "Bluetooth binder is null");
Nick Pellyf242b7b2009-10-08 00:12:45 +0200670 }
671 }
672 return sAdapter;
673 }
674
675 /**
676 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
Nick Pellybd022f42009-08-14 18:33:38 -0700677 */
fredc0f420372012-04-12 00:02:00 -0700678 BluetoothAdapter(IBluetoothManager managerService) {
679
680 if (managerService == null) {
681 throw new IllegalArgumentException("bluetooth manager service is null");
Nick Pellybd022f42009-08-14 18:33:38 -0700682 }
fredc0f420372012-04-12 00:02:00 -0700683 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700684 mServiceLock.writeLock().lock();
fredc0f420372012-04-12 00:02:00 -0700685 mService = managerService.registerAdapter(mManagerCallback);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700686 } catch (RemoteException e) {
687 Log.e(TAG, "", e);
688 } finally {
689 mServiceLock.writeLock().unlock();
690 }
fredc0f420372012-04-12 00:02:00 -0700691 mManagerService = managerService;
Wei Wangc3059cc2014-07-23 23:34:00 -0700692 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
Nitin Arorad055adb2015-03-02 15:03:51 -0800693 mToken = new Binder();
Nick Pellybd022f42009-08-14 18:33:38 -0700694 }
695
696 /**
Nick Pelly45e27042009-08-19 11:00:00 -0700697 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
698 * address.
699 * <p>Valid Bluetooth hardware addresses must be upper case, in a format
Nick Pelly005b2282009-09-10 10:21:56 -0700700 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
701 * available to validate a Bluetooth address.
Nick Pelly45e27042009-08-19 11:00:00 -0700702 * <p>A {@link BluetoothDevice} will always be returned for a valid
703 * hardware address, even if this adapter has never seen that device.
Nick Pellyde893f52009-09-08 13:15:33 -0700704 *
Nick Pellybd022f42009-08-14 18:33:38 -0700705 * @param address valid Bluetooth MAC address
Nick Pelly45e27042009-08-19 11:00:00 -0700706 * @throws IllegalArgumentException if address is invalid
Nick Pellybd022f42009-08-14 18:33:38 -0700707 */
708 public BluetoothDevice getRemoteDevice(String address) {
709 return new BluetoothDevice(address);
710 }
711
712 /**
Nick Pelly75596b42011-12-07 15:03:55 -0800713 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
714 * address.
715 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
716 * expects the address in network byte order (MSB first).
717 * <p>A {@link BluetoothDevice} will always be returned for a valid
718 * hardware address, even if this adapter has never seen that device.
719 *
720 * @param address Bluetooth MAC address (6 bytes)
721 * @throws IllegalArgumentException if address is invalid
722 */
723 public BluetoothDevice getRemoteDevice(byte[] address) {
724 if (address == null || address.length != 6) {
725 throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
726 }
Myles Watson125b5452017-11-27 16:41:47 -0800727 return new BluetoothDevice(
728 String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1],
729 address[2], address[3], address[4], address[5]));
Nick Pelly75596b42011-12-07 15:03:55 -0800730 }
731
732 /**
Prerepa Viswanadham248edc32014-10-15 16:36:01 -0700733 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
734 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
735 * supported on this device.
Wei Wangc3059cc2014-07-23 23:34:00 -0700736 * <p>
737 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
738 * on this device before calling this method.
Wei Wangadf6aff2014-05-20 06:30:20 +0000739 */
740 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
Myles Watson125b5452017-11-27 16:41:47 -0800741 if (!getLeAccess()) {
742 return null;
743 }
Jack Hea355e5e2017-08-22 16:06:54 -0700744 synchronized (mLock) {
Wei Wangc3059cc2014-07-23 23:34:00 -0700745 if (sBluetoothLeAdvertiser == null) {
746 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
747 }
748 }
749 return sBluetoothLeAdvertiser;
Wei Wangadf6aff2014-05-20 06:30:20 +0000750 }
751
752 /**
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800753 * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
754 * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
755 * Advertising is not supported on this device.
756 * <p>
757 * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
758 * supported on this device before calling this method.
Jack Hea355e5e2017-08-22 16:06:54 -0700759 *
Jakub Pawlowskia537b3f2017-03-29 17:00:44 -0700760 * @hide
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800761 */
762 public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
Jack Hea355e5e2017-08-22 16:06:54 -0700763 if (!getLeAccess()) {
764 return null;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800765 }
Jack Hea355e5e2017-08-22 16:06:54 -0700766
767 if (!isLePeriodicAdvertisingSupported()) {
768 return null;
769 }
770
771 synchronized (mLock) {
772 if (sPeriodicAdvertisingManager == null) {
Myles Watson125b5452017-11-27 16:41:47 -0800773 sPeriodicAdvertisingManager = new PeriodicAdvertisingManager(mManagerService);
Jack Hea355e5e2017-08-22 16:06:54 -0700774 }
775 }
776 return sPeriodicAdvertisingManager;
Jakub Pawlowskiac7fcfa2017-01-16 07:21:01 -0800777 }
778
779 /**
Wei Wangadf6aff2014-05-20 06:30:20 +0000780 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
781 */
782 public BluetoothLeScanner getBluetoothLeScanner() {
Myles Watson125b5452017-11-27 16:41:47 -0800783 if (!getLeAccess()) {
784 return null;
785 }
Jack Hea355e5e2017-08-22 16:06:54 -0700786 synchronized (mLock) {
Wei Wangc3059cc2014-07-23 23:34:00 -0700787 if (sBluetoothLeScanner == null) {
788 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
789 }
790 }
791 return sBluetoothLeScanner;
Wei Wangadf6aff2014-05-20 06:30:20 +0000792 }
793
794 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700795 * Return true if Bluetooth is currently enabled and ready for use.
796 * <p>Equivalent to:
797 * <code>getBluetoothState() == STATE_ON</code>
Nick Pellybd022f42009-08-14 18:33:38 -0700798 *
Nick Pellyde893f52009-09-08 13:15:33 -0700799 * @return true if the local adapter is turned on
Nick Pellybd022f42009-08-14 18:33:38 -0700800 */
Tor Norbye2d497522015-04-23 17:10:21 -0700801 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -0700802 public boolean isEnabled() {
803 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700804 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -0800805 if (mService != null) {
806 return mService.isEnabled();
807 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700808 } catch (RemoteException e) {
809 Log.e(TAG, "", e);
810 } finally {
811 mServiceLock.readLock().unlock();
812 }
813
Nick Pellybd022f42009-08-14 18:33:38 -0700814 return false;
815 }
816
817 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800818 * Return true if Bluetooth LE(Always BLE On feature) is currently
819 * enabled and ready for use
820 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
821 *
822 * @return true if the local Bluetooth LE adapter is turned on
823 * @hide
824 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700825 @SystemApi
826 public boolean isLeEnabled() {
Jack Hea355e5e2017-08-22 16:06:54 -0700827 final int state = getLeState();
Myles Watson125b5452017-11-27 16:41:47 -0800828 if (DBG) {
829 Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
830 }
Jack Hea355e5e2017-08-22 16:06:54 -0700831 return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
Nitin Arorad055adb2015-03-02 15:03:51 -0800832 }
833
834 /**
Marie Janssen59804562016-12-28 14:13:21 -0800835 * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
Nitin Arorad055adb2015-03-02 15:03:51 -0800836 *
837 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
838 * to STATE_OFF and completely shut-down Bluetooth
839 *
840 * <p> If the Adapter state is STATE_ON, This would unregister the existance of
841 * special Bluetooth LE application and hence the further turning off of Bluetooth
842 * from UI would ensure the complete turn-off of Bluetooth rather than staying back
843 * BLE only state
844 *
845 * <p>This is an asynchronous call: it will return immediately, and
846 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
847 * to be notified of subsequent adapter state changes If this call returns
848 * true, then the adapter state will immediately transition from {@link
849 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
850 * later transition to either {@link #STATE_BLE_ON} or {@link
851 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
852 * If this call returns false then there was an
853 * immediate problem that will prevent the QAdapter from being turned off -
854 * such as the QAadapter already being turned off.
855 *
Jack Hea355e5e2017-08-22 16:06:54 -0700856 * @return true to indicate success, or false on immediate error
Nitin Arorad055adb2015-03-02 15:03:51 -0800857 * @hide
858 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700859 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800860 public boolean disableBLE() {
Myles Watson125b5452017-11-27 16:41:47 -0800861 if (!isBleScanAlwaysAvailable()) {
862 return false;
863 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800864
865 int state = getLeState();
Marie Janssen59804562016-12-28 14:13:21 -0800866 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
867 String packageName = ActivityThread.currentPackageName();
Myles Watson125b5452017-11-27 16:41:47 -0800868 if (DBG) {
869 Log.d(TAG, "disableBLE(): de-registering " + packageName);
870 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800871 try {
Marie Janssen59804562016-12-28 14:13:21 -0800872 mManagerService.updateBleAppCount(mToken, false, packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800873 } catch (RemoteException e) {
874 Log.e(TAG, "", e);
875 }
876 return true;
Nitin Arorad055adb2015-03-02 15:03:51 -0800877 }
878
Myles Watson125b5452017-11-27 16:41:47 -0800879 if (DBG) {
880 Log.d(TAG, "disableBLE(): Already disabled");
881 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800882 return false;
883 }
884
885 /**
Marie Janssen59804562016-12-28 14:13:21 -0800886 * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
Nitin Arorad055adb2015-03-02 15:03:51 -0800887 *
Marie Janssen59804562016-12-28 14:13:21 -0800888 * enableBLE registers the existence of an app using only LE functions.
889 *
890 * enableBLE may enable Bluetooth to an LE only mode so that an app can use
891 * LE related features (BluetoothGatt or BluetoothGattServer classes)
892 *
893 * If the user disables Bluetooth while an app is registered to use LE only features,
894 * Bluetooth will remain on in LE only mode for the app.
895 *
896 * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
897 *
898 * <p>This is an asynchronous call: it returns immediately, and
Nitin Arorad055adb2015-03-02 15:03:51 -0800899 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
Marie Janssen59804562016-12-28 14:13:21 -0800900 * to be notified of adapter state changes.
901 *
902 * If this call returns * true, then the adapter state is either in a mode where
903 * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
904 * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
905 *
906 * If this call returns false then there was an immediate problem that prevents the
907 * adapter from being turned on - such as Airplane mode.
908 *
909 * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
Nitin Arorad055adb2015-03-02 15:03:51 -0800910 * states, It includes all the classic Bluetooth Adapter states along with
911 * internal BLE only states
912 *
Jack Hea355e5e2017-08-22 16:06:54 -0700913 * @return true to indicate Bluetooth LE will be available, or false on immediate error
Nitin Arorad055adb2015-03-02 15:03:51 -0800914 * @hide
915 */
Wei Wangf9e3e9e2015-06-01 12:14:28 -0700916 @SystemApi
Nitin Arorad055adb2015-03-02 15:03:51 -0800917 public boolean enableBLE() {
Myles Watson125b5452017-11-27 16:41:47 -0800918 if (!isBleScanAlwaysAvailable()) {
919 return false;
920 }
Nitin Arorad055adb2015-03-02 15:03:51 -0800921
Nitin Arorad055adb2015-03-02 15:03:51 -0800922 try {
Marie Janssen59804562016-12-28 14:13:21 -0800923 String packageName = ActivityThread.currentPackageName();
924 mManagerService.updateBleAppCount(mToken, true, packageName);
Marie Janssen6a383a72016-10-25 10:47:51 -0700925 if (isLeEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -0800926 if (DBG) {
927 Log.d(TAG, "enableBLE(): Bluetooth already enabled");
928 }
Marie Janssen6a383a72016-10-25 10:47:51 -0700929 return true;
930 }
Myles Watson125b5452017-11-27 16:41:47 -0800931 if (DBG) {
932 Log.d(TAG, "enableBLE(): Calling enable");
933 }
Marie Janssen59804562016-12-28 14:13:21 -0800934 return mManagerService.enable(packageName);
Nitin Arorad055adb2015-03-02 15:03:51 -0800935 } catch (RemoteException e) {
936 Log.e(TAG, "", e);
937 }
938
939 return false;
940 }
941
942 /**
Nick Pellyde893f52009-09-08 13:15:33 -0700943 * Get the current state of the local Bluetooth adapter.
944 * <p>Possible return values are
945 * {@link #STATE_OFF},
946 * {@link #STATE_TURNING_ON},
947 * {@link #STATE_ON},
948 * {@link #STATE_TURNING_OFF}.
Nick Pellybd022f42009-08-14 18:33:38 -0700949 *
Nick Pellyde893f52009-09-08 13:15:33 -0700950 * @return current state of Bluetooth adapter
Nick Pellybd022f42009-08-14 18:33:38 -0700951 */
Tor Norbye2d497522015-04-23 17:10:21 -0700952 @RequiresPermission(Manifest.permission.BLUETOOTH)
953 @AdapterState
Nick Pellyde893f52009-09-08 13:15:33 -0700954 public int getState() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700955 int state = BluetoothAdapter.STATE_OFF;
956
Nick Pellybd022f42009-08-14 18:33:38 -0700957 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700958 mServiceLock.readLock().lock();
959 if (mService != null) {
960 state = mService.getState();
fredc0f420372012-04-12 00:02:00 -0700961 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700962 } catch (RemoteException e) {
963 Log.e(TAG, "", e);
964 } finally {
965 mServiceLock.readLock().unlock();
966 }
967
968 // Consider all internal states as OFF
Myles Watson125b5452017-11-27 16:41:47 -0800969 if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON
Jack Hea355e5e2017-08-22 16:06:54 -0700970 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
971 if (VDBG) {
Myles Watson125b5452017-11-27 16:41:47 -0800972 Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
Jack Hea355e5e2017-08-22 16:06:54 -0700973 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700974 state = BluetoothAdapter.STATE_OFF;
975 }
Jack Hea355e5e2017-08-22 16:06:54 -0700976 if (VDBG) {
Myles Watson125b5452017-11-27 16:41:47 -0800977 Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(
978 state));
Jack Hea355e5e2017-08-22 16:06:54 -0700979 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -0700980 return state;
Nick Pellybd022f42009-08-14 18:33:38 -0700981 }
982
983 /**
Nitin Arorad055adb2015-03-02 15:03:51 -0800984 * Get the current state of the local Bluetooth adapter
985 * <p>This returns current internal state of Adapter including LE ON/OFF
986 *
987 * <p>Possible return values are
988 * {@link #STATE_OFF},
989 * {@link #STATE_BLE_TURNING_ON},
990 * {@link #STATE_BLE_ON},
991 * {@link #STATE_TURNING_ON},
992 * {@link #STATE_ON},
993 * {@link #STATE_TURNING_OFF},
994 * {@link #STATE_BLE_TURNING_OFF}.
Nitin Arorad055adb2015-03-02 15:03:51 -0800995 *
996 * @return current state of Bluetooth adapter
997 * @hide
998 */
Tor Norbye2d497522015-04-23 17:10:21 -0700999 @RequiresPermission(Manifest.permission.BLUETOOTH)
1000 @AdapterState
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001001 @UnsupportedAppUsage
Nitin Arorad055adb2015-03-02 15:03:51 -08001002 public int getLeState() {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001003 int state = BluetoothAdapter.STATE_OFF;
1004
Nitin Arorad055adb2015-03-02 15:03:51 -08001005 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001006 mServiceLock.readLock().lock();
1007 if (mService != null) {
1008 state = mService.getState();
Nitin Arorad055adb2015-03-02 15:03:51 -08001009 }
1010 } catch (RemoteException e) {
1011 Log.e(TAG, "", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001012 } finally {
1013 mServiceLock.readLock().unlock();
Nitin Arorad055adb2015-03-02 15:03:51 -08001014 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001015
Myles Watson125b5452017-11-27 16:41:47 -08001016 if (VDBG) {
1017 Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state));
1018 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001019 return state;
Nitin Arorad055adb2015-03-02 15:03:51 -08001020 }
1021
1022 boolean getLeAccess() {
Jack Hea355e5e2017-08-22 16:06:54 -07001023 if (getLeState() == STATE_ON) {
Nitin Arorad055adb2015-03-02 15:03:51 -08001024 return true;
Jack Hea355e5e2017-08-22 16:06:54 -07001025 } else if (getLeState() == STATE_BLE_ON) {
Nitin Arorad055adb2015-03-02 15:03:51 -08001026 return true; // TODO: FILTER SYSTEM APPS HERE <--
Jack Hea355e5e2017-08-22 16:06:54 -07001027 }
Nitin Arorad055adb2015-03-02 15:03:51 -08001028
1029 return false;
1030 }
1031
1032 /**
Scott Mained2a70d2009-12-09 16:07:39 -08001033 * Turn on the local Bluetooth adapter&mdash;do not use without explicit
1034 * user action to turn on Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -07001035 * <p>This powers on the underlying Bluetooth hardware, and starts all
1036 * Bluetooth system services.
Scott Mained2a70d2009-12-09 16:07:39 -08001037 * <p class="caution"><strong>Bluetooth should never be enabled without
1038 * direct user consent</strong>. If you want to turn on Bluetooth in order
1039 * to create a wireless connection, you should use the {@link
1040 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
1041 * user permission to turn on Bluetooth. The {@link #enable()} method is
1042 * provided only for applications that include a user interface for changing
1043 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +04001044 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -07001045 * clients should listen for {@link #ACTION_STATE_CHANGED}
1046 * to be notified of subsequent adapter state changes. If this call returns
1047 * true, then the adapter state will immediately transition from {@link
1048 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
1049 * later transition to either {@link #STATE_OFF} or {@link
1050 * #STATE_ON}. If this call returns false then there was an
1051 * immediate problem that will prevent the adapter from being turned on -
1052 * such as Airplane mode, or the adapter is already turned on.
Nick Pellyde893f52009-09-08 13:15:33 -07001053 *
Jack Hea355e5e2017-08-22 16:06:54 -07001054 * @return true to indicate adapter startup has begun, or false on immediate error
Nick Pellybd022f42009-08-14 18:33:38 -07001055 */
Tor Norbye2d497522015-04-23 17:10:21 -07001056 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001057 public boolean enable() {
Marie Janssencb21ad72016-12-13 10:51:02 -08001058 if (isEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -08001059 if (DBG) {
1060 Log.d(TAG, "enable(): BT already enabled!");
1061 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07001062 return true;
1063 }
Nick Pellybd022f42009-08-14 18:33:38 -07001064 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001065 return mManagerService.enable(ActivityThread.currentPackageName());
Jack Hea355e5e2017-08-22 16:06:54 -07001066 } catch (RemoteException e) {
1067 Log.e(TAG, "", e);
1068 }
Nick Pellybd022f42009-08-14 18:33:38 -07001069 return false;
1070 }
1071
1072 /**
Scott Mained2a70d2009-12-09 16:07:39 -08001073 * Turn off the local Bluetooth adapter&mdash;do not use without explicit
1074 * user action to turn off Bluetooth.
Nick Pellyde893f52009-09-08 13:15:33 -07001075 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
1076 * system services, and powers down the underlying Bluetooth hardware.
Jake Hambyf51eada2010-09-21 13:39:53 -07001077 * <p class="caution"><strong>Bluetooth should never be disabled without
Scott Mained2a70d2009-12-09 16:07:39 -08001078 * direct user consent</strong>. The {@link #disable()} method is
1079 * provided only for applications that include a user interface for changing
1080 * system settings, such as a "power manager" app.</p>
Brad Fitzpatrick3219ab42009-09-25 16:31:39 +04001081 * <p>This is an asynchronous call: it will return immediately, and
Nick Pellyde893f52009-09-08 13:15:33 -07001082 * clients should listen for {@link #ACTION_STATE_CHANGED}
1083 * to be notified of subsequent adapter state changes. If this call returns
1084 * true, then the adapter state will immediately transition from {@link
1085 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
1086 * later transition to either {@link #STATE_OFF} or {@link
1087 * #STATE_ON}. If this call returns false then there was an
1088 * immediate problem that will prevent the adapter from being turned off -
1089 * such as the adapter already being turned off.
Nick Pellybd022f42009-08-14 18:33:38 -07001090 *
Jack Hea355e5e2017-08-22 16:06:54 -07001091 * @return true to indicate adapter shutdown has begun, or false on immediate error
Nick Pellybd022f42009-08-14 18:33:38 -07001092 */
Tor Norbye2d497522015-04-23 17:10:21 -07001093 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001094 public boolean disable() {
1095 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001096 return mManagerService.disable(ActivityThread.currentPackageName(), true);
Jack Hea355e5e2017-08-22 16:06:54 -07001097 } catch (RemoteException e) {
1098 Log.e(TAG, "", e);
1099 }
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001100 return false;
1101 }
1102
1103 /**
1104 * Turn off the local Bluetooth adapter and don't persist the setting.
1105 *
1106 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1107 * permission
1108 *
Jack Hea355e5e2017-08-22 16:06:54 -07001109 * @return true to indicate adapter shutdown has begun, or false on immediate error
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001110 * @hide
1111 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001112 @UnsupportedAppUsage
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001113 public boolean disable(boolean persist) {
fredc0f420372012-04-12 00:02:00 -07001114
Jaikumar Ganeshe21a4ac2012-03-06 17:15:16 -08001115 try {
Svetoslav Ganovb1e2da72016-06-29 17:31:44 -07001116 return mManagerService.disable(ActivityThread.currentPackageName(), persist);
Jack Hea355e5e2017-08-22 16:06:54 -07001117 } catch (RemoteException e) {
1118 Log.e(TAG, "", e);
1119 }
Nick Pellybd022f42009-08-14 18:33:38 -07001120 return false;
1121 }
1122
Nick Pellyde893f52009-09-08 13:15:33 -07001123 /**
1124 * Returns the hardware address of the local Bluetooth adapter.
1125 * <p>For example, "00:11:22:AA:BB:CC".
Nick Pellyde893f52009-09-08 13:15:33 -07001126 *
1127 * @return Bluetooth hardware address as string
1128 */
Tor Norbye2d497522015-04-23 17:10:21 -07001129 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001130 public String getAddress() {
1131 try {
fredc0f420372012-04-12 00:02:00 -07001132 return mManagerService.getAddress();
Jack Hea355e5e2017-08-22 16:06:54 -07001133 } catch (RemoteException e) {
1134 Log.e(TAG, "", e);
1135 }
Nick Pellybd022f42009-08-14 18:33:38 -07001136 return null;
1137 }
1138
1139 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001140 * Get the friendly Bluetooth name of the local Bluetooth adapter.
1141 * <p>This name is visible to remote Bluetooth devices.
1142 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Nick Pellybd022f42009-08-14 18:33:38 -07001143 *
Nick Pellyde893f52009-09-08 13:15:33 -07001144 * @return the Bluetooth name, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07001145 */
1146 public String getName() {
1147 try {
fredc116d1d462012-04-20 14:47:08 -07001148 return mManagerService.getName();
Jack Hea355e5e2017-08-22 16:06:54 -07001149 } catch (RemoteException e) {
1150 Log.e(TAG, "", e);
1151 }
Nick Pellybd022f42009-08-14 18:33:38 -07001152 return null;
1153 }
1154
1155 /**
Ajay Panickercda6e872015-07-28 16:52:09 -07001156 * Factory reset bluetooth settings.
1157 *
1158 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
1159 * permission
1160 *
1161 * @return true to indicate that the config file was successfully cleared
Ajay Panickercda6e872015-07-28 16:52:09 -07001162 * @hide
1163 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001164 @UnsupportedAppUsage
Ajay Panickercda6e872015-07-28 16:52:09 -07001165 public boolean factoryReset() {
1166 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001167 mServiceLock.readLock().lock();
Ajay Panickercda6e872015-07-28 16:52:09 -07001168 if (mService != null) {
1169 return mService.factoryReset();
1170 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001171 SystemProperties.set("persist.bluetooth.factoryreset", "true");
1172 } catch (RemoteException e) {
1173 Log.e(TAG, "", e);
1174 } finally {
1175 mServiceLock.readLock().unlock();
1176 }
Ajay Panickercda6e872015-07-28 16:52:09 -07001177 return false;
1178 }
1179
1180 /**
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001181 * Get the UUIDs supported by the local Bluetooth adapter.
1182 *
1183 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1184 *
1185 * @return the UUIDs supported by the local Bluetooth Adapter.
1186 * @hide
1187 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001188 @UnsupportedAppUsage
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001189 public ParcelUuid[] getUuids() {
Myles Watson125b5452017-11-27 16:41:47 -08001190 if (getState() != STATE_ON) {
1191 return null;
1192 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001193 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001194 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001195 if (mService != null) {
1196 return mService.getUuids();
1197 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001198 } catch (RemoteException e) {
1199 Log.e(TAG, "", e);
1200 } finally {
1201 mServiceLock.readLock().unlock();
1202 }
Jaikumar Ganesh58b93c32010-11-23 20:03:10 -08001203 return null;
1204 }
1205
1206 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001207 * Set the friendly Bluetooth name of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001208 * <p>This name is visible to remote Bluetooth devices.
Jake Hamby0f584302010-09-16 18:12:51 -07001209 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1210 * encoding, although many remote devices can only display the first
1211 * 40 characters, and some may be limited to just 20.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001212 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1213 * will return false. After turning on Bluetooth,
1214 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1215 * to get the updated value.
Nick Pellybd022f42009-08-14 18:33:38 -07001216 *
Nick Pellyde893f52009-09-08 13:15:33 -07001217 * @param name a valid Bluetooth name
Jack Hea355e5e2017-08-22 16:06:54 -07001218 * @return true if the name was set, false otherwise
Nick Pellybd022f42009-08-14 18:33:38 -07001219 */
Tor Norbye2d497522015-04-23 17:10:21 -07001220 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001221 public boolean setName(String name) {
Myles Watson125b5452017-11-27 16:41:47 -08001222 if (getState() != STATE_ON) {
1223 return false;
1224 }
Nick Pellybd022f42009-08-14 18:33:38 -07001225 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001226 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001227 if (mService != null) {
1228 return mService.setName(name);
1229 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001230 } catch (RemoteException e) {
1231 Log.e(TAG, "", e);
1232 } finally {
1233 mServiceLock.readLock().unlock();
1234 }
Nick Pellybd022f42009-08-14 18:33:38 -07001235 return false;
1236 }
1237
1238 /**
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001239 * Returns the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1240 * adapter.
1241 *
1242 * @return {@link BluetoothClass} Bluetooth CoD of local Bluetooth device.
1243 *
1244 * @hide
1245 */
1246 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1247 public BluetoothClass getBluetoothClass() {
Myles Watson125b5452017-11-27 16:41:47 -08001248 if (getState() != STATE_ON) {
1249 return null;
1250 }
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001251 try {
1252 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001253 if (mService != null) {
1254 return mService.getBluetoothClass();
1255 }
Pulkit Bhuwalkad01fa6e2017-09-20 15:10:45 -07001256 } catch (RemoteException e) {
1257 Log.e(TAG, "", e);
1258 } finally {
1259 mServiceLock.readLock().unlock();
1260 }
1261 return null;
1262 }
1263
1264 /**
Pulkit Bhuwalka547853d2017-09-25 17:55:12 -07001265 * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1266 * adapter.
1267 *
1268 * <p>Note: This value persists across system reboot.
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001269 *
1270 * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
1271 * @return true if successful, false if unsuccessful.
1272 *
1273 * @hide
1274 */
1275 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
1276 public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
Myles Watson125b5452017-11-27 16:41:47 -08001277 if (getState() != STATE_ON) {
1278 return false;
1279 }
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001280 try {
1281 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001282 if (mService != null) {
1283 return mService.setBluetoothClass(bluetoothClass);
1284 }
Pulkit Bhuwalka66d61232017-08-16 21:52:04 -07001285 } catch (RemoteException e) {
1286 Log.e(TAG, "", e);
1287 } finally {
1288 mServiceLock.readLock().unlock();
1289 }
1290 return false;
1291 }
1292
1293 /**
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001294 * Returns the Input/Output capability of the device for classic Bluetooth.
1295 *
1296 * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1297 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1298 * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1299 *
1300 * @hide
1301 */
1302 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001303 @IoCapability
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001304 public int getIoCapability() {
1305 if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1306 try {
1307 mServiceLock.readLock().lock();
1308 if (mService != null) return mService.getIoCapability();
1309 } catch (RemoteException e) {
1310 Log.e(TAG, e.getMessage(), e);
1311 } finally {
1312 mServiceLock.readLock().unlock();
1313 }
1314 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1315 }
1316
1317 /**
1318 * Sets the Input/Output capability of the device for classic Bluetooth.
1319 *
1320 * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1321 * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1322 * and {@link BluetoothAdapter#enable()} to see the changes.
1323 *
1324 * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1325 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1326 * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1327 *
1328 * @hide
1329 */
1330 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001331 public boolean setIoCapability(@IoCapability int capability) {
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001332 if (getState() != STATE_ON) return false;
1333 try {
1334 mServiceLock.readLock().lock();
1335 if (mService != null) return mService.setIoCapability(capability);
1336 } catch (RemoteException e) {
1337 Log.e(TAG, e.getMessage(), e);
1338 } finally {
1339 mServiceLock.readLock().unlock();
1340 }
1341 return false;
1342 }
1343
1344 /**
1345 * Returns the Input/Output capability of the device for BLE operations.
1346 *
1347 * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1348 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1349 * {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1350 *
1351 * @hide
1352 */
1353 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001354 @IoCapability
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001355 public int getLeIoCapability() {
1356 if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1357 try {
1358 mServiceLock.readLock().lock();
1359 if (mService != null) return mService.getLeIoCapability();
1360 } catch (RemoteException e) {
1361 Log.e(TAG, e.getMessage(), e);
1362 } finally {
1363 mServiceLock.readLock().unlock();
1364 }
1365 return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1366 }
1367
1368 /**
1369 * Sets the Input/Output capability of the device for BLE operations.
1370 *
1371 * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1372 * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1373 * and {@link BluetoothAdapter#enable()} to see the changes.
1374 *
1375 * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1376 * {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1377 * {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1378 *
1379 * @hide
1380 */
1381 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
Pulkit Bhuwalka80238142018-04-20 16:56:53 -07001382 public boolean setLeIoCapability(@IoCapability int capability) {
Pulkit Bhuwalka979698b2018-03-28 13:51:43 -07001383 if (getState() != STATE_ON) return false;
1384 try {
1385 mServiceLock.readLock().lock();
1386 if (mService != null) return mService.setLeIoCapability(capability);
1387 } catch (RemoteException e) {
1388 Log.e(TAG, e.getMessage(), e);
1389 } finally {
1390 mServiceLock.readLock().unlock();
1391 }
1392 return false;
1393 }
1394
1395 /**
Jake Hamby0f584302010-09-16 18:12:51 -07001396 * Get the current Bluetooth scan mode of the local Bluetooth adapter.
Nick Pellyde893f52009-09-08 13:15:33 -07001397 * <p>The Bluetooth scan mode determines if the local adapter is
1398 * connectable and/or discoverable from remote Bluetooth devices.
1399 * <p>Possible values are:
1400 * {@link #SCAN_MODE_NONE},
1401 * {@link #SCAN_MODE_CONNECTABLE},
1402 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001403 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1404 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1405 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1406 * to get the updated value.
Nick Pellyde893f52009-09-08 13:15:33 -07001407 *
1408 * @return scan mode
Nick Pellybd022f42009-08-14 18:33:38 -07001409 */
Tor Norbye2d497522015-04-23 17:10:21 -07001410 @RequiresPermission(Manifest.permission.BLUETOOTH)
1411 @ScanMode
Nick Pellybd022f42009-08-14 18:33:38 -07001412 public int getScanMode() {
Myles Watson125b5452017-11-27 16:41:47 -08001413 if (getState() != STATE_ON) {
1414 return SCAN_MODE_NONE;
1415 }
Nick Pellybd022f42009-08-14 18:33:38 -07001416 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001417 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001418 if (mService != null) {
1419 return mService.getScanMode();
1420 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001421 } catch (RemoteException e) {
1422 Log.e(TAG, "", e);
1423 } finally {
1424 mServiceLock.readLock().unlock();
1425 }
Nick Pellyde893f52009-09-08 13:15:33 -07001426 return SCAN_MODE_NONE;
Nick Pellybd022f42009-08-14 18:33:38 -07001427 }
1428
1429 /**
Nick Pellyde893f52009-09-08 13:15:33 -07001430 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1431 * <p>The Bluetooth scan mode determines if the local adapter is
1432 * connectable and/or discoverable from remote Bluetooth devices.
Nick Pelly12835472009-09-25 15:00:29 -07001433 * <p>For privacy reasons, discoverable mode is automatically turned off
1434 * after <code>duration</code> seconds. For example, 120 seconds should be
1435 * enough for a remote device to initiate and complete its discovery
1436 * process.
Nick Pellyde893f52009-09-08 13:15:33 -07001437 * <p>Valid scan mode values are:
1438 * {@link #SCAN_MODE_NONE},
1439 * {@link #SCAN_MODE_CONNECTABLE},
1440 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001441 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1442 * will return false. After turning on Bluetooth,
1443 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1444 * to get the updated value.
Nick Pelly18b1e792009-09-24 11:14:15 -07001445 * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
1446 * <p>Applications cannot set the scan mode. They should use
1447 * <code>startActivityForResult(
1448 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1449 * </code>instead.
Nick Pellyde893f52009-09-08 13:15:33 -07001450 *
1451 * @param mode valid scan mode
Jack Hea355e5e2017-08-22 16:06:54 -07001452 * @param duration time in seconds to apply scan mode, only used for {@link
1453 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
1454 * @return true if the scan mode was set, false otherwise
Nick Pelly18b1e792009-09-24 11:14:15 -07001455 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07001456 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001457 @UnsupportedAppUsage
Tor Norbye2d497522015-04-23 17:10:21 -07001458 public boolean setScanMode(@ScanMode int mode, int duration) {
Myles Watson125b5452017-11-27 16:41:47 -08001459 if (getState() != STATE_ON) {
1460 return false;
1461 }
Nick Pellybd022f42009-08-14 18:33:38 -07001462 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001463 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001464 if (mService != null) {
1465 return mService.setScanMode(mode, duration);
1466 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001467 } catch (RemoteException e) {
1468 Log.e(TAG, "", e);
1469 } finally {
1470 mServiceLock.readLock().unlock();
1471 }
Nick Pellyde893f52009-09-08 13:15:33 -07001472 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001473 }
1474
Nick Pelly45e27042009-08-19 11:00:00 -07001475 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001476 @UnsupportedAppUsage
Nick Pelly12835472009-09-25 15:00:29 -07001477 public boolean setScanMode(int mode) {
Myles Watson125b5452017-11-27 16:41:47 -08001478 if (getState() != STATE_ON) {
1479 return false;
1480 }
Srikanth Uppala827de2d2012-04-04 03:33:26 -07001481 /* getDiscoverableTimeout() to use the latest from NV than use 0 */
1482 return setScanMode(mode, getDiscoverableTimeout());
Nick Pelly12835472009-09-25 15:00:29 -07001483 }
1484
1485 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001486 @UnsupportedAppUsage
Nick Pellybd022f42009-08-14 18:33:38 -07001487 public int getDiscoverableTimeout() {
Myles Watson125b5452017-11-27 16:41:47 -08001488 if (getState() != STATE_ON) {
1489 return -1;
1490 }
Nick Pellybd022f42009-08-14 18:33:38 -07001491 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001492 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001493 if (mService != null) {
1494 return mService.getDiscoverableTimeout();
1495 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001496 } catch (RemoteException e) {
1497 Log.e(TAG, "", e);
1498 } finally {
1499 mServiceLock.readLock().unlock();
1500 }
Nick Pellybd022f42009-08-14 18:33:38 -07001501 return -1;
1502 }
1503
Nick Pelly45e27042009-08-19 11:00:00 -07001504 /** @hide */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01001505 @UnsupportedAppUsage
Nick Pellybd022f42009-08-14 18:33:38 -07001506 public void setDiscoverableTimeout(int timeout) {
Myles Watson125b5452017-11-27 16:41:47 -08001507 if (getState() != STATE_ON) {
1508 return;
1509 }
Nick Pellybd022f42009-08-14 18:33:38 -07001510 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001511 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001512 if (mService != null) {
1513 mService.setDiscoverableTimeout(timeout);
1514 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001515 } catch (RemoteException e) {
1516 Log.e(TAG, "", e);
1517 } finally {
1518 mServiceLock.readLock().unlock();
1519 }
Nick Pellybd022f42009-08-14 18:33:38 -07001520 }
1521
Nick Pelly005b2282009-09-10 10:21:56 -07001522 /**
Marie Janssen23a48332017-01-24 14:09:59 -08001523 * Get the end time of the latest remote device discovery process.
Jack Hea355e5e2017-08-22 16:06:54 -07001524 *
1525 * @return the latest time that the bluetooth adapter was/will be in discovery mode, in
1526 * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has
1527 * been called recently.
Marie Janssen23a48332017-01-24 14:09:59 -08001528 * @hide
1529 */
1530 public long getDiscoveryEndMillis() {
1531 try {
1532 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001533 if (mService != null) {
1534 return mService.getDiscoveryEndMillis();
1535 }
Marie Janssen23a48332017-01-24 14:09:59 -08001536 } catch (RemoteException e) {
1537 Log.e(TAG, "", e);
1538 } finally {
1539 mServiceLock.readLock().unlock();
1540 }
1541 return -1;
1542 }
1543
1544 /**
Zach Johnson57e6e902018-12-12 17:11:25 -08001545 * Set the context for this BluetoothAdapter (only called from BluetoothManager)
1546 * @hide
1547 */
1548 public void setContext(Context context) {
1549 mContext = context;
1550 }
1551
1552 private String getOpPackageName() {
1553 // Workaround for legacy API for getting a BluetoothAdapter not
1554 // passing a context
1555 if (mContext != null) {
1556 return mContext.getOpPackageName();
1557 }
1558 return ActivityThread.currentOpPackageName();
1559 }
1560
1561 /**
Nick Pelly005b2282009-09-10 10:21:56 -07001562 * Start the remote device discovery process.
1563 * <p>The discovery process usually involves an inquiry scan of about 12
1564 * seconds, followed by a page scan of each new device to retrieve its
1565 * Bluetooth name.
1566 * <p>This is an asynchronous call, it will return immediately. Register
1567 * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1568 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1569 * discovery starts and completes. Register for {@link
1570 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1571 * are found.
1572 * <p>Device discovery is a heavyweight procedure. New connections to
1573 * remote Bluetooth devices should not be attempted while discovery is in
1574 * progress, and existing connections will experience limited bandwidth
1575 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
Scott Main6d95fc02009-11-19 17:00:19 -08001576 * discovery. Discovery is not managed by the Activity,
1577 * but is run as a system service, so an application should always call
1578 * {@link BluetoothAdapter#cancelDiscovery()} even if it
1579 * did not directly request a discovery, just to be sure.
Nick Pelly005b2282009-09-10 10:21:56 -07001580 * <p>Device discovery will only find remote devices that are currently
1581 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1582 * not discoverable by default, and need to be entered into a special mode.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001583 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1584 * will return false. After turning on Bluetooth,
1585 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1586 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001587 *
1588 * @return true on success, false on error
1589 */
Tor Norbye2d497522015-04-23 17:10:21 -07001590 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pellybd022f42009-08-14 18:33:38 -07001591 public boolean startDiscovery() {
Myles Watson125b5452017-11-27 16:41:47 -08001592 if (getState() != STATE_ON) {
1593 return false;
1594 }
Nick Pellybd022f42009-08-14 18:33:38 -07001595 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001596 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001597 if (mService != null) {
Zach Johnson57e6e902018-12-12 17:11:25 -08001598 return mService.startDiscovery(getOpPackageName());
Myles Watson125b5452017-11-27 16:41:47 -08001599 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001600 } catch (RemoteException e) {
1601 Log.e(TAG, "", e);
1602 } finally {
1603 mServiceLock.readLock().unlock();
1604 }
Nick Pellybd022f42009-08-14 18:33:38 -07001605 return false;
1606 }
1607
Nick Pelly005b2282009-09-10 10:21:56 -07001608 /**
1609 * Cancel the current device discovery process.
Jake Hamby0f584302010-09-16 18:12:51 -07001610 * <p>Because discovery is a heavyweight procedure for the Bluetooth
Scott Main6d95fc02009-11-19 17:00:19 -08001611 * adapter, this method should always be called before attempting to connect
1612 * to a remote device with {@link
1613 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1614 * the Activity, but is run as a system service, so an application should
1615 * always call cancel discovery even if it did not directly request a
1616 * discovery, just to be sure.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001617 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1618 * will return false. After turning on Bluetooth,
1619 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1620 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001621 *
1622 * @return true on success, false on error
1623 */
Tor Norbye2d497522015-04-23 17:10:21 -07001624 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Nick Pelly005b2282009-09-10 10:21:56 -07001625 public boolean cancelDiscovery() {
Myles Watson125b5452017-11-27 16:41:47 -08001626 if (getState() != STATE_ON) {
1627 return false;
1628 }
Nick Pellybd022f42009-08-14 18:33:38 -07001629 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001630 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001631 if (mService != null) {
1632 return mService.cancelDiscovery();
1633 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001634 } catch (RemoteException e) {
1635 Log.e(TAG, "", e);
1636 } finally {
1637 mServiceLock.readLock().unlock();
1638 }
Nick Pelly005b2282009-09-10 10:21:56 -07001639 return false;
Nick Pellybd022f42009-08-14 18:33:38 -07001640 }
1641
Nick Pelly005b2282009-09-10 10:21:56 -07001642 /**
1643 * Return true if the local Bluetooth adapter is currently in the device
1644 * discovery process.
1645 * <p>Device discovery is a heavyweight procedure. New connections to
1646 * remote Bluetooth devices should not be attempted while discovery is in
1647 * progress, and existing connections will experience limited bandwidth
1648 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1649 * discovery.
1650 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1651 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1652 * starts or completes.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001653 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1654 * will return false. After turning on Bluetooth,
1655 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1656 * to get the updated value.
Nick Pelly005b2282009-09-10 10:21:56 -07001657 *
1658 * @return true if discovering
1659 */
Tor Norbye2d497522015-04-23 17:10:21 -07001660 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001661 public boolean isDiscovering() {
Myles Watson125b5452017-11-27 16:41:47 -08001662 if (getState() != STATE_ON) {
1663 return false;
1664 }
Nick Pellybd022f42009-08-14 18:33:38 -07001665 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001666 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001667 if (mService != null) {
1668 return mService.isDiscovering();
1669 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001670 } catch (RemoteException e) {
1671 Log.e(TAG, "", e);
1672 } finally {
1673 mServiceLock.readLock().unlock();
1674 }
Nick Pellybd022f42009-08-14 18:33:38 -07001675 return false;
1676 }
1677
1678 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001679 * Return true if the multi advertisement is supported by the chipset
1680 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001681 * @return true if Multiple Advertisement feature is supported
1682 */
1683 public boolean isMultipleAdvertisementSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001684 if (getState() != STATE_ON) {
1685 return false;
1686 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001687 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001688 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001689 if (mService != null) {
1690 return mService.isMultiAdvertisementSupported();
1691 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001692 } catch (RemoteException e) {
1693 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001694 } finally {
1695 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001696 }
1697 return false;
1698 }
1699
1700 /**
Wei Wangd91f1932015-03-19 15:09:56 -07001701 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1702 *
1703 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1704 * fetch scan results even when Bluetooth is turned off.<p>
1705 *
1706 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1707 *
1708 * @hide
1709 */
1710 @SystemApi
1711 public boolean isBleScanAlwaysAvailable() {
Wei Wang67d84162015-04-26 17:04:29 -07001712 try {
1713 return mManagerService.isBleScanAlwaysAvailable();
1714 } catch (RemoteException e) {
1715 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1716 return false;
1717 }
Wei Wangd91f1932015-03-19 15:09:56 -07001718 }
1719
1720 /**
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001721 * Return true if offloaded filters are supported
1722 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001723 * @return true if chipset supports on-chip filtering
1724 */
1725 public boolean isOffloadedFilteringSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001726 if (!getLeAccess()) {
1727 return false;
1728 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001729 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001730 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001731 if (mService != null) {
1732 return mService.isOffloadedFilteringSupported();
1733 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001734 } catch (RemoteException e) {
1735 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001736 } finally {
1737 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001738 }
1739 return false;
1740 }
1741
1742 /**
1743 * Return true if offloaded scan batching is supported
1744 *
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001745 * @return true if chipset supports on-chip scan batching
1746 */
1747 public boolean isOffloadedScanBatchingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001748 if (!getLeAccess()) {
1749 return false;
1750 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001751 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001752 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001753 if (mService != null) {
1754 return mService.isOffloadedScanBatchingSupported();
1755 }
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001756 } catch (RemoteException e) {
1757 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001758 } finally {
1759 mServiceLock.readLock().unlock();
Prerepa Viswanadham0c116e12014-07-02 12:30:38 -07001760 }
1761 return false;
1762 }
1763
1764 /**
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001765 * Return true if LE 2M PHY feature is supported.
1766 *
1767 * @return true if chipset supports LE 2M PHY feature
1768 */
1769 public boolean isLe2MPhySupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001770 if (!getLeAccess()) {
1771 return false;
1772 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001773 try {
1774 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001775 if (mService != null) {
1776 return mService.isLe2MPhySupported();
1777 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001778 } catch (RemoteException e) {
1779 Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
1780 } finally {
1781 mServiceLock.readLock().unlock();
1782 }
1783 return false;
1784 }
1785
1786 /**
1787 * Return true if LE Coded PHY feature is supported.
1788 *
1789 * @return true if chipset supports LE Coded PHY feature
1790 */
1791 public boolean isLeCodedPhySupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001792 if (!getLeAccess()) {
1793 return false;
1794 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001795 try {
1796 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001797 if (mService != null) {
1798 return mService.isLeCodedPhySupported();
1799 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001800 } catch (RemoteException e) {
1801 Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
1802 } finally {
1803 mServiceLock.readLock().unlock();
1804 }
1805 return false;
1806 }
1807
1808 /**
Jakub Pawlowskibc2991e2017-03-10 16:07:59 -08001809 * Return true if LE Extended Advertising feature is supported.
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001810 *
Jakub Pawlowskibc2991e2017-03-10 16:07:59 -08001811 * @return true if chipset supports LE Extended Advertising feature
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001812 */
1813 public boolean isLeExtendedAdvertisingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001814 if (!getLeAccess()) {
1815 return false;
1816 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001817 try {
1818 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001819 if (mService != null) {
1820 return mService.isLeExtendedAdvertisingSupported();
1821 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001822 } catch (RemoteException e) {
1823 Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
1824 } finally {
1825 mServiceLock.readLock().unlock();
1826 }
1827 return false;
1828 }
1829
1830 /**
1831 * Return true if LE Periodic Advertising feature is supported.
1832 *
1833 * @return true if chipset supports LE Periodic Advertising feature
1834 */
1835 public boolean isLePeriodicAdvertisingSupported() {
Myles Watson125b5452017-11-27 16:41:47 -08001836 if (!getLeAccess()) {
1837 return false;
1838 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001839 try {
1840 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001841 if (mService != null) {
1842 return mService.isLePeriodicAdvertisingSupported();
1843 }
Jakub Pawlowski48091bb2017-02-07 18:05:39 -08001844 } catch (RemoteException e) {
1845 Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
1846 } finally {
1847 mServiceLock.readLock().unlock();
1848 }
1849 return false;
1850 }
1851
1852 /**
Jakub Pawlowski76cceb12017-04-21 04:59:55 -07001853 * Return the maximum LE advertising data length in bytes,
1854 * if LE Extended Advertising feature is supported, 0 otherwise.
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001855 *
1856 * @return the maximum LE advertising data length.
1857 */
1858 public int getLeMaximumAdvertisingDataLength() {
Myles Watson125b5452017-11-27 16:41:47 -08001859 if (!getLeAccess()) {
1860 return 0;
1861 }
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001862 try {
1863 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001864 if (mService != null) {
1865 return mService.getLeMaximumAdvertisingDataLength();
1866 }
Jakub Pawlowskiad10aff2017-03-16 18:22:36 -07001867 } catch (RemoteException e) {
1868 Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
1869 } finally {
1870 mServiceLock.readLock().unlock();
1871 }
1872 return 0;
1873 }
1874
1875 /**
Pavlin Radoslavova5137922018-01-17 02:09:53 -08001876 * Get the maximum number of connected audio devices.
1877 *
1878 * @return the maximum number of connected audio devices
1879 * @hide
1880 */
1881 @RequiresPermission(Manifest.permission.BLUETOOTH)
1882 public int getMaxConnectedAudioDevices() {
1883 try {
1884 mServiceLock.readLock().lock();
1885 if (mService != null) {
1886 return mService.getMaxConnectedAudioDevices();
1887 }
1888 } catch (RemoteException e) {
1889 Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
1890 } finally {
1891 mServiceLock.readLock().unlock();
1892 }
1893 return 1;
1894 }
1895
1896 /**
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001897 * Return true if hardware has entries available for matching beacons
1898 *
1899 * @return true if there are hw entries available for matching beacons
1900 * @hide
1901 */
1902 public boolean isHardwareTrackingFiltersAvailable() {
Myles Watson125b5452017-11-27 16:41:47 -08001903 if (!getLeAccess()) {
1904 return false;
1905 }
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001906 try {
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07001907 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
1908 if (iGatt == null) {
1909 // BLE is not supported
1910 return false;
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001911 }
Prerepa Viswanadhamdb1dbb82015-04-09 17:14:50 -07001912 return (iGatt.numHwTrackFiltersAvailable() != 0);
Prerepa Viswanadhame593d0a2015-04-07 14:36:53 -07001913 } catch (RemoteException e) {
1914 Log.e(TAG, "", e);
1915 }
1916 return false;
1917 }
1918
1919 /**
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001920 * Return the record of {@link BluetoothActivityEnergyInfo} object that
1921 * has the activity and energy info. This can be used to ascertain what
1922 * the controller has been up to, since the last sample.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001923 *
Jack Hea355e5e2017-08-22 16:06:54 -07001924 * @param updateType Type of info, cached vs refreshed.
1925 * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or
1926 * unsupported
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001927 * @hide
Jack Hea355e5e2017-08-22 16:06:54 -07001928 * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)}
1929 * instead.
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001930 */
Adam Lesinski010bf372016-04-11 12:18:18 -07001931 @Deprecated
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001932 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001933 SynchronousResultReceiver receiver = new SynchronousResultReceiver();
Adam Lesinski991357f2016-05-10 14:00:03 -07001934 requestControllerActivityEnergyInfo(receiver);
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001935 try {
Adam Lesinski010bf372016-04-11 12:18:18 -07001936 SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
1937 if (result.bundle != null) {
1938 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1939 }
1940 } catch (TimeoutException e) {
1941 Log.e(TAG, "getControllerActivityEnergyInfo timed out");
1942 }
1943 return null;
1944 }
1945
1946 /**
1947 * Request the record of {@link BluetoothActivityEnergyInfo} object that
1948 * has the activity and energy info. This can be used to ascertain what
1949 * the controller has been up to, since the last sample.
1950 *
1951 * A null value for the activity info object may be sent if the bluetooth service is
1952 * unreachable or the device does not support reporting such information.
1953 *
Adam Lesinski010bf372016-04-11 12:18:18 -07001954 * @param result The callback to which to send the activity info.
1955 * @hide
1956 */
Adam Lesinski991357f2016-05-10 14:00:03 -07001957 public void requestControllerActivityEnergyInfo(ResultReceiver result) {
Adam Lesinski010bf372016-04-11 12:18:18 -07001958 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001959 mServiceLock.readLock().lock();
1960 if (mService != null) {
1961 mService.requestActivityInfo(result);
1962 result = null;
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001963 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001964 } catch (RemoteException e) {
1965 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
Adam Lesinski991357f2016-05-10 14:00:03 -07001966 } finally {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001967 mServiceLock.readLock().unlock();
Adam Lesinski991357f2016-05-10 14:00:03 -07001968 if (result != null) {
1969 // Only send an immediate result if we failed.
1970 result.send(0, null);
1971 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001972 }
Prerepa Viswanadham8caac742014-07-22 17:00:09 -07001973 }
1974
1975 /**
Nick Pelly005b2282009-09-10 10:21:56 -07001976 * Return the set of {@link BluetoothDevice} objects that are bonded
1977 * (paired) to the local adapter.
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001978 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1979 * will return an empty set. After turning on Bluetooth,
1980 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1981 * to get the updated value.
Nick Pellybd022f42009-08-14 18:33:38 -07001982 *
Nick Pelly005b2282009-09-10 10:21:56 -07001983 * @return unmodifiable set of {@link BluetoothDevice}, or null on error
Nick Pellybd022f42009-08-14 18:33:38 -07001984 */
Tor Norbye2d497522015-04-23 17:10:21 -07001985 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pellybd022f42009-08-14 18:33:38 -07001986 public Set<BluetoothDevice> getBondedDevices() {
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001987 if (getState() != STATE_ON) {
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08001988 return toDeviceSet(new BluetoothDevice[0]);
Jaikumar Ganeshfec86f42010-08-09 16:54:03 -07001989 }
Nick Pellybd022f42009-08-14 18:33:38 -07001990 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001991 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08001992 if (mService != null) {
1993 return toDeviceSet(mService.getBondedDevices());
1994 }
fredc0f420372012-04-12 00:02:00 -07001995 return toDeviceSet(new BluetoothDevice[0]);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07001996 } catch (RemoteException e) {
1997 Log.e(TAG, "", e);
1998 } finally {
1999 mServiceLock.readLock().unlock();
2000 }
Nick Pellybd022f42009-08-14 18:33:38 -07002001 return null;
2002 }
2003
2004 /**
Bryce Leeb1301fa2016-10-09 12:54:42 -07002005 * Gets the currently supported profiles by the adapter.
2006 *
Jack Hea355e5e2017-08-22 16:06:54 -07002007 * <p> This can be used to check whether a profile is supported before attempting
Bryce Leeb1301fa2016-10-09 12:54:42 -07002008 * to connect to its respective proxy.
2009 *
Jack Hea355e5e2017-08-22 16:06:54 -07002010 * @return a list of integers indicating the ids of supported profiles as defined in {@link
2011 * BluetoothProfile}.
Bryce Leeb1301fa2016-10-09 12:54:42 -07002012 * @hide
2013 */
2014 public List<Integer> getSupportedProfiles() {
2015 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
2016
2017 try {
2018 synchronized (mManagerCallback) {
2019 if (mService != null) {
2020 final long supportedProfilesBitMask = mService.getSupportedProfiles();
2021
2022 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
2023 if ((supportedProfilesBitMask & (1 << i)) != 0) {
2024 supportedProfiles.add(i);
2025 }
2026 }
2027 }
2028 }
Marie Janssencb21ad72016-12-13 10:51:02 -08002029 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -07002030 Log.e(TAG, "getSupportedProfiles:", e);
Marie Janssencb21ad72016-12-13 10:51:02 -08002031 }
Bryce Leeb1301fa2016-10-09 12:54:42 -07002032 return supportedProfiles;
2033 }
2034
2035 /**
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002036 * Get the current connection state of the local Bluetooth adapter.
2037 * This can be used to check whether the local Bluetooth adapter is connected
2038 * to any profile of any other remote Bluetooth Device.
2039 *
2040 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
2041 * intent to get the connection state of the adapter.
2042 *
Jack Hea355e5e2017-08-22 16:06:54 -07002043 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link
2044 * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002045 * @hide
2046 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002047 @UnsupportedAppUsage
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002048 public int getConnectionState() {
Myles Watson125b5452017-11-27 16:41:47 -08002049 if (getState() != STATE_ON) {
2050 return BluetoothAdapter.STATE_DISCONNECTED;
2051 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002052 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002053 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002054 if (mService != null) {
2055 return mService.getAdapterConnectionState();
2056 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002057 } catch (RemoteException e) {
2058 Log.e(TAG, "getConnectionState:", e);
2059 } finally {
2060 mServiceLock.readLock().unlock();
2061 }
Jaikumar Ganeshc53cab22010-10-26 16:02:26 -07002062 return BluetoothAdapter.STATE_DISCONNECTED;
2063 }
2064
2065 /**
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002066 * Get the current connection state of a profile.
2067 * This function can be used to check whether the local Bluetooth adapter
2068 * is connected to any remote device for a specific profile.
Jack He6b73b322019-01-03 16:23:41 -08002069 * Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002070 *
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002071 * <p> Return value can be one of
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002072 * {@link BluetoothProfile#STATE_DISCONNECTED},
2073 * {@link BluetoothProfile#STATE_CONNECTING},
2074 * {@link BluetoothProfile#STATE_CONNECTED},
2075 * {@link BluetoothProfile#STATE_DISCONNECTING}
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002076 */
Tor Norbye2d497522015-04-23 17:10:21 -07002077 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002078 public int getProfileConnectionState(int profile) {
Myles Watson125b5452017-11-27 16:41:47 -08002079 if (getState() != STATE_ON) {
2080 return BluetoothProfile.STATE_DISCONNECTED;
2081 }
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002082 try {
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002083 mServiceLock.readLock().lock();
Myles Watson125b5452017-11-27 16:41:47 -08002084 if (mService != null) {
2085 return mService.getProfileConnectionState(profile);
2086 }
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002087 } catch (RemoteException e) {
2088 Log.e(TAG, "getProfileConnectionState:", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002089 } finally {
2090 mServiceLock.readLock().unlock();
Jaikumar Ganesh93547902011-08-23 12:21:55 -07002091 }
Jaikumar Ganeshcb1d3542011-08-19 10:26:32 -07002092 return BluetoothProfile.STATE_DISCONNECTED;
2093 }
2094
2095 /**
Nick Pelly45e27042009-08-19 11:00:00 -07002096 * Create a listening, secure RFCOMM Bluetooth socket.
2097 * <p>A remote device connecting to this socket will be authenticated and
Nick Pellybd022f42009-08-14 18:33:38 -07002098 * communication on this socket will be encrypted.
Nick Pelly45e27042009-08-19 11:00:00 -07002099 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
Nick Pelly24bb9b82009-10-02 20:34:18 -07002100 * connections from a listening {@link BluetoothServerSocket}.
Nick Pelly45e27042009-08-19 11:00:00 -07002101 * <p>Valid RFCOMM channels are in range 1 to 30.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002102 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
Jack Hea355e5e2017-08-22 16:06:54 -07002103 *
Nick Pelly45e27042009-08-19 11:00:00 -07002104 * @param channel RFCOMM channel to listen on
2105 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002106 * @throws IOException on error, for example Bluetooth not available, or insufficient
2107 * permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002108 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002109 */
Nick Pelly45e27042009-08-19 11:00:00 -07002110 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002111 return listenUsingRfcommOn(channel, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02002112 }
2113
2114 /**
2115 * Create a listening, secure RFCOMM Bluetooth socket.
2116 * <p>A remote device connecting to this socket will be authenticated and
2117 * communication on this socket will be encrypted.
2118 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2119 * connections from a listening {@link BluetoothServerSocket}.
2120 * <p>Valid RFCOMM channels are in range 1 to 30.
2121 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
2122 * <p>To auto assign a channel without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002123 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
Jack Hea355e5e2017-08-22 16:06:54 -07002124 *
Casper Bonde23284232015-04-21 13:12:05 +02002125 * @param channel RFCOMM channel to listen on
Jack Hea355e5e2017-08-22 16:06:54 -07002126 * @param mitm enforce man-in-the-middle protection for authentication.
2127 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2128 * connections.
Casper Bonde23284232015-04-21 13:12:05 +02002129 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002130 * @throws IOException on error, for example Bluetooth not available, or insufficient
2131 * permissions, or channel in use.
Casper Bonde23284232015-04-21 13:12:05 +02002132 * @hide
2133 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002134 @UnsupportedAppUsage
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002135 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
Myles Watson125b5452017-11-27 16:41:47 -08002136 boolean min16DigitPin) throws IOException {
2137 BluetoothServerSocket socket =
2138 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm,
2139 min16DigitPin);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002140 int errno = socket.mSocket.bindListen();
Casper Bonde23284232015-04-21 13:12:05 +02002141 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002142 socket.setChannel(socket.mSocket.getPort());
2143 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002144 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07002145 //TODO(BT): Throw the same exception error code
2146 // that the previous code was using.
2147 //socket.mSocket.throwErrnoNative(errno);
2148 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002149 }
2150 return socket;
2151 }
2152
2153 /**
Nick Pelly24bb9b82009-10-02 20:34:18 -07002154 * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
2155 * <p>A remote device connecting to this socket will be authenticated and
2156 * communication on this socket will be encrypted.
2157 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2158 * connections from a listening {@link BluetoothServerSocket}.
2159 * <p>The system will assign an unused RFCOMM channel to listen on.
2160 * <p>The system will also register a Service Discovery
2161 * Protocol (SDP) record with the local SDP server containing the specified
2162 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2163 * can use the same UUID to query our SDP server and discover which channel
2164 * to connect to. This SDP record will be removed when this socket is
2165 * closed, or if this application closes unexpectedly.
Nick Pelly16fb88a2009-10-07 07:44:03 +02002166 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2167 * connect to this socket from another device using the same {@link UUID}.
Jack Hea355e5e2017-08-22 16:06:54 -07002168 *
Nick Pelly24bb9b82009-10-02 20:34:18 -07002169 * @param name service name for SDP record
2170 * @param uuid uuid for SDP record
2171 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002172 * @throws IOException on error, for example Bluetooth not available, or insufficient
2173 * permissions, or channel in use.
Nick Pelly24bb9b82009-10-02 20:34:18 -07002174 */
Tor Norbye2d497522015-04-23 17:10:21 -07002175 @RequiresPermission(Manifest.permission.BLUETOOTH)
Nick Pelly16fb88a2009-10-07 07:44:03 +02002176 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
Nick Pelly24bb9b82009-10-02 20:34:18 -07002177 throws IOException {
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002178 return createNewRfcommSocketAndRecord(name, uuid, true, true);
2179 }
2180
2181 /**
2182 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002183 * <p>The link key is not required to be authenticated, i.e the communication may be
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002184 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002185 * the link will be encrypted, as encryption is mandartory.
2186 * For legacy devices (pre Bluetooth 2.1 devices) the link will not
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002187 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
2188 * encrypted and authenticated communication channel is desired.
2189 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2190 * connections from a listening {@link BluetoothServerSocket}.
2191 * <p>The system will assign an unused RFCOMM channel to listen on.
2192 * <p>The system will also register a Service Discovery
2193 * Protocol (SDP) record with the local SDP server containing the specified
2194 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2195 * can use the same UUID to query our SDP server and discover which channel
2196 * to connect to. This SDP record will be removed when this socket is
2197 * closed, or if this application closes unexpectedly.
2198 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2199 * connect to this socket from another device using the same {@link UUID}.
Jack Hea355e5e2017-08-22 16:06:54 -07002200 *
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002201 * @param name service name for SDP record
2202 * @param uuid uuid for SDP record
2203 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002204 * @throws IOException on error, for example Bluetooth not available, or insufficient
2205 * permissions, or channel in use.
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002206 */
Tor Norbye2d497522015-04-23 17:10:21 -07002207 @RequiresPermission(Manifest.permission.BLUETOOTH)
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002208 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
2209 throws IOException {
2210 return createNewRfcommSocketAndRecord(name, uuid, false, false);
2211 }
2212
Jack Hea355e5e2017-08-22 16:06:54 -07002213 /**
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002214 * Create a listening, encrypted,
2215 * RFCOMM Bluetooth socket with Service Record.
2216 * <p>The link will be encrypted, but the link key is not required to be authenticated
2217 * i.e the communication is vulnerable to Man In the Middle attacks. Use
2218 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
2219 * <p> Use this socket if authentication of link key is not possible.
2220 * For example, for Bluetooth 2.1 devices, if any of the devices does not have
2221 * an input and output capability or just has the ability to display a numeric key,
2222 * a secure socket connection is not possible and this socket can be used.
2223 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
2224 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
2225 * For more details, refer to the Security Model section 5.2 (vol 3) of
2226 * Bluetooth Core Specification version 2.1 + EDR.
2227 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2228 * connections from a listening {@link BluetoothServerSocket}.
2229 * <p>The system will assign an unused RFCOMM channel to listen on.
2230 * <p>The system will also register a Service Discovery
2231 * Protocol (SDP) record with the local SDP server containing the specified
2232 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2233 * can use the same UUID to query our SDP server and discover which channel
2234 * to connect to. This SDP record will be removed when this socket is
2235 * closed, or if this application closes unexpectedly.
2236 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2237 * connect to this socket from another device using the same {@link UUID}.
2238 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jack Hea355e5e2017-08-22 16:06:54 -07002239 *
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002240 * @param name service name for SDP record
2241 * @param uuid uuid for SDP record
2242 * @return a listening RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002243 * @throws IOException on error, for example Bluetooth not available, or insufficient
2244 * permissions, or channel in use.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002245 * @hide
2246 */
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002247 @UnsupportedAppUsage
Myles Watson125b5452017-11-27 16:41:47 -08002248 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)
2249 throws IOException {
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002250 return createNewRfcommSocketAndRecord(name, uuid, false, true);
2251 }
2252
zzy3b147b72012-04-03 19:48:32 -07002253
Jaikumar Ganesh6eef14a2010-12-23 12:57:02 -08002254 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
2255 boolean auth, boolean encrypt) throws IOException {
Nick Pelly24bb9b82009-10-02 20:34:18 -07002256 BluetoothServerSocket socket;
Myles Watson125b5452017-11-27 16:41:47 -08002257 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, encrypt,
2258 new ParcelUuid(uuid));
zzy3b147b72012-04-03 19:48:32 -07002259 socket.setServiceName(name);
2260 int errno = socket.mSocket.bindListen();
2261 if (errno != 0) {
2262 //TODO(BT): Throw the same exception error code
2263 // that the previous code was using.
2264 //socket.mSocket.throwErrnoNative(errno);
2265 throw new IOException("Error: " + errno);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002266 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002267 return socket;
2268 }
2269
2270 /**
Nick Pellybd022f42009-08-14 18:33:38 -07002271 * Construct an unencrypted, unauthenticated, RFCOMM server socket.
2272 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002273 *
Nick Pellybd022f42009-08-14 18:33:38 -07002274 * @return An RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002275 * @throws IOException On error, for example Bluetooth not available, or insufficient
2276 * permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07002277 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002278 */
2279 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002280 BluetoothServerSocket socket =
2281 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, false, port);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002282 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002283 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002284 socket.setChannel(socket.mSocket.getPort());
2285 }
Nick Pelly24bb9b82009-10-02 20:34:18 -07002286 if (errno != 0) {
zzy3b147b72012-04-03 19:48:32 -07002287 //TODO(BT): Throw the same exception error code
2288 // that the previous code was using.
2289 //socket.mSocket.throwErrnoNative(errno);
2290 throw new IOException("Error: " + errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002291 }
2292 return socket;
2293 }
2294
Jack Hea355e5e2017-08-22 16:06:54 -07002295 /**
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002296 * Construct an encrypted, RFCOMM server socket.
2297 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002298 *
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002299 * @return An RFCOMM BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002300 * @throws IOException On error, for example Bluetooth not available, or insufficient
2301 * permissions.
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002302 * @hide
2303 */
Myles Watson125b5452017-11-27 16:41:47 -08002304 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port) throws IOException {
2305 BluetoothServerSocket socket =
2306 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, true, port);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002307 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002308 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Casper Bonde238e0f92015-04-09 09:24:48 +02002309 socket.setChannel(socket.mSocket.getPort());
2310 }
zzy3b147b72012-04-03 19:48:32 -07002311 if (errno < 0) {
2312 //TODO(BT): Throw the same exception error code
2313 // that the previous code was using.
2314 //socket.mSocket.throwErrnoNative(errno);
2315 throw new IOException("Error: " + errno);
Mathias Jeppssone3b9dc102011-03-21 15:06:52 +01002316 }
2317 return socket;
2318 }
2319
Nick Pellybd022f42009-08-14 18:33:38 -07002320 /**
2321 * Construct a SCO server socket.
2322 * Call #accept to retrieve connections to this socket.
Jack Hea355e5e2017-08-22 16:06:54 -07002323 *
Nick Pellybd022f42009-08-14 18:33:38 -07002324 * @return A SCO BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002325 * @throws IOException On error, for example Bluetooth not available, or insufficient
2326 * permissions.
Nick Pelly45e27042009-08-19 11:00:00 -07002327 * @hide
Nick Pellybd022f42009-08-14 18:33:38 -07002328 */
2329 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002330 BluetoothServerSocket socket =
2331 new BluetoothServerSocket(BluetoothSocket.TYPE_SCO, false, false, -1);
Nick Pelly24bb9b82009-10-02 20:34:18 -07002332 int errno = socket.mSocket.bindListen();
zzy3b147b72012-04-03 19:48:32 -07002333 if (errno < 0) {
2334 //TODO(BT): Throw the same exception error code
2335 // that the previous code was using.
2336 //socket.mSocket.throwErrnoNative(errno);
Nick Pellybd022f42009-08-14 18:33:38 -07002337 }
2338 return socket;
2339 }
2340
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002341 /**
Casper Bonde238e0f92015-04-09 09:24:48 +02002342 * Construct an encrypted, authenticated, L2CAP server socket.
2343 * Call #accept to retrieve connections to this socket.
Casper Bonde23284232015-04-21 13:12:05 +02002344 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002345 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002346 *
2347 * @param port the PSM to listen on
2348 * @param mitm enforce man-in-the-middle protection for authentication.
2349 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2350 * connections.
Casper Bonde238e0f92015-04-09 09:24:48 +02002351 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002352 * @throws IOException On error, for example Bluetooth not available, or insufficient
2353 * permissions.
Casper Bonde238e0f92015-04-09 09:24:48 +02002354 * @hide
2355 */
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002356 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
2357 throws IOException {
Myles Watson125b5452017-11-27 16:41:47 -08002358 BluetoothServerSocket socket =
2359 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, true, true, port, mitm,
2360 min16DigitPin);
Casper Bonde238e0f92015-04-09 09:24:48 +02002361 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002362 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Stanley Tnge48468d2017-11-22 16:04:40 -08002363 int assignedChannel = socket.mSocket.getPort();
2364 if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
2365 socket.setChannel(assignedChannel);
Casper Bonde238e0f92015-04-09 09:24:48 +02002366 }
2367 if (errno != 0) {
2368 //TODO(BT): Throw the same exception error code
2369 // that the previous code was using.
2370 //socket.mSocket.throwErrnoNative(errno);
2371 throw new IOException("Error: " + errno);
2372 }
2373 return socket;
2374 }
2375
2376 /**
Casper Bonde23284232015-04-21 13:12:05 +02002377 * Construct an encrypted, authenticated, L2CAP server socket.
2378 * Call #accept to retrieve connections to this socket.
2379 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002380 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002381 *
2382 * @param port the PSM to listen on
Casper Bonde23284232015-04-21 13:12:05 +02002383 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002384 * @throws IOException On error, for example Bluetooth not available, or insufficient
2385 * permissions.
Casper Bonde23284232015-04-21 13:12:05 +02002386 * @hide
2387 */
2388 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
Casper Bonde3b3d1fe2015-05-08 14:32:24 +02002389 return listenUsingL2capOn(port, false, false);
Casper Bonde23284232015-04-21 13:12:05 +02002390 }
2391
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302392
2393 /**
2394 * Construct an insecure L2CAP server socket.
2395 * Call #accept to retrieve connections to this socket.
2396 * <p>To auto assign a port without creating a SDP record use
Myles Watson125b5452017-11-27 16:41:47 -08002397 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
Jack Hea355e5e2017-08-22 16:06:54 -07002398 *
2399 * @param port the PSM to listen on
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302400 * @return An L2CAP BluetoothServerSocket
Jack Hea355e5e2017-08-22 16:06:54 -07002401 * @throws IOException On error, for example Bluetooth not available, or insufficient
2402 * permissions.
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302403 * @hide
2404 */
2405 public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08002406 Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
Myles Watson125b5452017-11-27 16:41:47 -08002407 BluetoothServerSocket socket =
2408 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
Stanley Tnge48468d2017-11-22 16:04:40 -08002409 false);
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302410 int errno = socket.mSocket.bindListen();
Jack Hea355e5e2017-08-22 16:06:54 -07002411 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
Stanley Tnge48468d2017-11-22 16:04:40 -08002412 int assignedChannel = socket.mSocket.getPort();
2413 if (DBG) {
2414 Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
2415 + assignedChannel);
2416 }
2417 socket.setChannel(assignedChannel);
Hemant Guptaef3e0db2017-02-03 16:38:59 +05302418 }
2419 if (errno != 0) {
2420 //TODO(BT): Throw the same exception error code
2421 // that the previous code was using.
2422 //socket.mSocket.throwErrnoNative(errno);
2423 throw new IOException("Error: " + errno);
2424 }
2425 return socket;
2426
2427 }
2428
Casper Bonde23284232015-04-21 13:12:05 +02002429 /**
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002430 * Read the local Out of Band Pairing Data
2431 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2432 *
2433 * @return Pair<byte[], byte[]> of Hash and Randomizer
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002434 * @hide
2435 */
2436 public Pair<byte[], byte[]> readOutOfBandData() {
Jaikumar Ganeshcc5494c2010-09-09 15:37:57 -07002437 return null;
2438 }
2439
Scott Main299ae672011-01-19 21:13:18 -08002440 /**
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002441 * Get the profile proxy object associated with the profile.
2442 *
Jack He6b73b322019-01-03 16:23:41 -08002443 * <p>Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP},
2444 * {@link BluetoothProfile#GATT}, or {@link BluetoothProfile#GATT_SERVER}. Clients must
2445 * implement {@link BluetoothProfile.ServiceListener} to get notified of the connection status
2446 * and to get the proxy object.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002447 *
2448 * @param context Context of the application
2449 * @param listener The service Listener for connection callbacks.
Jack He6b73b322019-01-03 16:23:41 -08002450 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET},
2451 * {@link BluetoothProfile#A2DP}. {@link BluetoothProfile#GATT} or
Jack Hea355e5e2017-08-22 16:06:54 -07002452 * {@link BluetoothProfile#GATT_SERVER}.
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002453 * @return true on success, false on error
2454 */
2455 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
Jack Hea355e5e2017-08-22 16:06:54 -07002456 int profile) {
Myles Watson125b5452017-11-27 16:41:47 -08002457 if (context == null || listener == null) {
2458 return false;
2459 }
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002460
2461 if (profile == BluetoothProfile.HEADSET) {
2462 BluetoothHeadset headset = new BluetoothHeadset(context, listener);
2463 return true;
2464 } else if (profile == BluetoothProfile.A2DP) {
2465 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
2466 return true;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002467 } else if (profile == BluetoothProfile.A2DP_SINK) {
2468 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
2469 return true;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002470 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
2471 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
2472 return true;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002473 } else if (profile == BluetoothProfile.HID_HOST) {
2474 BluetoothHidHost iDev = new BluetoothHidHost(context, listener);
Jaikumar Ganesh4ab0e772011-02-18 14:52:32 -08002475 return true;
Jaikumar Ganesh74ef1192011-02-23 10:22:15 -08002476 } else if (profile == BluetoothProfile.PAN) {
2477 BluetoothPan pan = new BluetoothPan(context, listener);
2478 return true;
Jaikumar Ganesh2ea1e852011-04-01 16:33:09 -07002479 } else if (profile == BluetoothProfile.HEALTH) {
Jack He6b73b322019-01-03 16:23:41 -08002480 Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated");
2481 return false;
Kim Schulz0d376052013-08-22 11:18:02 +02002482 } else if (profile == BluetoothProfile.MAP) {
2483 BluetoothMap map = new BluetoothMap(context, listener);
2484 return true;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002485 } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
2486 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
Hemant Gupta7aca90f2013-08-19 19:03:51 +05302487 return true;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002488 } else if (profile == BluetoothProfile.SAP) {
2489 BluetoothSap sap = new BluetoothSap(context, listener);
2490 return true;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002491 } else if (profile == BluetoothProfile.PBAP_CLIENT) {
2492 BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
2493 return true;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002494 } else if (profile == BluetoothProfile.MAP_CLIENT) {
2495 BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
2496 return true;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002497 } else if (profile == BluetoothProfile.HID_DEVICE) {
2498 BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
Ivan Podogov5297dba2016-12-30 14:35:09 +00002499 return true;
Jakub Pawlowskiea580fa2017-11-22 11:02:34 -08002500 } else if (profile == BluetoothProfile.HEARING_AID) {
2501 BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener);
2502 return true;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002503 } else {
2504 return false;
2505 }
2506 }
2507
2508 /**
2509 * Close the connection of the profile proxy to the Service.
2510 *
2511 * <p> Clients should call this when they are no longer using
2512 * the proxy obtained from {@link #getProfileProxy}.
Jack He6b73b322019-01-03 16:23:41 -08002513 * Profile can be one of {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002514 *
2515 * @param profile
2516 * @param proxy Profile proxy object
2517 */
2518 public void closeProfileProxy(int profile, BluetoothProfile proxy) {
Myles Watson125b5452017-11-27 16:41:47 -08002519 if (proxy == null) {
2520 return;
2521 }
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002522
2523 switch (profile) {
2524 case BluetoothProfile.HEADSET:
Jack Hea355e5e2017-08-22 16:06:54 -07002525 BluetoothHeadset headset = (BluetoothHeadset) proxy;
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002526 headset.close();
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002527 break;
2528 case BluetoothProfile.A2DP:
Jack Hea355e5e2017-08-22 16:06:54 -07002529 BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002530 a2dp.close();
2531 break;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002532 case BluetoothProfile.A2DP_SINK:
Jack Hea355e5e2017-08-22 16:06:54 -07002533 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy;
Mike Lockwood2263dd12014-05-14 09:51:30 -07002534 a2dpSink.close();
2535 break;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002536 case BluetoothProfile.AVRCP_CONTROLLER:
Jack Hea355e5e2017-08-22 16:06:54 -07002537 BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy;
Mike Lockwood94b59de2014-06-02 16:20:37 -07002538 avrcp.close();
2539 break;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002540 case BluetoothProfile.HID_HOST:
2541 BluetoothHidHost iDev = (BluetoothHidHost) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002542 iDev.close();
2543 break;
2544 case BluetoothProfile.PAN:
Jack Hea355e5e2017-08-22 16:06:54 -07002545 BluetoothPan pan = (BluetoothPan) proxy;
Jaikumar Ganesh9bb27512011-11-28 09:59:08 -08002546 pan.close();
2547 break;
Jack Hea355e5e2017-08-22 16:06:54 -07002548 case BluetoothProfile.GATT:
2549 BluetoothGatt gatt = (BluetoothGatt) proxy;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08002550 gatt.close();
2551 break;
2552 case BluetoothProfile.GATT_SERVER:
Jack Hea355e5e2017-08-22 16:06:54 -07002553 BluetoothGattServer gattServer = (BluetoothGattServer) proxy;
Ganesh Ganapathi Batta99081122013-02-05 15:28:33 -08002554 gattServer.close();
2555 break;
Kim Schulz0d376052013-08-22 11:18:02 +02002556 case BluetoothProfile.MAP:
Jack Hea355e5e2017-08-22 16:06:54 -07002557 BluetoothMap map = (BluetoothMap) proxy;
Kim Schulz0d376052013-08-22 11:18:02 +02002558 map.close();
2559 break;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002560 case BluetoothProfile.HEADSET_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002561 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy;
Mike Lockwoodcf916d32014-06-12 11:23:40 -07002562 headsetClient.close();
Hemant Gupta7aca90f2013-08-19 19:03:51 +05302563 break;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002564 case BluetoothProfile.SAP:
Jack Hea355e5e2017-08-22 16:06:54 -07002565 BluetoothSap sap = (BluetoothSap) proxy;
Casper Bonde2a5f6082015-03-19 10:36:45 +01002566 sap.close();
2567 break;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002568 case BluetoothProfile.PBAP_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002569 BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy;
Joseph Pirozzocfa8a642016-03-04 13:02:54 -08002570 pbapClient.close();
2571 break;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002572 case BluetoothProfile.MAP_CLIENT:
Jack Hea355e5e2017-08-22 16:06:54 -07002573 BluetoothMapClient mapClient = (BluetoothMapClient) proxy;
Joseph Pirozzo631768d2016-09-01 14:19:28 -07002574 mapClient.close();
2575 break;
Hansong Zhangc26c76c2017-10-20 15:55:59 -07002576 case BluetoothProfile.HID_DEVICE:
2577 BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
2578 hidDevice.close();
Ivan Podogov5297dba2016-12-30 14:35:09 +00002579 break;
Jakub Pawlowskiea580fa2017-11-22 11:02:34 -08002580 case BluetoothProfile.HEARING_AID:
2581 BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
2582 hearingAid.close();
Jaikumar Ganesh62c37ef2010-08-24 17:36:13 -07002583 }
2584 }
2585
Jack He2992cd02017-08-22 21:21:23 -07002586 private final IBluetoothManagerCallback mManagerCallback =
Jack Hea355e5e2017-08-22 16:06:54 -07002587 new IBluetoothManagerCallback.Stub() {
2588 public void onBluetoothServiceUp(IBluetooth bluetoothService) {
Myles Watson125b5452017-11-27 16:41:47 -08002589 if (DBG) {
2590 Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
2591 }
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002592
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002593 mServiceLock.writeLock().lock();
Jack Hea355e5e2017-08-22 16:06:54 -07002594 mService = bluetoothService;
Pavlin Radoslavove957a8a2016-05-24 15:28:41 -07002595 mServiceLock.writeLock().unlock();
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002596
Jack Hea355e5e2017-08-22 16:06:54 -07002597 synchronized (mProxyServiceStateCallbacks) {
2598 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2599 try {
2600 if (cb != null) {
2601 cb.onBluetoothServiceUp(bluetoothService);
2602 } else {
2603 Log.d(TAG, "onBluetoothServiceUp: cb is null!");
2604 }
2605 } catch (Exception e) {
2606 Log.e(TAG, "", e);
Pavlin Radoslavoveb50a392016-05-22 22:16:41 -07002607 }
Matthew Xie60675b22015-02-06 14:09:54 -08002608 }
fredc903ac6f2012-04-24 03:59:57 -07002609 }
fredc0f420372012-04-12 00:02:00 -07002610 }
Nitin Arorad055adb2015-03-02 15:03:51 -08002611
Jack Hea355e5e2017-08-22 16:06:54 -07002612 public void onBluetoothServiceDown() {
Myles Watson125b5452017-11-27 16:41:47 -08002613 if (DBG) {
2614 Log.d(TAG, "onBluetoothServiceDown: " + mService);
2615 }
Jack Hea355e5e2017-08-22 16:06:54 -07002616
2617 try {
2618 mServiceLock.writeLock().lock();
2619 mService = null;
Myles Watson125b5452017-11-27 16:41:47 -08002620 if (mLeScanClients != null) {
2621 mLeScanClients.clear();
2622 }
2623 if (sBluetoothLeAdvertiser != null) {
2624 sBluetoothLeAdvertiser.cleanup();
2625 }
2626 if (sBluetoothLeScanner != null) {
2627 sBluetoothLeScanner.cleanup();
2628 }
Jack Hea355e5e2017-08-22 16:06:54 -07002629 } finally {
2630 mServiceLock.writeLock().unlock();
2631 }
2632
2633 synchronized (mProxyServiceStateCallbacks) {
2634 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2635 try {
2636 if (cb != null) {
2637 cb.onBluetoothServiceDown();
2638 } else {
2639 Log.d(TAG, "onBluetoothServiceDown: cb is null!");
2640 }
2641 } catch (Exception e) {
2642 Log.e(TAG, "", e);
2643 }
2644 }
2645 }
2646 }
2647
2648 public void onBrEdrDown() {
Myles Watson125b5452017-11-27 16:41:47 -08002649 if (VDBG) {
2650 Log.i(TAG, "onBrEdrDown: " + mService);
2651 }
Jack Hea355e5e2017-08-22 16:06:54 -07002652 }
2653 };
fredc0f420372012-04-12 00:02:00 -07002654
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002655 /**
Martijn Coenen6c614b72012-04-18 13:01:15 -07002656 * Enable the Bluetooth Adapter, but don't auto-connect devices
2657 * and don't persist state. Only for use by system applications.
Jack Hea355e5e2017-08-22 16:06:54 -07002658 *
Martijn Coenen6c614b72012-04-18 13:01:15 -07002659 * @hide
2660 */
Selim Gurun64bd35e2017-10-17 17:01:38 -07002661 @SystemApi
2662 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
Martijn Coenen6c614b72012-04-18 13:01:15 -07002663 public boolean enableNoAutoConnect() {
Jack He2992cd02017-08-22 21:21:23 -07002664 if (isEnabled()) {
Myles Watson125b5452017-11-27 16:41:47 -08002665 if (DBG) {
2666 Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
2667 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002668 return true;
2669 }
2670 try {
Marie Janssen59804562016-12-28 14:13:21 -08002671 return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
Jack Hea355e5e2017-08-22 16:06:54 -07002672 } catch (RemoteException e) {
2673 Log.e(TAG, "", e);
2674 }
Ganesh Ganapathi Battafffa86b2012-08-08 15:35:49 -07002675 return false;
Martijn Coenen6c614b72012-04-18 13:01:15 -07002676 }
2677
2678 /**
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002679 * Enable control of the Bluetooth Adapter for a single application.
2680 *
2681 * <p>Some applications need to use Bluetooth for short periods of time to
2682 * transfer data but don't want all the associated implications like
2683 * automatic connection to headsets etc.
2684 *
2685 * <p> Multiple applications can call this. This is reference counted and
2686 * Bluetooth disabled only when no one else is using it. There will be no UI
2687 * shown to the user while bluetooth is being enabled. Any user action will
2688 * override this call. For example, if user wants Bluetooth on and the last
2689 * user of this API wanted to disable Bluetooth, Bluetooth will not be
2690 * turned off.
2691 *
2692 * <p> This API is only meant to be used by internal applications. Third
2693 * party applications but use {@link #enable} and {@link #disable} APIs.
2694 *
2695 * <p> If this API returns true, it means the callback will be called.
2696 * The callback will be called with the current state of Bluetooth.
2697 * If the state is not what was requested, an internal error would be the
Jaikumar Ganeshf5fb6c82011-08-03 14:17:22 -07002698 * reason. If Bluetooth is already on and if this function is called to turn
2699 * it on, the api will return true and a callback will be called.
2700 *
2701 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002702 *
2703 * @param on True for on, false for off.
2704 * @param callback The callback to notify changes to the state.
2705 * @hide
2706 */
2707 public boolean changeApplicationBluetoothState(boolean on,
Jack Hea355e5e2017-08-22 16:06:54 -07002708 BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002709 return false;
2710 }
2711
2712 /**
2713 * @hide
2714 */
2715 public interface BluetoothStateChangeCallback {
Myles Watson125b5452017-11-27 16:41:47 -08002716 /**
2717 * @hide
2718 */
2719 void onBluetoothStateChange(boolean on);
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002720 }
2721
2722 /**
2723 * @hide
2724 */
2725 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
2726 private BluetoothStateChangeCallback mCallback;
2727
Myles Watson125b5452017-11-27 16:41:47 -08002728 StateChangeCallbackWrapper(BluetoothStateChangeCallback callback) {
Jaikumar Ganeshef2cb7c2011-07-21 18:13:38 -07002729 mCallback = callback;
2730 }
2731
2732 @Override
2733 public void onBluetoothStateChange(boolean on) {
2734 mCallback.onBluetoothStateChange(on);
2735 }
2736 }
2737
Jaikumar Ganeshe4caddb2012-01-25 16:16:48 -08002738 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
2739 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
2740 return Collections.unmodifiableSet(deviceSet);
Nick Pellybd022f42009-08-14 18:33:38 -07002741 }
Nick Pelly005b2282009-09-10 10:21:56 -07002742
fredc0f420372012-04-12 00:02:00 -07002743 protected void finalize() throws Throwable {
2744 try {
2745 mManagerService.unregisterAdapter(mManagerCallback);
2746 } catch (RemoteException e) {
2747 Log.e(TAG, "", e);
2748 } finally {
2749 super.finalize();
2750 }
2751 }
2752
2753
Nick Pelly005b2282009-09-10 10:21:56 -07002754 /**
Nick Pelly75596b42011-12-07 15:03:55 -08002755 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
Nick Pelly55e66f12009-09-18 11:37:06 -07002756 * <p>Alphabetic characters must be uppercase to be valid.
Nick Pelly005b2282009-09-10 10:21:56 -07002757 *
2758 * @param address Bluetooth address as string
2759 * @return true if the address is valid, false otherwise
2760 */
2761 public static boolean checkBluetoothAddress(String address) {
2762 if (address == null || address.length() != ADDRESS_LENGTH) {
2763 return false;
2764 }
2765 for (int i = 0; i < ADDRESS_LENGTH; i++) {
2766 char c = address.charAt(i);
2767 switch (i % 3) {
Jack Hea355e5e2017-08-22 16:06:54 -07002768 case 0:
2769 case 1:
2770 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
2771 // hex character, OK
2772 break;
2773 }
2774 return false;
2775 case 2:
2776 if (c == ':') {
2777 break; // OK
2778 }
2779 return false;
Nick Pelly005b2282009-09-10 10:21:56 -07002780 }
2781 }
2782 return true;
2783 }
fredc0f420372012-04-12 00:02:00 -07002784
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002785 @UnsupportedAppUsage
fredc0f420372012-04-12 00:02:00 -07002786 /*package*/ IBluetoothManager getBluetoothManager() {
Jack Hea355e5e2017-08-22 16:06:54 -07002787 return mManagerService;
fredc0f420372012-04-12 00:02:00 -07002788 }
2789
Jack He2992cd02017-08-22 21:21:23 -07002790 private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks =
Jack Hea355e5e2017-08-22 16:06:54 -07002791 new ArrayList<IBluetoothManagerCallback>();
fredcd6883532012-04-25 17:46:13 -07002792
Mathew Inwood4dc66d32018-08-01 15:07:20 +01002793 @UnsupportedAppUsage
fredc903ac6f2012-04-24 03:59:57 -07002794 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08002795 synchronized (mProxyServiceStateCallbacks) {
fredcd6883532012-04-25 17:46:13 -07002796 if (cb == null) {
fredcbf072a72012-05-09 16:52:50 -07002797 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
2798 } else if (!mProxyServiceStateCallbacks.contains(cb)) {
2799 mProxyServiceStateCallbacks.add(cb);
fredc903ac6f2012-04-24 03:59:57 -07002800 }
2801 }
2802 return mService;
2803 }
2804
2805 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
Matthew Xie60675b22015-02-06 14:09:54 -08002806 synchronized (mProxyServiceStateCallbacks) {
fredcbf072a72012-05-09 16:52:50 -07002807 mProxyServiceStateCallbacks.remove(cb);
fredc0f420372012-04-12 00:02:00 -07002808 }
2809 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002810
2811 /**
Matthew Xiecdd94e32013-04-11 16:36:26 -07002812 * Callback interface used to deliver LE scan results.
Matthew Xieddf7e472013-03-01 18:41:02 -08002813 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07002814 * @see #startLeScan(LeScanCallback)
2815 * @see #startLeScan(UUID[], LeScanCallback)
Matthew Xieddf7e472013-03-01 18:41:02 -08002816 */
Matthew Xiecdd94e32013-04-11 16:36:26 -07002817 public interface LeScanCallback {
2818 /**
2819 * Callback reporting an LE device found during a device scan initiated
2820 * by the {@link BluetoothAdapter#startLeScan} function.
2821 *
2822 * @param device Identifies the remote device
Jack Hea355e5e2017-08-22 16:06:54 -07002823 * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0
2824 * if no RSSI value is available.
2825 * @param scanRecord The content of the advertisement record offered by the remote device.
Matthew Xiecdd94e32013-04-11 16:36:26 -07002826 */
Myles Watson125b5452017-11-27 16:41:47 -08002827 void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
Matthew Xieddf7e472013-03-01 18:41:02 -08002828 }
2829
2830 /**
2831 * Starts a scan for Bluetooth LE devices.
2832 *
2833 * <p>Results of the scan are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07002834 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08002835 *
Matthew Xiecdd94e32013-04-11 16:36:26 -07002836 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08002837 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07002838 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack Hea355e5e2017-08-22 16:06:54 -07002839 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002840 */
Wei Wangaf74e662014-07-09 14:03:42 -07002841 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002842 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07002843 public boolean startLeScan(LeScanCallback callback) {
2844 return startLeScan(null, callback);
Matthew Xieddf7e472013-03-01 18:41:02 -08002845 }
2846
2847 /**
2848 * Starts a scan for Bluetooth LE devices, looking for devices that
2849 * advertise given services.
2850 *
2851 * <p>Devices which advertise all specified services are reported using the
Matthew Xiecdd94e32013-04-11 16:36:26 -07002852 * {@link LeScanCallback#onLeScan} callback.
Matthew Xieddf7e472013-03-01 18:41:02 -08002853 *
Matthew Xieddf7e472013-03-01 18:41:02 -08002854 * @param serviceUuids Array of services to look for
Matthew Xiecdd94e32013-04-11 16:36:26 -07002855 * @param callback the callback LE scan results are delivered
Matthew Xieddf7e472013-03-01 18:41:02 -08002856 * @return true, if the scan was started successfully
Wei Wangaf74e662014-07-09 14:03:42 -07002857 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
Jack Hea355e5e2017-08-22 16:06:54 -07002858 * instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002859 */
Wei Wangaf74e662014-07-09 14:03:42 -07002860 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002861 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Wei Wangc3059cc2014-07-23 23:34:00 -07002862 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
Myles Watson125b5452017-11-27 16:41:47 -08002863 if (DBG) {
2864 Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
2865 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07002866 if (callback == null) {
Myles Watson125b5452017-11-27 16:41:47 -08002867 if (DBG) {
2868 Log.e(TAG, "startLeScan: null callback");
2869 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002870 return false;
2871 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002872 BluetoothLeScanner scanner = getBluetoothLeScanner();
2873 if (scanner == null) {
Myles Watson125b5452017-11-27 16:41:47 -08002874 if (DBG) {
2875 Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
2876 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002877 return false;
2878 }
Matthew Xieddf7e472013-03-01 18:41:02 -08002879
Jack Hea355e5e2017-08-22 16:06:54 -07002880 synchronized (mLeScanClients) {
Matthew Xiecdd94e32013-04-11 16:36:26 -07002881 if (mLeScanClients.containsKey(callback)) {
Myles Watson125b5452017-11-27 16:41:47 -08002882 if (DBG) {
2883 Log.e(TAG, "LE Scan has already started");
2884 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07002885 return false;
2886 }
2887
2888 try {
2889 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
Matthew Xie32ab77b2013-05-08 19:26:57 -07002890 if (iGatt == null) {
2891 // BLE is not supported
2892 return false;
2893 }
2894
Wei Wangc3059cc2014-07-23 23:34:00 -07002895 ScanCallback scanCallback = new ScanCallback() {
2896 @Override
2897 public void onScanResult(int callbackType, ScanResult result) {
2898 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
2899 // Should not happen.
2900 Log.e(TAG, "LE Scan has already started");
2901 return;
2902 }
2903 ScanRecord scanRecord = result.getScanRecord();
2904 if (scanRecord == null) {
2905 return;
2906 }
2907 if (serviceUuids != null) {
2908 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
2909 for (UUID uuid : serviceUuids) {
2910 uuids.add(new ParcelUuid(uuid));
2911 }
2912 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
2913 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
Myles Watson125b5452017-11-27 16:41:47 -08002914 if (DBG) {
2915 Log.d(TAG, "uuids does not match");
2916 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002917 return;
2918 }
2919 }
2920 callback.onLeScan(result.getDevice(), result.getRssi(),
2921 scanRecord.getBytes());
2922 }
2923 };
Myles Watson125b5452017-11-27 16:41:47 -08002924 ScanSettings settings = new ScanSettings.Builder().setCallbackType(
2925 ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
2926 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
2927 .build();
Wei Wangc3059cc2014-07-23 23:34:00 -07002928
2929 List<ScanFilter> filters = new ArrayList<ScanFilter>();
2930 if (serviceUuids != null && serviceUuids.length > 0) {
2931 // Note scan filter does not support matching an UUID array so we put one
2932 // UUID to hardware and match the whole array in callback.
Myles Watson125b5452017-11-27 16:41:47 -08002933 ScanFilter filter =
2934 new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuids[0]))
2935 .build();
Wei Wangc3059cc2014-07-23 23:34:00 -07002936 filters.add(filter);
Matthew Xiecdd94e32013-04-11 16:36:26 -07002937 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002938 scanner.startScan(filters, settings, scanCallback);
2939
2940 mLeScanClients.put(callback, scanCallback);
2941 return true;
2942
Matthew Xiecdd94e32013-04-11 16:36:26 -07002943 } catch (RemoteException e) {
Jack Hea355e5e2017-08-22 16:06:54 -07002944 Log.e(TAG, "", e);
Matthew Xiecdd94e32013-04-11 16:36:26 -07002945 }
2946 }
2947 return false;
Matthew Xieddf7e472013-03-01 18:41:02 -08002948 }
2949
2950 /**
2951 * Stops an ongoing Bluetooth LE device scan.
2952 *
Jack Hea355e5e2017-08-22 16:06:54 -07002953 * @param callback used to identify which scan to stop must be the same handle used to start the
2954 * scan
Wei Wangaf74e662014-07-09 14:03:42 -07002955 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
Matthew Xieddf7e472013-03-01 18:41:02 -08002956 */
Wei Wangaf74e662014-07-09 14:03:42 -07002957 @Deprecated
Tor Norbye2d497522015-04-23 17:10:21 -07002958 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
Matthew Xiecdd94e32013-04-11 16:36:26 -07002959 public void stopLeScan(LeScanCallback callback) {
Myles Watson125b5452017-11-27 16:41:47 -08002960 if (DBG) {
2961 Log.d(TAG, "stopLeScan()");
2962 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002963 BluetoothLeScanner scanner = getBluetoothLeScanner();
2964 if (scanner == null) {
2965 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08002966 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002967 synchronized (mLeScanClients) {
2968 ScanCallback scanCallback = mLeScanClients.remove(callback);
2969 if (scanCallback == null) {
Myles Watson125b5452017-11-27 16:41:47 -08002970 if (DBG) {
2971 Log.d(TAG, "scan not started yet");
2972 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002973 return;
Matthew Xieddf7e472013-03-01 18:41:02 -08002974 }
Wei Wangc3059cc2014-07-23 23:34:00 -07002975 scanner.stopScan(scanCallback);
Prerepa Viswanadham8f2e74c2014-07-09 12:51:59 -07002976 }
Matthew Xiecdd94e32013-04-11 16:36:26 -07002977 }
Stanley Tnge48468d2017-11-22 16:04:40 -08002978
2979 /**
2980 * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
2981 * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
Stanley Tng1bff4ba2018-06-29 14:05:04 -07002982 * for incoming connections. The supported Bluetooth transport is LE only.
Stanley Tnge48468d2017-11-22 16:04:40 -08002983 * <p>A remote device connecting to this socket will be authenticated and communication on this
2984 * socket will be encrypted.
2985 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
2986 * {@link BluetoothServerSocket}.
2987 * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {#link
2988 * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
2989 * closed, Bluetooth is turned off, or the application exits unexpectedly.
2990 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
2991 * defined and performed by the application.
Stanley Tng1bff4ba2018-06-29 14:05:04 -07002992 * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
Stanley Tnge48468d2017-11-22 16:04:40 -08002993 * socket from another Android device that is given the PSM value.
2994 *
Stanley Tnge48468d2017-11-22 16:04:40 -08002995 * @return an L2CAP CoC BluetoothServerSocket
2996 * @throws IOException on error, for example Bluetooth not available, or insufficient
2997 * permissions, or unable to start this CoC
Stanley Tnge48468d2017-11-22 16:04:40 -08002998 */
2999 @RequiresPermission(Manifest.permission.BLUETOOTH)
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003000 public BluetoothServerSocket listenUsingL2capChannel()
Stanley Tnge48468d2017-11-22 16:04:40 -08003001 throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08003002 BluetoothServerSocket socket =
3003 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
3004 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3005 int errno = socket.mSocket.bindListen();
3006 if (errno != 0) {
3007 throw new IOException("Error: " + errno);
3008 }
3009
3010 int assignedPsm = socket.mSocket.getPort();
3011 if (assignedPsm == 0) {
3012 throw new IOException("Error: Unable to assign PSM value");
3013 }
3014 if (DBG) {
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003015 Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
Stanley Tnge48468d2017-11-22 16:04:40 -08003016 + assignedPsm);
3017 }
3018 socket.setChannel(assignedPsm);
3019
3020 return socket;
3021 }
3022
3023 /**
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003024 * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
3025 * API name, listenUsingL2capChannel.
3026 * @hide
3027 */
3028 @RequiresPermission(Manifest.permission.BLUETOOTH)
3029 public BluetoothServerSocket listenUsingL2capCoc(int transport)
3030 throws IOException {
3031 Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel");
3032 return listenUsingL2capChannel();
3033 }
3034
3035 /**
Stanley Tnge48468d2017-11-22 16:04:40 -08003036 * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003037 * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
3038 * supported Bluetooth transport is LE only.
Stanley Tnge48468d2017-11-22 16:04:40 -08003039 * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003040 * to man-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
Stanley Tnge48468d2017-11-22 16:04:40 -08003041 * authenticated communication channel is desired.
3042 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3043 * {@link BluetoothServerSocket}.
3044 * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
3045 * can be read from the {#link BluetoothServerSocket#getPsm()} and this value will be released
3046 * when this server socket is closed, Bluetooth is turned off, or the application exits
3047 * unexpectedly.
3048 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3049 * defined and performed by the application.
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003050 * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
3051 * socket from another Android device that is given the PSM value.
Stanley Tnge48468d2017-11-22 16:04:40 -08003052 *
Stanley Tnge48468d2017-11-22 16:04:40 -08003053 * @return an L2CAP CoC BluetoothServerSocket
3054 * @throws IOException on error, for example Bluetooth not available, or insufficient
3055 * permissions, or unable to start this CoC
Stanley Tnge48468d2017-11-22 16:04:40 -08003056 */
3057 @RequiresPermission(Manifest.permission.BLUETOOTH)
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003058 public BluetoothServerSocket listenUsingInsecureL2capChannel()
Stanley Tnge48468d2017-11-22 16:04:40 -08003059 throws IOException {
Stanley Tnge48468d2017-11-22 16:04:40 -08003060 BluetoothServerSocket socket =
3061 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
3062 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3063 int errno = socket.mSocket.bindListen();
3064 if (errno != 0) {
3065 throw new IOException("Error: " + errno);
3066 }
3067
3068 int assignedPsm = socket.mSocket.getPort();
3069 if (assignedPsm == 0) {
3070 throw new IOException("Error: Unable to assign PSM value");
3071 }
3072 if (DBG) {
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003073 Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
Stanley Tnge48468d2017-11-22 16:04:40 -08003074 + assignedPsm);
3075 }
3076 socket.setChannel(assignedPsm);
3077
3078 return socket;
3079 }
Stanley Tng1bff4ba2018-06-29 14:05:04 -07003080
3081 /**
3082 * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
3083 * API name, listenUsingInsecureL2capChannel.
3084 * @hide
3085 */
3086 @RequiresPermission(Manifest.permission.BLUETOOTH)
3087 public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
3088 throws IOException {
3089 Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, "
3090 + "listenUsingInsecureL2capChannel");
3091 return listenUsingInsecureL2capChannel();
3092 }
Nick Pellybd022f42009-08-14 18:33:38 -07003093}