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