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