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