OSDN Git Service

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