2 * Copyright (C) 2009-2016 The Android Open Source Project
3 * Copyright (C) 2015 Samsung LSI
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package android.bluetooth;
20 import android.Manifest;
21 import android.annotation.IntDef;
22 import android.annotation.RequiresPermission;
23 import android.annotation.SdkConstant;
24 import android.annotation.SdkConstant.SdkConstantType;
25 import android.annotation.SystemApi;
26 import android.bluetooth.le.BluetoothLeAdvertiser;
27 import android.bluetooth.le.BluetoothLeScanner;
28 import android.bluetooth.le.ScanCallback;
29 import android.bluetooth.le.ScanFilter;
30 import android.bluetooth.le.ScanRecord;
31 import android.bluetooth.le.ScanResult;
32 import android.bluetooth.le.ScanSettings;
33 import android.content.Context;
34 import android.os.BatteryStats;
35 import android.os.Binder;
36 import android.os.IBinder;
37 import android.os.ParcelUuid;
38 import android.os.RemoteException;
39 import android.os.ResultReceiver;
40 import android.os.ServiceManager;
41 import android.os.SynchronousResultReceiver;
42 import android.os.SystemProperties;
43 import android.util.Log;
44 import android.util.Pair;
46 import java.io.IOException;
47 import java.lang.annotation.Retention;
48 import java.lang.annotation.RetentionPolicy;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.Collections;
52 import java.util.HashMap;
53 import java.util.HashSet;
54 import java.util.List;
55 import java.util.Locale;
58 import java.util.UUID;
59 import java.util.concurrent.TimeoutException;
60 import java.util.concurrent.locks.ReentrantReadWriteLock;
63 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
64 * lets you perform fundamental Bluetooth tasks, such as initiate
65 * device discovery, query a list of bonded (paired) devices,
66 * instantiate a {@link BluetoothDevice} using a known MAC address, and create
67 * a {@link BluetoothServerSocket} to listen for connection requests from other
68 * devices, and start a scan for Bluetooth LE devices.
70 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
71 * adapter, when running on JELLY_BEAN_MR1 and below, call the
72 * static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
73 * higher, call {@link BluetoothManager#getAdapter}.
74 * Fundamentally, this is your starting point for all
75 * Bluetooth actions. Once you have the local adapter, you can get a set of
76 * {@link BluetoothDevice} objects representing all paired devices with
77 * {@link #getBondedDevices()}; start device discovery with
78 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
79 * listen for incoming connection requests with
80 * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}; or start a scan for
81 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
83 * <p>This class is thread safe.
85 * <p class="note"><strong>Note:</strong>
86 * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
87 * permission and some also require the
88 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
90 * <div class="special reference">
91 * <h3>Developer Guides</h3>
93 * For more information about using Bluetooth, read the <a href=
94 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
99 * {@see BluetoothDevice}
100 * {@see BluetoothServerSocket}
102 public final class BluetoothAdapter {
103 private static final String TAG = "BluetoothAdapter";
104 private static final boolean DBG = true;
105 private static final boolean VDBG = false;
108 * Default MAC address reported to a client that does not have the
109 * android.permission.LOCAL_MAC_ADDRESS permission.
113 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
116 * Sentinel error value for this class. Guaranteed to not equal any other
117 * integer constant in this class. Provided as a convenience for functions
118 * that require a sentinel error value, for example:
119 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
120 * BluetoothAdapter.ERROR)</code>
122 public static final int ERROR = Integer.MIN_VALUE;
125 * Broadcast Action: The state of the local Bluetooth adapter has been
127 * <p>For example, Bluetooth has been turned on or off.
128 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
129 * #EXTRA_PREVIOUS_STATE} containing the new and old states
131 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
133 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
134 public static final String ACTION_STATE_CHANGED =
135 "android.bluetooth.adapter.action.STATE_CHANGED";
138 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
139 * intents to request the current power state. Possible values are:
140 * {@link #STATE_OFF},
141 * {@link #STATE_TURNING_ON},
143 * {@link #STATE_TURNING_OFF},
145 public static final String EXTRA_STATE =
146 "android.bluetooth.adapter.extra.STATE";
148 * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
149 * intents to request the previous power state. Possible values are:
150 * {@link #STATE_OFF},
151 * {@link #STATE_TURNING_ON},
153 * {@link #STATE_TURNING_OFF}
155 public static final String EXTRA_PREVIOUS_STATE =
156 "android.bluetooth.adapter.extra.PREVIOUS_STATE";
159 @IntDef({STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON,
160 STATE_BLE_ON, STATE_BLE_TURNING_OFF})
161 @Retention(RetentionPolicy.SOURCE)
162 public @interface AdapterState {}
165 * Indicates the local Bluetooth adapter is off.
167 public static final int STATE_OFF = 10;
169 * Indicates the local Bluetooth adapter is turning on. However local
170 * clients should wait for {@link #STATE_ON} before attempting to
173 public static final int STATE_TURNING_ON = 11;
175 * Indicates the local Bluetooth adapter is on, and ready for use.
177 public static final int STATE_ON = 12;
179 * Indicates the local Bluetooth adapter is turning off. Local clients
180 * should immediately attempt graceful disconnection of any remote links.
182 public static final int STATE_TURNING_OFF = 13;
185 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
188 public static final int STATE_BLE_TURNING_ON = 14;
191 * Indicates the local Bluetooth adapter is in LE only mode.
194 public static final int STATE_BLE_ON = 15;
197 * Indicates the local Bluetooth adapter is turning off LE only mode.
200 public static final int STATE_BLE_TURNING_OFF = 16;
203 * Activity Action: Show a system activity that requests discoverable mode.
204 * This activity will also request the user to turn on Bluetooth if it
205 * is not currently enabled.
206 * <p>Discoverable mode is equivalent to {@link
207 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
208 * this Bluetooth adapter when they perform a discovery.
209 * <p>For privacy, Android is not discoverable by default.
210 * <p>The sender of this Intent can optionally use extra field {@link
211 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
212 * discoverability. Currently the default duration is 120 seconds, and
213 * maximum duration is capped at 300 seconds for each request.
214 * <p>Notification of the result of this activity is posted using the
215 * {@link android.app.Activity#onActivityResult} callback. The
216 * <code>resultCode</code>
217 * will be the duration (in seconds) of discoverability or
218 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
219 * discoverability or an error has occurred.
220 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
221 * for global notification whenever the scan mode changes. For example, an
222 * application can be notified when the device has ended discoverability.
223 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
225 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
226 public static final String ACTION_REQUEST_DISCOVERABLE =
227 "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
230 * Used as an optional int extra field in {@link
231 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
232 * for discoverability in seconds. The current default is 120 seconds, and
233 * requests over 300 seconds will be capped. These values could change.
235 public static final String EXTRA_DISCOVERABLE_DURATION =
236 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
239 * Activity Action: Show a system activity that allows the user to turn on
241 * <p>This system activity will return once Bluetooth has completed turning
242 * on, or the user has decided not to turn Bluetooth on.
243 * <p>Notification of the result of this activity is posted using the
244 * {@link android.app.Activity#onActivityResult} callback. The
245 * <code>resultCode</code>
246 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
247 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
248 * has rejected the request or an error has occurred.
249 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
250 * for global notification whenever Bluetooth is turned on or off.
251 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
253 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
254 public static final String ACTION_REQUEST_ENABLE =
255 "android.bluetooth.adapter.action.REQUEST_ENABLE";
258 * Activity Action: Show a system activity that allows user to enable BLE scans even when
259 * Bluetooth is turned off.<p>
261 * Notification of result of this activity is posted using
262 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
263 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
264 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
270 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
271 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
272 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
275 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
277 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
278 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
280 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
282 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
283 public static final String ACTION_SCAN_MODE_CHANGED =
284 "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
287 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
288 * intents to request the current scan mode. Possible values are:
289 * {@link #SCAN_MODE_NONE},
290 * {@link #SCAN_MODE_CONNECTABLE},
291 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
293 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
295 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
296 * intents to request the previous scan mode. Possible values are:
297 * {@link #SCAN_MODE_NONE},
298 * {@link #SCAN_MODE_CONNECTABLE},
299 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
301 public static final String EXTRA_PREVIOUS_SCAN_MODE =
302 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
305 @IntDef({SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE})
306 @Retention(RetentionPolicy.SOURCE)
307 public @interface ScanMode {}
310 * Indicates that both inquiry scan and page scan are disabled on the local
311 * Bluetooth adapter. Therefore this device is neither discoverable
312 * nor connectable from remote Bluetooth devices.
314 public static final int SCAN_MODE_NONE = 20;
316 * Indicates that inquiry scan is disabled, but page scan is enabled on the
317 * local Bluetooth adapter. Therefore this device is not discoverable from
318 * remote Bluetooth devices, but is connectable from remote devices that
319 * have previously discovered this device.
321 public static final int SCAN_MODE_CONNECTABLE = 21;
323 * Indicates that both inquiry scan and page scan are enabled on the local
324 * Bluetooth adapter. Therefore this device is both discoverable and
325 * connectable from remote Bluetooth devices.
327 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
330 * Broadcast Action: The local Bluetooth adapter has started the remote
331 * device discovery process.
332 * <p>This usually involves an inquiry scan of about 12 seconds, followed
333 * by a page scan of each new device to retrieve its Bluetooth name.
334 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
335 * remote Bluetooth devices are found.
336 * <p>Device discovery is a heavyweight procedure. New connections to
337 * remote Bluetooth devices should not be attempted while discovery is in
338 * progress, and existing connections will experience limited bandwidth
339 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
341 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
343 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
344 public static final String ACTION_DISCOVERY_STARTED =
345 "android.bluetooth.adapter.action.DISCOVERY_STARTED";
347 * Broadcast Action: The local Bluetooth adapter has finished the device
349 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
351 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
352 public static final String ACTION_DISCOVERY_FINISHED =
353 "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
356 * Broadcast Action: The local Bluetooth adapter has changed its friendly
358 * <p>This name is visible to remote Bluetooth devices.
359 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
361 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
363 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
364 public static final String ACTION_LOCAL_NAME_CHANGED =
365 "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
367 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
368 * intents to request the local Bluetooth name.
370 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
373 * Intent used to broadcast the change in connection state of the local
374 * Bluetooth adapter to a profile of the remote device. When the adapter is
375 * not connected to any profiles of any remote devices and it attempts a
376 * connection to a profile this intent will sent. Once connected, this intent
377 * will not be sent for any more connection attempts to any profiles of any
378 * remote device. When the adapter disconnects from the last profile its
379 * connected to of any remote device, this intent will be sent.
381 * <p> This intent is useful for applications that are only concerned about
382 * whether the local adapter is connected to any profile of any device and
383 * are not really concerned about which profile. For example, an application
384 * which displays an icon to display whether Bluetooth is connected or not
385 * can use this intent.
387 * <p>This intent will have 3 extras:
388 * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
389 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
390 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
392 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
393 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
394 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
396 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
398 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
399 public static final String ACTION_CONNECTION_STATE_CHANGED =
400 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
403 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
405 * This extra represents the current connection state.
407 public static final String EXTRA_CONNECTION_STATE =
408 "android.bluetooth.adapter.extra.CONNECTION_STATE";
411 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
413 * This extra represents the previous connection state.
415 public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
416 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
419 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
423 public static final String ACTION_BLE_STATE_CHANGED =
424 "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
427 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
428 * by BLE Always on enabled application to know the ACL_CONNECTED event
429 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
430 * as Bluetooth LE is the only feature available in STATE_BLE_ON
432 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
433 * works in Bluetooth state STATE_ON
436 public static final String ACTION_BLE_ACL_CONNECTED =
437 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
440 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
441 * by BLE Always on enabled application to know the ACL_DISCONNECTED event
442 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
443 * LE is the only feature available in STATE_BLE_ON
445 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
446 * works in Bluetooth state STATE_ON
449 public static final String ACTION_BLE_ACL_DISCONNECTED =
450 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
452 /** The profile is in disconnected state */
453 public static final int STATE_DISCONNECTED = 0;
454 /** The profile is in connecting state */
455 public static final int STATE_CONNECTING = 1;
456 /** The profile is in connected state */
457 public static final int STATE_CONNECTED = 2;
458 /** The profile is in disconnecting state */
459 public static final int STATE_DISCONNECTING = 3;
462 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
463 private final IBinder mToken;
466 /** When creating a ServerSocket using listenUsingRfcommOn() or
467 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
468 * a ServerSocket that auto assigns a channel number to the first
470 * The channel number assigned to this first Bluetooth Socket will
471 * be stored in the ServerSocket, and reused for subsequent Bluetooth
474 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
477 private static final int ADDRESS_LENGTH = 17;
480 * Lazily initialized singleton. Guaranteed final after first object
483 private static BluetoothAdapter sAdapter;
485 private static BluetoothLeScanner sBluetoothLeScanner;
486 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
488 private final IBluetoothManager mManagerService;
489 private IBluetooth mService;
490 private final ReentrantReadWriteLock mServiceLock =
491 new ReentrantReadWriteLock();
493 private final Object mLock = new Object();
494 private final Map<LeScanCallback, ScanCallback> mLeScanClients;
497 * Get a handle to the default local Bluetooth adapter.
498 * <p>Currently Android only supports one Bluetooth adapter, but the API
499 * could be extended to support more. This will always return the default
501 * @return the default local adapter, or null if Bluetooth is not supported
502 * on this hardware platform
504 public static synchronized BluetoothAdapter getDefaultAdapter() {
505 if (sAdapter == null) {
506 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
508 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
509 sAdapter = new BluetoothAdapter(managerService);
511 Log.e(TAG, "Bluetooth binder is null");
518 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
520 BluetoothAdapter(IBluetoothManager managerService) {
522 if (managerService == null) {
523 throw new IllegalArgumentException("bluetooth manager service is null");
526 mServiceLock.writeLock().lock();
527 mService = managerService.registerAdapter(mManagerCallback);
528 } catch (RemoteException e) {
531 mServiceLock.writeLock().unlock();
533 mManagerService = managerService;
534 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
535 mToken = new Binder();
539 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
541 * <p>Valid Bluetooth hardware addresses must be upper case, in a format
542 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
543 * available to validate a Bluetooth address.
544 * <p>A {@link BluetoothDevice} will always be returned for a valid
545 * hardware address, even if this adapter has never seen that device.
547 * @param address valid Bluetooth MAC address
548 * @throws IllegalArgumentException if address is invalid
550 public BluetoothDevice getRemoteDevice(String address) {
551 return new BluetoothDevice(address);
555 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
557 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
558 * expects the address in network byte order (MSB first).
559 * <p>A {@link BluetoothDevice} will always be returned for a valid
560 * hardware address, even if this adapter has never seen that device.
562 * @param address Bluetooth MAC address (6 bytes)
563 * @throws IllegalArgumentException if address is invalid
565 public BluetoothDevice getRemoteDevice(byte[] address) {
566 if (address == null || address.length != 6) {
567 throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
569 return new BluetoothDevice(String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
570 address[0], address[1], address[2], address[3], address[4], address[5]));
574 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
575 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
576 * supported on this device.
578 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
579 * on this device before calling this method.
581 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
582 if (!getLeAccess()) return null;
583 if (!isMultipleAdvertisementSupported() && !isPeripheralModeSupported()) {
584 Log.e(TAG, "Bluetooth LE advertising not supported");
587 synchronized(mLock) {
588 if (sBluetoothLeAdvertiser == null) {
589 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
592 return sBluetoothLeAdvertiser;
596 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
598 public BluetoothLeScanner getBluetoothLeScanner() {
599 if (!getLeAccess()) return null;
600 synchronized(mLock) {
601 if (sBluetoothLeScanner == null) {
602 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
605 return sBluetoothLeScanner;
609 * Return true if Bluetooth is currently enabled and ready for use.
611 * <code>getBluetoothState() == STATE_ON</code>
612 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
614 * @return true if the local adapter is turned on
616 @RequiresPermission(Manifest.permission.BLUETOOTH)
617 public boolean isEnabled() {
619 mServiceLock.readLock().lock();
620 if (mService != null) return mService.isEnabled();
621 } catch (RemoteException e) {
624 mServiceLock.readLock().unlock();
631 * Return true if Bluetooth LE(Always BLE On feature) is currently
632 * enabled and ready for use
633 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
635 * @return true if the local Bluetooth LE adapter is turned on
639 public boolean isLeEnabled() {
640 final int state = getLeState();
641 if (state == BluetoothAdapter.STATE_ON) {
642 if (DBG) Log.d (TAG, "STATE_ON");
643 } else if (state == BluetoothAdapter.STATE_BLE_ON) {
644 if (DBG) Log.d (TAG, "STATE_BLE_ON");
646 if (DBG) Log.d (TAG, "STATE_OFF");
653 * Performs action based on user action to turn BT ON
654 * or OFF if BT is in BLE_ON state
656 private void notifyUserAction(boolean enable) {
658 mServiceLock.readLock().lock();
659 if (mService == null) {
660 Log.e(TAG, "mService is null");
664 mService.onLeServiceUp(); //NA:TODO implementation pending
666 mService.onBrEdrDown(); //NA:TODO implementation pending
668 } catch (RemoteException e) {
671 mServiceLock.readLock().unlock();
676 * Turns off Bluetooth LE which was earlier turned on by calling EnableBLE().
678 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
679 * to STATE_OFF and completely shut-down Bluetooth
681 * <p> If the Adapter state is STATE_ON, This would unregister the existance of
682 * special Bluetooth LE application and hence the further turning off of Bluetooth
683 * from UI would ensure the complete turn-off of Bluetooth rather than staying back
686 * <p>This is an asynchronous call: it will return immediately, and
687 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
688 * to be notified of subsequent adapter state changes If this call returns
689 * true, then the adapter state will immediately transition from {@link
690 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
691 * later transition to either {@link #STATE_BLE_ON} or {@link
692 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
693 * If this call returns false then there was an
694 * immediate problem that will prevent the QAdapter from being turned off -
695 * such as the QAadapter already being turned off.
697 * @return true to indicate success, or false on
702 public boolean disableBLE() {
703 if (!isBleScanAlwaysAvailable()) return false;
705 int state = getLeState();
706 if (state == BluetoothAdapter.STATE_ON) {
707 if (DBG) Log.d (TAG, "STATE_ON: shouldn't disable");
709 mManagerService.updateBleAppCount(mToken, false);
710 } catch (RemoteException e) {
715 } else if (state == BluetoothAdapter.STATE_BLE_ON) {
716 if (DBG) Log.d (TAG, "STATE_BLE_ON");
719 bleAppCnt = mManagerService.updateBleAppCount(mToken, false);
720 } catch (RemoteException e) {
723 if (bleAppCnt == 0) {
724 // Disable only if there are no other clients
725 notifyUserAction(false);
730 if (DBG) Log.d (TAG, "STATE_OFF: Already disabled");
735 * Special Applications who want to only turn on Bluetooth Low Energy (BLE) would
736 * EnableBLE, EnableBLE brings-up Bluetooth so that application can access
737 * only LE related feature (Bluetooth GATT layers interfaces using the respective class)
738 * EnableBLE in turn registers the existance of a special App which wants to
739 * turn on Bluetooth Low enrgy part without making it visible at the settings UI
741 * <p>Invoking EnableBLE when Bluetooth is already in ON state, would just registers
742 * the existance of special Application and doesn't do anything to current BT state.
743 * when user turn OFF Bluetooth from UI, if there is an existance of special app, Bluetooth
744 * would stay in BLE_ON state so that LE features are still acessible to the special
747 * <p>This is an asynchronous call: it will return immediately, and
748 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
749 * to be notified of subsequent adapter state changes. If this call returns
750 * true, then the adapter state will immediately transition from {@link
751 * #STATE_OFF} to {@link #STATE_BLE_TURNING_ON}, and some time
752 * later transition to either {@link #STATE_OFF} or {@link
753 * #STATE_BLE_ON}. If this call returns false then there was an
754 * immediate problem that will prevent the adapter from being turned on -
755 * such as Airplane mode, or the adapter is already turned on.
756 * (@link #ACTION_BLE_STATE_CHANGED) returns the Bluetooth Adapter's various
757 * states, It includes all the classic Bluetooth Adapter states along with
758 * internal BLE only states
760 * @return true to indicate Bluetooth LE start-up has begun, or false on
765 public boolean enableBLE() {
766 if (!isBleScanAlwaysAvailable()) return false;
768 if (isLeEnabled() == true) {
769 if (DBG) Log.d(TAG, "enableBLE(): BT is already enabled..!");
771 mManagerService.updateBleAppCount(mToken, true);
772 } catch (RemoteException e) {
779 if (DBG) Log.d(TAG, "Calling enableBLE");
780 mManagerService.updateBleAppCount(mToken, true);
781 return mManagerService.enable();
782 } catch (RemoteException e) {
790 * Get the current state of the local Bluetooth adapter.
791 * <p>Possible return values are
792 * {@link #STATE_OFF},
793 * {@link #STATE_TURNING_ON},
795 * {@link #STATE_TURNING_OFF}.
796 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
798 * @return current state of Bluetooth adapter
800 @RequiresPermission(Manifest.permission.BLUETOOTH)
802 public int getState() {
803 int state = BluetoothAdapter.STATE_OFF;
806 mServiceLock.readLock().lock();
807 if (mService != null) {
808 state = mService.getState();
810 } catch (RemoteException e) {
813 mServiceLock.readLock().unlock();
816 // Consider all internal states as OFF
817 if (state == BluetoothAdapter.STATE_BLE_ON
818 || state == BluetoothAdapter.STATE_BLE_TURNING_ON
819 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
820 if (VDBG) Log.d(TAG, "Consider internal state as OFF");
821 state = BluetoothAdapter.STATE_OFF;
823 if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + state);
828 * Get the current state of the local Bluetooth adapter
829 * <p>This returns current internal state of Adapter including LE ON/OFF
831 * <p>Possible return values are
832 * {@link #STATE_OFF},
833 * {@link #STATE_BLE_TURNING_ON},
834 * {@link #STATE_BLE_ON},
835 * {@link #STATE_TURNING_ON},
837 * {@link #STATE_TURNING_OFF},
838 * {@link #STATE_BLE_TURNING_OFF}.
839 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
841 * @return current state of Bluetooth adapter
844 @RequiresPermission(Manifest.permission.BLUETOOTH)
846 public int getLeState() {
847 int state = BluetoothAdapter.STATE_OFF;
850 mServiceLock.readLock().lock();
851 if (mService != null) {
852 state = mService.getState();
854 } catch (RemoteException e) {
857 mServiceLock.readLock().unlock();
860 if (VDBG) Log.d(TAG,"getLeState() returning " + state);
864 boolean getLeAccess() {
865 if(getLeState() == STATE_ON)
868 else if (getLeState() == STATE_BLE_ON)
869 return true; // TODO: FILTER SYSTEM APPS HERE <--
875 * Turn on the local Bluetooth adapter—do not use without explicit
876 * user action to turn on Bluetooth.
877 * <p>This powers on the underlying Bluetooth hardware, and starts all
878 * Bluetooth system services.
879 * <p class="caution"><strong>Bluetooth should never be enabled without
880 * direct user consent</strong>. If you want to turn on Bluetooth in order
881 * to create a wireless connection, you should use the {@link
882 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
883 * user permission to turn on Bluetooth. The {@link #enable()} method is
884 * provided only for applications that include a user interface for changing
885 * system settings, such as a "power manager" app.</p>
886 * <p>This is an asynchronous call: it will return immediately, and
887 * clients should listen for {@link #ACTION_STATE_CHANGED}
888 * to be notified of subsequent adapter state changes. If this call returns
889 * true, then the adapter state will immediately transition from {@link
890 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
891 * later transition to either {@link #STATE_OFF} or {@link
892 * #STATE_ON}. If this call returns false then there was an
893 * immediate problem that will prevent the adapter from being turned on -
894 * such as Airplane mode, or the adapter is already turned on.
895 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
898 * @return true to indicate adapter startup has begun, or false on
901 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
902 public boolean enable() {
903 if (isEnabled() == true) {
904 if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
908 return mManagerService.enable();
909 } catch (RemoteException e) {Log.e(TAG, "", e);}
914 * Turn off the local Bluetooth adapter—do not use without explicit
915 * user action to turn off Bluetooth.
916 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
917 * system services, and powers down the underlying Bluetooth hardware.
918 * <p class="caution"><strong>Bluetooth should never be disabled without
919 * direct user consent</strong>. The {@link #disable()} method is
920 * provided only for applications that include a user interface for changing
921 * system settings, such as a "power manager" app.</p>
922 * <p>This is an asynchronous call: it will return immediately, and
923 * clients should listen for {@link #ACTION_STATE_CHANGED}
924 * to be notified of subsequent adapter state changes. If this call returns
925 * true, then the adapter state will immediately transition from {@link
926 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
927 * later transition to either {@link #STATE_OFF} or {@link
928 * #STATE_ON}. If this call returns false then there was an
929 * immediate problem that will prevent the adapter from being turned off -
930 * such as the adapter already being turned off.
931 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
934 * @return true to indicate adapter shutdown has begun, or false on
937 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
938 public boolean disable() {
940 return mManagerService.disable(true);
941 } catch (RemoteException e) {Log.e(TAG, "", e);}
946 * Turn off the local Bluetooth adapter and don't persist the setting.
948 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
951 * @return true to indicate adapter shutdown has begun, or false on
955 public boolean disable(boolean persist) {
958 return mManagerService.disable(persist);
959 } catch (RemoteException e) {Log.e(TAG, "", e);}
964 * Returns the hardware address of the local Bluetooth adapter.
965 * <p>For example, "00:11:22:AA:BB:CC".
966 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
968 * @return Bluetooth hardware address as string
970 @RequiresPermission(Manifest.permission.BLUETOOTH)
971 public String getAddress() {
973 return mManagerService.getAddress();
974 } catch (RemoteException e) {Log.e(TAG, "", e);}
979 * Get the friendly Bluetooth name of the local Bluetooth adapter.
980 * <p>This name is visible to remote Bluetooth devices.
981 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
983 * @return the Bluetooth name, or null on error
985 public String getName() {
987 return mManagerService.getName();
988 } catch (RemoteException e) {Log.e(TAG, "", e);}
993 * enable or disable Bluetooth HCI snoop log.
995 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
998 * @return true to indicate configure HCI log successfully, or false on
1002 public boolean configHciSnoopLog(boolean enable) {
1004 mServiceLock.readLock().lock();
1005 if (mService != null) return mService.configHciSnoopLog(enable);
1006 } catch (RemoteException e) {
1009 mServiceLock.readLock().unlock();
1015 * Factory reset bluetooth settings.
1017 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
1020 * @return true to indicate that the config file was successfully cleared
1024 public boolean factoryReset() {
1026 mServiceLock.readLock().lock();
1027 if (mService != null) {
1028 return mService.factoryReset();
1030 SystemProperties.set("persist.bluetooth.factoryreset", "true");
1031 } catch (RemoteException e) {
1034 mServiceLock.readLock().unlock();
1040 * Get the UUIDs supported by the local Bluetooth adapter.
1042 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1044 * @return the UUIDs supported by the local Bluetooth Adapter.
1047 public ParcelUuid[] getUuids() {
1048 if (getState() != STATE_ON) return null;
1050 mServiceLock.readLock().lock();
1051 if (mService != null) return mService.getUuids();
1052 } catch (RemoteException e) {
1055 mServiceLock.readLock().unlock();
1061 * Set the friendly Bluetooth name of the local Bluetooth adapter.
1062 * <p>This name is visible to remote Bluetooth devices.
1063 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1064 * encoding, although many remote devices can only display the first
1065 * 40 characters, and some may be limited to just 20.
1066 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1067 * will return false. After turning on Bluetooth,
1068 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1069 * to get the updated value.
1070 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1072 * @param name a valid Bluetooth name
1073 * @return true if the name was set, false otherwise
1075 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1076 public boolean setName(String name) {
1077 if (getState() != STATE_ON) return false;
1079 mServiceLock.readLock().lock();
1080 if (mService != null) return mService.setName(name);
1081 } catch (RemoteException e) {
1084 mServiceLock.readLock().unlock();
1090 * Get the current Bluetooth scan mode of the local Bluetooth adapter.
1091 * <p>The Bluetooth scan mode determines if the local adapter is
1092 * connectable and/or discoverable from remote Bluetooth devices.
1093 * <p>Possible values are:
1094 * {@link #SCAN_MODE_NONE},
1095 * {@link #SCAN_MODE_CONNECTABLE},
1096 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
1097 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1098 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1099 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1100 * to get the updated value.
1101 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1105 @RequiresPermission(Manifest.permission.BLUETOOTH)
1107 public int getScanMode() {
1108 if (getState() != STATE_ON) return SCAN_MODE_NONE;
1110 mServiceLock.readLock().lock();
1111 if (mService != null) return mService.getScanMode();
1112 } catch (RemoteException e) {
1115 mServiceLock.readLock().unlock();
1117 return SCAN_MODE_NONE;
1121 * Set the Bluetooth scan mode of the local Bluetooth adapter.
1122 * <p>The Bluetooth scan mode determines if the local adapter is
1123 * connectable and/or discoverable from remote Bluetooth devices.
1124 * <p>For privacy reasons, discoverable mode is automatically turned off
1125 * after <code>duration</code> seconds. For example, 120 seconds should be
1126 * enough for a remote device to initiate and complete its discovery
1128 * <p>Valid scan mode values are:
1129 * {@link #SCAN_MODE_NONE},
1130 * {@link #SCAN_MODE_CONNECTABLE},
1131 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
1132 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1133 * will return false. After turning on Bluetooth,
1134 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1135 * to get the updated value.
1136 * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
1137 * <p>Applications cannot set the scan mode. They should use
1138 * <code>startActivityForResult(
1139 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1142 * @param mode valid scan mode
1143 * @param duration time in seconds to apply scan mode, only used for
1144 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
1145 * @return true if the scan mode was set, false otherwise
1148 public boolean setScanMode(@ScanMode int mode, int duration) {
1149 if (getState() != STATE_ON) return false;
1151 mServiceLock.readLock().lock();
1152 if (mService != null) return mService.setScanMode(mode, duration);
1153 } catch (RemoteException e) {
1156 mServiceLock.readLock().unlock();
1162 public boolean setScanMode(int mode) {
1163 if (getState() != STATE_ON) return false;
1164 /* getDiscoverableTimeout() to use the latest from NV than use 0 */
1165 return setScanMode(mode, getDiscoverableTimeout());
1169 public int getDiscoverableTimeout() {
1170 if (getState() != STATE_ON) return -1;
1172 mServiceLock.readLock().lock();
1173 if (mService != null) return mService.getDiscoverableTimeout();
1174 } catch (RemoteException e) {
1177 mServiceLock.readLock().unlock();
1183 public void setDiscoverableTimeout(int timeout) {
1184 if (getState() != STATE_ON) return;
1186 mServiceLock.readLock().lock();
1187 if (mService != null) mService.setDiscoverableTimeout(timeout);
1188 } catch (RemoteException e) {
1191 mServiceLock.readLock().unlock();
1196 * Start the remote device discovery process.
1197 * <p>The discovery process usually involves an inquiry scan of about 12
1198 * seconds, followed by a page scan of each new device to retrieve its
1200 * <p>This is an asynchronous call, it will return immediately. Register
1201 * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1202 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1203 * discovery starts and completes. Register for {@link
1204 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1206 * <p>Device discovery is a heavyweight procedure. New connections to
1207 * remote Bluetooth devices should not be attempted while discovery is in
1208 * progress, and existing connections will experience limited bandwidth
1209 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1210 * discovery. Discovery is not managed by the Activity,
1211 * but is run as a system service, so an application should always call
1212 * {@link BluetoothAdapter#cancelDiscovery()} even if it
1213 * did not directly request a discovery, just to be sure.
1214 * <p>Device discovery will only find remote devices that are currently
1215 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1216 * not discoverable by default, and need to be entered into a special mode.
1217 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1218 * will return false. After turning on Bluetooth,
1219 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1220 * to get the updated value.
1221 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
1223 * @return true on success, false on error
1225 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1226 public boolean startDiscovery() {
1227 if (getState() != STATE_ON) return false;
1229 mServiceLock.readLock().lock();
1230 if (mService != null) return mService.startDiscovery();
1231 } catch (RemoteException e) {
1234 mServiceLock.readLock().unlock();
1240 * Cancel the current device discovery process.
1241 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
1242 * <p>Because discovery is a heavyweight procedure for the Bluetooth
1243 * adapter, this method should always be called before attempting to connect
1244 * to a remote device with {@link
1245 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1246 * the Activity, but is run as a system service, so an application should
1247 * always call cancel discovery even if it did not directly request a
1248 * discovery, just to be sure.
1249 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1250 * will return false. After turning on Bluetooth,
1251 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1252 * to get the updated value.
1254 * @return true on success, false on error
1256 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1257 public boolean cancelDiscovery() {
1258 if (getState() != STATE_ON) return false;
1260 mServiceLock.readLock().lock();
1261 if (mService != null) return mService.cancelDiscovery();
1262 } catch (RemoteException e) {
1265 mServiceLock.readLock().unlock();
1271 * Return true if the local Bluetooth adapter is currently in the device
1272 * discovery process.
1273 * <p>Device discovery is a heavyweight procedure. New connections to
1274 * remote Bluetooth devices should not be attempted while discovery is in
1275 * progress, and existing connections will experience limited bandwidth
1276 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1278 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1279 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1280 * starts or completes.
1281 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1282 * will return false. After turning on Bluetooth,
1283 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1284 * to get the updated value.
1285 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
1287 * @return true if discovering
1289 @RequiresPermission(Manifest.permission.BLUETOOTH)
1290 public boolean isDiscovering() {
1291 if (getState() != STATE_ON) return false;
1293 mServiceLock.readLock().lock();
1294 if (mService != null) return mService.isDiscovering();
1295 } catch (RemoteException e) {
1298 mServiceLock.readLock().unlock();
1304 * Return true if the multi advertisement is supported by the chipset
1306 * @return true if Multiple Advertisement feature is supported
1308 public boolean isMultipleAdvertisementSupported() {
1309 if (getState() != STATE_ON) return false;
1311 mServiceLock.readLock().lock();
1312 if (mService != null) return mService.isMultiAdvertisementSupported();
1313 } catch (RemoteException e) {
1314 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
1316 mServiceLock.readLock().unlock();
1322 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1324 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1325 * fetch scan results even when Bluetooth is turned off.<p>
1327 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1332 public boolean isBleScanAlwaysAvailable() {
1334 return mManagerService.isBleScanAlwaysAvailable();
1335 } catch (RemoteException e) {
1336 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1342 * Returns whether peripheral mode is supported.
1346 public boolean isPeripheralModeSupported() {
1347 if (getState() != STATE_ON) return false;
1349 mServiceLock.readLock().lock();
1350 if (mService != null) return mService.isPeripheralModeSupported();
1351 } catch (RemoteException e) {
1352 Log.e(TAG, "failed to get peripheral mode capability: ", e);
1354 mServiceLock.readLock().unlock();
1360 * Return true if offloaded filters are supported
1362 * @return true if chipset supports on-chip filtering
1364 public boolean isOffloadedFilteringSupported() {
1365 if (!getLeAccess()) return false;
1367 mServiceLock.readLock().lock();
1368 if (mService != null) return mService.isOffloadedFilteringSupported();
1369 } catch (RemoteException e) {
1370 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
1372 mServiceLock.readLock().unlock();
1378 * Return true if offloaded scan batching is supported
1380 * @return true if chipset supports on-chip scan batching
1382 public boolean isOffloadedScanBatchingSupported() {
1383 if (!getLeAccess()) return false;
1385 mServiceLock.readLock().lock();
1386 if (mService != null) return mService.isOffloadedScanBatchingSupported();
1387 } catch (RemoteException e) {
1388 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
1390 mServiceLock.readLock().unlock();
1396 * Return true if hardware has entries available for matching beacons
1398 * @return true if there are hw entries available for matching beacons
1401 public boolean isHardwareTrackingFiltersAvailable() {
1402 if (!getLeAccess()) return false;
1404 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
1405 if (iGatt == null) {
1406 // BLE is not supported
1409 return (iGatt.numHwTrackFiltersAvailable() != 0);
1410 } catch (RemoteException e) {
1417 * Return the record of {@link BluetoothActivityEnergyInfo} object that
1418 * has the activity and energy info. This can be used to ascertain what
1419 * the controller has been up to, since the last sample.
1420 * @param updateType Type of info, cached vs refreshed.
1422 * @return a record with {@link BluetoothActivityEnergyInfo} or null if
1423 * report is unavailable or unsupported
1424 * @deprecated use the asynchronous
1425 * {@link #requestControllerActivityEnergyInfo(ResultReceiver)} instead.
1429 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
1430 SynchronousResultReceiver receiver = new SynchronousResultReceiver();
1431 requestControllerActivityEnergyInfo(receiver);
1433 SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
1434 if (result.bundle != null) {
1435 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1437 } catch (TimeoutException e) {
1438 Log.e(TAG, "getControllerActivityEnergyInfo timed out");
1444 * Request the record of {@link BluetoothActivityEnergyInfo} object that
1445 * has the activity and energy info. This can be used to ascertain what
1446 * the controller has been up to, since the last sample.
1448 * A null value for the activity info object may be sent if the bluetooth service is
1449 * unreachable or the device does not support reporting such information.
1451 * @param result The callback to which to send the activity info.
1454 public void requestControllerActivityEnergyInfo(ResultReceiver result) {
1456 mServiceLock.readLock().lock();
1457 if (mService != null) {
1458 mService.requestActivityInfo(result);
1461 } catch (RemoteException e) {
1462 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
1464 mServiceLock.readLock().unlock();
1465 if (result != null) {
1466 // Only send an immediate result if we failed.
1467 result.send(0, null);
1473 * Return the set of {@link BluetoothDevice} objects that are bonded
1474 * (paired) to the local adapter.
1475 * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1476 * will return an empty set. After turning on Bluetooth,
1477 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1478 * to get the updated value.
1479 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
1481 * @return unmodifiable set of {@link BluetoothDevice}, or null on error
1483 @RequiresPermission(Manifest.permission.BLUETOOTH)
1484 public Set<BluetoothDevice> getBondedDevices() {
1485 if (getState() != STATE_ON) {
1486 return toDeviceSet(new BluetoothDevice[0]);
1489 mServiceLock.readLock().lock();
1490 if (mService != null) return toDeviceSet(mService.getBondedDevices());
1491 return toDeviceSet(new BluetoothDevice[0]);
1492 } catch (RemoteException e) {
1495 mServiceLock.readLock().unlock();
1501 * Gets the currently supported profiles by the adapter.
1503 *<p> This can be used to check whether a profile is supported before attempting
1504 * to connect to its respective proxy.
1506 * @return a list of integers indicating the ids of supported profiles as defined in
1507 * {@link BluetoothProfile}.
1510 public List<Integer> getSupportedProfiles() {
1511 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
1514 synchronized (mManagerCallback) {
1515 if (mService != null) {
1516 final long supportedProfilesBitMask = mService.getSupportedProfiles();
1518 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
1519 if ((supportedProfilesBitMask & (1 << i)) != 0) {
1520 supportedProfiles.add(i);
1525 } catch (RemoteException e) {Log.e(TAG, "getSupportedProfiles:", e);}
1527 return supportedProfiles;
1531 * Get the current connection state of the local Bluetooth adapter.
1532 * This can be used to check whether the local Bluetooth adapter is connected
1533 * to any profile of any other remote Bluetooth Device.
1535 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
1536 * intent to get the connection state of the adapter.
1538 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED},
1539 * {@link #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
1543 public int getConnectionState() {
1544 if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
1546 mServiceLock.readLock().lock();
1547 if (mService != null) return mService.getAdapterConnectionState();
1548 } catch (RemoteException e) {
1549 Log.e(TAG, "getConnectionState:", e);
1551 mServiceLock.readLock().unlock();
1553 return BluetoothAdapter.STATE_DISCONNECTED;
1557 * Get the current connection state of a profile.
1558 * This function can be used to check whether the local Bluetooth adapter
1559 * is connected to any remote device for a specific profile.
1560 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
1561 * {@link BluetoothProfile#A2DP}.
1563 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
1565 * <p> Return value can be one of
1566 * {@link BluetoothProfile#STATE_DISCONNECTED},
1567 * {@link BluetoothProfile#STATE_CONNECTING},
1568 * {@link BluetoothProfile#STATE_CONNECTED},
1569 * {@link BluetoothProfile#STATE_DISCONNECTING}
1571 @RequiresPermission(Manifest.permission.BLUETOOTH)
1572 public int getProfileConnectionState(int profile) {
1573 if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
1575 mServiceLock.readLock().lock();
1576 if (mService != null) return mService.getProfileConnectionState(profile);
1577 } catch (RemoteException e) {
1578 Log.e(TAG, "getProfileConnectionState:", e);
1580 mServiceLock.readLock().unlock();
1582 return BluetoothProfile.STATE_DISCONNECTED;
1586 * Create a listening, secure RFCOMM Bluetooth socket.
1587 * <p>A remote device connecting to this socket will be authenticated and
1588 * communication on this socket will be encrypted.
1589 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1590 * connections from a listening {@link BluetoothServerSocket}.
1591 * <p>Valid RFCOMM channels are in range 1 to 30.
1592 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1593 * @param channel RFCOMM channel to listen on
1594 * @return a listening RFCOMM BluetoothServerSocket
1595 * @throws IOException on error, for example Bluetooth not available, or
1596 * insufficient permissions, or channel in use.
1599 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
1600 return listenUsingRfcommOn(channel, false, false);
1604 * Create a listening, secure RFCOMM Bluetooth socket.
1605 * <p>A remote device connecting to this socket will be authenticated and
1606 * communication on this socket will be encrypted.
1607 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1608 * connections from a listening {@link BluetoothServerSocket}.
1609 * <p>Valid RFCOMM channels are in range 1 to 30.
1610 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1611 * <p>To auto assign a channel without creating a SDP record use
1612 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
1613 * @param channel RFCOMM channel to listen on
1614 * @param mitm enforce man-in-the-middle protection for authentication.
1615 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections.
1616 * @return a listening RFCOMM BluetoothServerSocket
1617 * @throws IOException on error, for example Bluetooth not available, or
1618 * insufficient permissions, or channel in use.
1621 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
1622 boolean min16DigitPin)
1623 throws IOException {
1624 BluetoothServerSocket socket = new BluetoothServerSocket(
1625 BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm, min16DigitPin);
1626 int errno = socket.mSocket.bindListen();
1627 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1628 socket.setChannel(socket.mSocket.getPort());
1631 //TODO(BT): Throw the same exception error code
1632 // that the previous code was using.
1633 //socket.mSocket.throwErrnoNative(errno);
1634 throw new IOException("Error: " + errno);
1640 * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
1641 * <p>A remote device connecting to this socket will be authenticated and
1642 * communication on this socket will be encrypted.
1643 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1644 * connections from a listening {@link BluetoothServerSocket}.
1645 * <p>The system will assign an unused RFCOMM channel to listen on.
1646 * <p>The system will also register a Service Discovery
1647 * Protocol (SDP) record with the local SDP server containing the specified
1648 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1649 * can use the same UUID to query our SDP server and discover which channel
1650 * to connect to. This SDP record will be removed when this socket is
1651 * closed, or if this application closes unexpectedly.
1652 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1653 * connect to this socket from another device using the same {@link UUID}.
1654 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1655 * @param name service name for SDP record
1656 * @param uuid uuid for SDP record
1657 * @return a listening RFCOMM BluetoothServerSocket
1658 * @throws IOException on error, for example Bluetooth not available, or
1659 * insufficient permissions, or channel in use.
1661 @RequiresPermission(Manifest.permission.BLUETOOTH)
1662 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
1663 throws IOException {
1664 return createNewRfcommSocketAndRecord(name, uuid, true, true);
1668 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
1669 * <p>The link key is not required to be authenticated, i.e the communication may be
1670 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
1671 * the link will be encrypted, as encryption is mandartory.
1672 * For legacy devices (pre Bluetooth 2.1 devices) the link will not
1673 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
1674 * encrypted and authenticated communication channel is desired.
1675 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1676 * connections from a listening {@link BluetoothServerSocket}.
1677 * <p>The system will assign an unused RFCOMM channel to listen on.
1678 * <p>The system will also register a Service Discovery
1679 * Protocol (SDP) record with the local SDP server containing the specified
1680 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1681 * can use the same UUID to query our SDP server and discover which channel
1682 * to connect to. This SDP record will be removed when this socket is
1683 * closed, or if this application closes unexpectedly.
1684 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1685 * connect to this socket from another device using the same {@link UUID}.
1686 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1687 * @param name service name for SDP record
1688 * @param uuid uuid for SDP record
1689 * @return a listening RFCOMM BluetoothServerSocket
1690 * @throws IOException on error, for example Bluetooth not available, or
1691 * insufficient permissions, or channel in use.
1693 @RequiresPermission(Manifest.permission.BLUETOOTH)
1694 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
1695 throws IOException {
1696 return createNewRfcommSocketAndRecord(name, uuid, false, false);
1700 * Create a listening, encrypted,
1701 * RFCOMM Bluetooth socket with Service Record.
1702 * <p>The link will be encrypted, but the link key is not required to be authenticated
1703 * i.e the communication is vulnerable to Man In the Middle attacks. Use
1704 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
1705 * <p> Use this socket if authentication of link key is not possible.
1706 * For example, for Bluetooth 2.1 devices, if any of the devices does not have
1707 * an input and output capability or just has the ability to display a numeric key,
1708 * a secure socket connection is not possible and this socket can be used.
1709 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
1710 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
1711 * For more details, refer to the Security Model section 5.2 (vol 3) of
1712 * Bluetooth Core Specification version 2.1 + EDR.
1713 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1714 * connections from a listening {@link BluetoothServerSocket}.
1715 * <p>The system will assign an unused RFCOMM channel to listen on.
1716 * <p>The system will also register a Service Discovery
1717 * Protocol (SDP) record with the local SDP server containing the specified
1718 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1719 * can use the same UUID to query our SDP server and discover which channel
1720 * to connect to. This SDP record will be removed when this socket is
1721 * closed, or if this application closes unexpectedly.
1722 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1723 * connect to this socket from another device using the same {@link UUID}.
1724 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1725 * @param name service name for SDP record
1726 * @param uuid uuid for SDP record
1727 * @return a listening RFCOMM BluetoothServerSocket
1728 * @throws IOException on error, for example Bluetooth not available, or
1729 * insufficient permissions, or channel in use.
1732 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(
1733 String name, UUID uuid) throws IOException {
1734 return createNewRfcommSocketAndRecord(name, uuid, false, true);
1738 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
1739 boolean auth, boolean encrypt) throws IOException {
1740 BluetoothServerSocket socket;
1741 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth,
1742 encrypt, new ParcelUuid(uuid));
1743 socket.setServiceName(name);
1744 int errno = socket.mSocket.bindListen();
1746 //TODO(BT): Throw the same exception error code
1747 // that the previous code was using.
1748 //socket.mSocket.throwErrnoNative(errno);
1749 throw new IOException("Error: " + errno);
1755 * Construct an unencrypted, unauthenticated, RFCOMM server socket.
1756 * Call #accept to retrieve connections to this socket.
1757 * @return An RFCOMM BluetoothServerSocket
1758 * @throws IOException On error, for example Bluetooth not available, or
1759 * insufficient permissions.
1762 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
1763 BluetoothServerSocket socket = new BluetoothServerSocket(
1764 BluetoothSocket.TYPE_RFCOMM, false, false, port);
1765 int errno = socket.mSocket.bindListen();
1766 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1767 socket.setChannel(socket.mSocket.getPort());
1770 //TODO(BT): Throw the same exception error code
1771 // that the previous code was using.
1772 //socket.mSocket.throwErrnoNative(errno);
1773 throw new IOException("Error: " + errno);
1779 * Construct an encrypted, RFCOMM server socket.
1780 * Call #accept to retrieve connections to this socket.
1781 * @return An RFCOMM BluetoothServerSocket
1782 * @throws IOException On error, for example Bluetooth not available, or
1783 * insufficient permissions.
1786 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port)
1787 throws IOException {
1788 BluetoothServerSocket socket = new BluetoothServerSocket(
1789 BluetoothSocket.TYPE_RFCOMM, false, true, port);
1790 int errno = socket.mSocket.bindListen();
1791 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1792 socket.setChannel(socket.mSocket.getPort());
1795 //TODO(BT): Throw the same exception error code
1796 // that the previous code was using.
1797 //socket.mSocket.throwErrnoNative(errno);
1798 throw new IOException("Error: " + errno);
1804 * Construct a SCO server socket.
1805 * Call #accept to retrieve connections to this socket.
1806 * @return A SCO BluetoothServerSocket
1807 * @throws IOException On error, for example Bluetooth not available, or
1808 * insufficient permissions.
1811 public static BluetoothServerSocket listenUsingScoOn() throws IOException {
1812 BluetoothServerSocket socket = new BluetoothServerSocket(
1813 BluetoothSocket.TYPE_SCO, false, false, -1);
1814 int errno = socket.mSocket.bindListen();
1816 //TODO(BT): Throw the same exception error code
1817 // that the previous code was using.
1818 //socket.mSocket.throwErrnoNative(errno);
1824 * Construct an encrypted, authenticated, L2CAP server socket.
1825 * Call #accept to retrieve connections to this socket.
1826 * <p>To auto assign a port without creating a SDP record use
1827 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
1828 * @param port the PSM to listen on
1829 * @param mitm enforce man-in-the-middle protection for authentication.
1830 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections.
1831 * @return An L2CAP BluetoothServerSocket
1832 * @throws IOException On error, for example Bluetooth not available, or
1833 * insufficient permissions.
1836 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
1837 throws IOException {
1838 BluetoothServerSocket socket = new BluetoothServerSocket(
1839 BluetoothSocket.TYPE_L2CAP, true, true, port, mitm, min16DigitPin);
1840 int errno = socket.mSocket.bindListen();
1841 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1842 socket.setChannel(socket.mSocket.getPort());
1845 //TODO(BT): Throw the same exception error code
1846 // that the previous code was using.
1847 //socket.mSocket.throwErrnoNative(errno);
1848 throw new IOException("Error: " + errno);
1854 * Construct an encrypted, authenticated, L2CAP server socket.
1855 * Call #accept to retrieve connections to this socket.
1856 * <p>To auto assign a port without creating a SDP record use
1857 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
1858 * @param port the PSM to listen on
1859 * @return An L2CAP BluetoothServerSocket
1860 * @throws IOException On error, for example Bluetooth not available, or
1861 * insufficient permissions.
1864 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
1865 return listenUsingL2capOn(port, false, false);
1869 * Read the local Out of Band Pairing Data
1870 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1872 * @return Pair<byte[], byte[]> of Hash and Randomizer
1876 public Pair<byte[], byte[]> readOutOfBandData() {
1877 if (getState() != STATE_ON) return null;
1885 mServiceLock.readLock().lock();
1886 if (mService != null) mService.readOutOfBandData();
1888 if (ret == null || ret.length != 32) return null;
1890 hash = Arrays.copyOfRange(ret, 0, 16);
1891 randomizer = Arrays.copyOfRange(ret, 16, 32);
1894 Log.d(TAG, "readOutOfBandData:" + Arrays.toString(hash) +
1895 ":" + Arrays.toString(randomizer));
1897 return new Pair<byte[], byte[]>(hash, randomizer);
1899 } catch (RemoteException e) {
1902 mServiceLock.readLock().unlock();
1909 * Get the profile proxy object associated with the profile.
1911 * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
1912 * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or
1913 * {@link BluetoothProfile#GATT_SERVER}. Clients must implement
1914 * {@link BluetoothProfile.ServiceListener} to get notified of
1915 * the connection status and to get the proxy object.
1917 * @param context Context of the application
1918 * @param listener The service Listener for connection callbacks.
1919 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH},
1920 * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
1921 * {@link BluetoothProfile#GATT} or {@link BluetoothProfile#GATT_SERVER}.
1922 * @return true on success, false on error
1924 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
1926 if (context == null || listener == null) return false;
1928 if (profile == BluetoothProfile.HEADSET) {
1929 BluetoothHeadset headset = new BluetoothHeadset(context, listener);
1931 } else if (profile == BluetoothProfile.A2DP) {
1932 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
1934 } else if (profile == BluetoothProfile.A2DP_SINK) {
1935 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
1937 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
1938 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
1940 } else if (profile == BluetoothProfile.INPUT_DEVICE) {
1941 BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
1943 } else if (profile == BluetoothProfile.PAN) {
1944 BluetoothPan pan = new BluetoothPan(context, listener);
1946 } else if (profile == BluetoothProfile.HEALTH) {
1947 BluetoothHealth health = new BluetoothHealth(context, listener);
1949 } else if (profile == BluetoothProfile.MAP) {
1950 BluetoothMap map = new BluetoothMap(context, listener);
1952 } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
1953 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
1955 } else if (profile == BluetoothProfile.SAP) {
1956 BluetoothSap sap = new BluetoothSap(context, listener);
1958 } else if (profile == BluetoothProfile.PBAP_CLIENT) {
1959 BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
1967 * Close the connection of the profile proxy to the Service.
1969 * <p> Clients should call this when they are no longer using
1970 * the proxy obtained from {@link #getProfileProxy}.
1971 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or
1972 * {@link BluetoothProfile#A2DP}
1975 * @param proxy Profile proxy object
1977 public void closeProfileProxy(int profile, BluetoothProfile proxy) {
1978 if (proxy == null) return;
1981 case BluetoothProfile.HEADSET:
1982 BluetoothHeadset headset = (BluetoothHeadset)proxy;
1985 case BluetoothProfile.A2DP:
1986 BluetoothA2dp a2dp = (BluetoothA2dp)proxy;
1989 case BluetoothProfile.A2DP_SINK:
1990 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink)proxy;
1993 case BluetoothProfile.AVRCP_CONTROLLER:
1994 BluetoothAvrcpController avrcp = (BluetoothAvrcpController)proxy;
1997 case BluetoothProfile.INPUT_DEVICE:
1998 BluetoothInputDevice iDev = (BluetoothInputDevice)proxy;
2001 case BluetoothProfile.PAN:
2002 BluetoothPan pan = (BluetoothPan)proxy;
2005 case BluetoothProfile.HEALTH:
2006 BluetoothHealth health = (BluetoothHealth)proxy;
2009 case BluetoothProfile.GATT:
2010 BluetoothGatt gatt = (BluetoothGatt)proxy;
2013 case BluetoothProfile.GATT_SERVER:
2014 BluetoothGattServer gattServer = (BluetoothGattServer)proxy;
2017 case BluetoothProfile.MAP:
2018 BluetoothMap map = (BluetoothMap)proxy;
2021 case BluetoothProfile.HEADSET_CLIENT:
2022 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy;
2023 headsetClient.close();
2025 case BluetoothProfile.SAP:
2026 BluetoothSap sap = (BluetoothSap)proxy;
2029 case BluetoothProfile.PBAP_CLIENT:
2030 BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy;
2036 final private IBluetoothManagerCallback mManagerCallback =
2037 new IBluetoothManagerCallback.Stub() {
2038 public void onBluetoothServiceUp(IBluetooth bluetoothService) {
2039 if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
2041 mServiceLock.writeLock().lock();
2042 mService = bluetoothService;
2043 mServiceLock.writeLock().unlock();
2045 synchronized (mProxyServiceStateCallbacks) {
2046 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ) {
2049 cb.onBluetoothServiceUp(bluetoothService);
2051 Log.d(TAG, "onBluetoothServiceUp: cb is null!!!");
2053 } catch (Exception e) {
2060 public void onBluetoothServiceDown() {
2061 if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
2064 mServiceLock.writeLock().lock();
2066 if (mLeScanClients != null) mLeScanClients.clear();
2067 if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
2068 if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
2070 mServiceLock.writeLock().unlock();
2073 synchronized (mProxyServiceStateCallbacks) {
2074 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
2077 cb.onBluetoothServiceDown();
2079 Log.d(TAG, "onBluetoothServiceDown: cb is null!!!");
2081 } catch (Exception e) {
2088 public void onBrEdrDown() {
2089 if (DBG) Log.i(TAG, "onBrEdrDown:");
2094 * Enable the Bluetooth Adapter, but don't auto-connect devices
2095 * and don't persist state. Only for use by system applications.
2098 public boolean enableNoAutoConnect() {
2099 if (isEnabled() == true){
2100 if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT is already enabled..!");
2104 return mManagerService.enableNoAutoConnect();
2105 } catch (RemoteException e) {Log.e(TAG, "", e);}
2110 * Enable control of the Bluetooth Adapter for a single application.
2112 * <p>Some applications need to use Bluetooth for short periods of time to
2113 * transfer data but don't want all the associated implications like
2114 * automatic connection to headsets etc.
2116 * <p> Multiple applications can call this. This is reference counted and
2117 * Bluetooth disabled only when no one else is using it. There will be no UI
2118 * shown to the user while bluetooth is being enabled. Any user action will
2119 * override this call. For example, if user wants Bluetooth on and the last
2120 * user of this API wanted to disable Bluetooth, Bluetooth will not be
2123 * <p> This API is only meant to be used by internal applications. Third
2124 * party applications but use {@link #enable} and {@link #disable} APIs.
2126 * <p> If this API returns true, it means the callback will be called.
2127 * The callback will be called with the current state of Bluetooth.
2128 * If the state is not what was requested, an internal error would be the
2129 * reason. If Bluetooth is already on and if this function is called to turn
2130 * it on, the api will return true and a callback will be called.
2132 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2134 * @param on True for on, false for off.
2135 * @param callback The callback to notify changes to the state.
2138 public boolean changeApplicationBluetoothState(boolean on,
2139 BluetoothStateChangeCallback callback) {
2140 if (callback == null) return false;
2145 mServiceLock.readLock().lock();
2146 if (mService != null) {
2147 return mService.changeApplicationBluetoothState(on, new
2148 StateChangeCallbackWrapper(callback), new Binder());
2150 } catch (RemoteException e) {
2151 Log.e(TAG, "changeBluetoothState", e);
2153 mServiceLock.readLock().unlock();
2162 public interface BluetoothStateChangeCallback {
2163 public void onBluetoothStateChange(boolean on);
2169 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
2170 private BluetoothStateChangeCallback mCallback;
2172 StateChangeCallbackWrapper(BluetoothStateChangeCallback
2174 mCallback = callback;
2178 public void onBluetoothStateChange(boolean on) {
2179 mCallback.onBluetoothStateChange(on);
2183 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
2184 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
2185 return Collections.unmodifiableSet(deviceSet);
2188 protected void finalize() throws Throwable {
2190 mManagerService.unregisterAdapter(mManagerCallback);
2191 } catch (RemoteException e) {
2200 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
2201 * <p>Alphabetic characters must be uppercase to be valid.
2203 * @param address Bluetooth address as string
2204 * @return true if the address is valid, false otherwise
2206 public static boolean checkBluetoothAddress(String address) {
2207 if (address == null || address.length() != ADDRESS_LENGTH) {
2210 for (int i = 0; i < ADDRESS_LENGTH; i++) {
2211 char c = address.charAt(i);
2215 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
2216 // hex character, OK
2230 /*package*/ IBluetoothManager getBluetoothManager() {
2231 return mManagerService;
2234 final private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>();
2236 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
2237 synchronized (mProxyServiceStateCallbacks) {
2239 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
2240 } else if (!mProxyServiceStateCallbacks.contains(cb)) {
2241 mProxyServiceStateCallbacks.add(cb);
2247 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
2248 synchronized (mProxyServiceStateCallbacks) {
2249 mProxyServiceStateCallbacks.remove(cb);
2254 * Callback interface used to deliver LE scan results.
2256 * @see #startLeScan(LeScanCallback)
2257 * @see #startLeScan(UUID[], LeScanCallback)
2259 public interface LeScanCallback {
2261 * Callback reporting an LE device found during a device scan initiated
2262 * by the {@link BluetoothAdapter#startLeScan} function.
2264 * @param device Identifies the remote device
2265 * @param rssi The RSSI value for the remote device as reported by the
2266 * Bluetooth hardware. 0 if no RSSI value is available.
2267 * @param scanRecord The content of the advertisement record offered by
2268 * the remote device.
2270 public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
2274 * Starts a scan for Bluetooth LE devices.
2276 * <p>Results of the scan are reported using the
2277 * {@link LeScanCallback#onLeScan} callback.
2279 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
2281 * @param callback the callback LE scan results are delivered
2282 * @return true, if the scan was started successfully
2283 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
2287 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
2288 public boolean startLeScan(LeScanCallback callback) {
2289 return startLeScan(null, callback);
2293 * Starts a scan for Bluetooth LE devices, looking for devices that
2294 * advertise given services.
2296 * <p>Devices which advertise all specified services are reported using the
2297 * {@link LeScanCallback#onLeScan} callback.
2299 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
2301 * @param serviceUuids Array of services to look for
2302 * @param callback the callback LE scan results are delivered
2303 * @return true, if the scan was started successfully
2304 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
2308 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
2309 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
2310 if (DBG) Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
2311 if (callback == null) {
2312 if (DBG) Log.e(TAG, "startLeScan: null callback");
2315 BluetoothLeScanner scanner = getBluetoothLeScanner();
2316 if (scanner == null) {
2317 if (DBG) Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
2321 synchronized(mLeScanClients) {
2322 if (mLeScanClients.containsKey(callback)) {
2323 if (DBG) Log.e(TAG, "LE Scan has already started");
2328 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
2329 if (iGatt == null) {
2330 // BLE is not supported
2334 ScanCallback scanCallback = new ScanCallback() {
2336 public void onScanResult(int callbackType, ScanResult result) {
2337 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
2338 // Should not happen.
2339 Log.e(TAG, "LE Scan has already started");
2342 ScanRecord scanRecord = result.getScanRecord();
2343 if (scanRecord == null) {
2346 if (serviceUuids != null) {
2347 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
2348 for (UUID uuid : serviceUuids) {
2349 uuids.add(new ParcelUuid(uuid));
2351 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
2352 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
2353 if (DBG) Log.d(TAG, "uuids does not match");
2357 callback.onLeScan(result.getDevice(), result.getRssi(),
2358 scanRecord.getBytes());
2361 ScanSettings settings = new ScanSettings.Builder()
2362 .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
2363 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
2365 List<ScanFilter> filters = new ArrayList<ScanFilter>();
2366 if (serviceUuids != null && serviceUuids.length > 0) {
2367 // Note scan filter does not support matching an UUID array so we put one
2368 // UUID to hardware and match the whole array in callback.
2369 ScanFilter filter = new ScanFilter.Builder().setServiceUuid(
2370 new ParcelUuid(serviceUuids[0])).build();
2371 filters.add(filter);
2373 scanner.startScan(filters, settings, scanCallback);
2375 mLeScanClients.put(callback, scanCallback);
2378 } catch (RemoteException e) {
2386 * Stops an ongoing Bluetooth LE device scan.
2388 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
2390 * @param callback used to identify which scan to stop
2391 * must be the same handle used to start the scan
2392 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
2395 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
2396 public void stopLeScan(LeScanCallback callback) {
2397 if (DBG) Log.d(TAG, "stopLeScan()");
2398 BluetoothLeScanner scanner = getBluetoothLeScanner();
2399 if (scanner == null) {
2402 synchronized (mLeScanClients) {
2403 ScanCallback scanCallback = mLeScanClients.remove(callback);
2404 if (scanCallback == null) {
2405 if (DBG) Log.d(TAG, "scan not started yet");
2408 scanner.stopScan(scanCallback);