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