1 /*
2  * Copyright (C) 2009-2016 The Android Open Source Project
3  * Copyright (C) 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.RequiresPermission;
23 import android.annotation.SdkConstant;
24 import android.annotation.SdkConstant.SdkConstantType;
25 import android.annotation.SystemApi;
26 import android.app.ActivityThread;
27 import android.bluetooth.le.BluetoothLeAdvertiser;
28 import android.bluetooth.le.BluetoothLeScanner;
29 import android.bluetooth.le.PeriodicAdvertisingManager;
30 import android.bluetooth.le.ScanCallback;
31 import android.bluetooth.le.ScanFilter;
32 import android.bluetooth.le.ScanRecord;
33 import android.bluetooth.le.ScanResult;
34 import android.bluetooth.le.ScanSettings;
35 import android.content.Context;
36 import android.os.BatteryStats;
37 import android.os.Binder;
38 import android.os.IBinder;
39 import android.os.ParcelUuid;
40 import android.os.RemoteException;
41 import android.os.ResultReceiver;
42 import android.os.ServiceManager;
43 import android.os.SynchronousResultReceiver;
44 import android.os.SystemProperties;
45 import android.util.Log;
46 import android.util.Pair;
47 
48 import java.io.IOException;
49 import java.lang.annotation.Retention;
50 import java.lang.annotation.RetentionPolicy;
51 import java.util.ArrayList;
52 import java.util.Arrays;
53 import java.util.Collections;
54 import java.util.HashMap;
55 import java.util.HashSet;
56 import java.util.List;
57 import java.util.Locale;
58 import java.util.Map;
59 import java.util.Set;
60 import java.util.UUID;
61 import java.util.concurrent.TimeoutException;
62 import java.util.concurrent.locks.ReentrantReadWriteLock;
63 
64 /**
65  * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
66  * lets you perform fundamental Bluetooth tasks, such as initiate
67  * device discovery, query a list of bonded (paired) devices,
68  * instantiate a {@link BluetoothDevice} using a known MAC address, and create
69  * a {@link BluetoothServerSocket} to listen for connection requests from other
70  * devices, and start a scan for Bluetooth LE devices.
71  *
72  * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth
73  * adapter, when running on JELLY_BEAN_MR1 and below, call the
74  * static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and
75  * higher, call {@link BluetoothManager#getAdapter}.
76  * Fundamentally, this is your starting point for all
77  * Bluetooth actions. Once you have the local adapter, you can get a set of
78  * {@link BluetoothDevice} objects representing all paired devices with
79  * {@link #getBondedDevices()}; start device discovery with
80  * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
81  * listen for incoming connection requests with
82  * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}; or start a scan for
83  * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
84  *
85  * <p>This class is thread safe.
86  *
87  * <p class="note"><strong>Note:</strong>
88  * Most methods require the {@link android.Manifest.permission#BLUETOOTH}
89  * permission and some also require the
90  * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
91  *
92  * <div class="special reference">
93  * <h3>Developer Guides</h3>
94  * <p>
95  *  For more information about using Bluetooth, read the <a href=
96  * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
97  * guide.
98  * </p>
99  * </div>
100  *
101  * {@see BluetoothDevice}
102  * {@see BluetoothServerSocket}
103  */
104 public final class BluetoothAdapter {
105     private static final String TAG = "BluetoothAdapter";
106     private static final boolean DBG = true;
107     private static final boolean VDBG = false;
108 
109     /**
110      * Default MAC address reported to a client that does not have the
111      * android.permission.LOCAL_MAC_ADDRESS permission.
112      *
113      * @hide
114      */
115     public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
116 
117     /**
118      * Sentinel error value for this class. Guaranteed to not equal any other
119      * integer constant in this class. Provided as a convenience for functions
120      * that require a sentinel error value, for example:
121      * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
122      * BluetoothAdapter.ERROR)</code>
123      */
124     public static final int ERROR = Integer.MIN_VALUE;
125 
126     /**
127      * Broadcast Action: The state of the local Bluetooth adapter has been
128      * changed.
129      * <p>For example, Bluetooth has been turned on or off.
130      * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link
131      * #EXTRA_PREVIOUS_STATE} containing the new and old states
132      * respectively.
133      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
134      */
135     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
136     public static final String ACTION_STATE_CHANGED =
137             "android.bluetooth.adapter.action.STATE_CHANGED";
138 
139     /**
140      * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
141      * intents to request the current power state. Possible values are:
142      * {@link #STATE_OFF},
143      * {@link #STATE_TURNING_ON},
144      * {@link #STATE_ON},
145      * {@link #STATE_TURNING_OFF},
146      */
147     public static final String EXTRA_STATE =
148             "android.bluetooth.adapter.extra.STATE";
149     /**
150      * Used as an int extra field in {@link #ACTION_STATE_CHANGED}
151      * intents to request the previous power state. Possible values are:
152      * {@link #STATE_OFF},
153      * {@link #STATE_TURNING_ON},
154      * {@link #STATE_ON},
155      * {@link #STATE_TURNING_OFF}
156      */
157     public static final String EXTRA_PREVIOUS_STATE =
158             "android.bluetooth.adapter.extra.PREVIOUS_STATE";
159 
160     /** @hide */
161     @IntDef({STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON,
162             STATE_BLE_ON, STATE_BLE_TURNING_OFF})
163     @Retention(RetentionPolicy.SOURCE)
164     public @interface AdapterState {}
165 
166     /**
167      * Indicates the local Bluetooth adapter is off.
168      */
169     public static final int STATE_OFF = 10;
170     /**
171      * Indicates the local Bluetooth adapter is turning on. However local
172      * clients should wait for {@link #STATE_ON} before attempting to
173      * use the adapter.
174      */
175     public static final int STATE_TURNING_ON = 11;
176     /**
177      * Indicates the local Bluetooth adapter is on, and ready for use.
178      */
179     public static final int STATE_ON = 12;
180     /**
181      * Indicates the local Bluetooth adapter is turning off. Local clients
182      * should immediately attempt graceful disconnection of any remote links.
183      */
184     public static final int STATE_TURNING_OFF = 13;
185 
186     /**
187      * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on.
188      * @hide
189      */
190     public static final int STATE_BLE_TURNING_ON = 14;
191 
192     /**
193      * Indicates the local Bluetooth adapter is in LE only mode.
194      * @hide
195      */
196     public static final int STATE_BLE_ON = 15;
197 
198     /**
199      * Indicates the local Bluetooth adapter is turning off LE only mode.
200      * @hide
201      */
202     public static final int STATE_BLE_TURNING_OFF = 16;
203 
204     /**
205      * Human-readable string helper for AdapterState
206      * @hide
207      */
nameForState(@dapterState int state)208     public static String nameForState(@AdapterState int state) {
209         switch(state) {
210             case STATE_OFF: return "OFF";
211             case STATE_TURNING_ON: return "TURNING_ON";
212             case STATE_ON: return "ON";
213             case STATE_TURNING_OFF: return "TURNING_OFF";
214             case STATE_BLE_TURNING_ON: return "BLE_TURNING_ON";
215             case STATE_BLE_ON: return "BLE_ON";
216             case STATE_BLE_TURNING_OFF: return "BLE_TURNING_OFF";
217             default: return "?!?!? (" + state + ")";
218         }
219     }
220 
221     /**
222      * Activity Action: Show a system activity that requests discoverable mode.
223      * This activity will also request the user to turn on Bluetooth if it
224      * is not currently enabled.
225      * <p>Discoverable mode is equivalent to {@link
226      * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see
227      * this Bluetooth adapter when they perform a discovery.
228      * <p>For privacy, Android is not discoverable by default.
229      * <p>The sender of this Intent can optionally use extra field {@link
230      * #EXTRA_DISCOVERABLE_DURATION} to request the duration of
231      * discoverability. Currently the default duration is 120 seconds, and
232      * maximum duration is capped at 300 seconds for each request.
233      * <p>Notification of the result of this activity is posted using the
234      * {@link android.app.Activity#onActivityResult} callback. The
235      * <code>resultCode</code>
236      * will be the duration (in seconds) of discoverability or
237      * {@link android.app.Activity#RESULT_CANCELED} if the user rejected
238      * discoverability or an error has occurred.
239      * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED}
240      * for global notification whenever the scan mode changes. For example, an
241      * application can be notified when the device has ended discoverability.
242      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
243      */
244     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
245     public static final String ACTION_REQUEST_DISCOVERABLE =
246             "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
247 
248     /**
249      * Used as an optional int extra field in {@link
250      * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration
251      * for discoverability in seconds. The current default is 120 seconds, and
252      * requests over 300 seconds will be capped. These values could change.
253      */
254     public static final String EXTRA_DISCOVERABLE_DURATION =
255             "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION";
256 
257     /**
258      * Activity Action: Show a system activity that allows the user to turn on
259      * Bluetooth.
260      * <p>This system activity will return once Bluetooth has completed turning
261      * on, or the user has decided not to turn Bluetooth on.
262      * <p>Notification of the result of this activity is posted using the
263      * {@link android.app.Activity#onActivityResult} callback. The
264      * <code>resultCode</code>
265      * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
266      * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
267      * has rejected the request or an error has occurred.
268      * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
269      * for global notification whenever Bluetooth is turned on or off.
270      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
271      */
272     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
273     public static final String ACTION_REQUEST_ENABLE =
274             "android.bluetooth.adapter.action.REQUEST_ENABLE";
275 
276     /**
277      * Activity Action: Show a system activity that allows the user to turn off
278      * Bluetooth. This is used only if permission review is enabled which is for
279      * apps targeting API less than 23 require a permission review before any of
280      * the app's components can run.
281      * <p>This system activity will return once Bluetooth has completed turning
282      * off, or the user has decided not to turn Bluetooth off.
283      * <p>Notification of the result of this activity is posted using the
284      * {@link android.app.Activity#onActivityResult} callback. The
285      * <code>resultCode</code>
286      * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been
287      * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user
288      * has rejected the request or an error has occurred.
289      * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED}
290      * for global notification whenever Bluetooth is turned on or off.
291      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
292      *
293      * @hide
294      */
295     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
296     public static final String ACTION_REQUEST_DISABLE =
297             "android.bluetooth.adapter.action.REQUEST_DISABLE";
298 
299     /**
300      * Activity Action: Show a system activity that allows user to enable BLE scans even when
301      * Bluetooth is turned off.<p>
302      *
303      * Notification of result of this activity is posted using
304      * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be
305      * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or
306      * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an
307      * error occurred.
308      *
309      * @hide
310      */
311     @SystemApi
312     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
313     public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE =
314             "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
315 
316     /**
317      * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter
318      * has changed.
319      * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link
320      * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes
321      * respectively.
322      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
323      */
324     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
325     public static final String ACTION_SCAN_MODE_CHANGED =
326             "android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
327 
328     /**
329      * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
330      * intents to request the current scan mode. Possible values are:
331      * {@link #SCAN_MODE_NONE},
332      * {@link #SCAN_MODE_CONNECTABLE},
333      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
334      */
335     public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE";
336     /**
337      * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
338      * intents to request the previous scan mode. Possible values are:
339      * {@link #SCAN_MODE_NONE},
340      * {@link #SCAN_MODE_CONNECTABLE},
341      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
342      */
343     public static final String EXTRA_PREVIOUS_SCAN_MODE =
344             "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
345 
346     /** @hide */
347     @IntDef({SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE})
348     @Retention(RetentionPolicy.SOURCE)
349     public @interface ScanMode {}
350 
351     /**
352      * Indicates that both inquiry scan and page scan are disabled on the local
353      * Bluetooth adapter. Therefore this device is neither discoverable
354      * nor connectable from remote Bluetooth devices.
355      */
356     public static final int SCAN_MODE_NONE = 20;
357     /**
358      * Indicates that inquiry scan is disabled, but page scan is enabled on the
359      * local Bluetooth adapter. Therefore this device is not discoverable from
360      * remote Bluetooth devices, but is connectable from remote devices that
361      * have previously discovered this device.
362      */
363     public static final int SCAN_MODE_CONNECTABLE = 21;
364     /**
365      * Indicates that both inquiry scan and page scan are enabled on the local
366      * Bluetooth adapter. Therefore this device is both discoverable and
367      * connectable from remote Bluetooth devices.
368      */
369     public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
370 
371     /**
372      * Broadcast Action: The local Bluetooth adapter has started the remote
373      * device discovery process.
374      * <p>This usually involves an inquiry scan of about 12 seconds, followed
375      * by a page scan of each new device to retrieve its Bluetooth name.
376      * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as
377      * remote Bluetooth devices are found.
378      * <p>Device discovery is a heavyweight procedure. New connections to
379      * remote Bluetooth devices should not be attempted while discovery is in
380      * progress, and existing connections will experience limited bandwidth
381      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
382      * discovery.
383      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
384      */
385     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
386     public static final String ACTION_DISCOVERY_STARTED =
387             "android.bluetooth.adapter.action.DISCOVERY_STARTED";
388     /**
389      * Broadcast Action: The local Bluetooth adapter has finished the device
390      * discovery process.
391      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
392      */
393     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
394     public static final String ACTION_DISCOVERY_FINISHED =
395             "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
396 
397     /**
398      * Broadcast Action: The local Bluetooth adapter has changed its friendly
399      * Bluetooth name.
400      * <p>This name is visible to remote Bluetooth devices.
401      * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing
402      * the name.
403      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
404      */
405     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
406     public static final String ACTION_LOCAL_NAME_CHANGED =
407             "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED";
408     /**
409      * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED}
410      * intents to request the local Bluetooth name.
411      */
412     public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
413 
414     /**
415      * Intent used to broadcast the change in connection state of the local
416      * Bluetooth adapter to a profile of the remote device. When the adapter is
417      * not connected to any profiles of any remote devices and it attempts a
418      * connection to a profile this intent will sent. Once connected, this intent
419      * will not be sent for any more connection attempts to any profiles of any
420      * remote device. When the adapter disconnects from the last profile its
421      * connected to of any remote device, this intent will be sent.
422      *
423      * <p> This intent is useful for applications that are only concerned about
424      * whether the local adapter is connected to any profile of any device and
425      * are not really concerned about which profile. For example, an application
426      * which displays an icon to display whether Bluetooth is connected or not
427      * can use this intent.
428      *
429      * <p>This intent will have 3 extras:
430      * {@link #EXTRA_CONNECTION_STATE} - The current connection state.
431      * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state.
432      * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device.
433      *
434      * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE}
435      * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
436      * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
437      *
438      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
439      */
440     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
441     public static final String ACTION_CONNECTION_STATE_CHANGED =
442         "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
443 
444     /**
445      * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
446      *
447      * This extra represents the current connection state.
448      */
449     public static final String EXTRA_CONNECTION_STATE =
450         "android.bluetooth.adapter.extra.CONNECTION_STATE";
451 
452     /**
453      * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED}
454      *
455      * This extra represents the previous connection state.
456      */
457     public static final String EXTRA_PREVIOUS_CONNECTION_STATE =
458           "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE";
459 
460     /**
461      * Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
462      * @hide
463      */
464     @SystemApi
465     public static final String ACTION_BLE_STATE_CHANGED =
466         "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
467 
468     /**
469      * Intent used to broadcast the change in the Bluetooth address
470      * of the local Bluetooth adapter.
471      * <p>Always contains the extra field {@link
472      * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address.
473      *
474      * Note: only system level processes are allowed to send this
475      * defined broadcast.
476      *
477      * @hide
478      */
479     public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED =
480         "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED";
481 
482     /**
483      * Used as a String extra field in {@link
484      * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local
485      * Bluetooth address.
486      *
487      * @hide
488      */
489     public static final String EXTRA_BLUETOOTH_ADDRESS =
490           "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS";
491 
492     /**
493      * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
494      * by BLE Always on enabled application to know the ACL_CONNECTED event
495      * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection
496      * as Bluetooth LE is the only feature available in STATE_BLE_ON
497      *
498      * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which
499      * works in Bluetooth state STATE_ON
500      * @hide
501      */
502     public static final String ACTION_BLE_ACL_CONNECTED =
503         "android.bluetooth.adapter.action.BLE_ACL_CONNECTED";
504 
505     /**
506      * Broadcast Action: The notifys Bluetooth ACL connected event. This will be
507      * by BLE Always on enabled application to know the ACL_DISCONNECTED event
508      * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth
509      * LE is the only feature available in STATE_BLE_ON
510      *
511      * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which
512      * works in Bluetooth state STATE_ON
513      * @hide
514      */
515     public static final String ACTION_BLE_ACL_DISCONNECTED =
516         "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
517 
518     /** The profile is in disconnected state */
519     public static final int STATE_DISCONNECTED  = 0;
520     /** The profile is in connecting state */
521     public static final int STATE_CONNECTING    = 1;
522     /** The profile is in connected state */
523     public static final int STATE_CONNECTED     = 2;
524     /** The profile is in disconnecting state */
525     public static final int STATE_DISCONNECTING = 3;
526 
527     /** @hide */
528     public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
529     private final IBinder mToken;
530 
531 
532     /** When creating a ServerSocket using listenUsingRfcommOn() or
533      *  listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create
534      *  a ServerSocket that auto assigns a channel number to the first
535      *  bluetooth socket.
536      *  The channel number assigned to this first Bluetooth Socket will
537      *  be stored in the ServerSocket, and reused for subsequent Bluetooth
538      *  sockets.
539      * @hide */
540     public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2;
541 
542 
543     private static final int ADDRESS_LENGTH = 17;
544 
545     /**
546      * Lazily initialized singleton. Guaranteed final after first object
547      * constructed.
548      */
549     private static BluetoothAdapter sAdapter;
550 
551     private static BluetoothLeScanner sBluetoothLeScanner;
552     private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
553     private static PeriodicAdvertisingManager sPeriodicAdvertisingManager;
554 
555     private final IBluetoothManager mManagerService;
556     private IBluetooth mService;
557     private final ReentrantReadWriteLock mServiceLock =
558         new ReentrantReadWriteLock();
559 
560     private final Object mLock = new Object();
561     private final Map<LeScanCallback, ScanCallback> mLeScanClients;
562 
563     /**
564      * Get a handle to the default local Bluetooth adapter.
565      * <p>Currently Android only supports one Bluetooth adapter, but the API
566      * could be extended to support more. This will always return the default
567      * adapter.
568      * @return the default local adapter, or null if Bluetooth is not supported
569      *         on this hardware platform
570      */
getDefaultAdapter()571     public static synchronized BluetoothAdapter getDefaultAdapter() {
572         if (sAdapter == null) {
573             IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
574             if (b != null) {
575                 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
576                 sAdapter = new BluetoothAdapter(managerService);
577             } else {
578                 Log.e(TAG, "Bluetooth binder is null");
579             }
580         }
581         return sAdapter;
582     }
583 
584     /**
585      * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
586      */
BluetoothAdapter(IBluetoothManager managerService)587     BluetoothAdapter(IBluetoothManager managerService) {
588 
589         if (managerService == null) {
590             throw new IllegalArgumentException("bluetooth manager service is null");
591         }
592         try {
593             mServiceLock.writeLock().lock();
594             mService = managerService.registerAdapter(mManagerCallback);
595         } catch (RemoteException e) {
596             Log.e(TAG, "", e);
597         } finally {
598             mServiceLock.writeLock().unlock();
599         }
600         mManagerService = managerService;
601         mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
602         mToken = new Binder();
603     }
604 
605     /**
606      * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
607      * address.
608      * <p>Valid Bluetooth hardware addresses must be upper case, in a format
609      * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is
610      * available to validate a Bluetooth address.
611      * <p>A {@link BluetoothDevice} will always be returned for a valid
612      * hardware address, even if this adapter has never seen that device.
613      *
614      * @param address valid Bluetooth MAC address
615      * @throws IllegalArgumentException if address is invalid
616      */
getRemoteDevice(String address)617     public BluetoothDevice getRemoteDevice(String address) {
618         return new BluetoothDevice(address);
619     }
620 
621     /**
622      * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
623      * address.
624      * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method
625      * expects the address in network byte order (MSB first).
626      * <p>A {@link BluetoothDevice} will always be returned for a valid
627      * hardware address, even if this adapter has never seen that device.
628      *
629      * @param address Bluetooth MAC address (6 bytes)
630      * @throws IllegalArgumentException if address is invalid
631      */
getRemoteDevice(byte[] address)632     public BluetoothDevice getRemoteDevice(byte[] address) {
633         if (address == null || address.length != 6) {
634             throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
635         }
636         return new BluetoothDevice(String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X",
637                 address[0], address[1], address[2], address[3], address[4], address[5]));
638     }
639 
640     /**
641      * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
642      * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not
643      * supported on this device.
644      * <p>
645      * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
646      * on this device before calling this method.
647      */
getBluetoothLeAdvertiser()648     public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
649         if (!getLeAccess()) return null;
650         synchronized(mLock) {
651             if (sBluetoothLeAdvertiser == null) {
652                 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
653             }
654         }
655         return sBluetoothLeAdvertiser;
656     }
657 
658     /**
659      * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising
660      * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic
661      * Advertising is not supported on this device.
662      * <p>
663      * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is
664      * supported on this device before calling this method.
665      * @hide
666      */
getPeriodicAdvertisingManager()667     public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
668       if (!getLeAccess())
669         return null;
670 
671       if (!isLePeriodicAdvertisingSupported())
672         return null;
673 
674       synchronized (mLock) {
675         if (sPeriodicAdvertisingManager == null) {
676           sPeriodicAdvertisingManager =
677               new PeriodicAdvertisingManager(mManagerService);
678         }
679       }
680       return sPeriodicAdvertisingManager;
681     }
682 
683     /**
684      * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
685      */
getBluetoothLeScanner()686     public BluetoothLeScanner getBluetoothLeScanner() {
687         if (!getLeAccess()) return null;
688         synchronized(mLock) {
689             if (sBluetoothLeScanner == null) {
690                 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
691             }
692         }
693         return sBluetoothLeScanner;
694     }
695 
696     /**
697      * Return true if Bluetooth is currently enabled and ready for use.
698      * <p>Equivalent to:
699      * <code>getBluetoothState() == STATE_ON</code>
700      *
701      * @return true if the local adapter is turned on
702      */
703     @RequiresPermission(Manifest.permission.BLUETOOTH)
isEnabled()704     public boolean isEnabled() {
705         try {
706             mServiceLock.readLock().lock();
707             if (mService != null) return mService.isEnabled();
708         } catch (RemoteException e) {
709             Log.e(TAG, "", e);
710         } finally {
711             mServiceLock.readLock().unlock();
712         }
713 
714         return false;
715     }
716 
717     /**
718      * Return true if Bluetooth LE(Always BLE On feature) is currently
719      * enabled and ready for use
720      * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON
721      *
722      * @return true if the local Bluetooth LE adapter is turned on
723      * @hide
724      */
725     @SystemApi
isLeEnabled()726     public boolean isLeEnabled() {
727        final int state = getLeState();
728        if (DBG) Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
729        return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
730     }
731 
732     /**
733      * Turns off Bluetooth LE which was earlier turned on by calling enableBLE().
734      *
735      * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition
736      * to STATE_OFF and completely shut-down Bluetooth
737      *
738      * <p> If the Adapter state is STATE_ON, This would unregister the existance of
739      * special Bluetooth LE application and hence the further turning off of Bluetooth
740      * from UI would ensure the complete turn-off of Bluetooth rather than staying back
741      * BLE only state
742      *
743      * <p>This is an asynchronous call: it will return immediately, and
744      * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
745      * to be notified of subsequent adapter state changes If this call returns
746      * true, then the adapter state will immediately transition from {@link
747      * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
748      * later transition to either {@link #STATE_BLE_ON} or {@link
749      * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications
750      * If this call returns false then there was an
751      * immediate problem that will prevent the QAdapter from being turned off -
752      * such as the QAadapter already being turned off.
753      *
754      * @return true to indicate success, or false on
755      *         immediate error
756      * @hide
757      */
758     @SystemApi
disableBLE()759     public boolean disableBLE() {
760         if (!isBleScanAlwaysAvailable()) return false;
761 
762         int state = getLeState();
763         if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) {
764             String packageName = ActivityThread.currentPackageName();
765             if (DBG) Log.d (TAG, "disableBLE(): de-registering " + packageName);
766             try {
767                 mManagerService.updateBleAppCount(mToken, false, packageName);
768             } catch (RemoteException e) {
769                 Log.e(TAG, "", e);
770             }
771             return true;
772         }
773 
774         if (DBG) Log.d (TAG, "disableBLE(): Already disabled");
775         return false;
776     }
777 
778     /**
779      * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE.
780      *
781      * enableBLE registers the existence of an app using only LE functions.
782      *
783      * enableBLE may enable Bluetooth to an LE only mode so that an app can use
784      * LE related features (BluetoothGatt or BluetoothGattServer classes)
785      *
786      * If the user disables Bluetooth while an app is registered to use LE only features,
787      * Bluetooth will remain on in LE only mode for the app.
788      *
789      * When Bluetooth is in LE only mode, it is not shown as ON to the UI.
790      *
791      * <p>This is an asynchronous call: it returns immediately, and
792      * clients should listen for {@link #ACTION_BLE_STATE_CHANGED}
793      * to be notified of adapter state changes.
794      *
795      * If this call returns * true, then the adapter state is either in a mode where
796      * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON},
797      * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}.
798      *
799      * If this call returns false then there was an immediate problem that prevents the
800      * adapter from being turned on - such as Airplane mode.
801      *
802      * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various
803      * states, It includes all the classic Bluetooth Adapter states along with
804      * internal BLE only states
805      *
806      * @return true to indicate Bluetooth LE will be available, or false on
807      *         immediate error
808      * @hide
809      */
810     @SystemApi
enableBLE()811     public boolean enableBLE() {
812         if (!isBleScanAlwaysAvailable()) return false;
813 
814         try {
815             String packageName = ActivityThread.currentPackageName();
816             mManagerService.updateBleAppCount(mToken, true, packageName);
817             if (isLeEnabled()) {
818                 if (DBG) Log.d(TAG, "enableBLE(): Bluetooth already enabled");
819                 return true;
820             }
821             if (DBG) Log.d(TAG, "enableBLE(): Calling enable");
822             return mManagerService.enable(packageName);
823         } catch (RemoteException e) {
824             Log.e(TAG, "", e);
825         }
826 
827         return false;
828     }
829 
830     /**
831      * Get the current state of the local Bluetooth adapter.
832      * <p>Possible return values are
833      * {@link #STATE_OFF},
834      * {@link #STATE_TURNING_ON},
835      * {@link #STATE_ON},
836      * {@link #STATE_TURNING_OFF}.
837      *
838      * @return current state of Bluetooth adapter
839      */
840     @RequiresPermission(Manifest.permission.BLUETOOTH)
841     @AdapterState
getState()842     public int getState() {
843         int state = BluetoothAdapter.STATE_OFF;
844 
845         try {
846             mServiceLock.readLock().lock();
847             if (mService != null) {
848                 state = mService.getState();
849             }
850         } catch (RemoteException e) {
851             Log.e(TAG, "", e);
852         } finally {
853             mServiceLock.readLock().unlock();
854         }
855 
856         // Consider all internal states as OFF
857         if (state == BluetoothAdapter.STATE_BLE_ON
858             || state == BluetoothAdapter.STATE_BLE_TURNING_ON
859             || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) {
860             if (VDBG) Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF");
861             state = BluetoothAdapter.STATE_OFF;
862         }
863         if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState(state));
864         return state;
865     }
866 
867     /**
868      * Get the current state of the local Bluetooth adapter
869      * <p>This returns current internal state of Adapter including LE ON/OFF
870      *
871      * <p>Possible return values are
872      * {@link #STATE_OFF},
873      * {@link #STATE_BLE_TURNING_ON},
874      * {@link #STATE_BLE_ON},
875      * {@link #STATE_TURNING_ON},
876      * {@link #STATE_ON},
877      * {@link #STATE_TURNING_OFF},
878      * {@link #STATE_BLE_TURNING_OFF}.
879      *
880      * @return current state of Bluetooth adapter
881      * @hide
882      */
883     @RequiresPermission(Manifest.permission.BLUETOOTH)
884     @AdapterState
getLeState()885     public int getLeState() {
886         int state = BluetoothAdapter.STATE_OFF;
887 
888         try {
889             mServiceLock.readLock().lock();
890             if (mService != null) {
891                 state = mService.getState();
892             }
893         } catch (RemoteException e) {
894             Log.e(TAG, "", e);
895         } finally {
896             mServiceLock.readLock().unlock();
897         }
898 
899         if (VDBG) Log.d(TAG,"getLeState() returning " + BluetoothAdapter.nameForState(state));
900         return state;
901     }
902 
getLeAccess()903     boolean getLeAccess() {
904         if (getLeState() == STATE_ON)
905             return true;
906 
907         else if (getLeState() == STATE_BLE_ON)
908             return true; // TODO: FILTER SYSTEM APPS HERE <--
909 
910         return false;
911     }
912 
913     /**
914      * Turn on the local Bluetooth adapter&mdash;do not use without explicit
915      * user action to turn on Bluetooth.
916      * <p>This powers on the underlying Bluetooth hardware, and starts all
917      * Bluetooth system services.
918      * <p class="caution"><strong>Bluetooth should never be enabled without
919      * direct user consent</strong>. If you want to turn on Bluetooth in order
920      * to create a wireless connection, you should use the {@link
921      * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests
922      * user permission to turn on Bluetooth. The {@link #enable()} method is
923      * provided only for applications that include a user interface for changing
924      * system settings, such as a "power manager" app.</p>
925      * <p>This is an asynchronous call: it will return immediately, and
926      * clients should listen for {@link #ACTION_STATE_CHANGED}
927      * to be notified of subsequent adapter state changes. If this call returns
928      * true, then the adapter state will immediately transition from {@link
929      * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time
930      * later transition to either {@link #STATE_OFF} or {@link
931      * #STATE_ON}. If this call returns false then there was an
932      * immediate problem that will prevent the adapter from being turned on -
933      * such as Airplane mode, or the adapter is already turned on.
934      *
935      * @return true to indicate adapter startup has begun, or false on
936      *         immediate error
937      */
938     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
enable()939     public boolean enable() {
940         if (isEnabled()) {
941             if (DBG) Log.d(TAG, "enable(): BT already enabled!");
942             return true;
943         }
944         try {
945             return mManagerService.enable(ActivityThread.currentPackageName());
946         } catch (RemoteException e) {Log.e(TAG, "", e);}
947         return false;
948     }
949 
950     /**
951      * Turn off the local Bluetooth adapter&mdash;do not use without explicit
952      * user action to turn off Bluetooth.
953      * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth
954      * system services, and powers down the underlying Bluetooth hardware.
955      * <p class="caution"><strong>Bluetooth should never be disabled without
956      * direct user consent</strong>. The {@link #disable()} method is
957      * provided only for applications that include a user interface for changing
958      * system settings, such as a "power manager" app.</p>
959      * <p>This is an asynchronous call: it will return immediately, and
960      * clients should listen for {@link #ACTION_STATE_CHANGED}
961      * to be notified of subsequent adapter state changes. If this call returns
962      * true, then the adapter state will immediately transition from {@link
963      * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time
964      * later transition to either {@link #STATE_OFF} or {@link
965      * #STATE_ON}. If this call returns false then there was an
966      * immediate problem that will prevent the adapter from being turned off -
967      * such as the adapter already being turned off.
968      *
969      * @return true to indicate adapter shutdown has begun, or false on
970      *         immediate error
971      */
972     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
disable()973     public boolean disable() {
974         try {
975             return mManagerService.disable(ActivityThread.currentPackageName(), true);
976         } catch (RemoteException e) {Log.e(TAG, "", e);}
977         return false;
978     }
979 
980     /**
981      * Turn off the local Bluetooth adapter and don't persist the setting.
982      *
983      * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN}
984      * permission
985      *
986      * @return true to indicate adapter shutdown has begun, or false on
987      *         immediate error
988      * @hide
989      */
disable(boolean persist)990     public boolean disable(boolean persist) {
991 
992         try {
993             return mManagerService.disable(ActivityThread.currentPackageName(), persist);
994         } catch (RemoteException e) {Log.e(TAG, "", e);}
995         return false;
996     }
997 
998     /**
999      * Returns the hardware address of the local Bluetooth adapter.
1000      * <p>For example, "00:11:22:AA:BB:CC".
1001      *
1002      * @return Bluetooth hardware address as string
1003      */
1004     @RequiresPermission(Manifest.permission.BLUETOOTH)
getAddress()1005     public String getAddress() {
1006         try {
1007             return mManagerService.getAddress();
1008         } catch (RemoteException e) {Log.e(TAG, "", e);}
1009         return null;
1010     }
1011 
1012     /**
1013      * Get the friendly Bluetooth name of the local Bluetooth adapter.
1014      * <p>This name is visible to remote Bluetooth devices.
1015      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1016      *
1017      * @return the Bluetooth name, or null on error
1018      */
getName()1019     public String getName() {
1020         try {
1021             return mManagerService.getName();
1022         } catch (RemoteException e) {Log.e(TAG, "", e);}
1023         return null;
1024     }
1025 
1026     /**
1027      * Factory reset bluetooth settings.
1028      *
1029      * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
1030      * permission
1031      *
1032      * @return true to indicate that the config file was successfully cleared
1033      *
1034      * @hide
1035      */
factoryReset()1036     public boolean factoryReset() {
1037         try {
1038             mServiceLock.readLock().lock();
1039             if (mService != null) {
1040                 return mService.factoryReset();
1041             }
1042             SystemProperties.set("persist.bluetooth.factoryreset", "true");
1043         } catch (RemoteException e) {
1044             Log.e(TAG, "", e);
1045         } finally {
1046             mServiceLock.readLock().unlock();
1047         }
1048         return false;
1049     }
1050 
1051     /**
1052      * Get the UUIDs supported by the local Bluetooth adapter.
1053      *
1054      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1055      *
1056      * @return the UUIDs supported by the local Bluetooth Adapter.
1057      * @hide
1058      */
getUuids()1059     public ParcelUuid[] getUuids() {
1060         if (getState() != STATE_ON) return null;
1061         try {
1062             mServiceLock.readLock().lock();
1063             if (mService != null) return mService.getUuids();
1064         } catch (RemoteException e) {
1065             Log.e(TAG, "", e);
1066         } finally {
1067             mServiceLock.readLock().unlock();
1068         }
1069         return null;
1070     }
1071 
1072     /**
1073      * Set the friendly Bluetooth name of the local Bluetooth adapter.
1074      * <p>This name is visible to remote Bluetooth devices.
1075      * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8
1076      * encoding, although many remote devices can only display the first
1077      * 40 characters, and some may be limited to just 20.
1078      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1079      * will return false. After turning on Bluetooth,
1080      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1081      * to get the updated value.
1082      *
1083      * @param name a valid Bluetooth name
1084      * @return     true if the name was set, false otherwise
1085      */
1086     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
setName(String name)1087     public boolean setName(String name) {
1088         if (getState() != STATE_ON) return false;
1089         try {
1090             mServiceLock.readLock().lock();
1091             if (mService != null) return mService.setName(name);
1092         } catch (RemoteException e) {
1093             Log.e(TAG, "", e);
1094         } finally {
1095             mServiceLock.readLock().unlock();
1096         }
1097         return false;
1098     }
1099 
1100     /**
1101      * Get the current Bluetooth scan mode of the local Bluetooth adapter.
1102      * <p>The Bluetooth scan mode determines if the local adapter is
1103      * connectable and/or discoverable from remote Bluetooth devices.
1104      * <p>Possible values are:
1105      * {@link #SCAN_MODE_NONE},
1106      * {@link #SCAN_MODE_CONNECTABLE},
1107      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
1108      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1109      * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth,
1110      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1111      * to get the updated value.
1112      *
1113      * @return scan mode
1114      */
1115     @RequiresPermission(Manifest.permission.BLUETOOTH)
1116     @ScanMode
getScanMode()1117     public int getScanMode() {
1118         if (getState() != STATE_ON) return SCAN_MODE_NONE;
1119         try {
1120             mServiceLock.readLock().lock();
1121             if (mService != null) return mService.getScanMode();
1122         } catch (RemoteException e) {
1123             Log.e(TAG, "", e);
1124         } finally {
1125             mServiceLock.readLock().unlock();
1126         }
1127         return SCAN_MODE_NONE;
1128     }
1129 
1130     /**
1131      * Set the Bluetooth scan mode of the local Bluetooth adapter.
1132      * <p>The Bluetooth scan mode determines if the local adapter is
1133      * connectable and/or discoverable from remote Bluetooth devices.
1134      * <p>For privacy reasons, discoverable mode is automatically turned off
1135      * after <code>duration</code> seconds. For example, 120 seconds should be
1136      * enough for a remote device to initiate and complete its discovery
1137      * process.
1138      * <p>Valid scan mode values are:
1139      * {@link #SCAN_MODE_NONE},
1140      * {@link #SCAN_MODE_CONNECTABLE},
1141      * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
1142      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1143      * will return false. After turning on Bluetooth,
1144      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1145      * to get the updated value.
1146      * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}
1147      * <p>Applications cannot set the scan mode. They should use
1148      * <code>startActivityForResult(
1149      * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
1150      * </code>instead.
1151      *
1152      * @param mode valid scan mode
1153      * @param duration time in seconds to apply scan mode, only used for
1154      *                 {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
1155      * @return     true if the scan mode was set, false otherwise
1156      * @hide
1157      */
setScanMode(@canMode int mode, int duration)1158     public boolean setScanMode(@ScanMode int mode, int duration) {
1159         if (getState() != STATE_ON) return false;
1160         try {
1161             mServiceLock.readLock().lock();
1162             if (mService != null) return mService.setScanMode(mode, duration);
1163         } catch (RemoteException e) {
1164             Log.e(TAG, "", e);
1165         } finally {
1166             mServiceLock.readLock().unlock();
1167         }
1168         return false;
1169     }
1170 
1171     /** @hide */
setScanMode(int mode)1172     public boolean setScanMode(int mode) {
1173         if (getState() != STATE_ON) return false;
1174         /* getDiscoverableTimeout() to use the latest from NV than use 0 */
1175         return setScanMode(mode, getDiscoverableTimeout());
1176     }
1177 
1178     /** @hide */
getDiscoverableTimeout()1179     public int getDiscoverableTimeout() {
1180         if (getState() != STATE_ON) return -1;
1181         try {
1182             mServiceLock.readLock().lock();
1183             if (mService != null) return mService.getDiscoverableTimeout();
1184         } catch (RemoteException e) {
1185             Log.e(TAG, "", e);
1186         } finally {
1187             mServiceLock.readLock().unlock();
1188         }
1189         return -1;
1190     }
1191 
1192     /** @hide */
setDiscoverableTimeout(int timeout)1193     public void setDiscoverableTimeout(int timeout) {
1194         if (getState() != STATE_ON) return;
1195         try {
1196             mServiceLock.readLock().lock();
1197             if (mService != null) mService.setDiscoverableTimeout(timeout);
1198         } catch (RemoteException e) {
1199             Log.e(TAG, "", e);
1200         } finally {
1201             mServiceLock.readLock().unlock();
1202         }
1203     }
1204 
1205     /**
1206      * Get the end time of the latest remote device discovery process.
1207      * @return the latest time that the bluetooth adapter was/will be in discovery mode,
1208      * in milliseconds since the epoch.
1209      * This time can be in the future if {@link #startDiscovery()} has been called recently.
1210      * @hide
1211      */
getDiscoveryEndMillis()1212     public long getDiscoveryEndMillis() {
1213         try {
1214             mServiceLock.readLock().lock();
1215             if (mService != null) return mService.getDiscoveryEndMillis();
1216         } catch (RemoteException e) {
1217             Log.e(TAG, "", e);
1218         } finally {
1219             mServiceLock.readLock().unlock();
1220         }
1221         return -1;
1222     }
1223 
1224     /**
1225      * Start the remote device discovery process.
1226      * <p>The discovery process usually involves an inquiry scan of about 12
1227      * seconds, followed by a page scan of each new device to retrieve its
1228      * Bluetooth name.
1229      * <p>This is an asynchronous call, it will return immediately. Register
1230      * for {@link #ACTION_DISCOVERY_STARTED} and {@link
1231      * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the
1232      * discovery starts and completes. Register for {@link
1233      * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices
1234      * are found.
1235      * <p>Device discovery is a heavyweight procedure. New connections to
1236      * remote Bluetooth devices should not be attempted while discovery is in
1237      * progress, and existing connections will experience limited bandwidth
1238      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1239      * discovery. Discovery is not managed by the Activity,
1240      * but is run as a system service, so an application should always call
1241      * {@link BluetoothAdapter#cancelDiscovery()} even if it
1242      * did not directly request a discovery, just to be sure.
1243      * <p>Device discovery will only find remote devices that are currently
1244      * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are
1245      * not discoverable by default, and need to be entered into a special mode.
1246      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1247      * will return false. After turning on Bluetooth,
1248      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1249      * to get the updated value.
1250      *
1251      * @return true on success, false on error
1252      */
1253     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
startDiscovery()1254     public boolean startDiscovery() {
1255         if (getState() != STATE_ON) return false;
1256         try {
1257             mServiceLock.readLock().lock();
1258             if (mService != null) return mService.startDiscovery();
1259         } catch (RemoteException e) {
1260             Log.e(TAG, "", e);
1261         } finally {
1262             mServiceLock.readLock().unlock();
1263         }
1264         return false;
1265     }
1266 
1267     /**
1268      * Cancel the current device discovery process.
1269      * <p>Because discovery is a heavyweight procedure for the Bluetooth
1270      * adapter, this method should always be called before attempting to connect
1271      * to a remote device with {@link
1272      * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by
1273      * the  Activity, but is run as a system service, so an application should
1274      * always call cancel discovery even if it did not directly request a
1275      * discovery, just to be sure.
1276      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1277      * will return false. After turning on Bluetooth,
1278      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1279      * to get the updated value.
1280      *
1281      * @return true on success, false on error
1282      */
1283     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
cancelDiscovery()1284     public boolean cancelDiscovery() {
1285         if (getState() != STATE_ON) return false;
1286         try {
1287             mServiceLock.readLock().lock();
1288             if (mService != null) return mService.cancelDiscovery();
1289         } catch (RemoteException e) {
1290             Log.e(TAG, "", e);
1291         } finally {
1292             mServiceLock.readLock().unlock();
1293         }
1294         return false;
1295     }
1296 
1297     /**
1298      * Return true if the local Bluetooth adapter is currently in the device
1299      * discovery process.
1300      * <p>Device discovery is a heavyweight procedure. New connections to
1301      * remote Bluetooth devices should not be attempted while discovery is in
1302      * progress, and existing connections will experience limited bandwidth
1303      * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing
1304      * discovery.
1305      * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED}
1306      * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery
1307      * starts or completes.
1308      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1309      * will return false. After turning on Bluetooth,
1310      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1311      * to get the updated value.
1312      *
1313      * @return true if discovering
1314      */
1315     @RequiresPermission(Manifest.permission.BLUETOOTH)
isDiscovering()1316     public boolean isDiscovering() {
1317         if (getState() != STATE_ON) return false;
1318         try {
1319             mServiceLock.readLock().lock();
1320             if (mService != null) return mService.isDiscovering();
1321         } catch (RemoteException e) {
1322             Log.e(TAG, "", e);
1323         } finally {
1324             mServiceLock.readLock().unlock();
1325         }
1326         return false;
1327     }
1328 
1329     /**
1330      * Return true if the multi advertisement is supported by the chipset
1331      *
1332      * @return true if Multiple Advertisement feature is supported
1333      */
isMultipleAdvertisementSupported()1334     public boolean isMultipleAdvertisementSupported() {
1335         if (getState() != STATE_ON) return false;
1336         try {
1337             mServiceLock.readLock().lock();
1338             if (mService != null) return mService.isMultiAdvertisementSupported();
1339         } catch (RemoteException e) {
1340             Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e);
1341         } finally {
1342             mServiceLock.readLock().unlock();
1343         }
1344         return false;
1345     }
1346 
1347     /**
1348      * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p>
1349      *
1350      * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and
1351      * fetch scan results even when Bluetooth is turned off.<p>
1352      *
1353      * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}.
1354      *
1355      * @hide
1356      */
1357     @SystemApi
isBleScanAlwaysAvailable()1358     public boolean isBleScanAlwaysAvailable() {
1359         try {
1360             return mManagerService.isBleScanAlwaysAvailable();
1361         } catch (RemoteException e) {
1362             Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e);
1363             return false;
1364         }
1365     }
1366 
1367     /**
1368      * Return true if offloaded filters are supported
1369      *
1370      * @return true if chipset supports on-chip filtering
1371      */
isOffloadedFilteringSupported()1372     public boolean isOffloadedFilteringSupported() {
1373         if (!getLeAccess()) return false;
1374         try {
1375             mServiceLock.readLock().lock();
1376             if (mService != null) return mService.isOffloadedFilteringSupported();
1377         } catch (RemoteException e) {
1378             Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e);
1379         } finally {
1380             mServiceLock.readLock().unlock();
1381         }
1382         return false;
1383     }
1384 
1385     /**
1386      * Return true if offloaded scan batching is supported
1387      *
1388      * @return true if chipset supports on-chip scan batching
1389      */
isOffloadedScanBatchingSupported()1390     public boolean isOffloadedScanBatchingSupported() {
1391         if (!getLeAccess()) return false;
1392         try {
1393             mServiceLock.readLock().lock();
1394             if (mService != null) return mService.isOffloadedScanBatchingSupported();
1395         } catch (RemoteException e) {
1396             Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e);
1397         } finally {
1398             mServiceLock.readLock().unlock();
1399         }
1400         return false;
1401     }
1402 
1403     /**
1404      * Return true if LE 2M PHY feature is supported.
1405      *
1406      * @return true if chipset supports LE 2M PHY feature
1407      */
isLe2MPhySupported()1408     public boolean isLe2MPhySupported() {
1409         if (!getLeAccess()) return false;
1410         try {
1411             mServiceLock.readLock().lock();
1412             if (mService != null) return mService.isLe2MPhySupported();
1413         } catch (RemoteException e) {
1414             Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e);
1415         } finally {
1416             mServiceLock.readLock().unlock();
1417         }
1418         return false;
1419     }
1420 
1421     /**
1422      * Return true if LE Coded PHY feature is supported.
1423      *
1424      * @return true if chipset supports LE Coded PHY feature
1425      */
isLeCodedPhySupported()1426     public boolean isLeCodedPhySupported() {
1427         if (!getLeAccess()) return false;
1428         try {
1429             mServiceLock.readLock().lock();
1430             if (mService != null) return mService.isLeCodedPhySupported();
1431         } catch (RemoteException e) {
1432             Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e);
1433         } finally {
1434             mServiceLock.readLock().unlock();
1435         }
1436         return false;
1437     }
1438 
1439     /**
1440      * Return true if LE Extended Advertising feature is supported.
1441      *
1442      * @return true if chipset supports LE Extended Advertising feature
1443      */
isLeExtendedAdvertisingSupported()1444     public boolean isLeExtendedAdvertisingSupported() {
1445         if (!getLeAccess()) return false;
1446         try {
1447             mServiceLock.readLock().lock();
1448             if (mService != null) return mService.isLeExtendedAdvertisingSupported();
1449         } catch (RemoteException e) {
1450             Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e);
1451         } finally {
1452             mServiceLock.readLock().unlock();
1453         }
1454         return false;
1455     }
1456 
1457     /**
1458      * Return true if LE Periodic Advertising feature is supported.
1459      *
1460      * @return true if chipset supports LE Periodic Advertising feature
1461      */
isLePeriodicAdvertisingSupported()1462     public boolean isLePeriodicAdvertisingSupported() {
1463         if (!getLeAccess()) return false;
1464         try {
1465             mServiceLock.readLock().lock();
1466             if (mService != null) return mService.isLePeriodicAdvertisingSupported();
1467         } catch (RemoteException e) {
1468             Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e);
1469         } finally {
1470             mServiceLock.readLock().unlock();
1471         }
1472         return false;
1473     }
1474 
1475     /**
1476      * Return the maximum LE advertising data length in bytes,
1477      * if LE Extended Advertising feature is supported, 0 otherwise.
1478      *
1479      * @return the maximum LE advertising data length.
1480      */
getLeMaximumAdvertisingDataLength()1481     public int getLeMaximumAdvertisingDataLength() {
1482         if (!getLeAccess()) return 0;
1483         try {
1484             mServiceLock.readLock().lock();
1485             if (mService != null) return mService.getLeMaximumAdvertisingDataLength();
1486         } catch (RemoteException e) {
1487             Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
1488         } finally {
1489             mServiceLock.readLock().unlock();
1490         }
1491         return 0;
1492     }
1493 
1494     /**
1495      * Return true if hardware has entries available for matching beacons
1496      *
1497      * @return true if there are hw entries available for matching beacons
1498      * @hide
1499      */
isHardwareTrackingFiltersAvailable()1500     public boolean isHardwareTrackingFiltersAvailable() {
1501         if (!getLeAccess()) return false;
1502         try {
1503             IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
1504             if (iGatt == null) {
1505                 // BLE is not supported
1506                 return false;
1507             }
1508             return (iGatt.numHwTrackFiltersAvailable() != 0);
1509         } catch (RemoteException e) {
1510             Log.e(TAG, "", e);
1511         }
1512         return false;
1513     }
1514 
1515     /**
1516      * Return the record of {@link BluetoothActivityEnergyInfo} object that
1517      * has the activity and energy info. This can be used to ascertain what
1518      * the controller has been up to, since the last sample.
1519      * @param updateType Type of info, cached vs refreshed.
1520      *
1521      * @return a record with {@link BluetoothActivityEnergyInfo} or null if
1522      * report is unavailable or unsupported
1523      * @deprecated use the asynchronous
1524      * {@link #requestControllerActivityEnergyInfo(ResultReceiver)} instead.
1525      * @hide
1526      */
1527     @Deprecated
getControllerActivityEnergyInfo(int updateType)1528     public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
1529         SynchronousResultReceiver receiver = new SynchronousResultReceiver();
1530         requestControllerActivityEnergyInfo(receiver);
1531         try {
1532             SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
1533             if (result.bundle != null) {
1534                 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
1535             }
1536         } catch (TimeoutException e) {
1537             Log.e(TAG, "getControllerActivityEnergyInfo timed out");
1538         }
1539         return null;
1540     }
1541 
1542     /**
1543      * Request the record of {@link BluetoothActivityEnergyInfo} object that
1544      * has the activity and energy info. This can be used to ascertain what
1545      * the controller has been up to, since the last sample.
1546      *
1547      * A null value for the activity info object may be sent if the bluetooth service is
1548      * unreachable or the device does not support reporting such information.
1549      *
1550      * @param result The callback to which to send the activity info.
1551      * @hide
1552      */
requestControllerActivityEnergyInfo(ResultReceiver result)1553     public void requestControllerActivityEnergyInfo(ResultReceiver result) {
1554         try {
1555             mServiceLock.readLock().lock();
1556             if (mService != null) {
1557                 mService.requestActivityInfo(result);
1558                 result = null;
1559             }
1560         } catch (RemoteException e) {
1561             Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
1562         } finally {
1563             mServiceLock.readLock().unlock();
1564             if (result != null) {
1565                 // Only send an immediate result if we failed.
1566                 result.send(0, null);
1567             }
1568         }
1569     }
1570 
1571     /**
1572      * Return the set of {@link BluetoothDevice} objects that are bonded
1573      * (paired) to the local adapter.
1574      * <p>If Bluetooth state is not {@link #STATE_ON}, this API
1575      * will return an empty set. After turning on Bluetooth,
1576      * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
1577      * to get the updated value.
1578      *
1579      * @return unmodifiable set of {@link BluetoothDevice}, or null on error
1580      */
1581     @RequiresPermission(Manifest.permission.BLUETOOTH)
getBondedDevices()1582     public Set<BluetoothDevice> getBondedDevices() {
1583         if (getState() != STATE_ON) {
1584             return toDeviceSet(new BluetoothDevice[0]);
1585         }
1586         try {
1587             mServiceLock.readLock().lock();
1588             if (mService != null) return toDeviceSet(mService.getBondedDevices());
1589             return toDeviceSet(new BluetoothDevice[0]);
1590         } catch (RemoteException e) {
1591             Log.e(TAG, "", e);
1592         } finally {
1593             mServiceLock.readLock().unlock();
1594         }
1595         return null;
1596     }
1597 
1598     /**
1599      * Gets the currently supported profiles by the adapter.
1600      *
1601      *<p> This can be used to check whether a profile is supported before attempting
1602      * to connect to its respective proxy.
1603      *
1604      * @return a list of integers indicating the ids of supported profiles as defined in
1605      * {@link BluetoothProfile}.
1606      * @hide
1607      */
getSupportedProfiles()1608     public List<Integer> getSupportedProfiles() {
1609         final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>();
1610 
1611         try {
1612             synchronized (mManagerCallback) {
1613                 if (mService != null) {
1614                     final long supportedProfilesBitMask = mService.getSupportedProfiles();
1615 
1616                     for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) {
1617                         if ((supportedProfilesBitMask & (1 << i)) != 0) {
1618                             supportedProfiles.add(i);
1619                         }
1620                     }
1621                 }
1622             }
1623         } catch (RemoteException e) {
1624           Log.e(TAG, "getSupportedProfiles:", e);
1625         }
1626         return supportedProfiles;
1627     }
1628 
1629     /**
1630      * Get the current connection state of the local Bluetooth adapter.
1631      * This can be used to check whether the local Bluetooth adapter is connected
1632      * to any profile of any other remote Bluetooth Device.
1633      *
1634      * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED}
1635      * intent to get the connection state of the adapter.
1636      *
1637      * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED},
1638      * {@link #STATE_CONNECTING} or {@link #STATE_DISCONNECTED}
1639      *
1640      * @hide
1641      */
getConnectionState()1642     public int getConnectionState() {
1643         if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED;
1644         try {
1645             mServiceLock.readLock().lock();
1646             if (mService != null) return mService.getAdapterConnectionState();
1647         } catch (RemoteException e) {
1648             Log.e(TAG, "getConnectionState:", e);
1649         } finally {
1650             mServiceLock.readLock().unlock();
1651         }
1652         return BluetoothAdapter.STATE_DISCONNECTED;
1653     }
1654 
1655     /**
1656      * Get the current connection state of a profile.
1657      * This function can be used to check whether the local Bluetooth adapter
1658      * is connected to any remote device for a specific profile.
1659      * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
1660      * {@link BluetoothProfile#A2DP}.
1661      *
1662      * <p> Return value can be one of
1663      * {@link BluetoothProfile#STATE_DISCONNECTED},
1664      * {@link BluetoothProfile#STATE_CONNECTING},
1665      * {@link BluetoothProfile#STATE_CONNECTED},
1666      * {@link BluetoothProfile#STATE_DISCONNECTING}
1667      */
1668     @RequiresPermission(Manifest.permission.BLUETOOTH)
getProfileConnectionState(int profile)1669     public int getProfileConnectionState(int profile) {
1670         if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
1671         try {
1672             mServiceLock.readLock().lock();
1673             if (mService != null) return mService.getProfileConnectionState(profile);
1674         } catch (RemoteException e) {
1675             Log.e(TAG, "getProfileConnectionState:", e);
1676         } finally {
1677             mServiceLock.readLock().unlock();
1678         }
1679         return BluetoothProfile.STATE_DISCONNECTED;
1680     }
1681 
1682     /**
1683      * Create a listening, secure RFCOMM Bluetooth socket.
1684      * <p>A remote device connecting to this socket will be authenticated and
1685      * communication on this socket will be encrypted.
1686      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1687      * connections from a listening {@link BluetoothServerSocket}.
1688      * <p>Valid RFCOMM channels are in range 1 to 30.
1689      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1690      * @param channel RFCOMM channel to listen on
1691      * @return a listening RFCOMM BluetoothServerSocket
1692      * @throws IOException on error, for example Bluetooth not available, or
1693      *                     insufficient permissions, or channel in use.
1694      * @hide
1695      */
listenUsingRfcommOn(int channel)1696     public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException {
1697         return listenUsingRfcommOn(channel, false, false);
1698     }
1699 
1700     /**
1701      * Create a listening, secure RFCOMM Bluetooth socket.
1702      * <p>A remote device connecting to this socket will be authenticated and
1703      * communication on this socket will be encrypted.
1704      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1705      * connections from a listening {@link BluetoothServerSocket}.
1706      * <p>Valid RFCOMM channels are in range 1 to 30.
1707      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
1708      * <p>To auto assign a channel without creating a SDP record use
1709      * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number.
1710      * @param channel RFCOMM channel to listen on
1711      * @param mitm    enforce man-in-the-middle protection for authentication.
1712      * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections.
1713      * @return a listening RFCOMM BluetoothServerSocket
1714      * @throws IOException on error, for example Bluetooth not available, or
1715      *                     insufficient permissions, or channel in use.
1716      * @hide
1717      */
listenUsingRfcommOn(int channel, boolean mitm, boolean min16DigitPin)1718     public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm,
1719             boolean min16DigitPin)
1720             throws IOException {
1721         BluetoothServerSocket socket = new BluetoothServerSocket(
1722                 BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm, min16DigitPin);
1723         int errno = socket.mSocket.bindListen();
1724         if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1725             socket.setChannel(socket.mSocket.getPort());
1726         }
1727         if (errno != 0) {
1728             //TODO(BT): Throw the same exception error code
1729             // that the previous code was using.
1730             //socket.mSocket.throwErrnoNative(errno);
1731             throw new IOException("Error: " + errno);
1732         }
1733         return socket;
1734     }
1735 
1736     /**
1737      * Create a listening, secure RFCOMM Bluetooth socket with Service Record.
1738      * <p>A remote device connecting to this socket will be authenticated and
1739      * communication on this socket will be encrypted.
1740      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1741      * connections from a listening {@link BluetoothServerSocket}.
1742      * <p>The system will assign an unused RFCOMM channel to listen on.
1743      * <p>The system will also register a Service Discovery
1744      * Protocol (SDP) record with the local SDP server containing the specified
1745      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1746      * can use the same UUID to query our SDP server and discover which channel
1747      * to connect to. This SDP record will be removed when this socket is
1748      * closed, or if this application closes unexpectedly.
1749      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1750      * connect to this socket from another device using the same {@link UUID}.
1751      * @param name service name for SDP record
1752      * @param uuid uuid for SDP record
1753      * @return a listening RFCOMM BluetoothServerSocket
1754      * @throws IOException on error, for example Bluetooth not available, or
1755      *                     insufficient permissions, or channel in use.
1756      */
1757     @RequiresPermission(Manifest.permission.BLUETOOTH)
listenUsingRfcommWithServiceRecord(String name, UUID uuid)1758     public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
1759             throws IOException {
1760         return createNewRfcommSocketAndRecord(name, uuid, true, true);
1761     }
1762 
1763     /**
1764      * Create a listening, insecure RFCOMM Bluetooth socket with Service Record.
1765      * <p>The link key is not required to be authenticated, i.e the communication may be
1766      * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices,
1767      * the link will be encrypted, as encryption is mandartory.
1768      * For legacy devices (pre Bluetooth 2.1 devices) the link will not
1769      * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an
1770      * encrypted and authenticated communication channel is desired.
1771      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1772      * connections from a listening {@link BluetoothServerSocket}.
1773      * <p>The system will assign an unused RFCOMM channel to listen on.
1774      * <p>The system will also register a Service Discovery
1775      * Protocol (SDP) record with the local SDP server containing the specified
1776      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1777      * can use the same UUID to query our SDP server and discover which channel
1778      * to connect to. This SDP record will be removed when this socket is
1779      * closed, or if this application closes unexpectedly.
1780      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1781      * connect to this socket from another device using the same {@link UUID}.
1782      * @param name service name for SDP record
1783      * @param uuid uuid for SDP record
1784      * @return a listening RFCOMM BluetoothServerSocket
1785      * @throws IOException on error, for example Bluetooth not available, or
1786      *                     insufficient permissions, or channel in use.
1787      */
1788     @RequiresPermission(Manifest.permission.BLUETOOTH)
listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)1789     public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
1790             throws IOException {
1791         return createNewRfcommSocketAndRecord(name, uuid, false, false);
1792     }
1793 
1794      /**
1795      * Create a listening, encrypted,
1796      * RFCOMM Bluetooth socket with Service Record.
1797      * <p>The link will be encrypted, but the link key is not required to be authenticated
1798      * i.e the communication is vulnerable to Man In the Middle attacks. Use
1799      * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key.
1800      * <p> Use this socket if authentication of link key is not possible.
1801      * For example, for Bluetooth 2.1 devices, if any of the devices does not have
1802      * an input and output capability or just has the ability to display a numeric key,
1803      * a secure socket connection is not possible and this socket can be used.
1804      * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required.
1805      * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory.
1806      * For more details, refer to the Security Model section 5.2 (vol 3) of
1807      * Bluetooth Core Specification version 2.1 + EDR.
1808      * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming
1809      * connections from a listening {@link BluetoothServerSocket}.
1810      * <p>The system will assign an unused RFCOMM channel to listen on.
1811      * <p>The system will also register a Service Discovery
1812      * Protocol (SDP) record with the local SDP server containing the specified
1813      * UUID, service name, and auto-assigned channel. Remote Bluetooth devices
1814      * can use the same UUID to query our SDP server and discover which channel
1815      * to connect to. This SDP record will be removed when this socket is
1816      * closed, or if this application closes unexpectedly.
1817      * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to
1818      * connect to this socket from another device using the same {@link UUID}.
1819      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1820      * @param name service name for SDP record
1821      * @param uuid uuid for SDP record
1822      * @return a listening RFCOMM BluetoothServerSocket
1823      * @throws IOException on error, for example Bluetooth not available, or
1824      *                     insufficient permissions, or channel in use.
1825      * @hide
1826      */
listenUsingEncryptedRfcommWithServiceRecord( String name, UUID uuid)1827     public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(
1828             String name, UUID uuid) throws IOException {
1829         return createNewRfcommSocketAndRecord(name, uuid, false, true);
1830     }
1831 
1832 
createNewRfcommSocketAndRecord(String name, UUID uuid, boolean auth, boolean encrypt)1833     private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
1834             boolean auth, boolean encrypt) throws IOException {
1835         BluetoothServerSocket socket;
1836         socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth,
1837                         encrypt, new ParcelUuid(uuid));
1838         socket.setServiceName(name);
1839         int errno = socket.mSocket.bindListen();
1840         if (errno != 0) {
1841             //TODO(BT): Throw the same exception error code
1842             // that the previous code was using.
1843             //socket.mSocket.throwErrnoNative(errno);
1844             throw new IOException("Error: " + errno);
1845         }
1846         return socket;
1847     }
1848 
1849     /**
1850      * Construct an unencrypted, unauthenticated, RFCOMM server socket.
1851      * Call #accept to retrieve connections to this socket.
1852      * @return An RFCOMM BluetoothServerSocket
1853      * @throws IOException On error, for example Bluetooth not available, or
1854      *                     insufficient permissions.
1855      * @hide
1856      */
listenUsingInsecureRfcommOn(int port)1857     public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
1858         BluetoothServerSocket socket = new BluetoothServerSocket(
1859                 BluetoothSocket.TYPE_RFCOMM, false, false, port);
1860         int errno = socket.mSocket.bindListen();
1861         if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1862             socket.setChannel(socket.mSocket.getPort());
1863         }
1864         if (errno != 0) {
1865             //TODO(BT): Throw the same exception error code
1866             // that the previous code was using.
1867             //socket.mSocket.throwErrnoNative(errno);
1868             throw new IOException("Error: " + errno);
1869         }
1870         return socket;
1871     }
1872 
1873      /**
1874      * Construct an encrypted, RFCOMM server socket.
1875      * Call #accept to retrieve connections to this socket.
1876      * @return An RFCOMM BluetoothServerSocket
1877      * @throws IOException On error, for example Bluetooth not available, or
1878      *                     insufficient permissions.
1879      * @hide
1880      */
listenUsingEncryptedRfcommOn(int port)1881     public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port)
1882             throws IOException {
1883         BluetoothServerSocket socket = new BluetoothServerSocket(
1884                 BluetoothSocket.TYPE_RFCOMM, false, true, port);
1885         int errno = socket.mSocket.bindListen();
1886         if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1887             socket.setChannel(socket.mSocket.getPort());
1888         }
1889         if (errno < 0) {
1890             //TODO(BT): Throw the same exception error code
1891             // that the previous code was using.
1892             //socket.mSocket.throwErrnoNative(errno);
1893             throw new IOException("Error: " + errno);
1894         }
1895         return socket;
1896     }
1897 
1898     /**
1899      * Construct a SCO server socket.
1900      * Call #accept to retrieve connections to this socket.
1901      * @return A SCO BluetoothServerSocket
1902      * @throws IOException On error, for example Bluetooth not available, or
1903      *                     insufficient permissions.
1904      * @hide
1905      */
listenUsingScoOn()1906     public static BluetoothServerSocket listenUsingScoOn() throws IOException {
1907         BluetoothServerSocket socket = new BluetoothServerSocket(
1908                 BluetoothSocket.TYPE_SCO, false, false, -1);
1909         int errno = socket.mSocket.bindListen();
1910         if (errno < 0) {
1911             //TODO(BT): Throw the same exception error code
1912             // that the previous code was using.
1913             //socket.mSocket.throwErrnoNative(errno);
1914         }
1915         return socket;
1916     }
1917 
1918     /**
1919      * Construct an encrypted, authenticated, L2CAP server socket.
1920      * Call #accept to retrieve connections to this socket.
1921      * <p>To auto assign a port without creating a SDP record use
1922      * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
1923      * @param port    the PSM to listen on
1924      * @param mitm    enforce man-in-the-middle protection for authentication.
1925      * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections.
1926      * @return An L2CAP BluetoothServerSocket
1927      * @throws IOException On error, for example Bluetooth not available, or
1928      *                     insufficient permissions.
1929      * @hide
1930      */
listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)1931     public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
1932             throws IOException {
1933         BluetoothServerSocket socket = new BluetoothServerSocket(
1934                 BluetoothSocket.TYPE_L2CAP, true, true, port, mitm, min16DigitPin);
1935         int errno = socket.mSocket.bindListen();
1936         if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1937             socket.setChannel(socket.mSocket.getPort());
1938         }
1939         if (errno != 0) {
1940             //TODO(BT): Throw the same exception error code
1941             // that the previous code was using.
1942             //socket.mSocket.throwErrnoNative(errno);
1943             throw new IOException("Error: " + errno);
1944         }
1945         return socket;
1946     }
1947 
1948     /**
1949      * Construct an encrypted, authenticated, L2CAP server socket.
1950      * Call #accept to retrieve connections to this socket.
1951      * <p>To auto assign a port without creating a SDP record use
1952      * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
1953      * @param port    the PSM to listen on
1954      * @return An L2CAP BluetoothServerSocket
1955      * @throws IOException On error, for example Bluetooth not available, or
1956      *                     insufficient permissions.
1957      * @hide
1958      */
listenUsingL2capOn(int port)1959     public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
1960         return listenUsingL2capOn(port, false, false);
1961     }
1962 
1963 
1964     /**
1965      * Construct an insecure L2CAP server socket.
1966      * Call #accept to retrieve connections to this socket.
1967      * <p>To auto assign a port without creating a SDP record use
1968      * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number.
1969      * @param port    the PSM to listen on
1970      * @return An L2CAP BluetoothServerSocket
1971      * @throws IOException On error, for example Bluetooth not available, or
1972      *                     insufficient permissions.
1973      * @hide
1974      */
listenUsingInsecureL2capOn(int port)1975     public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
1976         BluetoothServerSocket socket = new BluetoothServerSocket(
1977                 BluetoothSocket.TYPE_L2CAP, false, false, port, false, false);
1978         int errno = socket.mSocket.bindListen();
1979         if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) {
1980             socket.setChannel(socket.mSocket.getPort());
1981         }
1982         if (errno != 0) {
1983             //TODO(BT): Throw the same exception error code
1984             // that the previous code was using.
1985             //socket.mSocket.throwErrnoNative(errno);
1986             throw new IOException("Error: " + errno);
1987         }
1988         return socket;
1989 
1990     }
1991 
1992     /**
1993      * Read the local Out of Band Pairing Data
1994      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
1995      *
1996      * @return Pair<byte[], byte[]> of Hash and Randomizer
1997      *
1998      * @hide
1999      */
readOutOfBandData()2000     public Pair<byte[], byte[]> readOutOfBandData() {
2001         return null;
2002     }
2003 
2004     /**
2005      * Get the profile proxy object associated with the profile.
2006      *
2007      * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
2008      * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or
2009      * {@link BluetoothProfile#GATT_SERVER}. Clients must implement
2010      * {@link BluetoothProfile.ServiceListener} to get notified of
2011      * the connection status and to get the proxy object.
2012      *
2013      * @param context Context of the application
2014      * @param listener The service Listener for connection callbacks.
2015      * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH},
2016      *                {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}.
2017      *                {@link BluetoothProfile#GATT} or {@link BluetoothProfile#GATT_SERVER}.
2018      * @return true on success, false on error
2019      */
getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile)2020     public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
2021                                    int profile) {
2022         if (context == null || listener == null) return false;
2023 
2024         if (profile == BluetoothProfile.HEADSET) {
2025             BluetoothHeadset headset = new BluetoothHeadset(context, listener);
2026             return true;
2027         } else if (profile == BluetoothProfile.A2DP) {
2028             BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
2029             return true;
2030         } else if (profile == BluetoothProfile.A2DP_SINK) {
2031             BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
2032             return true;
2033         } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
2034             BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
2035             return true;
2036         } else if (profile == BluetoothProfile.INPUT_DEVICE) {
2037             BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
2038             return true;
2039         } else if (profile == BluetoothProfile.PAN) {
2040             BluetoothPan pan = new BluetoothPan(context, listener);
2041             return true;
2042         } else if (profile == BluetoothProfile.HEALTH) {
2043             BluetoothHealth health = new BluetoothHealth(context, listener);
2044             return true;
2045         } else if (profile == BluetoothProfile.MAP) {
2046             BluetoothMap map = new BluetoothMap(context, listener);
2047             return true;
2048         } else if (profile == BluetoothProfile.HEADSET_CLIENT) {
2049             BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
2050             return true;
2051         } else if (profile == BluetoothProfile.SAP) {
2052             BluetoothSap sap = new BluetoothSap(context, listener);
2053             return true;
2054         } else if (profile == BluetoothProfile.PBAP_CLIENT) {
2055             BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
2056             return true;
2057         } else if (profile == BluetoothProfile.MAP_CLIENT) {
2058             BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
2059             return true;
2060         } else if (profile == BluetoothProfile.INPUT_HOST) {
2061             BluetoothInputHost iHost = new BluetoothInputHost(context, listener);
2062             return true;
2063         } else {
2064             return false;
2065         }
2066     }
2067 
2068     /**
2069      * Close the connection of the profile proxy to the Service.
2070      *
2071      * <p> Clients should call this when they are no longer using
2072      * the proxy obtained from {@link #getProfileProxy}.
2073      * Profile can be one of  {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or
2074      * {@link BluetoothProfile#A2DP}
2075      *
2076      * @param profile
2077      * @param proxy Profile proxy object
2078      */
closeProfileProxy(int profile, BluetoothProfile proxy)2079     public void closeProfileProxy(int profile, BluetoothProfile proxy) {
2080         if (proxy == null) return;
2081 
2082         switch (profile) {
2083             case BluetoothProfile.HEADSET:
2084                 BluetoothHeadset headset = (BluetoothHeadset)proxy;
2085                 headset.close();
2086                 break;
2087             case BluetoothProfile.A2DP:
2088                 BluetoothA2dp a2dp = (BluetoothA2dp)proxy;
2089                 a2dp.close();
2090                 break;
2091             case BluetoothProfile.A2DP_SINK:
2092                 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink)proxy;
2093                 a2dpSink.close();
2094                 break;
2095             case BluetoothProfile.AVRCP_CONTROLLER:
2096                 BluetoothAvrcpController avrcp = (BluetoothAvrcpController)proxy;
2097                 avrcp.close();
2098                 break;
2099             case BluetoothProfile.INPUT_DEVICE:
2100                 BluetoothInputDevice iDev = (BluetoothInputDevice)proxy;
2101                 iDev.close();
2102                 break;
2103             case BluetoothProfile.PAN:
2104                 BluetoothPan pan = (BluetoothPan)proxy;
2105                 pan.close();
2106                 break;
2107             case BluetoothProfile.HEALTH:
2108                 BluetoothHealth health = (BluetoothHealth)proxy;
2109                 health.close();
2110                 break;
2111            case BluetoothProfile.GATT:
2112                 BluetoothGatt gatt = (BluetoothGatt)proxy;
2113                 gatt.close();
2114                 break;
2115             case BluetoothProfile.GATT_SERVER:
2116                 BluetoothGattServer gattServer = (BluetoothGattServer)proxy;
2117                 gattServer.close();
2118                 break;
2119             case BluetoothProfile.MAP:
2120                 BluetoothMap map = (BluetoothMap)proxy;
2121                 map.close();
2122                 break;
2123             case BluetoothProfile.HEADSET_CLIENT:
2124                 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy;
2125                 headsetClient.close();
2126                 break;
2127             case BluetoothProfile.SAP:
2128                 BluetoothSap sap = (BluetoothSap)proxy;
2129                 sap.close();
2130                 break;
2131             case BluetoothProfile.PBAP_CLIENT:
2132                 BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy;
2133                 pbapClient.close();
2134                 break;
2135             case BluetoothProfile.MAP_CLIENT:
2136                 BluetoothMapClient mapClient = (BluetoothMapClient)proxy;
2137                 mapClient.close();
2138                 break;
2139             case BluetoothProfile.INPUT_HOST:
2140                 BluetoothInputHost iHost = (BluetoothInputHost) proxy;
2141                 iHost.close();
2142                 break;
2143         }
2144     }
2145 
2146     final private IBluetoothManagerCallback mManagerCallback =
2147         new IBluetoothManagerCallback.Stub() {
2148             public void onBluetoothServiceUp(IBluetooth bluetoothService) {
2149                 if (DBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService);
2150 
2151                 mServiceLock.writeLock().lock();
2152                 mService = bluetoothService;
2153                 mServiceLock.writeLock().unlock();
2154 
2155                 synchronized (mProxyServiceStateCallbacks) {
2156                     for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ) {
2157                         try {
2158                             if (cb != null) {
2159                                 cb.onBluetoothServiceUp(bluetoothService);
2160                             } else {
2161                                 Log.d(TAG, "onBluetoothServiceUp: cb is null!");
2162                             }
2163                         } catch (Exception e) {
2164                             Log.e(TAG,"",e);
2165                         }
2166                     }
2167                 }
2168             }
2169 
2170             public void onBluetoothServiceDown() {
2171                 if (DBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
2172 
2173                 try {
2174                     mServiceLock.writeLock().lock();
2175                     mService = null;
2176                     if (mLeScanClients != null) mLeScanClients.clear();
2177                     if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup();
2178                     if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup();
2179                 } finally {
2180                     mServiceLock.writeLock().unlock();
2181                 }
2182 
2183                 synchronized (mProxyServiceStateCallbacks) {
2184                     for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
2185                         try {
2186                             if (cb != null) {
2187                                 cb.onBluetoothServiceDown();
2188                             } else {
2189                                 Log.d(TAG, "onBluetoothServiceDown: cb is null!");
2190                             }
2191                         } catch (Exception e) {
2192                             Log.e(TAG,"",e);
2193                         }
2194                     }
2195                 }
2196             }
2197 
2198             public void onBrEdrDown() {
2199                 if (VDBG) Log.i(TAG, "onBrEdrDown: " + mService);
2200             }
2201     };
2202 
2203     /**
2204      * Enable the Bluetooth Adapter, but don't auto-connect devices
2205      * and don't persist state. Only for use by system applications.
2206      * @hide
2207      */
enableNoAutoConnect()2208     public boolean enableNoAutoConnect() {
2209         if (isEnabled() == true){
2210             if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT already enabled!");
2211             return true;
2212         }
2213         try {
2214             return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName());
2215         } catch (RemoteException e) {Log.e(TAG, "", e);}
2216         return false;
2217     }
2218 
2219     /**
2220      * Enable control of the Bluetooth Adapter for a single application.
2221      *
2222      * <p>Some applications need to use Bluetooth for short periods of time to
2223      * transfer data but don't want all the associated implications like
2224      * automatic connection to headsets etc.
2225      *
2226      * <p> Multiple applications can call this. This is reference counted and
2227      * Bluetooth disabled only when no one else is using it. There will be no UI
2228      * shown to the user while bluetooth is being enabled. Any user action will
2229      * override this call. For example, if user wants Bluetooth on and the last
2230      * user of this API wanted to disable Bluetooth, Bluetooth will not be
2231      * turned off.
2232      *
2233      * <p> This API is only meant to be used by internal applications. Third
2234      * party applications but use {@link #enable} and {@link #disable} APIs.
2235      *
2236      * <p> If this API returns true, it means the callback will be called.
2237      * The callback will be called with the current state of Bluetooth.
2238      * If the state is not what was requested, an internal error would be the
2239      * reason. If Bluetooth is already on and if this function is called to turn
2240      * it on, the api will return true and a callback will be called.
2241      *
2242      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
2243      *
2244      * @param on True for on, false for off.
2245      * @param callback The callback to notify changes to the state.
2246      * @hide
2247      */
changeApplicationBluetoothState(boolean on, BluetoothStateChangeCallback callback)2248     public boolean changeApplicationBluetoothState(boolean on,
2249                                                    BluetoothStateChangeCallback callback) {
2250         return false;
2251     }
2252 
2253     /**
2254      * @hide
2255      */
2256     public interface BluetoothStateChangeCallback {
onBluetoothStateChange(boolean on)2257         public void onBluetoothStateChange(boolean on);
2258     }
2259 
2260     /**
2261      * @hide
2262      */
2263     public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
2264         private BluetoothStateChangeCallback mCallback;
2265 
StateChangeCallbackWrapper(BluetoothStateChangeCallback callback)2266         StateChangeCallbackWrapper(BluetoothStateChangeCallback
2267                 callback) {
2268             mCallback = callback;
2269         }
2270 
2271         @Override
onBluetoothStateChange(boolean on)2272         public void onBluetoothStateChange(boolean on) {
2273             mCallback.onBluetoothStateChange(on);
2274         }
2275     }
2276 
toDeviceSet(BluetoothDevice[] devices)2277     private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
2278         Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
2279         return Collections.unmodifiableSet(deviceSet);
2280     }
2281 
finalize()2282     protected void finalize() throws Throwable {
2283         try {
2284             mManagerService.unregisterAdapter(mManagerCallback);
2285         } catch (RemoteException e) {
2286             Log.e(TAG, "", e);
2287         } finally {
2288             super.finalize();
2289         }
2290     }
2291 
2292 
2293     /**
2294      * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0"
2295      * <p>Alphabetic characters must be uppercase to be valid.
2296      *
2297      * @param address Bluetooth address as string
2298      * @return true if the address is valid, false otherwise
2299      */
checkBluetoothAddress(String address)2300     public static boolean checkBluetoothAddress(String address) {
2301         if (address == null || address.length() != ADDRESS_LENGTH) {
2302             return false;
2303         }
2304         for (int i = 0; i < ADDRESS_LENGTH; i++) {
2305             char c = address.charAt(i);
2306             switch (i % 3) {
2307             case 0:
2308             case 1:
2309                 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
2310                     // hex character, OK
2311                     break;
2312                 }
2313                 return false;
2314             case 2:
2315                 if (c == ':') {
2316                     break;  // OK
2317                 }
2318                 return false;
2319             }
2320         }
2321         return true;
2322     }
2323 
getBluetoothManager()2324     /*package*/ IBluetoothManager getBluetoothManager() {
2325             return mManagerService;
2326     }
2327 
2328     final private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>();
2329 
getBluetoothService(IBluetoothManagerCallback cb)2330     /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) {
2331         synchronized (mProxyServiceStateCallbacks) {
2332             if (cb == null) {
2333                 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback");
2334             } else if (!mProxyServiceStateCallbacks.contains(cb)) {
2335                 mProxyServiceStateCallbacks.add(cb);
2336             }
2337         }
2338         return mService;
2339     }
2340 
removeServiceStateCallback(IBluetoothManagerCallback cb)2341     /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) {
2342         synchronized (mProxyServiceStateCallbacks) {
2343             mProxyServiceStateCallbacks.remove(cb);
2344         }
2345     }
2346 
2347     /**
2348      * Callback interface used to deliver LE scan results.
2349      *
2350      * @see #startLeScan(LeScanCallback)
2351      * @see #startLeScan(UUID[], LeScanCallback)
2352      */
2353     public interface LeScanCallback {
2354         /**
2355          * Callback reporting an LE device found during a device scan initiated
2356          * by the {@link BluetoothAdapter#startLeScan} function.
2357          *
2358          * @param device Identifies the remote device
2359          * @param rssi The RSSI value for the remote device as reported by the
2360          *             Bluetooth hardware. 0 if no RSSI value is available.
2361          * @param scanRecord The content of the advertisement record offered by
2362          *                   the remote device.
2363          */
onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)2364         public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord);
2365     }
2366 
2367     /**
2368      * Starts a scan for Bluetooth LE devices.
2369      *
2370      * <p>Results of the scan are reported using the
2371      * {@link LeScanCallback#onLeScan} callback.
2372      *
2373      * @param callback the callback LE scan results are delivered
2374      * @return true, if the scan was started successfully
2375      * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
2376      *             instead.
2377      */
2378     @Deprecated
2379     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
startLeScan(LeScanCallback callback)2380     public boolean startLeScan(LeScanCallback callback) {
2381         return startLeScan(null, callback);
2382     }
2383 
2384     /**
2385      * Starts a scan for Bluetooth LE devices, looking for devices that
2386      * advertise given services.
2387      *
2388      * <p>Devices which advertise all specified services are reported using the
2389      * {@link LeScanCallback#onLeScan} callback.
2390      *
2391      * @param serviceUuids Array of services to look for
2392      * @param callback the callback LE scan results are delivered
2393      * @return true, if the scan was started successfully
2394      * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)}
2395      *             instead.
2396      */
2397     @Deprecated
2398     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
startLeScan(final UUID[] serviceUuids, final LeScanCallback callback)2399     public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
2400         if (DBG) Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids));
2401         if (callback == null) {
2402             if (DBG) Log.e(TAG, "startLeScan: null callback");
2403             return false;
2404         }
2405         BluetoothLeScanner scanner = getBluetoothLeScanner();
2406         if (scanner == null) {
2407             if (DBG) Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
2408             return false;
2409         }
2410 
2411         synchronized(mLeScanClients) {
2412             if (mLeScanClients.containsKey(callback)) {
2413                 if (DBG) Log.e(TAG, "LE Scan has already started");
2414                 return false;
2415             }
2416 
2417             try {
2418                 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
2419                 if (iGatt == null) {
2420                     // BLE is not supported
2421                     return false;
2422                 }
2423 
2424                 ScanCallback scanCallback = new ScanCallback() {
2425                     @Override
2426                     public void onScanResult(int callbackType, ScanResult result) {
2427                         if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
2428                             // Should not happen.
2429                             Log.e(TAG, "LE Scan has already started");
2430                             return;
2431                         }
2432                         ScanRecord scanRecord = result.getScanRecord();
2433                         if (scanRecord == null) {
2434                             return;
2435                         }
2436                         if (serviceUuids != null) {
2437                             List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
2438                             for (UUID uuid : serviceUuids) {
2439                                 uuids.add(new ParcelUuid(uuid));
2440                             }
2441                             List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
2442                             if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
2443                                 if (DBG) Log.d(TAG, "uuids does not match");
2444                                 return;
2445                             }
2446                         }
2447                         callback.onLeScan(result.getDevice(), result.getRssi(),
2448                                 scanRecord.getBytes());
2449                     }
2450                 };
2451                 ScanSettings settings = new ScanSettings.Builder()
2452                     .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
2453                     .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
2454 
2455                 List<ScanFilter> filters = new ArrayList<ScanFilter>();
2456                 if (serviceUuids != null && serviceUuids.length > 0) {
2457                     // Note scan filter does not support matching an UUID array so we put one
2458                     // UUID to hardware and match the whole array in callback.
2459                     ScanFilter filter = new ScanFilter.Builder().setServiceUuid(
2460                             new ParcelUuid(serviceUuids[0])).build();
2461                     filters.add(filter);
2462                 }
2463                 scanner.startScan(filters, settings, scanCallback);
2464 
2465                 mLeScanClients.put(callback, scanCallback);
2466                 return true;
2467 
2468             } catch (RemoteException e) {
2469                 Log.e(TAG,"",e);
2470             }
2471         }
2472         return false;
2473     }
2474 
2475     /**
2476      * Stops an ongoing Bluetooth LE device scan.
2477      *
2478      * @param callback used to identify which scan to stop
2479      *        must be the same handle used to start the scan
2480      * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
2481      */
2482     @Deprecated
2483     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
stopLeScan(LeScanCallback callback)2484     public void stopLeScan(LeScanCallback callback) {
2485         if (DBG) Log.d(TAG, "stopLeScan()");
2486         BluetoothLeScanner scanner = getBluetoothLeScanner();
2487         if (scanner == null) {
2488             return;
2489         }
2490         synchronized (mLeScanClients) {
2491             ScanCallback scanCallback = mLeScanClients.remove(callback);
2492             if (scanCallback == null) {
2493                 if (DBG) Log.d(TAG, "scan not started yet");
2494                 return;
2495             }
2496             scanner.stopScan(scanCallback);
2497         }
2498     }
2499 }
2500