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