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