• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2009-2016 The Android Open Source Project
3  * Copyright 2015 Samsung LSI
4  *
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 
18 package android.bluetooth;
19 
20 import android.Manifest;
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresPermission;
25 import android.annotation.SdkConstant;
26 import android.annotation.SdkConstant.SdkConstantType;
27 import android.annotation.SystemApi;
28 import android.annotation.UnsupportedAppUsage;
29 import android.app.ActivityThread;
30 import android.bluetooth.le.BluetoothLeAdvertiser;
31 import android.bluetooth.le.BluetoothLeScanner;
32 import android.bluetooth.le.PeriodicAdvertisingManager;
33 import android.bluetooth.le.ScanCallback;
34 import android.bluetooth.le.ScanFilter;
35 import android.bluetooth.le.ScanRecord;
36 import android.bluetooth.le.ScanResult;
37 import android.bluetooth.le.ScanSettings;
38 import android.content.Context;
39 import android.os.BatteryStats;
40 import android.os.Binder;
41 import android.os.IBinder;
42 import android.os.ParcelUuid;
43 import android.os.RemoteException;
44 import android.os.ResultReceiver;
45 import android.os.ServiceManager;
46 import android.os.SynchronousResultReceiver;
47 import android.os.SystemProperties;
48 import android.util.Log;
49 import android.util.Pair;
50 
51 import java.io.IOException;
52 import java.lang.annotation.Retention;
53 import java.lang.annotation.RetentionPolicy;
54 import java.util.ArrayList;
55 import java.util.Arrays;
56 import java.util.Collections;
57 import java.util.HashMap;
58 import java.util.HashSet;
59 import java.util.List;
60 import java.util.Locale;
61 import java.util.Map;
62 import java.util.Set;
63 import java.util.UUID;
64 import java.util.concurrent.Executor;
65 import java.util.concurrent.TimeoutException;
66 import java.util.concurrent.locks.ReentrantReadWriteLock;
67 
68 /**
69  * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
70  * lets you perform fundamental Bluetooth tasks, such as initiate
71  * device discovery, query a list of bonded (paired) devices,
72  * instantiate a {@link BluetoothDevice} using a known MAC address, and create
73  * a {@link BluetoothServerSocket} to listen for connection requests from other
74  * devices, and start a scan for Bluetooth LE devices.
75  *
76  * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
77  * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}.
78  * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter}
79  * method instead.
80  * </p><p>
81  * Fundamentally, this is your starting point for all
82  * Bluetooth actions. Once you have the local adapter, you can get a set of
83  * {@link BluetoothDevice} objects representing all paired devices with
84  * {@link #getBondedDevices()}; start device discovery with
85  * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
86  * listen for incoming RFComm connection requests with {@link
87  * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
88  * Channels (CoC) connection requests with {@link #listenUsingL2capChannel()}; or start a scan for
89  * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
90  * </p>
91  * <p>This class is thread safe.</p>
92  * <p class="note"><strong>Note:</strong>
93  * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
94  * permission and some also require the
95  * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
96  * </p>
97  * <div class="special reference">
98  * <h3>Developer Guides</h3>
99  * <p>
100  * For more information about using Bluetooth, read the <a href=
101  * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
102  * guide.
103  * </p>
104  * </div>
105  *
106  * {@see BluetoothDevice}
107  * {@see BluetoothServerSocket}
108  */
109 public final class BluetoothAdapter {
110     private static final String TAG = "BluetoothAdapter";
111     private static final boolean DBG = true;
112     private static final boolean VDBG = false;
113 
114     /**
115      * Default MAC address reported to a client that does not have the
116      * android.permission.LOCAL_MAC_ADDRESS permission.
117      *
118      * @hide
119      */
120     public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
121 
122     /**
123      * Sentinel error value for this class. Guaranteed to not equal any other
124      * integer constant in this class. Provided as a convenience for functions
125      * that require a sentinel error value, for example:
126      * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
127      * BluetoothAdapter.ERROR)</code>
128      */
129     public static final int ERROR = Integer.MIN_VALUE;
130 
131     /**
132      * Broadcast Action: The state of the local Bluetooth adapter has been
133      * changed.
134      * <p>For example, Bluetooth has been turned on or off.
135      * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
136      * #EXTRA_PREVIOUS_STATE} containing the new and old states
137      * respectively.
138      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
139      */
140     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
141             ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED";
142 
143     /**
144      * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
145      * intents to request the current power state. Possible values are:
146      * {@link #STATE_OFF},
147      * {@link #STATE_TURNING_ON},
148      * {@link #STATE_ON},
149      * {@link #STATE_TURNING_OFF},
150      */
151     public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE";
152     /**
153      * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
154      * intents to request the previous power state. Possible values are:
155      * {@link #STATE_OFF},
156      * {@link #STATE_TURNING_ON},
157      * {@link #STATE_ON},
158      * {@link #STATE_TURNING_OFF}
159      */
160     public static final String EXTRA_PREVIOUS_STATE =
161             "android.bluetooth.adapter.extra.PREVIOUS_STATE";
162 
163     /** @hide */
164     @IntDef(prefix = { "STATE_" }, value = {
165             STATE_OFF,
166             STATE_TURNING_ON,
167             STATE_ON,
168             STATE_TURNING_OFF,
169             STATE_BLE_TURNING_ON,
170             STATE_BLE_ON,
171             STATE_BLE_TURNING_OFF
172     })
173     @Retention(RetentionPolicy.SOURCE)
174     public @interface AdapterState {}
175 
176     /**
177      * Indicates the local Bluetooth adapter is off.
178      */
179     public static final int STATE_OFF = 10;
180     /**
181      * Indicates the local Bluetooth adapter is turning on. However local
182      * clients should wait for {@link #STATE_ON} before attempting to
183      * use the adapter.
184      */
185     public static final int STATE_TURNING_ON = 11;
186     /**
187      * Indicates the local Bluetooth adapter is on, and ready for use.
188      */
189     public static final int STATE_ON = 12;
190     /**
191      * Indicates the local Bluetooth adapter is turning off. Local clients
192      * should immediately attempt graceful disconnection of any remote links.
193      */
194     public static final int STATE_TURNING_OFF = 13;
195 
196     /**
197      * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
198      *
199      * @hide
200      */
201     public static final int STATE_BLE_TURNING_ON = 14;
202 
203     /**
204      * Indicates the local Bluetooth adapter is in LE only mode.
205      *
206      * @hide
207      */
208     public static final int STATE_BLE_ON = 15;
209 
210     /**
211      * Indicates the local Bluetooth adapter is turning off LE only mode.
212      *
213      * @hide
214      */
215     public static final int STATE_BLE_TURNING_OFF = 16;
216 
217     /**
218      * UUID of the GATT Read Characteristics for LE_PSM value.
219      *
220      * @hide
221      */
222     public static final UUID LE_PSM_CHARACTERISTIC_UUID =
223             UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a");
224 
225     /**
226      * Human-readable string helper for AdapterState
227      *
228      * @hide
229      */
nameForState(@dapterState int state)230     public static String nameForState(@AdapterState int state) {
231         switch (state) {
232             case STATE_OFF:
233                 return "OFF";
234             case STATE_TURNING_ON:
235                 return "TURNING_ON";
236             case STATE_ON:
237                 return "ON";
238             case STATE_TURNING_OFF:
239                 return "TURNING_OFF";
240             case STATE_BLE_TURNING_ON:
241                 return "BLE_TURNING_ON";
242             case STATE_BLE_ON:
243                 return "BLE_ON";
244             case STATE_BLE_TURNING_OFF:
245                 return "BLE_TURNING_OFF";
246             default:
247                 return "?!?!? (" + state + ")";
248         }
249     }
250 
251     /**
252      * Activity Action: Show a system activity that requests discoverable mode.
253      * This activity will also request the user to turn on Bluetooth if it
254      * is not currently enabled.
255      * <p>Discoverable mode is equivalent to {@link
256      * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
257      * this Bluetooth adapter when they perform a discovery.
258      * <p>For privacy, Android is not discoverable by default.
259      * <p>The sender of this Intent can optionally use extra field {@link
260      * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
261      * discoverability. Currently the default duration is 120 seconds, and
262      * maximum duration is capped at 300 seconds for each request.
263      * <p>Notification of the result of this activity is posted using the
264      * {@link android.app.Activity#onActivityResult} callback. The
265      * <code>resultCode</code>
266      * will be the duration (in seconds) of discoverability or
267      * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
268      * discoverability or an error has occurred.
269      * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
270      * for global notification whenever the scan mode changes. For example, an
271      * application can be notified when the device has ended discoverability.
272      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
273      */
274     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
275             ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
276 
277     /**
278      * Used as an optional int extra field in {@link
279      * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
280      * for discoverability in seconds. The current default is 120 seconds, and
281      * requests over 300 seconds will be capped. These values could change.
282      */
283     public static final String EXTRA_DISCOVERABLE_DURATION =
284             "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
285 
286     /**
287      * Activity Action: Show a system activity that allows the user to turn on
288      * Bluetooth.
289      * <p>This system activity will return once Bluetooth has completed turning
290      * on, or the user has decided not to turn Bluetooth on.
291      * <p>Notification of the result of this activity is posted using the
292      * {@link android.app.Activity#onActivityResult} callback. The
293      * <code>resultCode</code>
294      * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
295      * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
296      * has rejected the request or an error has occurred.
297      * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
298      * for global notification whenever Bluetooth is turned on or off.
299      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
300      */
301     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
302             ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE";
303 
304     /**
305      * Activity Action: Show a system activity that allows the user to turn off
306      * Bluetooth. This is used only if permission review is enabled which is for
307      * apps targeting API less than 23 require a permission review before any of
308      * the app's components can run.
309      * <p>This system activity will return once Bluetooth has completed turning
310      * off, or the user has decided not to turn Bluetooth off.
311      * <p>Notification of the result of this activity is posted using the
312      * {@link android.app.Activity#onActivityResult} callback. The
313      * <code>resultCode</code>
314      * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
315      * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
316      * has rejected the request or an error has occurred.
317      * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
318      * for global notification whenever Bluetooth is turned on or off.
319      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
320      *
321      * @hide
322      */
323     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String
324             ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE";
325 
326     /**
327      * Activity Action: Show a system activity that allows user to enable BLE scans even when
328      * Bluetooth is turned off.<p>
329      *
330      * Notification of result of this activity is posted using
331      * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
332      * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
333      * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
334      * error occurred.
335      *
336      * @hide
337      */
338     @SystemApi
339     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
340     public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
341             "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
342 
343     /**
344      * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
345      * has changed.
346      * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
347      * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
348      * respectively.
349      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
350      */
351     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
352             ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
353 
354     /**
355      * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
356      * intents to request the current scan mode. Possible values are:
357      * {@link #SCAN_MODE_NONE},
358      * {@link #SCAN_MODE_CONNECTABLE},
359      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
360      */
361     public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
362     /**
363      * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
364      * intents to request the previous scan mode. Possible values are:
365      * {@link #SCAN_MODE_NONE},
366      * {@link #SCAN_MODE_CONNECTABLE},
367      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
368      */
369     public static final String EXTRA_PREVIOUS_SCAN_MODE =
370             "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
371 
372     /** @hide */
373     @IntDef(prefix = { "SCAN_" }, value = {
374             SCAN_MODE_NONE,
375             SCAN_MODE_CONNECTABLE,
376             SCAN_MODE_CONNECTABLE_DISCOVERABLE
377     })
378     @Retention(RetentionPolicy.SOURCE)
379     public @interface ScanMode {}
380 
381     /**
382      * Indicates that both inquiry scan and page scan are disabled on the local
383      * Bluetooth adapter. Therefore this device is neither discoverable
384      * nor connectable from remote Bluetooth devices.
385      */
386     public static final int SCAN_MODE_NONE = 20;
387     /**
388      * Indicates that inquiry scan is disabled, but page scan is enabled on the
389      * local Bluetooth adapter. Therefore this device is not discoverable from
390      * remote Bluetooth devices, but is connectable from remote devices that
391      * have previously discovered this device.
392      */
393     public static final int SCAN_MODE_CONNECTABLE = 21;
394     /**
395      * Indicates that both inquiry scan and page scan are enabled on the local
396      * Bluetooth adapter. Therefore this device is both discoverable and
397      * connectable from remote Bluetooth devices.
398      */
399     public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
400 
401     /**
402      * Device only has a display.
403      *
404      * @hide
405      */
406     public static final int IO_CAPABILITY_OUT = 0;
407 
408     /**
409      * Device has a display and the ability to input Yes/No.
410      *
411      * @hide
412      */
413     public static final int IO_CAPABILITY_IO = 1;
414 
415     /**
416      * Device only has a keyboard for entry but no display.
417      *
418      * @hide
419      */
420     public static final int IO_CAPABILITY_IN = 2;
421 
422     /**
423      * Device has no Input or Output capability.
424      *
425      * @hide
426      */
427     public static final int IO_CAPABILITY_NONE = 3;
428 
429     /**
430      * Device has a display and a full keyboard.
431      *
432      * @hide
433      */
434     public static final int IO_CAPABILITY_KBDISP = 4;
435 
436     /**
437      * Maximum range value for Input/Output capabilities.
438      *
439      * <p>This should be updated when adding a new Input/Output capability. Other code
440      * like validation depends on this being accurate.
441      *
442      * @hide
443      */
444     public static final int IO_CAPABILITY_MAX = 5;
445 
446     /**
447      * The Input/Output capability of the device is unknown.
448      *
449      * @hide
450      */
451     public static final int IO_CAPABILITY_UNKNOWN = 255;
452 
453     /** @hide */
454     @IntDef({IO_CAPABILITY_OUT, IO_CAPABILITY_IO, IO_CAPABILITY_IN, IO_CAPABILITY_NONE,
455             IO_CAPABILITY_KBDISP})
456     @Retention(RetentionPolicy.SOURCE)
457     public @interface IoCapability {}
458 
459     /**
460      * Broadcast Action: The local Bluetooth adapter has started the remote
461      * device discovery process.
462      * <p>This usually involves an inquiry scan of about 12 seconds, followed
463      * by a page scan of each new device to retrieve its Bluetooth name.
464      * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
465      * remote Bluetooth devices are found.
466      * <p>Device discovery is a heavyweight procedure. New connections to
467      * remote Bluetooth devices should not be attempted while discovery is in
468      * progress, and existing connections will experience limited bandwidth
469      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
470      * discovery.
471      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
472      */
473     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
474             ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
475     /**
476      * Broadcast Action: The local Bluetooth adapter has finished the device
477      * discovery process.
478      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
479      */
480     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
481             ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
482 
483     /**
484      * Broadcast Action: The local Bluetooth adapter has changed its friendly
485      * Bluetooth name.
486      * <p>This name is visible to remote Bluetooth devices.
487      * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
488      * the name.
489      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
490      */
491     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
492             ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
493     /**
494      * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
495      * intents to request the local Bluetooth name.
496      */
497     public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
498 
499     /**
500      * Intent used to broadcast the change in connection state of the local
501      * Bluetooth adapter to a profile of the remote device. When the adapter is
502      * not connected to any profiles of any remote devices and it attempts a
503      * connection to a profile this intent will be sent. Once connected, this intent
504      * will not be sent for any more connection attempts to any profiles of any
505      * remote device. When the adapter disconnects from the last profile its
506      * connected to of any remote device, this intent will be sent.
507      *
508      * <p> This intent is useful for applications that are only concerned about
509      * whether the local adapter is connected to any profile of any device and
510      * are not really concerned about which profile. For example, an application
511      * which displays an icon to display whether Bluetooth is connected or not
512      * can use this intent.
513      *
514      * <p>This intent will have 3 extras:
515      * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
516      * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
517      * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
518      *
519      * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
520      * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
521      * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
522      *
523      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
524      */
525     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String
526             ACTION_CONNECTION_STATE_CHANGED =
527             "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
528 
529     /**
530      * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
531      *
532      * This extra represents the current connection state.
533      */
534     public static final String EXTRA_CONNECTION_STATE =
535             "android.bluetooth.adapter.extra.CONNECTION_STATE";
536 
537     /**
538      * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
539      *
540      * This extra represents the previous connection state.
541      */
542     public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
543             "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
544 
545     /**
546      * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
547      *
548      * @hide
549      */
550     @SystemApi public static final String ACTION_BLE_STATE_CHANGED =
551             "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
552 
553     /**
554      * Intent used to broadcast the change in the Bluetooth address
555      * of the local Bluetooth adapter.
556      * <p>Always contains the extra field {@link
557      * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
558      *
559      * Note: only system level processes are allowed to send this
560      * defined broadcast.
561      *
562      * @hide
563      */
564     public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
565             "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
566 
567     /**
568      * Used as a String extra field in {@link
569      * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
570      * Bluetooth address.
571      *
572      * @hide
573      */
574     public static final String EXTRA_BLUETOOTH_ADDRESS =
575             "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
576 
577     /**
578      * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
579      * by BLE Always on enabled application to know the ACL_CONNECTED event
580      * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
581      * as Bluetooth LE is the only feature available in STATE_BLE_ON
582      *
583      * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
584      * works in Bluetooth state STATE_ON
585      *
586      * @hide
587      */
588     public static final String ACTION_BLE_ACL_CONNECTED =
589             "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
590 
591     /**
592      * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
593      * by BLE Always on enabled application to know the ACL_DISCONNECTED event
594      * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
595      * LE is the only feature available in STATE_BLE_ON
596      *
597      * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
598      * works in Bluetooth state STATE_ON
599      *
600      * @hide
601      */
602     public static final String ACTION_BLE_ACL_DISCONNECTED =
603             "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
604 
605     /** The profile is in disconnected state */
606     public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
607     /** The profile is in connecting state */
608     public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
609     /** The profile is in connected state */
610     public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
611     /** The profile is in disconnecting state */
612     public static final int STATE_DISCONNECTING =
613             BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
614 
615     /** @hide */
616     public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
617     private final IBinder mToken;
618 
619 
620     /**
621      * When creating a ServerSocket using listenUsingRfcommOn() or
622      * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
623      * a ServerSocket that auto assigns a channel number to the first
624      * bluetooth socket.
625      * The channel number assigned to this first Bluetooth Socket will
626      * be stored in the ServerSocket, and reused for subsequent Bluetooth
627      * sockets.
628      *
629      * @hide
630      */
631     public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
632 
633 
634     private static final int ADDRESS_LENGTH = 17;
635 
636     /**
637      * Lazily initialized singleton. Guaranteed final after first object
638      * constructed.
639      */
640     private static BluetoothAdapter sAdapter;
641 
642     private static BluetoothLeScanner sBluetoothLeScanner;
643     private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
644     private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
645 
646     private final IBluetoothManager mManagerService;
647     @UnsupportedAppUsage
648     private IBluetooth mService;
649     private Context mContext;
650     private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
651 
652     private final Object mLock = new Object();
653     private final Map<LeScanCallback, ScanCallback> mLeScanClients;
654     private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
655                 sMetadataListeners = new HashMap<>();
656 
657     /**
658      * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
659      * implementation.
660      */
661     private static final IBluetoothMetadataListener sBluetoothMetadataListener =
662             new IBluetoothMetadataListener.Stub() {
663         @Override
664         public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) {
665             synchronized (sMetadataListeners) {
666                 if (sMetadataListeners.containsKey(device)) {
667                     List<Pair<OnMetadataChangedListener, Executor>> list =
668                             sMetadataListeners.get(device);
669                     for (Pair<OnMetadataChangedListener, Executor> pair : list) {
670                         OnMetadataChangedListener listener = pair.first;
671                         Executor executor = pair.second;
672                         executor.execute(() -> {
673                             listener.onMetadataChanged(device, key, value);
674                         });
675                     }
676                 }
677             }
678             return;
679         }
680     };
681 
682     /**
683      * Get a handle to the default local Bluetooth adapter.
684      * <p>Currently Android only supports one Bluetooth adapter, but the API
685      * could be extended to support more. This will always return the default
686      * adapter.
687      * </p>
688      *
689      * @return the default local adapter, or null if Bluetooth is not supported on this hardware
690      * platform
691      */
getDefaultAdapter()692     public static synchronized BluetoothAdapter getDefaultAdapter() {
693         if (sAdapter == null) {
694             IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
695             if (b != null) {
696                 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
697                 sAdapter = new BluetoothAdapter(managerService);
698             } else {
699                 Log.e(TAG, "Bluetooth binder is null");
700             }
701         }
702         return sAdapter;
703     }
704 
705     /**
706      * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
707      */
BluetoothAdapter(IBluetoothManager managerService)708     BluetoothAdapter(IBluetoothManager managerService) {
709 
710         if (managerService == null) {
711             throw new IllegalArgumentException("bluetooth manager service is null");
712         }
713         try {
714             mServiceLock.writeLock().lock();
715             mService = managerService.registerAdapter(mManagerCallback);
716         } catch (RemoteException e) {
717             Log.e(TAG, "", e);
718         } finally {
719             mServiceLock.writeLock().unlock();
720         }
721         mManagerService = managerService;
722         mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
723         mToken = new Binder();
724     }
725 
726     /**
727      * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
728      * address.
729      * <p>Valid Bluetooth hardware addresses must be upper case, in a format
730      * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
731      * available to validate a Bluetooth address.
732      * <p>A {@link BluetoothDevice} will always be returned for a valid
733      * hardware address, even if this adapter has never seen that device.
734      *
735      * @param address valid Bluetooth MAC address
736      * @throws IllegalArgumentException if address is invalid
737      */
getRemoteDevice(String address)738     public BluetoothDevice getRemoteDevice(String address) {
739         return new BluetoothDevice(address);
740     }
741 
742     /**
743      * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
744      * address.
745      * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
746      * expects the address in network byte order (MSB first).
747      * <p>A {@link BluetoothDevice} will always be returned for a valid
748      * hardware address, even if this adapter has never seen that device.
749      *
750      * @param address Bluetooth MAC address (6 bytes)
751      * @throws IllegalArgumentException if address is invalid
752      */
getRemoteDevice(byte[] address)753     public BluetoothDevice getRemoteDevice(byte[] address) {
754         if (address == null || address.length != 6) {
755             throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
756         }
757         return new BluetoothDevice(
758                 String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1],
759                         address[2], address[3], address[4], address[5]));
760     }
761 
762     /**
763      * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
764      * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
765      * supported on this device.
766      * <p>
767      * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
768      * on this device before calling this method.
769      */
getBluetoothLeAdvertiser()770     public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
771         if (!getLeAccess()) {
772             return null;
773         }
774         synchronized (mLock) {
775             if (sBluetoothLeAdvertiser == null) {
776                 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
777             }
778         }
779         return sBluetoothLeAdvertiser;
780     }
781 
782     /**
783      * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
784      * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
785      * Advertising is not supported on this device.
786      * <p>
787      * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
788      * supported on this device before calling this method.
789      *
790      * @hide
791      */
getPeriodicAdvertisingManager()792     public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
793         if (!getLeAccess()) {
794             return null;
795         }
796 
797         if (!isLePeriodicAdvertisingSupported()) {
798             return null;
799         }
800 
801         synchronized (mLock) {
802             if (sPeriodicAdvertisingManager == null) {
803                 sPeriodicAdvertisingManager = new PeriodicAdvertisingManager(mManagerService);
804             }
805         }
806         return sPeriodicAdvertisingManager;
807     }
808 
809     /**
810      * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
811      */
getBluetoothLeScanner()812     public BluetoothLeScanner getBluetoothLeScanner() {
813         if (!getLeAccess()) {
814             return null;
815         }
816         synchronized (mLock) {
817             if (sBluetoothLeScanner == null) {
818                 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
819             }
820         }
821         return sBluetoothLeScanner;
822     }
823 
824     /**
825      * Return true if Bluetooth is currently enabled and ready for use.
826      * <p>Equivalent to:
827      * <code>getBluetoothState() == STATE_ON</code>
828      *
829      * @return true if the local adapter is turned on
830      */
831     @RequiresPermission(Manifest.permission.BLUETOOTH)
isEnabled()832     public boolean isEnabled() {
833         try {
834             mServiceLock.readLock().lock();
835             if (mService != null) {
836                 return mService.isEnabled();
837             }
838         } catch (RemoteException e) {
839             Log.e(TAG, "", e);
840         } finally {
841             mServiceLock.readLock().unlock();
842         }
843 
844         return false;
845     }
846 
847     /**
848      * Return true if Bluetooth LE(Always BLE On feature) is currently
849      * enabled and ready for use
850      * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
851      *
852      * @return true if the local Bluetooth LE adapter is turned on
853      * @hide
854      */
855     @SystemApi
isLeEnabled()856     public boolean isLeEnabled() {
857         final int state = getLeState();
858         if (DBG) {
859             Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
860         }
861         return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
862     }
863 
864     /**
865      * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
866      *
867      * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
868      * to STATE_OFF and completely shut-down Bluetooth
869      *
870      * <p> If the Adapter state is STATE_ON, This would unregister the existance of
871      * special Bluetooth LE application and hence the further turning off of Bluetooth
872      * from UI would ensure the complete turn-off of Bluetooth rather than staying back
873      * BLE only state
874      *
875      * <p>This is an asynchronous call: it will return immediately, and
876      * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
877      * to be notified of subsequent adapter state changes If this call returns
878      * true, then the adapter state will immediately transition from {@link
879      * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
880      * later transition to either {@link #STATE_BLE_ON} or {@link
881      * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
882      * If this call returns false then there was an
883      * immediate problem that will prevent the QAdapter from being turned off -
884      * such as the QAadapter already being turned off.
885      *
886      * @return true to indicate success, or false on immediate error
887      * @hide
888      */
889     @SystemApi
disableBLE()890     public boolean disableBLE() {
891         if (!isBleScanAlwaysAvailable()) {
892             return false;
893         }
894 
895         int state = getLeState();
896         if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
897             String packageName = ActivityThread.currentPackageName();
898             if (DBG) {
899                 Log.d(TAG, "disableBLE(): de-registering " + packageName);
900             }
901             try {
902                 mManagerService.updateBleAppCount(mToken, false, packageName);
903             } catch (RemoteException e) {
904                 Log.e(TAG, "", e);
905             }
906             return true;
907         }
908 
909         if (DBG) {
910             Log.d(TAG, "disableBLE(): Already disabled");
911         }
912         return false;
913     }
914 
915     /**
916      * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
917      *
918      * enableBLE registers the existence of an app using only LE functions.
919      *
920      * enableBLE may enable Bluetooth to an LE only mode so that an app can use
921      * LE related features (BluetoothGatt or BluetoothGattServer classes)
922      *
923      * If the user disables Bluetooth while an app is registered to use LE only features,
924      * Bluetooth will remain on in LE only mode for the app.
925      *
926      * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
927      *
928      * <p>This is an asynchronous call: it returns immediately, and
929      * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
930      * to be notified of adapter state changes.
931      *
932      * If this call returns * true, then the adapter state is either in a mode where
933      * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
934      * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
935      *
936      * If this call returns false then there was an immediate problem that prevents the
937      * adapter from being turned on - such as Airplane mode.
938      *
939      * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
940      * states, It includes all the classic Bluetooth Adapter states along with
941      * internal BLE only states
942      *
943      * @return true to indicate Bluetooth LE will be available, or false on immediate error
944      * @hide
945      */
946     @SystemApi
enableBLE()947     public boolean enableBLE() {
948         if (!isBleScanAlwaysAvailable()) {
949             return false;
950         }
951 
952         try {
953             String packageName = ActivityThread.currentPackageName();
954             mManagerService.updateBleAppCount(mToken, true, packageName);
955             if (isLeEnabled()) {
956                 if (DBG) {
957                     Log.d(TAG, "enableBLE(): Bluetooth already enabled");
958                 }
959                 return true;
960             }
961             if (DBG) {
962                 Log.d(TAG, "enableBLE(): Calling enable");
963             }
964             return mManagerService.enable(packageName);
965         } catch (RemoteException e) {
966             Log.e(TAG, "", e);
967         }
968 
969         return false;
970     }
971 
972     /**
973      * Get the current state of the local Bluetooth adapter.
974      * <p>Possible return values are
975      * {@link #STATE_OFF},
976      * {@link #STATE_TURNING_ON},
977      * {@link #STATE_ON},
978      * {@link #STATE_TURNING_OFF}.
979      *
980      * @return current state of Bluetooth adapter
981      */
982     @RequiresPermission(Manifest.permission.BLUETOOTH)
983     @AdapterState
getState()984     public int getState() {
985         int state = BluetoothAdapter.STATE_OFF;
986 
987         try {
988             mServiceLock.readLock().lock();
989             if (mService != null) {
990                 state = mService.getState();
991             }
992         } catch (RemoteException e) {
993             Log.e(TAG, "", e);
994         } finally {
995             mServiceLock.readLock().unlock();
996         }
997 
998         // Consider all internal states as OFF
999         if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON
1000                 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
1001             if (VDBG) {
1002                 Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
1003             }
1004             state = BluetoothAdapter.STATE_OFF;
1005         }
1006         if (VDBG) {
1007             Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(
1008                     state));
1009         }
1010         return state;
1011     }
1012 
1013     /**
1014      * Get the current state of the local Bluetooth adapter
1015      * <p>This returns current internal state of Adapter including LE ON/OFF
1016      *
1017      * <p>Possible return values are
1018      * {@link #STATE_OFF},
1019      * {@link #STATE_BLE_TURNING_ON},
1020      * {@link #STATE_BLE_ON},
1021      * {@link #STATE_TURNING_ON},
1022      * {@link #STATE_ON},
1023      * {@link #STATE_TURNING_OFF},
1024      * {@link #STATE_BLE_TURNING_OFF}.
1025      *
1026      * @return current state of Bluetooth adapter
1027      * @hide
1028      */
1029     @RequiresPermission(Manifest.permission.BLUETOOTH)
1030     @AdapterState
1031     @UnsupportedAppUsage
getLeState()1032     public int getLeState() {
1033         int state = BluetoothAdapter.STATE_OFF;
1034 
1035         try {
1036             mServiceLock.readLock().lock();
1037             if (mService != null) {
1038                 state = mService.getState();
1039             }
1040         } catch (RemoteException e) {
1041             Log.e(TAG, "", e);
1042         } finally {
1043             mServiceLock.readLock().unlock();
1044         }
1045 
1046         if (VDBG) {
1047             Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state));
1048         }
1049         return state;
1050     }
1051 
getLeAccess()1052     boolean getLeAccess() {
1053         if (getLeState() == STATE_ON) {
1054             return true;
1055         } else if (getLeState() == STATE_BLE_ON) {
1056             return true; // TODO: FILTER SYSTEM APPS HERE <--
1057         }
1058 
1059         return false;
1060     }
1061 
1062     /**
1063      * Turn on the local Bluetooth adapter&mdash;do not use without explicit
1064      * user action to turn on Bluetooth.
1065      * <p>This powers on the underlying Bluetooth hardware, and starts all
1066      * Bluetooth system services.
1067      * <p class="caution"><strong>Bluetooth should never be enabled without
1068      * direct user consent</strong>. If you want to turn on Bluetooth in order
1069      * to create a wireless connection, you should use the {@link
1070      * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
1071      * user permission to turn on Bluetooth. The {@link #enable()} method is
1072      * provided only for applications that include a user interface for changing
1073      * system settings, such as a "power manager" app.</p>
1074      * <p>This is an asynchronous call: it will return immediately, and
1075      * clients should listen for {@link #ACTION_STATE_CHANGED}
1076      * to be notified of subsequent adapter state changes. If this call returns
1077      * true, then the adapter state will immediately transition from {@link
1078      * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
1079      * later transition to either {@link #STATE_OFF} or {@link
1080      * #STATE_ON}. If this call returns false then there was an
1081      * immediate problem that will prevent the adapter from being turned on -
1082      * such as Airplane mode, or the adapter is already turned on.
1083      *
1084      * @return true to indicate adapter startup has begun, or false on immediate error
1085      */
1086     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
enable()1087     public boolean enable() {
1088         if (isEnabled()) {
1089             if (DBG) {
1090                 Log.d(TAG, "enable(): BT already enabled!");
1091             }
1092             return true;
1093         }
1094         try {
1095             return mManagerService.enable(ActivityThread.currentPackageName());
1096         } catch (RemoteException e) {
1097             Log.e(TAG, "", e);
1098         }
1099         return false;
1100     }
1101 
1102     /**
1103      * Turn off the local Bluetooth adapter&mdash;do not use without explicit
1104      * user action to turn off Bluetooth.
1105      * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
1106      * system services, and powers down the underlying Bluetooth hardware.
1107      * <p class="caution"><strong>Bluetooth should never be disabled without
1108      * direct user consent</strong>. The {@link #disable()} method is
1109      * provided only for applications that include a user interface for changing
1110      * system settings, such as a "power manager" app.</p>
1111      * <p>This is an asynchronous call: it will return immediately, and
1112      * clients should listen for {@link #ACTION_STATE_CHANGED}
1113      * to be notified of subsequent adapter state changes. If this call returns
1114      * true, then the adapter state will immediately transition from {@link
1115      * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
1116      * later transition to either {@link #STATE_OFF} or {@link
1117      * #STATE_ON}. If this call returns false then there was an
1118      * immediate problem that will prevent the adapter from being turned off -
1119      * such as the adapter already being turned off.
1120      *
1121      * @return true to indicate adapter shutdown has begun, or false on immediate error
1122      */
1123     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
disable()1124     public boolean disable() {
1125         try {
1126             return mManagerService.disable(ActivityThread.currentPackageName(), true);
1127         } catch (RemoteException e) {
1128             Log.e(TAG, "", e);
1129         }
1130         return false;
1131     }
1132 
1133     /**
1134      * Turn off the local Bluetooth adapter and don't persist the setting.
1135      *
1136      * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1137      * permission
1138      *
1139      * @return true to indicate adapter shutdown has begun, or false on immediate error
1140      * @hide
1141      */
1142     @UnsupportedAppUsage
disable(boolean persist)1143     public boolean disable(boolean persist) {
1144 
1145         try {
1146             return mManagerService.disable(ActivityThread.currentPackageName(), persist);
1147         } catch (RemoteException e) {
1148             Log.e(TAG, "", e);
1149         }
1150         return false;
1151     }
1152 
1153     /**
1154      * Returns the hardware address of the local Bluetooth adapter.
1155      * <p>For example, "00:11:22:AA:BB:CC".
1156      *
1157      * @return Bluetooth hardware address as string
1158      */
1159     @RequiresPermission(Manifest.permission.BLUETOOTH)
getAddress()1160     public String getAddress() {
1161         try {
1162             return mManagerService.getAddress();
1163         } catch (RemoteException e) {
1164             Log.e(TAG, "", e);
1165         }
1166         return null;
1167     }
1168 
1169     /**
1170      * Get the friendly Bluetooth name of the local Bluetooth adapter.
1171      * <p>This name is visible to remote Bluetooth devices.
1172      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1173      *
1174      * @return the Bluetooth name, or null on error
1175      */
getName()1176     public String getName() {
1177         try {
1178             return mManagerService.getName();
1179         } catch (RemoteException e) {
1180             Log.e(TAG, "", e);
1181         }
1182         return null;
1183     }
1184 
1185     /**
1186      * Factory reset bluetooth settings.
1187      *
1188      * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
1189      * permission
1190      *
1191      * @return true to indicate that the config file was successfully cleared
1192      * @hide
1193      */
1194     @UnsupportedAppUsage
factoryReset()1195     public boolean factoryReset() {
1196         try {
1197             mServiceLock.readLock().lock();
1198             if (mService != null) {
1199                 return mService.factoryReset();
1200             }
1201             SystemProperties.set("persist.bluetooth.factoryreset", "true");
1202         } catch (RemoteException e) {
1203             Log.e(TAG, "", e);
1204         } finally {
1205             mServiceLock.readLock().unlock();
1206         }
1207         return false;
1208     }
1209 
1210     /**
1211      * Get the UUIDs supported by the local Bluetooth adapter.
1212      *
1213      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1214      *
1215      * @return the UUIDs supported by the local Bluetooth Adapter.
1216      * @hide
1217      */
1218     @UnsupportedAppUsage
getUuids()1219     public ParcelUuid[] getUuids() {
1220         if (getState() != STATE_ON) {
1221             return null;
1222         }
1223         try {
1224             mServiceLock.readLock().lock();
1225             if (mService != null) {
1226                 return mService.getUuids();
1227             }
1228         } catch (RemoteException e) {
1229             Log.e(TAG, "", e);
1230         } finally {
1231             mServiceLock.readLock().unlock();
1232         }
1233         return null;
1234     }
1235 
1236     /**
1237      * Set the friendly Bluetooth name of the local Bluetooth adapter.
1238      * <p>This name is visible to remote Bluetooth devices.
1239      * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1240      * encoding, although many remote devices can only display the first
1241      * 40 characters, and some may be limited to just 20.
1242      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1243      * will return false. After turning on Bluetooth,
1244      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1245      * to get the updated value.
1246      *
1247      * @param name a valid Bluetooth name
1248      * @return true if the name was set, false otherwise
1249      */
1250     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
setName(String name)1251     public boolean setName(String name) {
1252         if (getState() != STATE_ON) {
1253             return false;
1254         }
1255         try {
1256             mServiceLock.readLock().lock();
1257             if (mService != null) {
1258                 return mService.setName(name);
1259             }
1260         } catch (RemoteException e) {
1261             Log.e(TAG, "", e);
1262         } finally {
1263             mServiceLock.readLock().unlock();
1264         }
1265         return false;
1266     }
1267 
1268     /**
1269      * Returns the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1270      * adapter.
1271      *
1272      * @return {@link BluetoothClass} Bluetooth CoD of local Bluetooth device.
1273      *
1274      * @hide
1275      */
1276     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
getBluetoothClass()1277     public BluetoothClass getBluetoothClass() {
1278         if (getState() != STATE_ON) {
1279             return null;
1280         }
1281         try {
1282             mServiceLock.readLock().lock();
1283             if (mService != null) {
1284                 return mService.getBluetoothClass();
1285             }
1286         } catch (RemoteException e) {
1287             Log.e(TAG, "", e);
1288         } finally {
1289             mServiceLock.readLock().unlock();
1290         }
1291         return null;
1292     }
1293 
1294     /**
1295      * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth
1296      * adapter.
1297      *
1298      * <p>Note: This value persists across system reboot.
1299      *
1300      * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to.
1301      * @return true if successful, false if unsuccessful.
1302      *
1303      * @hide
1304      */
1305     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
setBluetoothClass(BluetoothClass bluetoothClass)1306     public boolean setBluetoothClass(BluetoothClass bluetoothClass) {
1307         if (getState() != STATE_ON) {
1308             return false;
1309         }
1310         try {
1311             mServiceLock.readLock().lock();
1312             if (mService != null) {
1313                 return mService.setBluetoothClass(bluetoothClass);
1314             }
1315         } catch (RemoteException e) {
1316             Log.e(TAG, "", e);
1317         } finally {
1318             mServiceLock.readLock().unlock();
1319         }
1320         return false;
1321     }
1322 
1323     /**
1324      * Returns the Input/Output capability of the device for classic Bluetooth.
1325      *
1326      * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1327      *         {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1328      *         {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1329      *
1330      * @hide
1331      */
1332     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1333     @IoCapability
getIoCapability()1334     public int getIoCapability() {
1335         if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1336         try {
1337             mServiceLock.readLock().lock();
1338             if (mService != null) return mService.getIoCapability();
1339         } catch (RemoteException e) {
1340             Log.e(TAG, e.getMessage(), e);
1341         } finally {
1342             mServiceLock.readLock().unlock();
1343         }
1344         return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1345     }
1346 
1347     /**
1348      * Sets the Input/Output capability of the device for classic Bluetooth.
1349      *
1350      * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1351      * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1352      * and {@link BluetoothAdapter#enable()} to see the changes.
1353      *
1354      * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1355      *                   {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1356      *                   {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1357      *
1358      * @hide
1359      */
1360     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
setIoCapability(@oCapability int capability)1361     public boolean setIoCapability(@IoCapability int capability) {
1362         if (getState() != STATE_ON) return false;
1363         try {
1364             mServiceLock.readLock().lock();
1365             if (mService != null) return mService.setIoCapability(capability);
1366         } catch (RemoteException e) {
1367             Log.e(TAG, e.getMessage(), e);
1368         } finally {
1369             mServiceLock.readLock().unlock();
1370         }
1371         return false;
1372     }
1373 
1374     /**
1375      * Returns the Input/Output capability of the device for BLE operations.
1376      *
1377      * @return Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1378      *         {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN}, {@link #IO_CAPABILITY_NONE},
1379      *         {@link #IO_CAPABILITY_KBDISP} or {@link #IO_CAPABILITY_UNKNOWN}.
1380      *
1381      * @hide
1382      */
1383     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
1384     @IoCapability
getLeIoCapability()1385     public int getLeIoCapability() {
1386         if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1387         try {
1388             mServiceLock.readLock().lock();
1389             if (mService != null) return mService.getLeIoCapability();
1390         } catch (RemoteException e) {
1391             Log.e(TAG, e.getMessage(), e);
1392         } finally {
1393             mServiceLock.readLock().unlock();
1394         }
1395         return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
1396     }
1397 
1398     /**
1399      * Sets the Input/Output capability of the device for BLE operations.
1400      *
1401      * <p>Changing the Input/Output capability of a device only takes effect on restarting the
1402      * Bluetooth stack. You would need to restart the stack using {@link BluetoothAdapter#disable()}
1403      * and {@link BluetoothAdapter#enable()} to see the changes.
1404      *
1405      * @param capability Input/Output capability of the device. One of {@link #IO_CAPABILITY_OUT},
1406      *                   {@link #IO_CAPABILITY_IO}, {@link #IO_CAPABILITY_IN},
1407      *                   {@link #IO_CAPABILITY_NONE} or {@link #IO_CAPABILITY_KBDISP}.
1408      *
1409      * @hide
1410      */
1411     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
setLeIoCapability(@oCapability int capability)1412     public boolean setLeIoCapability(@IoCapability int capability) {
1413         if (getState() != STATE_ON) return false;
1414         try {
1415             mServiceLock.readLock().lock();
1416             if (mService != null) return mService.setLeIoCapability(capability);
1417         } catch (RemoteException e) {
1418             Log.e(TAG, e.getMessage(), e);
1419         } finally {
1420             mServiceLock.readLock().unlock();
1421         }
1422         return false;
1423     }
1424 
1425     /**
1426      * Get the current Bluetooth scan mode of the local Bluetooth adapter.
1427      * <p>The Bluetooth scan mode determines if the local adapter is
1428      * connectable and/or discoverable from remote Bluetooth devices.
1429      * <p>Possible values are:
1430      * {@link #SCAN_MODE_NONE},
1431      * {@link #SCAN_MODE_CONNECTABLE},
1432      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
1433      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1434      * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1435      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1436      * to get the updated value.
1437      *
1438      * @return scan mode
1439      */
1440     @RequiresPermission(Manifest.permission.BLUETOOTH)
1441     @ScanMode
getScanMode()1442     public int getScanMode() {
1443         if (getState() != STATE_ON) {
1444             return SCAN_MODE_NONE;
1445         }
1446         try {
1447             mServiceLock.readLock().lock();
1448             if (mService != null) {
1449                 return mService.getScanMode();
1450             }
1451         } catch (RemoteException e) {
1452             Log.e(TAG, "", e);
1453         } finally {
1454             mServiceLock.readLock().unlock();
1455         }
1456         return SCAN_MODE_NONE;
1457     }
1458 
1459     /**
1460      * Set the Bluetooth scan mode of the local Bluetooth adapter.
1461      * <p>The Bluetooth scan mode determines if the local adapter is
1462      * connectable and/or discoverable from remote Bluetooth devices.
1463      * <p>For privacy reasons, discoverable mode is automatically turned off
1464      * after <code>duration</code> seconds. For example, 120 seconds should be
1465      * enough for a remote device to initiate and complete its discovery
1466      * process.
1467      * <p>Valid scan mode values are:
1468      * {@link #SCAN_MODE_NONE},
1469      * {@link #SCAN_MODE_CONNECTABLE},
1470      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
1471      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1472      * will return false. After turning on Bluetooth,
1473      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1474      * to get the updated value.
1475      * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
1476      * <p>Applications cannot set the scan mode. They should use
1477      * <code>startActivityForResult(
1478      * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1479      * </code>instead.
1480      *
1481      * @param mode valid scan mode
1482      * @param duration time in seconds to apply scan mode, only used for {@link
1483      * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
1484      * @return true if the scan mode was set, false otherwise
1485      * @hide
1486      */
1487     @UnsupportedAppUsage
setScanMode(@canMode int mode, int duration)1488     public boolean setScanMode(@ScanMode int mode, int duration) {
1489         if (getState() != STATE_ON) {
1490             return false;
1491         }
1492         try {
1493             mServiceLock.readLock().lock();
1494             if (mService != null) {
1495                 return mService.setScanMode(mode, duration);
1496             }
1497         } catch (RemoteException e) {
1498             Log.e(TAG, "", e);
1499         } finally {
1500             mServiceLock.readLock().unlock();
1501         }
1502         return false;
1503     }
1504 
1505     /** @hide */
1506     @UnsupportedAppUsage
setScanMode(int mode)1507     public boolean setScanMode(int mode) {
1508         if (getState() != STATE_ON) {
1509             return false;
1510         }
1511         /* getDiscoverableTimeout() to use the latest from NV than use 0 */
1512         return setScanMode(mode, getDiscoverableTimeout());
1513     }
1514 
1515     /** @hide */
1516     @UnsupportedAppUsage
getDiscoverableTimeout()1517     public int getDiscoverableTimeout() {
1518         if (getState() != STATE_ON) {
1519             return -1;
1520         }
1521         try {
1522             mServiceLock.readLock().lock();
1523             if (mService != null) {
1524                 return mService.getDiscoverableTimeout();
1525             }
1526         } catch (RemoteException e) {
1527             Log.e(TAG, "", e);
1528         } finally {
1529             mServiceLock.readLock().unlock();
1530         }
1531         return -1;
1532     }
1533 
1534     /** @hide */
1535     @UnsupportedAppUsage
setDiscoverableTimeout(int timeout)1536     public void setDiscoverableTimeout(int timeout) {
1537         if (getState() != STATE_ON) {
1538             return;
1539         }
1540         try {
1541             mServiceLock.readLock().lock();
1542             if (mService != null) {
1543                 mService.setDiscoverableTimeout(timeout);
1544             }
1545         } catch (RemoteException e) {
1546             Log.e(TAG, "", e);
1547         } finally {
1548             mServiceLock.readLock().unlock();
1549         }
1550     }
1551 
1552     /**
1553      * Get the end time of the latest remote device discovery process.
1554      *
1555      * @return the latest time that the bluetooth adapter was/will be in discovery mode, in
1556      * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has
1557      * been called recently.
1558      * @hide
1559      */
getDiscoveryEndMillis()1560     public long getDiscoveryEndMillis() {
1561         try {
1562             mServiceLock.readLock().lock();
1563             if (mService != null) {
1564                 return mService.getDiscoveryEndMillis();
1565             }
1566         } catch (RemoteException e) {
1567             Log.e(TAG, "", e);
1568         } finally {
1569             mServiceLock.readLock().unlock();
1570         }
1571         return -1;
1572     }
1573 
1574     /**
1575      * Set the context for this BluetoothAdapter (only called from BluetoothManager)
1576      * @hide
1577      */
setContext(Context context)1578     public void setContext(Context context) {
1579         mContext = context;
1580     }
1581 
getOpPackageName()1582     private String getOpPackageName() {
1583         // Workaround for legacy API for getting a BluetoothAdapter not
1584         // passing a context
1585         if (mContext != null) {
1586             return mContext.getOpPackageName();
1587         }
1588         return ActivityThread.currentOpPackageName();
1589     }
1590 
1591     /**
1592      * Start the remote device discovery process.
1593      * <p>The discovery process usually involves an inquiry scan of about 12
1594      * seconds, followed by a page scan of each new device to retrieve its
1595      * Bluetooth name.
1596      * <p>This is an asynchronous call, it will return immediately. Register
1597      * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1598      * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1599      * discovery starts and completes. Register for {@link
1600      * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1601      * are found.
1602      * <p>Device discovery is a heavyweight procedure. New connections to
1603      * remote Bluetooth devices should not be attempted while discovery is in
1604      * progress, and existing connections will experience limited bandwidth
1605      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1606      * discovery. Discovery is not managed by the Activity,
1607      * but is run as a system service, so an application should always call
1608      * {@link BluetoothAdapter#cancelDiscovery()} even if it
1609      * did not directly request a discovery, just to be sure.
1610      * <p>Device discovery will only find remote devices that are currently
1611      * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1612      * not discoverable by default, and need to be entered into a special mode.
1613      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1614      * will return false. After turning on Bluetooth,
1615      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1616      * to get the updated value.
1617      *
1618      * @return true on success, false on error
1619      */
1620     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
startDiscovery()1621     public boolean startDiscovery() {
1622         if (getState() != STATE_ON) {
1623             return false;
1624         }
1625         try {
1626             mServiceLock.readLock().lock();
1627             if (mService != null) {
1628                 return mService.startDiscovery(getOpPackageName());
1629             }
1630         } catch (RemoteException e) {
1631             Log.e(TAG, "", e);
1632         } finally {
1633             mServiceLock.readLock().unlock();
1634         }
1635         return false;
1636     }
1637 
1638     /**
1639      * Cancel the current device discovery process.
1640      * <p>Because discovery is a heavyweight procedure for the Bluetooth
1641      * adapter, this method should always be called before attempting to connect
1642      * to a remote device with {@link
1643      * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1644      * the  Activity, but is run as a system service, so an application should
1645      * always call cancel discovery even if it did not directly request a
1646      * discovery, just to be sure.
1647      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1648      * will return false. After turning on Bluetooth,
1649      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1650      * to get the updated value.
1651      *
1652      * @return true on success, false on error
1653      */
1654     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
cancelDiscovery()1655     public boolean cancelDiscovery() {
1656         if (getState() != STATE_ON) {
1657             return false;
1658         }
1659         try {
1660             mServiceLock.readLock().lock();
1661             if (mService != null) {
1662                 return mService.cancelDiscovery();
1663             }
1664         } catch (RemoteException e) {
1665             Log.e(TAG, "", e);
1666         } finally {
1667             mServiceLock.readLock().unlock();
1668         }
1669         return false;
1670     }
1671 
1672     /**
1673      * Return true if the local Bluetooth adapter is currently in the device
1674      * discovery process.
1675      * <p>Device discovery is a heavyweight procedure. New connections to
1676      * remote Bluetooth devices should not be attempted while discovery is in
1677      * progress, and existing connections will experience limited bandwidth
1678      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1679      * discovery.
1680      * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1681      * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1682      * starts or completes.
1683      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1684      * will return false. After turning on Bluetooth,
1685      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1686      * to get the updated value.
1687      *
1688      * @return true if discovering
1689      */
1690     @RequiresPermission(Manifest.permission.BLUETOOTH)
isDiscovering()1691     public boolean isDiscovering() {
1692         if (getState() != STATE_ON) {
1693             return false;
1694         }
1695         try {
1696             mServiceLock.readLock().lock();
1697             if (mService != null) {
1698                 return mService.isDiscovering();
1699             }
1700         } catch (RemoteException e) {
1701             Log.e(TAG, "", e);
1702         } finally {
1703             mServiceLock.readLock().unlock();
1704         }
1705         return false;
1706     }
1707 
1708     /**
1709      * Return true if the multi advertisement is supported by the chipset
1710      *
1711      * @return true if Multiple Advertisement feature is supported
1712      */
isMultipleAdvertisementSupported()1713     public boolean isMultipleAdvertisementSupported() {
1714         if (getState() != STATE_ON) {
1715             return false;
1716         }
1717         try {
1718             mServiceLock.readLock().lock();
1719             if (mService != null) {
1720                 return mService.isMultiAdvertisementSupported();
1721             }
1722         } catch (RemoteException e) {
1723             Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
1724         } finally {
1725             mServiceLock.readLock().unlock();
1726         }
1727         return false;
1728     }
1729 
1730     /**
1731      * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1732      *
1733      * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1734      * fetch scan results even when Bluetooth is turned off.<p>
1735      *
1736      * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1737      *
1738      * @hide
1739      */
1740     @SystemApi
isBleScanAlwaysAvailable()1741     public boolean isBleScanAlwaysAvailable() {
1742         try {
1743             return mManagerService.isBleScanAlwaysAvailable();
1744         } catch (RemoteException e) {
1745             Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1746             return false;
1747         }
1748     }
1749 
1750     /**
1751      * Return true if offloaded filters are supported
1752      *
1753      * @return true if chipset supports on-chip filtering
1754      */
isOffloadedFilteringSupported()1755     public boolean isOffloadedFilteringSupported() {
1756         if (!getLeAccess()) {
1757             return false;
1758         }
1759         try {
1760             mServiceLock.readLock().lock();
1761             if (mService != null) {
1762                 return mService.isOffloadedFilteringSupported();
1763             }
1764         } catch (RemoteException e) {
1765             Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
1766         } finally {
1767             mServiceLock.readLock().unlock();
1768         }
1769         return false;
1770     }
1771 
1772     /**
1773      * Return true if offloaded scan batching is supported
1774      *
1775      * @return true if chipset supports on-chip scan batching
1776      */
isOffloadedScanBatchingSupported()1777     public boolean isOffloadedScanBatchingSupported() {
1778         if (!getLeAccess()) {
1779             return false;
1780         }
1781         try {
1782             mServiceLock.readLock().lock();
1783             if (mService != null) {
1784                 return mService.isOffloadedScanBatchingSupported();
1785             }
1786         } catch (RemoteException e) {
1787             Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
1788         } finally {
1789             mServiceLock.readLock().unlock();
1790         }
1791         return false;
1792     }
1793 
1794     /**
1795      * Return true if LE 2M PHY feature is supported.
1796      *
1797      * @return true if chipset supports LE 2M PHY feature
1798      */
isLe2MPhySupported()1799     public boolean isLe2MPhySupported() {
1800         if (!getLeAccess()) {
1801             return false;
1802         }
1803         try {
1804             mServiceLock.readLock().lock();
1805             if (mService != null) {
1806                 return mService.isLe2MPhySupported();
1807             }
1808         } catch (RemoteException e) {
1809             Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
1810         } finally {
1811             mServiceLock.readLock().unlock();
1812         }
1813         return false;
1814     }
1815 
1816     /**
1817      * Return true if LE Coded PHY feature is supported.
1818      *
1819      * @return true if chipset supports LE Coded PHY feature
1820      */
isLeCodedPhySupported()1821     public boolean isLeCodedPhySupported() {
1822         if (!getLeAccess()) {
1823             return false;
1824         }
1825         try {
1826             mServiceLock.readLock().lock();
1827             if (mService != null) {
1828                 return mService.isLeCodedPhySupported();
1829             }
1830         } catch (RemoteException e) {
1831             Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
1832         } finally {
1833             mServiceLock.readLock().unlock();
1834         }
1835         return false;
1836     }
1837 
1838     /**
1839      * Return true if LE Extended Advertising feature is supported.
1840      *
1841      * @return true if chipset supports LE Extended Advertising feature
1842      */
isLeExtendedAdvertisingSupported()1843     public boolean isLeExtendedAdvertisingSupported() {
1844         if (!getLeAccess()) {
1845             return false;
1846         }
1847         try {
1848             mServiceLock.readLock().lock();
1849             if (mService != null) {
1850                 return mService.isLeExtendedAdvertisingSupported();
1851             }
1852         } catch (RemoteException e) {
1853             Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
1854         } finally {
1855             mServiceLock.readLock().unlock();
1856         }
1857         return false;
1858     }
1859 
1860     /**
1861      * Return true if LE Periodic Advertising feature is supported.
1862      *
1863      * @return true if chipset supports LE Periodic Advertising feature
1864      */
isLePeriodicAdvertisingSupported()1865     public boolean isLePeriodicAdvertisingSupported() {
1866         if (!getLeAccess()) {
1867             return false;
1868         }
1869         try {
1870             mServiceLock.readLock().lock();
1871             if (mService != null) {
1872                 return mService.isLePeriodicAdvertisingSupported();
1873             }
1874         } catch (RemoteException e) {
1875             Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
1876         } finally {
1877             mServiceLock.readLock().unlock();
1878         }
1879         return false;
1880     }
1881 
1882     /**
1883      * Return the maximum LE advertising data length in bytes,
1884      * if LE Extended Advertising feature is supported, 0 otherwise.
1885      *
1886      * @return the maximum LE advertising data length.
1887      */
getLeMaximumAdvertisingDataLength()1888     public int getLeMaximumAdvertisingDataLength() {
1889         if (!getLeAccess()) {
1890             return 0;
1891         }
1892         try {
1893             mServiceLock.readLock().lock();
1894             if (mService != null) {
1895                 return mService.getLeMaximumAdvertisingDataLength();
1896             }
1897         } catch (RemoteException e) {
1898             Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
1899         } finally {
1900             mServiceLock.readLock().unlock();
1901         }
1902         return 0;
1903     }
1904 
1905     /**
1906      * Return true if Hearing Aid Profile is supported.
1907      *
1908      * @return true if phone supports Hearing Aid Profile
1909      */
isHearingAidProfileSupported()1910     private boolean isHearingAidProfileSupported() {
1911         try {
1912             return mManagerService.isHearingAidProfileSupported();
1913         } catch (RemoteException e) {
1914             Log.e(TAG, "remote expection when calling isHearingAidProfileSupported", e);
1915             return false;
1916         }
1917     }
1918 
1919     /**
1920      * Get the maximum number of connected audio devices.
1921      *
1922      * @return the maximum number of connected audio devices
1923      * @hide
1924      */
1925     @RequiresPermission(Manifest.permission.BLUETOOTH)
getMaxConnectedAudioDevices()1926     public int getMaxConnectedAudioDevices() {
1927         try {
1928             mServiceLock.readLock().lock();
1929             if (mService != null) {
1930                 return mService.getMaxConnectedAudioDevices();
1931             }
1932         } catch (RemoteException e) {
1933             Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
1934         } finally {
1935             mServiceLock.readLock().unlock();
1936         }
1937         return 1;
1938     }
1939 
1940     /**
1941      * Return true if hardware has entries available for matching beacons
1942      *
1943      * @return true if there are hw entries available for matching beacons
1944      * @hide
1945      */
isHardwareTrackingFiltersAvailable()1946     public boolean isHardwareTrackingFiltersAvailable() {
1947         if (!getLeAccess()) {
1948             return false;
1949         }
1950         try {
1951             IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
1952             if (iGatt == null) {
1953                 // BLE is not supported
1954                 return false;
1955             }
1956             return (iGatt.numHwTrackFiltersAvailable() != 0);
1957         } catch (RemoteException e) {
1958             Log.e(TAG, "", e);
1959         }
1960         return false;
1961     }
1962 
1963     /**
1964      * Return the record of {@link BluetoothActivityEnergyInfo} object that
1965      * has the activity and energy info. This can be used to ascertain what
1966      * the controller has been up to, since the last sample.
1967      *
1968      * @param updateType Type of info, cached vs refreshed.
1969      * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or
1970      * unsupported
1971      * @hide
1972      * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)}
1973      * instead.
1974      */
1975     @Deprecated
getControllerActivityEnergyInfo(int updateType)1976     public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
1977         SynchronousResultReceiver receiver = new SynchronousResultReceiver();
1978         requestControllerActivityEnergyInfo(receiver);
1979         try {
1980             SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
1981             if (result.bundle != null) {
1982                 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1983             }
1984         } catch (TimeoutException e) {
1985             Log.e(TAG, "getControllerActivityEnergyInfo timed out");
1986         }
1987         return null;
1988     }
1989 
1990     /**
1991      * Request the record of {@link BluetoothActivityEnergyInfo} object that
1992      * has the activity and energy info. This can be used to ascertain what
1993      * the controller has been up to, since the last sample.
1994      *
1995      * A null value for the activity info object may be sent if the bluetooth service is
1996      * unreachable or the device does not support reporting such information.
1997      *
1998      * @param result The callback to which to send the activity info.
1999      * @hide
2000      */
requestControllerActivityEnergyInfo(ResultReceiver result)2001     public void requestControllerActivityEnergyInfo(ResultReceiver result) {
2002         try {
2003             mServiceLock.readLock().lock();
2004             if (mService != null) {
2005                 mService.requestActivityInfo(result);
2006                 result = null;
2007             }
2008         } catch (RemoteException e) {
2009             Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
2010         } finally {
2011             mServiceLock.readLock().unlock();
2012             if (result != null) {
2013                 // Only send an immediate result if we failed.
2014                 result.send(0, null);
2015             }
2016         }
2017     }
2018 
2019     /**
2020      * Return the set of {@link BluetoothDevice} objects that are bonded
2021      * (paired) to the local adapter.
2022      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
2023      * will return an empty set. After turning on Bluetooth,
2024      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
2025      * to get the updated value.
2026      *
2027      * @return unmodifiable set of {@link BluetoothDevice}, or null on error
2028      */
2029     @RequiresPermission(Manifest.permission.BLUETOOTH)
getBondedDevices()2030     public Set<BluetoothDevice> getBondedDevices() {
2031         if (getState() != STATE_ON) {
2032             return toDeviceSet(new BluetoothDevice[0]);
2033         }
2034         try {
2035             mServiceLock.readLock().lock();
2036             if (mService != null) {
2037                 return toDeviceSet(mService.getBondedDevices());
2038             }
2039             return toDeviceSet(new BluetoothDevice[0]);
2040         } catch (RemoteException e) {
2041             Log.e(TAG, "", e);
2042         } finally {
2043             mServiceLock.readLock().unlock();
2044         }
2045         return null;
2046     }
2047 
2048     /**
2049      * Gets the currently supported profiles by the adapter.
2050      *
2051      * <p> This can be used to check whether a profile is supported before attempting
2052      * to connect to its respective proxy.
2053      *
2054      * @return a list of integers indicating the ids of supported profiles as defined in {@link
2055      * BluetoothProfile}.
2056      * @hide
2057      */
getSupportedProfiles()2058     public List<Integer> getSupportedProfiles() {
2059         final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
2060 
2061         try {
2062             synchronized (mManagerCallback) {
2063                 if (mService != null) {
2064                     final long supportedProfilesBitMask = mService.getSupportedProfiles();
2065 
2066                     for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
2067                         if ((supportedProfilesBitMask & (1 << i)) != 0) {
2068                             supportedProfiles.add(i);
2069                         }
2070                     }
2071                 } else {
2072                     // Bluetooth is disabled. Just fill in known supported Profiles
2073                     if (isHearingAidProfileSupported()) {
2074                         supportedProfiles.add(BluetoothProfile.HEARING_AID);
2075                     }
2076                 }
2077             }
2078         } catch (RemoteException e) {
2079             Log.e(TAG, "getSupportedProfiles:", e);
2080         }
2081         return supportedProfiles;
2082     }
2083 
2084     /**
2085      * Get the current connection state of the local Bluetooth adapter.
2086      * This can be used to check whether the local Bluetooth adapter is connected
2087      * to any profile of any other remote Bluetooth Device.
2088      *
2089      * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
2090      * intent to get the connection state of the adapter.
2091      *
2092      * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link
2093      * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
2094      * @hide
2095      */
2096     @UnsupportedAppUsage
getConnectionState()2097     public int getConnectionState() {
2098         if (getState() != STATE_ON) {
2099             return BluetoothAdapter.STATE_DISCONNECTED;
2100         }
2101         try {
2102             mServiceLock.readLock().lock();
2103             if (mService != null) {
2104                 return mService.getAdapterConnectionState();
2105             }
2106         } catch (RemoteException e) {
2107             Log.e(TAG, "getConnectionState:", e);
2108         } finally {
2109             mServiceLock.readLock().unlock();
2110         }
2111         return BluetoothAdapter.STATE_DISCONNECTED;
2112     }
2113 
2114     /**
2115      * Get the current connection state of a profile.
2116      * This function can be used to check whether the local Bluetooth adapter
2117      * is connected to any remote device for a specific profile.
2118      * Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
2119      *
2120      * <p> Return value can be one of
2121      * {@link BluetoothProfile#STATE_DISCONNECTED},
2122      * {@link BluetoothProfile#STATE_CONNECTING},
2123      * {@link BluetoothProfile#STATE_CONNECTED},
2124      * {@link BluetoothProfile#STATE_DISCONNECTING}
2125      */
2126     @RequiresPermission(Manifest.permission.BLUETOOTH)
getProfileConnectionState(int profile)2127     public int getProfileConnectionState(int profile) {
2128         if (getState() != STATE_ON) {
2129             return BluetoothProfile.STATE_DISCONNECTED;
2130         }
2131         try {
2132             mServiceLock.readLock().lock();
2133             if (mService != null) {
2134                 return mService.getProfileConnectionState(profile);
2135             }
2136         } catch (RemoteException e) {
2137             Log.e(TAG, "getProfileConnectionState:", e);
2138         } finally {
2139             mServiceLock.readLock().unlock();
2140         }
2141         return BluetoothProfile.STATE_DISCONNECTED;
2142     }
2143 
2144     /**
2145      * Create a listening, secure RFCOMM Bluetooth socket.
2146      * <p>A remote device connecting to this socket will be authenticated and
2147      * communication on this socket will be encrypted.
2148      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2149      * connections from a listening {@link BluetoothServerSocket}.
2150      * <p>Valid RFCOMM channels are in range 1 to 30.
2151      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
2152      *
2153      * @param channel RFCOMM channel to listen on
2154      * @return a listening RFCOMM BluetoothServerSocket
2155      * @throws IOException on error, for example Bluetooth not available, or insufficient
2156      * permissions, or channel in use.
2157      * @hide
2158      */
listenUsingRfcommOn(int channel)2159     public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
2160         return listenUsingRfcommOn(channel, false, false);
2161     }
2162 
2163     /**
2164      * Create a listening, secure RFCOMM Bluetooth socket.
2165      * <p>A remote device connecting to this socket will be authenticated and
2166      * communication on this socket will be encrypted.
2167      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2168      * connections from a listening {@link BluetoothServerSocket}.
2169      * <p>Valid RFCOMM channels are in range 1 to 30.
2170      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
2171      * <p>To auto assign a channel without creating a SDP record use
2172      * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
2173      *
2174      * @param channel RFCOMM channel to listen on
2175      * @param mitm enforce man-in-the-middle protection for authentication.
2176      * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2177      * connections.
2178      * @return a listening RFCOMM BluetoothServerSocket
2179      * @throws IOException on error, for example Bluetooth not available, or insufficient
2180      * permissions, or channel in use.
2181      * @hide
2182      */
2183     @UnsupportedAppUsage
listenUsingRfcommOn(int channel, boolean mitm, boolean min16DigitPin)2184     public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
2185             boolean min16DigitPin) throws IOException {
2186         BluetoothServerSocket socket =
2187                 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm,
2188                         min16DigitPin);
2189         int errno = socket.mSocket.bindListen();
2190         if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
2191             socket.setChannel(socket.mSocket.getPort());
2192         }
2193         if (errno != 0) {
2194             //TODO(BT): Throw the same exception error code
2195             // that the previous code was using.
2196             //socket.mSocket.throwErrnoNative(errno);
2197             throw new IOException("Error: " + errno);
2198         }
2199         return socket;
2200     }
2201 
2202     /**
2203      * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
2204      * <p>A remote device connecting to this socket will be authenticated and
2205      * communication on this socket will be encrypted.
2206      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2207      * connections from a listening {@link BluetoothServerSocket}.
2208      * <p>The system will assign an unused RFCOMM channel to listen on.
2209      * <p>The system will also register a Service Discovery
2210      * Protocol (SDP) record with the local SDP server containing the specified
2211      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2212      * can use the same UUID to query our SDP server and discover which channel
2213      * to connect to. This SDP record will be removed when this socket is
2214      * closed, or if this application closes unexpectedly.
2215      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2216      * connect to this socket from another device using the same {@link UUID}.
2217      *
2218      * @param name service name for SDP record
2219      * @param uuid uuid for SDP record
2220      * @return a listening RFCOMM BluetoothServerSocket
2221      * @throws IOException on error, for example Bluetooth not available, or insufficient
2222      * permissions, or channel in use.
2223      */
2224     @RequiresPermission(Manifest.permission.BLUETOOTH)
listenUsingRfcommWithServiceRecord(String name, UUID uuid)2225     public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
2226             throws IOException {
2227         return createNewRfcommSocketAndRecord(name, uuid, true, true);
2228     }
2229 
2230     /**
2231      * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
2232      * <p>The link key is not required to be authenticated, i.e the communication may be
2233      * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
2234      * the link will be encrypted, as encryption is mandartory.
2235      * For legacy devices (pre Bluetooth 2.1 devices) the link will not
2236      * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
2237      * encrypted and authenticated communication channel is desired.
2238      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2239      * connections from a listening {@link BluetoothServerSocket}.
2240      * <p>The system will assign an unused RFCOMM channel to listen on.
2241      * <p>The system will also register a Service Discovery
2242      * Protocol (SDP) record with the local SDP server containing the specified
2243      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2244      * can use the same UUID to query our SDP server and discover which channel
2245      * to connect to. This SDP record will be removed when this socket is
2246      * closed, or if this application closes unexpectedly.
2247      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2248      * connect to this socket from another device using the same {@link UUID}.
2249      *
2250      * @param name service name for SDP record
2251      * @param uuid uuid for SDP record
2252      * @return a listening RFCOMM BluetoothServerSocket
2253      * @throws IOException on error, for example Bluetooth not available, or insufficient
2254      * permissions, or channel in use.
2255      */
2256     @RequiresPermission(Manifest.permission.BLUETOOTH)
listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)2257     public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
2258             throws IOException {
2259         return createNewRfcommSocketAndRecord(name, uuid, false, false);
2260     }
2261 
2262     /**
2263      * Create a listening, encrypted,
2264      * RFCOMM Bluetooth socket with Service Record.
2265      * <p>The link will be encrypted, but the link key is not required to be authenticated
2266      * i.e the communication is vulnerable to Man In the Middle attacks. Use
2267      * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
2268      * <p> Use this socket if authentication of link key is not possible.
2269      * For example, for Bluetooth 2.1 devices, if any of the devices does not have
2270      * an input and output capability or just has the ability to display a numeric key,
2271      * a secure socket connection is not possible and this socket can be used.
2272      * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
2273      * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
2274      * For more details, refer to the Security Model section 5.2 (vol 3) of
2275      * Bluetooth Core Specification version 2.1 + EDR.
2276      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
2277      * connections from a listening {@link BluetoothServerSocket}.
2278      * <p>The system will assign an unused RFCOMM channel to listen on.
2279      * <p>The system will also register a Service Discovery
2280      * Protocol (SDP) record with the local SDP server containing the specified
2281      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
2282      * can use the same UUID to query our SDP server and discover which channel
2283      * to connect to. This SDP record will be removed when this socket is
2284      * closed, or if this application closes unexpectedly.
2285      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
2286      * connect to this socket from another device using the same {@link UUID}.
2287      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2288      *
2289      * @param name service name for SDP record
2290      * @param uuid uuid for SDP record
2291      * @return a listening RFCOMM BluetoothServerSocket
2292      * @throws IOException on error, for example Bluetooth not available, or insufficient
2293      * permissions, or channel in use.
2294      * @hide
2295      */
2296     @UnsupportedAppUsage
listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)2297     public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)
2298             throws IOException {
2299         return createNewRfcommSocketAndRecord(name, uuid, false, true);
2300     }
2301 
2302 
createNewRfcommSocketAndRecord(String name, UUID uuid, boolean auth, boolean encrypt)2303     private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
2304             boolean auth, boolean encrypt) throws IOException {
2305         BluetoothServerSocket socket;
2306         socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, encrypt,
2307                 new ParcelUuid(uuid));
2308         socket.setServiceName(name);
2309         int errno = socket.mSocket.bindListen();
2310         if (errno != 0) {
2311             //TODO(BT): Throw the same exception error code
2312             // that the previous code was using.
2313             //socket.mSocket.throwErrnoNative(errno);
2314             throw new IOException("Error: " + errno);
2315         }
2316         return socket;
2317     }
2318 
2319     /**
2320      * Construct an unencrypted, unauthenticated, RFCOMM server socket.
2321      * Call #accept to retrieve connections to this socket.
2322      *
2323      * @return An RFCOMM BluetoothServerSocket
2324      * @throws IOException On error, for example Bluetooth not available, or insufficient
2325      * permissions.
2326      * @hide
2327      */
listenUsingInsecureRfcommOn(int port)2328     public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
2329         BluetoothServerSocket socket =
2330                 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, false, port);
2331         int errno = socket.mSocket.bindListen();
2332         if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
2333             socket.setChannel(socket.mSocket.getPort());
2334         }
2335         if (errno != 0) {
2336             //TODO(BT): Throw the same exception error code
2337             // that the previous code was using.
2338             //socket.mSocket.throwErrnoNative(errno);
2339             throw new IOException("Error: " + errno);
2340         }
2341         return socket;
2342     }
2343 
2344     /**
2345      * Construct an encrypted, RFCOMM server socket.
2346      * Call #accept to retrieve connections to this socket.
2347      *
2348      * @return An RFCOMM BluetoothServerSocket
2349      * @throws IOException On error, for example Bluetooth not available, or insufficient
2350      * permissions.
2351      * @hide
2352      */
listenUsingEncryptedRfcommOn(int port)2353     public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port) throws IOException {
2354         BluetoothServerSocket socket =
2355                 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, true, port);
2356         int errno = socket.mSocket.bindListen();
2357         if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
2358             socket.setChannel(socket.mSocket.getPort());
2359         }
2360         if (errno < 0) {
2361             //TODO(BT): Throw the same exception error code
2362             // that the previous code was using.
2363             //socket.mSocket.throwErrnoNative(errno);
2364             throw new IOException("Error: " + errno);
2365         }
2366         return socket;
2367     }
2368 
2369     /**
2370      * Construct a SCO server socket.
2371      * Call #accept to retrieve connections to this socket.
2372      *
2373      * @return A SCO BluetoothServerSocket
2374      * @throws IOException On error, for example Bluetooth not available, or insufficient
2375      * permissions.
2376      * @hide
2377      */
listenUsingScoOn()2378     public static BluetoothServerSocket listenUsingScoOn() throws IOException {
2379         BluetoothServerSocket socket =
2380                 new BluetoothServerSocket(BluetoothSocket.TYPE_SCO, false, false, -1);
2381         int errno = socket.mSocket.bindListen();
2382         if (errno < 0) {
2383             //TODO(BT): Throw the same exception error code
2384             // that the previous code was using.
2385             //socket.mSocket.throwErrnoNative(errno);
2386         }
2387         return socket;
2388     }
2389 
2390     /**
2391      * Construct an encrypted, authenticated, L2CAP server socket.
2392      * Call #accept to retrieve connections to this socket.
2393      * <p>To auto assign a port without creating a SDP record use
2394      * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
2395      *
2396      * @param port the PSM to listen on
2397      * @param mitm enforce man-in-the-middle protection for authentication.
2398      * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2
2399      * connections.
2400      * @return An L2CAP BluetoothServerSocket
2401      * @throws IOException On error, for example Bluetooth not available, or insufficient
2402      * permissions.
2403      * @hide
2404      */
listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)2405     public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
2406             throws IOException {
2407         BluetoothServerSocket socket =
2408                 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, true, true, port, mitm,
2409                         min16DigitPin);
2410         int errno = socket.mSocket.bindListen();
2411         if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
2412             int assignedChannel = socket.mSocket.getPort();
2413             if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel);
2414             socket.setChannel(assignedChannel);
2415         }
2416         if (errno != 0) {
2417             //TODO(BT): Throw the same exception error code
2418             // that the previous code was using.
2419             //socket.mSocket.throwErrnoNative(errno);
2420             throw new IOException("Error: " + errno);
2421         }
2422         return socket;
2423     }
2424 
2425     /**
2426      * Construct an encrypted, authenticated, L2CAP server socket.
2427      * Call #accept to retrieve connections to this socket.
2428      * <p>To auto assign a port without creating a SDP record use
2429      * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
2430      *
2431      * @param port the PSM to listen on
2432      * @return An L2CAP BluetoothServerSocket
2433      * @throws IOException On error, for example Bluetooth not available, or insufficient
2434      * permissions.
2435      * @hide
2436      */
listenUsingL2capOn(int port)2437     public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
2438         return listenUsingL2capOn(port, false, false);
2439     }
2440 
2441 
2442     /**
2443      * Construct an insecure L2CAP server socket.
2444      * Call #accept to retrieve connections to this socket.
2445      * <p>To auto assign a port without creating a SDP record use
2446      * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
2447      *
2448      * @param port the PSM to listen on
2449      * @return An L2CAP BluetoothServerSocket
2450      * @throws IOException On error, for example Bluetooth not available, or insufficient
2451      * permissions.
2452      * @hide
2453      */
listenUsingInsecureL2capOn(int port)2454     public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
2455         Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
2456         BluetoothServerSocket socket =
2457                 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false,
2458                                           false);
2459         int errno = socket.mSocket.bindListen();
2460         if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
2461             int assignedChannel = socket.mSocket.getPort();
2462             if (DBG) {
2463                 Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to "
2464                         + assignedChannel);
2465             }
2466             socket.setChannel(assignedChannel);
2467         }
2468         if (errno != 0) {
2469             //TODO(BT): Throw the same exception error code
2470             // that the previous code was using.
2471             //socket.mSocket.throwErrnoNative(errno);
2472             throw new IOException("Error: " + errno);
2473         }
2474         return socket;
2475 
2476     }
2477 
2478     /**
2479      * Read the local Out of Band Pairing Data
2480      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2481      *
2482      * @return Pair<byte[], byte[]> of Hash and Randomizer
2483      * @hide
2484      */
readOutOfBandData()2485     public Pair<byte[], byte[]> readOutOfBandData() {
2486         return null;
2487     }
2488 
2489     /**
2490      * Get the profile proxy object associated with the profile.
2491      *
2492      * <p>Profile can be one of {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP},
2493      * {@link BluetoothProfile#GATT}, {@link BluetoothProfile#HEARING_AID}, or {@link
2494      * BluetoothProfile#GATT_SERVER}. Clients must implement {@link
2495      * BluetoothProfile.ServiceListener} to get notified of the connection status and to get the
2496      * proxy object.
2497      *
2498      * @param context Context of the application
2499      * @param listener The service Listener for connection callbacks.
2500      * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET},
2501      * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, {@link
2502      * BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#GATT_SERVER}.
2503      * @return true on success, false on error
2504      */
getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile)2505     public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
2506             int profile) {
2507         if (context == null || listener == null) {
2508             return false;
2509         }
2510 
2511         if (profile == BluetoothProfile.HEADSET) {
2512             BluetoothHeadset headset = new BluetoothHeadset(context, listener);
2513             return true;
2514         } else if (profile == BluetoothProfile.A2DP) {
2515             BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
2516             return true;
2517         } else if (profile == BluetoothProfile.A2DP_SINK) {
2518             BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
2519             return true;
2520         } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
2521             BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
2522             return true;
2523         } else if (profile == BluetoothProfile.HID_HOST) {
2524             BluetoothHidHost iDev = new BluetoothHidHost(context, listener);
2525             return true;
2526         } else if (profile == BluetoothProfile.PAN) {
2527             BluetoothPan pan = new BluetoothPan(context, listener);
2528             return true;
2529         } else if (profile == BluetoothProfile.HEALTH) {
2530             Log.e(TAG, "getProfileProxy(): BluetoothHealth is deprecated");
2531             return false;
2532         } else if (profile == BluetoothProfile.MAP) {
2533             BluetoothMap map = new BluetoothMap(context, listener);
2534             return true;
2535         } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
2536             BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
2537             return true;
2538         } else if (profile == BluetoothProfile.SAP) {
2539             BluetoothSap sap = new BluetoothSap(context, listener);
2540             return true;
2541         } else if (profile == BluetoothProfile.PBAP_CLIENT) {
2542             BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
2543             return true;
2544         } else if (profile == BluetoothProfile.MAP_CLIENT) {
2545             BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
2546             return true;
2547         } else if (profile == BluetoothProfile.HID_DEVICE) {
2548             BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener);
2549             return true;
2550         } else if (profile == BluetoothProfile.HEARING_AID) {
2551             if (isHearingAidProfileSupported()) {
2552                 BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener);
2553                 return true;
2554             }
2555             return false;
2556         } else {
2557             return false;
2558         }
2559     }
2560 
2561     /**
2562      * Close the connection of the profile proxy to the Service.
2563      *
2564      * <p> Clients should call this when they are no longer using
2565      * the proxy obtained from {@link #getProfileProxy}.
2566      * Profile can be one of  {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}
2567      *
2568      * @param profile
2569      * @param proxy Profile proxy object
2570      */
closeProfileProxy(int profile, BluetoothProfile proxy)2571     public void closeProfileProxy(int profile, BluetoothProfile proxy) {
2572         if (proxy == null) {
2573             return;
2574         }
2575 
2576         switch (profile) {
2577             case BluetoothProfile.HEADSET:
2578                 BluetoothHeadset headset = (BluetoothHeadset) proxy;
2579                 headset.close();
2580                 break;
2581             case BluetoothProfile.A2DP:
2582                 BluetoothA2dp a2dp = (BluetoothA2dp) proxy;
2583                 a2dp.close();
2584                 break;
2585             case BluetoothProfile.A2DP_SINK:
2586                 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy;
2587                 a2dpSink.close();
2588                 break;
2589             case BluetoothProfile.AVRCP_CONTROLLER:
2590                 BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy;
2591                 avrcp.close();
2592                 break;
2593             case BluetoothProfile.HID_HOST:
2594                 BluetoothHidHost iDev = (BluetoothHidHost) proxy;
2595                 iDev.close();
2596                 break;
2597             case BluetoothProfile.PAN:
2598                 BluetoothPan pan = (BluetoothPan) proxy;
2599                 pan.close();
2600                 break;
2601             case BluetoothProfile.GATT:
2602                 BluetoothGatt gatt = (BluetoothGatt) proxy;
2603                 gatt.close();
2604                 break;
2605             case BluetoothProfile.GATT_SERVER:
2606                 BluetoothGattServer gattServer = (BluetoothGattServer) proxy;
2607                 gattServer.close();
2608                 break;
2609             case BluetoothProfile.MAP:
2610                 BluetoothMap map = (BluetoothMap) proxy;
2611                 map.close();
2612                 break;
2613             case BluetoothProfile.HEADSET_CLIENT:
2614                 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy;
2615                 headsetClient.close();
2616                 break;
2617             case BluetoothProfile.SAP:
2618                 BluetoothSap sap = (BluetoothSap) proxy;
2619                 sap.close();
2620                 break;
2621             case BluetoothProfile.PBAP_CLIENT:
2622                 BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy;
2623                 pbapClient.close();
2624                 break;
2625             case BluetoothProfile.MAP_CLIENT:
2626                 BluetoothMapClient mapClient = (BluetoothMapClient) proxy;
2627                 mapClient.close();
2628                 break;
2629             case BluetoothProfile.HID_DEVICE:
2630                 BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy;
2631                 hidDevice.close();
2632                 break;
2633             case BluetoothProfile.HEARING_AID:
2634                 BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy;
2635                 hearingAid.close();
2636         }
2637     }
2638 
2639     private final IBluetoothManagerCallback mManagerCallback =
2640             new IBluetoothManagerCallback.Stub() {
2641                 public void onBluetoothServiceUp(IBluetooth bluetoothService) {
2642                     if (DBG) {
2643                         Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
2644                     }
2645 
2646                     mServiceLock.writeLock().lock();
2647                     mService = bluetoothService;
2648                     mServiceLock.writeLock().unlock();
2649 
2650                     synchronized (mProxyServiceStateCallbacks) {
2651                         for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2652                             try {
2653                                 if (cb != null) {
2654                                     cb.onBluetoothServiceUp(bluetoothService);
2655                                 } else {
2656                                     Log.d(TAG, "onBluetoothServiceUp: cb is null!");
2657                                 }
2658                             } catch (Exception e) {
2659                                 Log.e(TAG, "", e);
2660                             }
2661                         }
2662                     }
2663                     synchronized (sMetadataListeners) {
2664                         sMetadataListeners.forEach((device, pair) -> {
2665                             try {
2666                                 mService.registerMetadataListener(sBluetoothMetadataListener,
2667                                         device);
2668                             } catch (RemoteException e) {
2669                                 Log.e(TAG, "Failed to register metadata listener", e);
2670                             }
2671                         });
2672                     }
2673                 }
2674 
2675                 public void onBluetoothServiceDown() {
2676                     if (DBG) {
2677                         Log.d(TAG, "onBluetoothServiceDown: " + mService);
2678                     }
2679 
2680                     try {
2681                         mServiceLock.writeLock().lock();
2682                         mService = null;
2683                         if (mLeScanClients != null) {
2684                             mLeScanClients.clear();
2685                         }
2686                         if (sBluetoothLeAdvertiser != null) {
2687                             sBluetoothLeAdvertiser.cleanup();
2688                         }
2689                         if (sBluetoothLeScanner != null) {
2690                             sBluetoothLeScanner.cleanup();
2691                         }
2692                     } finally {
2693                         mServiceLock.writeLock().unlock();
2694                     }
2695 
2696                     synchronized (mProxyServiceStateCallbacks) {
2697                         for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) {
2698                             try {
2699                                 if (cb != null) {
2700                                     cb.onBluetoothServiceDown();
2701                                 } else {
2702                                     Log.d(TAG, "onBluetoothServiceDown: cb is null!");
2703                                 }
2704                             } catch (Exception e) {
2705                                 Log.e(TAG, "", e);
2706                             }
2707                         }
2708                     }
2709                 }
2710 
2711                 public void onBrEdrDown() {
2712                     if (VDBG) {
2713                         Log.i(TAG, "onBrEdrDown: " + mService);
2714                     }
2715                 }
2716             };
2717 
2718     /**
2719      * Enable the Bluetooth Adapter, but don't auto-connect devices
2720      * and don't persist state. Only for use by system applications.
2721      *
2722      * @hide
2723      */
2724     @SystemApi
2725     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
enableNoAutoConnect()2726     public boolean enableNoAutoConnect() {
2727         if (isEnabled()) {
2728             if (DBG) {
2729                 Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
2730             }
2731             return true;
2732         }
2733         try {
2734             return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
2735         } catch (RemoteException e) {
2736             Log.e(TAG, "", e);
2737         }
2738         return false;
2739     }
2740 
2741     /**
2742      * Enable control of the Bluetooth Adapter for a single application.
2743      *
2744      * <p>Some applications need to use Bluetooth for short periods of time to
2745      * transfer data but don't want all the associated implications like
2746      * automatic connection to headsets etc.
2747      *
2748      * <p> Multiple applications can call this. This is reference counted and
2749      * Bluetooth disabled only when no one else is using it. There will be no UI
2750      * shown to the user while bluetooth is being enabled. Any user action will
2751      * override this call. For example, if user wants Bluetooth on and the last
2752      * user of this API wanted to disable Bluetooth, Bluetooth will not be
2753      * turned off.
2754      *
2755      * <p> This API is only meant to be used by internal applications. Third
2756      * party applications but use {@link #enable} and {@link #disable} APIs.
2757      *
2758      * <p> If this API returns true, it means the callback will be called.
2759      * The callback will be called with the current state of Bluetooth.
2760      * If the state is not what was requested, an internal error would be the
2761      * reason. If Bluetooth is already on and if this function is called to turn
2762      * it on, the api will return true and a callback will be called.
2763      *
2764      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2765      *
2766      * @param on True for on, false for off.
2767      * @param callback The callback to notify changes to the state.
2768      * @hide
2769      */
changeApplicationBluetoothState(boolean on, BluetoothStateChangeCallback callback)2770     public boolean changeApplicationBluetoothState(boolean on,
2771             BluetoothStateChangeCallback callback) {
2772         return false;
2773     }
2774 
2775     /**
2776      * @hide
2777      */
2778     public interface BluetoothStateChangeCallback {
2779         /**
2780          * @hide
2781          */
onBluetoothStateChange(boolean on)2782         void onBluetoothStateChange(boolean on);
2783     }
2784 
2785     /**
2786      * @hide
2787      */
2788     public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
2789         private BluetoothStateChangeCallback mCallback;
2790 
StateChangeCallbackWrapper(BluetoothStateChangeCallback callback)2791         StateChangeCallbackWrapper(BluetoothStateChangeCallback callback) {
2792             mCallback = callback;
2793         }
2794 
2795         @Override
onBluetoothStateChange(boolean on)2796         public void onBluetoothStateChange(boolean on) {
2797             mCallback.onBluetoothStateChange(on);
2798         }
2799     }
2800 
toDeviceSet(BluetoothDevice[] devices)2801     private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
2802         Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
2803         return Collections.unmodifiableSet(deviceSet);
2804     }
2805 
finalize()2806     protected void finalize() throws Throwable {
2807         try {
2808             mManagerService.unregisterAdapter(mManagerCallback);
2809         } catch (RemoteException e) {
2810             Log.e(TAG, "", e);
2811         } finally {
2812             super.finalize();
2813         }
2814     }
2815 
2816 
2817     /**
2818      * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
2819      * <p>Alphabetic characters must be uppercase to be valid.
2820      *
2821      * @param address Bluetooth address as string
2822      * @return true if the address is valid, false otherwise
2823      */
checkBluetoothAddress(String address)2824     public static boolean checkBluetoothAddress(String address) {
2825         if (address == null || address.length() != ADDRESS_LENGTH) {
2826             return false;
2827         }
2828         for (int i = 0; i < ADDRESS_LENGTH; i++) {
2829             char c = address.charAt(i);
2830             switch (i % 3) {
2831                 case 0:
2832                 case 1:
2833                     if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
2834                         // hex character, OK
2835                         break;
2836                     }
2837                     return false;
2838                 case 2:
2839                     if (c == ':') {
2840                         break;  // OK
2841                     }
2842                     return false;
2843             }
2844         }
2845         return true;
2846     }
2847 
2848     @UnsupportedAppUsage
getBluetoothManager()2849     /*package*/ IBluetoothManager getBluetoothManager() {
2850         return mManagerService;
2851     }
2852 
2853     private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks =
2854             new ArrayList<IBluetoothManagerCallback>();
2855 
2856     @UnsupportedAppUsage
getBluetoothService(IBluetoothManagerCallback cb)2857     /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
2858         synchronized (mProxyServiceStateCallbacks) {
2859             if (cb == null) {
2860                 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
2861             } else if (!mProxyServiceStateCallbacks.contains(cb)) {
2862                 mProxyServiceStateCallbacks.add(cb);
2863             }
2864         }
2865         return mService;
2866     }
2867 
removeServiceStateCallback(IBluetoothManagerCallback cb)2868     /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
2869         synchronized (mProxyServiceStateCallbacks) {
2870             mProxyServiceStateCallbacks.remove(cb);
2871         }
2872     }
2873 
2874     /**
2875      * Callback interface used to deliver LE scan results.
2876      *
2877      * @see #startLeScan(LeScanCallback)
2878      * @see #startLeScan(UUID[], LeScanCallback)
2879      */
2880     public interface LeScanCallback {
2881         /**
2882          * Callback reporting an LE device found during a device scan initiated
2883          * by the {@link BluetoothAdapter#startLeScan} function.
2884          *
2885          * @param device Identifies the remote device
2886          * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0
2887          * if no RSSI value is available.
2888          * @param scanRecord The content of the advertisement record offered by the remote device.
2889          */
onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)2890         void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
2891     }
2892 
2893     /**
2894      * Starts a scan for Bluetooth LE devices.
2895      *
2896      * <p>Results of the scan are reported using the
2897      * {@link LeScanCallback#onLeScan} callback.
2898      *
2899      * @param callback the callback LE scan results are delivered
2900      * @return true, if the scan was started successfully
2901      * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
2902      * instead.
2903      */
2904     @Deprecated
2905     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
startLeScan(LeScanCallback callback)2906     public boolean startLeScan(LeScanCallback callback) {
2907         return startLeScan(null, callback);
2908     }
2909 
2910     /**
2911      * Starts a scan for Bluetooth LE devices, looking for devices that
2912      * advertise given services.
2913      *
2914      * <p>Devices which advertise all specified services are reported using the
2915      * {@link LeScanCallback#onLeScan} callback.
2916      *
2917      * @param serviceUuids Array of services to look for
2918      * @param callback the callback LE scan results are delivered
2919      * @return true, if the scan was started successfully
2920      * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
2921      * instead.
2922      */
2923     @Deprecated
2924     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
startLeScan(final UUID[] serviceUuids, final LeScanCallback callback)2925     public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
2926         if (DBG) {
2927             Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
2928         }
2929         if (callback == null) {
2930             if (DBG) {
2931                 Log.e(TAG, "startLeScan: null callback");
2932             }
2933             return false;
2934         }
2935         BluetoothLeScanner scanner = getBluetoothLeScanner();
2936         if (scanner == null) {
2937             if (DBG) {
2938                 Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
2939             }
2940             return false;
2941         }
2942 
2943         synchronized (mLeScanClients) {
2944             if (mLeScanClients.containsKey(callback)) {
2945                 if (DBG) {
2946                     Log.e(TAG, "LE Scan has already started");
2947                 }
2948                 return false;
2949             }
2950 
2951             try {
2952                 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
2953                 if (iGatt == null) {
2954                     // BLE is not supported
2955                     return false;
2956                 }
2957 
2958                 ScanCallback scanCallback = new ScanCallback() {
2959                     @Override
2960                     public void onScanResult(int callbackType, ScanResult result) {
2961                         if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
2962                             // Should not happen.
2963                             Log.e(TAG, "LE Scan has already started");
2964                             return;
2965                         }
2966                         ScanRecord scanRecord = result.getScanRecord();
2967                         if (scanRecord == null) {
2968                             return;
2969                         }
2970                         if (serviceUuids != null) {
2971                             List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
2972                             for (UUID uuid : serviceUuids) {
2973                                 uuids.add(new ParcelUuid(uuid));
2974                             }
2975                             List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
2976                             if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
2977                                 if (DBG) {
2978                                     Log.d(TAG, "uuids does not match");
2979                                 }
2980                                 return;
2981                             }
2982                         }
2983                         callback.onLeScan(result.getDevice(), result.getRssi(),
2984                                 scanRecord.getBytes());
2985                     }
2986                 };
2987                 ScanSettings settings = new ScanSettings.Builder().setCallbackType(
2988                         ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
2989                         .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
2990                         .build();
2991 
2992                 List<ScanFilter> filters = new ArrayList<ScanFilter>();
2993                 if (serviceUuids != null && serviceUuids.length > 0) {
2994                     // Note scan filter does not support matching an UUID array so we put one
2995                     // UUID to hardware and match the whole array in callback.
2996                     ScanFilter filter =
2997                             new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuids[0]))
2998                                     .build();
2999                     filters.add(filter);
3000                 }
3001                 scanner.startScan(filters, settings, scanCallback);
3002 
3003                 mLeScanClients.put(callback, scanCallback);
3004                 return true;
3005 
3006             } catch (RemoteException e) {
3007                 Log.e(TAG, "", e);
3008             }
3009         }
3010         return false;
3011     }
3012 
3013     /**
3014      * Stops an ongoing Bluetooth LE device scan.
3015      *
3016      * @param callback used to identify which scan to stop must be the same handle used to start the
3017      * scan
3018      * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
3019      */
3020     @Deprecated
3021     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
stopLeScan(LeScanCallback callback)3022     public void stopLeScan(LeScanCallback callback) {
3023         if (DBG) {
3024             Log.d(TAG, "stopLeScan()");
3025         }
3026         BluetoothLeScanner scanner = getBluetoothLeScanner();
3027         if (scanner == null) {
3028             return;
3029         }
3030         synchronized (mLeScanClients) {
3031             ScanCallback scanCallback = mLeScanClients.remove(callback);
3032             if (scanCallback == null) {
3033                 if (DBG) {
3034                     Log.d(TAG, "scan not started yet");
3035                 }
3036                 return;
3037             }
3038             scanner.stopScan(scanCallback);
3039         }
3040     }
3041 
3042     /**
3043      * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
3044      * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen
3045      * for incoming connections. The supported Bluetooth transport is LE only.
3046      * <p>A remote device connecting to this socket will be authenticated and communication on this
3047      * socket will be encrypted.
3048      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3049      * {@link BluetoothServerSocket}.
3050      * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {@link
3051      * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is
3052      * closed, Bluetooth is turned off, or the application exits unexpectedly.
3053      * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3054      * defined and performed by the application.
3055      * <p>Use {@link BluetoothDevice#createL2capChannel(int)} to connect to this server
3056      * socket from another Android device that is given the PSM value.
3057      *
3058      * @return an L2CAP CoC BluetoothServerSocket
3059      * @throws IOException on error, for example Bluetooth not available, or insufficient
3060      * permissions, or unable to start this CoC
3061      */
3062     @RequiresPermission(Manifest.permission.BLUETOOTH)
listenUsingL2capChannel()3063     public @NonNull BluetoothServerSocket listenUsingL2capChannel()
3064             throws IOException {
3065         BluetoothServerSocket socket =
3066                             new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
3067                                       SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3068         int errno = socket.mSocket.bindListen();
3069         if (errno != 0) {
3070             throw new IOException("Error: " + errno);
3071         }
3072 
3073         int assignedPsm = socket.mSocket.getPort();
3074         if (assignedPsm == 0) {
3075             throw new IOException("Error: Unable to assign PSM value");
3076         }
3077         if (DBG) {
3078             Log.d(TAG, "listenUsingL2capChannel: set assigned PSM to "
3079                     + assignedPsm);
3080         }
3081         socket.setChannel(assignedPsm);
3082 
3083         return socket;
3084     }
3085 
3086     /**
3087      * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
3088      * API name, listenUsingL2capChannel.
3089      * @hide
3090      */
3091     @RequiresPermission(Manifest.permission.BLUETOOTH)
listenUsingL2capCoc(int transport)3092     public BluetoothServerSocket listenUsingL2capCoc(int transport)
3093             throws IOException {
3094         Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel");
3095         return listenUsingL2capChannel();
3096     }
3097 
3098     /**
3099      * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
3100      * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
3101      * supported Bluetooth transport is LE only.
3102      * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable
3103      * to man-in-the-middle attacks. Use {@link #listenUsingL2capChannel}, if an encrypted and
3104      * authenticated communication channel is desired.
3105      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening
3106      * {@link BluetoothServerSocket}.
3107      * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value
3108      * can be read from the {@link BluetoothServerSocket#getPsm()} and this value will be released
3109      * when this server socket is closed, Bluetooth is turned off, or the application exits
3110      * unexpectedly.
3111      * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is
3112      * defined and performed by the application.
3113      * <p>Use {@link BluetoothDevice#createInsecureL2capChannel(int)} to connect to this server
3114      * socket from another Android device that is given the PSM value.
3115      *
3116      * @return an L2CAP CoC BluetoothServerSocket
3117      * @throws IOException on error, for example Bluetooth not available, or insufficient
3118      * permissions, or unable to start this CoC
3119      */
3120     @RequiresPermission(Manifest.permission.BLUETOOTH)
listenUsingInsecureL2capChannel()3121     public @NonNull BluetoothServerSocket listenUsingInsecureL2capChannel()
3122             throws IOException {
3123         BluetoothServerSocket socket =
3124                             new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
3125                                       SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false);
3126         int errno = socket.mSocket.bindListen();
3127         if (errno != 0) {
3128             throw new IOException("Error: " + errno);
3129         }
3130 
3131         int assignedPsm = socket.mSocket.getPort();
3132         if (assignedPsm == 0) {
3133             throw new IOException("Error: Unable to assign PSM value");
3134         }
3135         if (DBG) {
3136             Log.d(TAG, "listenUsingInsecureL2capChannel: set assigned PSM to "
3137                     + assignedPsm);
3138         }
3139         socket.setChannel(assignedPsm);
3140 
3141         return socket;
3142     }
3143 
3144     /**
3145      * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
3146      * API name, listenUsingInsecureL2capChannel.
3147      * @hide
3148      */
3149     @RequiresPermission(Manifest.permission.BLUETOOTH)
listenUsingInsecureL2capCoc(int transport)3150     public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
3151             throws IOException {
3152         Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, "
3153                     + "listenUsingInsecureL2capChannel");
3154         return listenUsingInsecureL2capChannel();
3155     }
3156 
3157     /**
3158      * Register a {@link #OnMetadataChangedListener} to receive update about metadata
3159      * changes for this {@link BluetoothDevice}.
3160      * Registration must be done when Bluetooth is ON and will last until
3161      * {@link #removeOnMetadataChangedListener(BluetoothDevice)} is called, even when Bluetooth
3162      * restarted in the middle.
3163      * All input parameters should not be null or {@link NullPointerException} will be triggered.
3164      * The same {@link BluetoothDevice} and {@link #OnMetadataChangedListener} pair can only be
3165      * registered once, double registration would cause {@link IllegalArgumentException}.
3166      *
3167      * @param device {@link BluetoothDevice} that will be registered
3168      * @param executor the executor for listener callback
3169      * @param listener {@link #OnMetadataChangedListener} that will receive asynchronous callbacks
3170      * @return true on success, false on error
3171      * @throws NullPointerException If one of {@code listener}, {@code device} or {@code executor}
3172      * is null.
3173      * @throws IllegalArgumentException The same {@link #OnMetadataChangedListener} and
3174      * {@link BluetoothDevice} are registered twice.
3175      * @hide
3176      */
3177     @SystemApi
3178     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
addOnMetadataChangedListener(@onNull BluetoothDevice device, @NonNull Executor executor, @NonNull OnMetadataChangedListener listener)3179     public boolean addOnMetadataChangedListener(@NonNull BluetoothDevice device,
3180             @NonNull Executor executor, @NonNull OnMetadataChangedListener listener) {
3181         if (DBG) Log.d(TAG, "addOnMetadataChangedListener()");
3182 
3183         final IBluetooth service = mService;
3184         if (service == null) {
3185             Log.e(TAG, "Bluetooth is not enabled. Cannot register metadata listener");
3186             return false;
3187         }
3188         if (listener == null) {
3189             throw new NullPointerException("listener is null");
3190         }
3191         if (device == null) {
3192             throw new NullPointerException("device is null");
3193         }
3194         if (executor == null) {
3195             throw new NullPointerException("executor is null");
3196         }
3197 
3198         synchronized (sMetadataListeners) {
3199             List<Pair<OnMetadataChangedListener, Executor>> listenerList =
3200                     sMetadataListeners.get(device);
3201             if (listenerList == null) {
3202                 // Create new listener/executor list for registeration
3203                 listenerList = new ArrayList<>();
3204                 sMetadataListeners.put(device, listenerList);
3205             } else {
3206                 // Check whether this device was already registed by the lisenter
3207                 if (listenerList.stream().anyMatch((pair) -> (pair.first.equals(listener)))) {
3208                     throw new IllegalArgumentException("listener was already regestered"
3209                             + " for the device");
3210                 }
3211             }
3212 
3213             Pair<OnMetadataChangedListener, Executor> listenerPair = new Pair(listener, executor);
3214             listenerList.add(listenerPair);
3215 
3216             boolean ret = false;
3217             try {
3218                 ret = service.registerMetadataListener(sBluetoothMetadataListener, device);
3219             } catch (RemoteException e) {
3220                 Log.e(TAG, "registerMetadataListener fail", e);
3221             } finally {
3222                 if (!ret) {
3223                     // Remove listener registered earlier when fail.
3224                     listenerList.remove(listenerPair);
3225                     if (listenerList.isEmpty()) {
3226                         // Remove the device if its listener list is empty
3227                         sMetadataListeners.remove(device);
3228                     }
3229                 }
3230             }
3231             return ret;
3232         }
3233     }
3234 
3235     /**
3236      * Unregister a {@link #OnMetadataChangedListener} from a registered {@link BluetoothDevice}.
3237      * Unregistration can be done when Bluetooth is either ON or OFF.
3238      * {@link #addOnMetadataChangedListener(OnMetadataChangedListener, BluetoothDevice, Executor)}
3239      * must be called before unregisteration.
3240      *
3241      * @param device {@link BluetoothDevice} that will be unregistered. It
3242      * should not be null or {@link NullPointerException} will be triggered.
3243      * @param listener {@link OnMetadataChangedListener} that will be unregistered. It
3244      * should not be null or {@link NullPointerException} will be triggered.
3245      * @return true on success, false on error
3246      * @throws NullPointerException If {@code listener} or {@code device} is null.
3247      * @throws IllegalArgumentException If {@code device} has not been registered before.
3248      * @hide
3249      */
3250     @SystemApi
3251     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
removeOnMetadataChangedListener(@onNull BluetoothDevice device, @NonNull OnMetadataChangedListener listener)3252     public boolean removeOnMetadataChangedListener(@NonNull BluetoothDevice device,
3253             @NonNull OnMetadataChangedListener listener) {
3254         if (DBG) Log.d(TAG, "removeOnMetadataChangedListener()");
3255         if (device == null) {
3256             throw new NullPointerException("device is null");
3257         }
3258         if (listener == null) {
3259             throw new NullPointerException("listener is null");
3260         }
3261 
3262         synchronized (sMetadataListeners) {
3263             if (!sMetadataListeners.containsKey(device)) {
3264                 throw new IllegalArgumentException("device was not registered");
3265             }
3266             // Remove issued listener from the registered device
3267             sMetadataListeners.get(device).removeIf((pair) -> (pair.first.equals(listener)));
3268 
3269             if (sMetadataListeners.get(device).isEmpty()) {
3270                 // Unregister to Bluetooth service if all listeners are removed from
3271                 // the registered device
3272                 sMetadataListeners.remove(device);
3273                 final IBluetooth service = mService;
3274                 if (service == null) {
3275                     // Bluetooth is OFF, do nothing to Bluetooth service.
3276                     return true;
3277                 }
3278                 try {
3279                     return service.unregisterMetadataListener(device);
3280                 } catch (RemoteException e) {
3281                     Log.e(TAG, "unregisterMetadataListener fail", e);
3282                     return false;
3283                 }
3284             }
3285         }
3286         return true;
3287     }
3288 
3289     /**
3290      * This interface is used to implement {@link BluetoothAdapter} metadata listener.
3291      * @hide
3292      */
3293     @SystemApi
3294     public interface OnMetadataChangedListener {
3295         /**
3296          * Callback triggered if the metadata of {@link BluetoothDevice} registered in
3297          * {@link #addOnMetadataChangedListener}.
3298          *
3299          * @param device changed {@link BluetoothDevice}.
3300          * @param key changed metadata key, one of BluetoothDevice.METADATA_*.
3301          * @param value the new value of metadata as byte array.
3302          */
onMetadataChanged(@onNull BluetoothDevice device, int key, @Nullable byte[] value)3303         void onMetadataChanged(@NonNull BluetoothDevice device, int key,
3304                 @Nullable byte[] value);
3305     }
3306 }
3307