Home | History | Annotate | Download | only in bluetooth
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.bluetooth;
     18 
     19 import android.Manifest;
     20 import android.annotation.NonNull;
     21 import android.annotation.Nullable;
     22 import android.annotation.RequiresPermission;
     23 import android.annotation.SdkConstant;
     24 import android.annotation.SdkConstant.SdkConstantType;
     25 import android.annotation.SystemApi;
     26 import android.annotation.UnsupportedAppUsage;
     27 import android.content.Context;
     28 import android.os.Handler;
     29 import android.os.Parcel;
     30 import android.os.ParcelUuid;
     31 import android.os.Parcelable;
     32 import android.os.Process;
     33 import android.os.RemoteException;
     34 import android.util.Log;
     35 
     36 import java.io.IOException;
     37 import java.io.UnsupportedEncodingException;
     38 import java.util.UUID;
     39 
     40 /**
     41  * Represents a remote Bluetooth device. A {@link BluetoothDevice} lets you
     42  * create a connection with the respective device or query information about
     43  * it, such as the name, address, class, and bonding state.
     44  *
     45  * <p>This class is really just a thin wrapper for a Bluetooth hardware
     46  * address. Objects of this class are immutable. Operations on this class
     47  * are performed on the remote Bluetooth hardware address, using the
     48  * {@link BluetoothAdapter} that was used to create this {@link
     49  * BluetoothDevice}.
     50  *
     51  * <p>To get a {@link BluetoothDevice}, use
     52  * {@link BluetoothAdapter#getRemoteDevice(String)
     53  * BluetoothAdapter.getRemoteDevice(String)} to create one representing a device
     54  * of a known MAC address (which you can get through device discovery with
     55  * {@link BluetoothAdapter}) or get one from the set of bonded devices
     56  * returned by {@link BluetoothAdapter#getBondedDevices()
     57  * BluetoothAdapter.getBondedDevices()}. You can then open a
     58  * {@link BluetoothSocket} for communication with the remote device, using
     59  * {@link #createRfcommSocketToServiceRecord(UUID)} over Bluetooth BR/EDR or using
     60  * {@link #createL2capChannel(int)} over Bluetooth LE.
     61  *
     62  * <p class="note"><strong>Note:</strong>
     63  * Requires the {@link android.Manifest.permission#BLUETOOTH} permission.
     64  *
     65  * <div class="special reference">
     66  * <h3>Developer Guides</h3>
     67  * <p>
     68  * For more information about using Bluetooth, read the <a href=
     69  * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
     70  * guide.
     71  * </p>
     72  * </div>
     73  *
     74  * {@see BluetoothAdapter}
     75  * {@see BluetoothSocket}
     76  */
     77 public final class BluetoothDevice implements Parcelable {
     78     private static final String TAG = "BluetoothDevice";
     79     private static final boolean DBG = false;
     80 
     81     /**
     82      * Connection state bitmask as returned by getConnectionState.
     83      */
     84     private static final int CONNECTION_STATE_DISCONNECTED = 0;
     85     private static final int CONNECTION_STATE_CONNECTED = 1;
     86     private static final int CONNECTION_STATE_ENCRYPTED_BREDR = 2;
     87     private static final int CONNECTION_STATE_ENCRYPTED_LE = 4;
     88 
     89     /**
     90      * Sentinel error value for this class. Guaranteed to not equal any other
     91      * integer constant in this class. Provided as a convenience for functions
     92      * that require a sentinel error value, for example:
     93      * <p><code>Intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
     94      * BluetoothDevice.ERROR)</code>
     95      */
     96     public static final int ERROR = Integer.MIN_VALUE;
     97 
     98     /**
     99      * Broadcast Action: Remote device discovered.
    100      * <p>Sent when a remote device is found during discovery.
    101      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
    102      * #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or
    103      * {@link #EXTRA_RSSI} if they are available.
    104      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} and
    105      * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to receive.
    106      */
    107     // TODO: Change API to not broadcast RSSI if not available (incoming connection)
    108     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    109     public static final String ACTION_FOUND =
    110             "android.bluetooth.device.action.FOUND";
    111 
    112     /**
    113      * Broadcast Action: Bluetooth class of a remote device has changed.
    114      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
    115      * #EXTRA_CLASS}.
    116      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    117      * {@see BluetoothClass}
    118      */
    119     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    120     public static final String ACTION_CLASS_CHANGED =
    121             "android.bluetooth.device.action.CLASS_CHANGED";
    122 
    123     /**
    124      * Broadcast Action: Indicates a low level (ACL) connection has been
    125      * established with a remote device.
    126      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    127      * <p>ACL connections are managed automatically by the Android Bluetooth
    128      * stack.
    129      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    130      */
    131     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    132     public static final String ACTION_ACL_CONNECTED =
    133             "android.bluetooth.device.action.ACL_CONNECTED";
    134 
    135     /**
    136      * Broadcast Action: Indicates that a low level (ACL) disconnection has
    137      * been requested for a remote device, and it will soon be disconnected.
    138      * <p>This is useful for graceful disconnection. Applications should use
    139      * this intent as a hint to immediately terminate higher level connections
    140      * (RFCOMM, L2CAP, or profile connections) to the remote device.
    141      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    142      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    143      */
    144     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    145     public static final String ACTION_ACL_DISCONNECT_REQUESTED =
    146             "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
    147 
    148     /**
    149      * Broadcast Action: Indicates a low level (ACL) disconnection from a
    150      * remote device.
    151      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    152      * <p>ACL connections are managed automatically by the Android Bluetooth
    153      * stack.
    154      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    155      */
    156     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    157     public static final String ACTION_ACL_DISCONNECTED =
    158             "android.bluetooth.device.action.ACL_DISCONNECTED";
    159 
    160     /**
    161      * Broadcast Action: Indicates the friendly name of a remote device has
    162      * been retrieved for the first time, or changed since the last retrieval.
    163      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
    164      * #EXTRA_NAME}.
    165      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    166      */
    167     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    168     public static final String ACTION_NAME_CHANGED =
    169             "android.bluetooth.device.action.NAME_CHANGED";
    170 
    171     /**
    172      * Broadcast Action: Indicates the alias of a remote device has been
    173      * changed.
    174      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    175      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    176      *
    177      * @hide
    178      */
    179     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    180     @UnsupportedAppUsage
    181     public static final String ACTION_ALIAS_CHANGED =
    182             "android.bluetooth.device.action.ALIAS_CHANGED";
    183 
    184     /**
    185      * Broadcast Action: Indicates a change in the bond state of a remote
    186      * device. For example, if a device is bonded (paired).
    187      * <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link
    188      * #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}.
    189      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    190      */
    191     // Note: When EXTRA_BOND_STATE is BOND_NONE then this will also
    192     // contain a hidden extra field EXTRA_REASON with the result code.
    193     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    194     public static final String ACTION_BOND_STATE_CHANGED =
    195             "android.bluetooth.device.action.BOND_STATE_CHANGED";
    196 
    197     /**
    198      * Broadcast Action: Indicates the battery level of a remote device has
    199      * been retrieved for the first time, or changed since the last retrieval
    200      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
    201      * #EXTRA_BATTERY_LEVEL}.
    202      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    203      *
    204      * @hide
    205      */
    206     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    207     public static final String ACTION_BATTERY_LEVEL_CHANGED =
    208             "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";
    209 
    210     /**
    211      * Used as an Integer extra field in {@link #ACTION_BATTERY_LEVEL_CHANGED}
    212      * intent. It contains the most recently retrieved battery level information
    213      * ranging from 0% to 100% for a remote device, {@link #BATTERY_LEVEL_UNKNOWN}
    214      * when the valid is unknown or there is an error
    215      *
    216      * @hide
    217      */
    218     public static final String EXTRA_BATTERY_LEVEL =
    219             "android.bluetooth.device.extra.BATTERY_LEVEL";
    220 
    221     /**
    222      * Used as the unknown value for {@link #EXTRA_BATTERY_LEVEL} and {@link #getBatteryLevel()}
    223      *
    224      * @hide
    225      */
    226     public static final int BATTERY_LEVEL_UNKNOWN = -1;
    227 
    228     /**
    229      * Used as a Parcelable {@link BluetoothDevice} extra field in every intent
    230      * broadcast by this class. It contains the {@link BluetoothDevice} that
    231      * the intent applies to.
    232      */
    233     public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
    234 
    235     /**
    236      * Used as a String extra field in {@link #ACTION_NAME_CHANGED} and {@link
    237      * #ACTION_FOUND} intents. It contains the friendly Bluetooth name.
    238      */
    239     public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
    240 
    241     /**
    242      * Used as an optional short extra field in {@link #ACTION_FOUND} intents.
    243      * Contains the RSSI value of the remote device as reported by the
    244      * Bluetooth hardware.
    245      */
    246     public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
    247 
    248     /**
    249      * Used as a Parcelable {@link BluetoothClass} extra field in {@link
    250      * #ACTION_FOUND} and {@link #ACTION_CLASS_CHANGED} intents.
    251      */
    252     public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
    253 
    254     /**
    255      * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
    256      * Contains the bond state of the remote device.
    257      * <p>Possible values are:
    258      * {@link #BOND_NONE},
    259      * {@link #BOND_BONDING},
    260      * {@link #BOND_BONDED}.
    261      */
    262     public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
    263     /**
    264      * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
    265      * Contains the previous bond state of the remote device.
    266      * <p>Possible values are:
    267      * {@link #BOND_NONE},
    268      * {@link #BOND_BONDING},
    269      * {@link #BOND_BONDED}.
    270      */
    271     public static final String EXTRA_PREVIOUS_BOND_STATE =
    272             "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
    273     /**
    274      * Indicates the remote device is not bonded (paired).
    275      * <p>There is no shared link key with the remote device, so communication
    276      * (if it is allowed at all) will be unauthenticated and unencrypted.
    277      */
    278     public static final int BOND_NONE = 10;
    279     /**
    280      * Indicates bonding (pairing) is in progress with the remote device.
    281      */
    282     public static final int BOND_BONDING = 11;
    283     /**
    284      * Indicates the remote device is bonded (paired).
    285      * <p>A shared link keys exists locally for the remote device, so
    286      * communication can be authenticated and encrypted.
    287      * <p><i>Being bonded (paired) with a remote device does not necessarily
    288      * mean the device is currently connected. It just means that the pending
    289      * procedure was completed at some earlier time, and the link key is still
    290      * stored locally, ready to use on the next connection.
    291      * </i>
    292      */
    293     public static final int BOND_BONDED = 12;
    294 
    295     /**
    296      * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
    297      * intents for unbond reason.
    298      *
    299      * @hide
    300      */
    301     @UnsupportedAppUsage
    302     public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON";
    303 
    304     /**
    305      * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
    306      * intents to indicate pairing method used. Possible values are:
    307      * {@link #PAIRING_VARIANT_PIN},
    308      * {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION},
    309      */
    310     public static final String EXTRA_PAIRING_VARIANT =
    311             "android.bluetooth.device.extra.PAIRING_VARIANT";
    312 
    313     /**
    314      * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
    315      * intents as the value of passkey.
    316      */
    317     public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
    318 
    319     /**
    320      * Bluetooth device type, Unknown
    321      */
    322     public static final int DEVICE_TYPE_UNKNOWN = 0;
    323 
    324     /**
    325      * Bluetooth device type, Classic - BR/EDR devices
    326      */
    327     public static final int DEVICE_TYPE_CLASSIC = 1;
    328 
    329     /**
    330      * Bluetooth device type, Low Energy - LE-only
    331      */
    332     public static final int DEVICE_TYPE_LE = 2;
    333 
    334     /**
    335      * Bluetooth device type, Dual Mode - BR/EDR/LE
    336      */
    337     public static final int DEVICE_TYPE_DUAL = 3;
    338 
    339 
    340     /** @hide */
    341     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    342     @UnsupportedAppUsage
    343     public static final String ACTION_SDP_RECORD =
    344             "android.bluetooth.device.action.SDP_RECORD";
    345 
    346     /**
    347      * Maximum length of a metadata entry, this is to avoid exploding Bluetooth
    348      * disk usage
    349      * @hide
    350      */
    351     @SystemApi
    352     public static final int METADATA_MAX_LENGTH = 2048;
    353 
    354     /**
    355      * Manufacturer name of this Bluetooth device
    356      * Data type should be {@String} as {@link Byte} array.
    357      * @hide
    358      */
    359     @SystemApi
    360     public static final int METADATA_MANUFACTURER_NAME = 0;
    361 
    362     /**
    363      * Model name of this Bluetooth device
    364      * Data type should be {@String} as {@link Byte} array.
    365      * @hide
    366      */
    367     @SystemApi
    368     public static final int METADATA_MODEL_NAME = 1;
    369 
    370     /**
    371      * Software version of this Bluetooth device
    372      * Data type should be {@String} as {@link Byte} array.
    373      * @hide
    374      */
    375     @SystemApi
    376     public static final int METADATA_SOFTWARE_VERSION = 2;
    377 
    378     /**
    379      * Hardware version of this Bluetooth device
    380      * Data type should be {@String} as {@link Byte} array.
    381      * @hide
    382      */
    383     @SystemApi
    384     public static final int METADATA_HARDWARE_VERSION = 3;
    385 
    386     /**
    387      * Package name of the companion app, if any
    388      * Data type should be {@String} as {@link Byte} array.
    389      * @hide
    390      */
    391     @SystemApi
    392     public static final int METADATA_COMPANION_APP = 4;
    393 
    394     /**
    395      * URI to the main icon shown on the settings UI
    396      * Data type should be {@link Byte} array.
    397      * @hide
    398      */
    399     @SystemApi
    400     public static final int METADATA_MAIN_ICON = 5;
    401 
    402     /**
    403      * Whether this device is an untethered headset with left, right and case
    404      * Data type should be {@String} as {@link Byte} array.
    405      * @hide
    406      */
    407     @SystemApi
    408     public static final int METADATA_IS_UNTETHERED_HEADSET = 6;
    409 
    410     /**
    411      * URI to icon of the left headset
    412      * Data type should be {@link Byte} array.
    413      * @hide
    414      */
    415     @SystemApi
    416     public static final int METADATA_UNTETHERED_LEFT_ICON = 7;
    417 
    418     /**
    419      * URI to icon of the right headset
    420      * Data type should be {@link Byte} array.
    421      * @hide
    422      */
    423     @SystemApi
    424     public static final int METADATA_UNTETHERED_RIGHT_ICON = 8;
    425 
    426     /**
    427      * URI to icon of the headset charging case
    428      * Data type should be {@link Byte} array.
    429      * @hide
    430      */
    431     @SystemApi
    432     public static final int METADATA_UNTETHERED_CASE_ICON = 9;
    433 
    434     /**
    435      * Battery level of left headset
    436      * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
    437      * as invalid.
    438      * @hide
    439      */
    440     @SystemApi
    441     public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10;
    442 
    443     /**
    444      * Battery level of rigth headset
    445      * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
    446      * as invalid.
    447      * @hide
    448      */
    449     @SystemApi
    450     public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11;
    451 
    452     /**
    453      * Battery level of the headset charging case
    454      * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
    455      * as invalid.
    456      * @hide
    457      */
    458     @SystemApi
    459     public static final int METADATA_UNTETHERED_CASE_BATTERY = 12;
    460 
    461     /**
    462      * Whether the left headset is charging
    463      * Data type should be {@String} as {@link Byte} array.
    464      * @hide
    465      */
    466     @SystemApi
    467     public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13;
    468 
    469     /**
    470      * Whether the right headset is charging
    471      * Data type should be {@String} as {@link Byte} array.
    472      * @hide
    473      */
    474     @SystemApi
    475     public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14;
    476 
    477     /**
    478      * Whether the headset charging case is charging
    479      * Data type should be {@String} as {@link Byte} array.
    480      * @hide
    481      */
    482     @SystemApi
    483     public static final int METADATA_UNTETHERED_CASE_CHARGING = 15;
    484 
    485     /**
    486      * URI to the enhanced settings UI slice
    487      * Data type should be {@String} as {@link Byte} array, null means
    488      * the UI does not exist.
    489      * @hide
    490      */
    491     @SystemApi
    492     public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16;
    493 
    494     /**
    495      * Broadcast Action: This intent is used to broadcast the {@link UUID}
    496      * wrapped as a {@link android.os.ParcelUuid} of the remote device after it
    497      * has been fetched. This intent is sent only when the UUIDs of the remote
    498      * device are requested to be fetched using Service Discovery Protocol
    499      * <p> Always contains the extra field {@link #EXTRA_DEVICE}
    500      * <p> Always contains the extra field {@link #EXTRA_UUID}
    501      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} to receive.
    502      */
    503     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    504     public static final String ACTION_UUID =
    505             "android.bluetooth.device.action.UUID";
    506 
    507     /** @hide */
    508     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    509     public static final String ACTION_MAS_INSTANCE =
    510             "android.bluetooth.device.action.MAS_INSTANCE";
    511 
    512     /**
    513      * Broadcast Action: Indicates a failure to retrieve the name of a remote
    514      * device.
    515      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    516      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    517      *
    518      * @hide
    519      */
    520     //TODO: is this actually useful?
    521     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    522     public static final String ACTION_NAME_FAILED =
    523             "android.bluetooth.device.action.NAME_FAILED";
    524 
    525     /**
    526      * Broadcast Action: This intent is used to broadcast PAIRING REQUEST
    527      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} to
    528      * receive.
    529      */
    530     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    531     public static final String ACTION_PAIRING_REQUEST =
    532             "android.bluetooth.device.action.PAIRING_REQUEST";
    533     /** @hide */
    534     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    535     @UnsupportedAppUsage
    536     public static final String ACTION_PAIRING_CANCEL =
    537             "android.bluetooth.device.action.PAIRING_CANCEL";
    538 
    539     /** @hide */
    540     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    541     public static final String ACTION_CONNECTION_ACCESS_REQUEST =
    542             "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST";
    543 
    544     /** @hide */
    545     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    546     public static final String ACTION_CONNECTION_ACCESS_REPLY =
    547             "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY";
    548 
    549     /** @hide */
    550     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    551     public static final String ACTION_CONNECTION_ACCESS_CANCEL =
    552             "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL";
    553 
    554     /**
    555      * Intent to broadcast silence mode changed.
    556      * Alway contains the extra field {@link #EXTRA_DEVICE}
    557      *
    558      * @hide
    559      */
    560     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    561     @SystemApi
    562     public static final String ACTION_SILENCE_MODE_CHANGED =
    563             "android.bluetooth.device.action.SILENCE_MODE_CHANGED";
    564 
    565     /**
    566      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent.
    567      *
    568      * @hide
    569      */
    570     public static final String EXTRA_ACCESS_REQUEST_TYPE =
    571             "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE";
    572 
    573     /** @hide */
    574     public static final int REQUEST_TYPE_PROFILE_CONNECTION = 1;
    575 
    576     /** @hide */
    577     public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2;
    578 
    579     /** @hide */
    580     public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3;
    581 
    582     /** @hide */
    583     public static final int REQUEST_TYPE_SIM_ACCESS = 4;
    584 
    585     /**
    586      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
    587      * Contains package name to return reply intent to.
    588      *
    589      * @hide
    590      */
    591     public static final String EXTRA_PACKAGE_NAME = "android.bluetooth.device.extra.PACKAGE_NAME";
    592 
    593     /**
    594      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
    595      * Contains class name to return reply intent to.
    596      *
    597      * @hide
    598      */
    599     public static final String EXTRA_CLASS_NAME = "android.bluetooth.device.extra.CLASS_NAME";
    600 
    601     /**
    602      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent.
    603      *
    604      * @hide
    605      */
    606     public static final String EXTRA_CONNECTION_ACCESS_RESULT =
    607             "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT";
    608 
    609     /** @hide */
    610     public static final int CONNECTION_ACCESS_YES = 1;
    611 
    612     /** @hide */
    613     public static final int CONNECTION_ACCESS_NO = 2;
    614 
    615     /**
    616      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intents,
    617      * Contains boolean to indicate if the allowed response is once-for-all so that
    618      * next request will be granted without asking user again.
    619      *
    620      * @hide
    621      */
    622     public static final String EXTRA_ALWAYS_ALLOWED =
    623             "android.bluetooth.device.extra.ALWAYS_ALLOWED";
    624 
    625     /**
    626      * A bond attempt succeeded
    627      *
    628      * @hide
    629      */
    630     public static final int BOND_SUCCESS = 0;
    631 
    632     /**
    633      * A bond attempt failed because pins did not match, or remote device did
    634      * not respond to pin request in time
    635      *
    636      * @hide
    637      */
    638     @UnsupportedAppUsage
    639     public static final int UNBOND_REASON_AUTH_FAILED = 1;
    640 
    641     /**
    642      * A bond attempt failed because the other side explicitly rejected
    643      * bonding
    644      *
    645      * @hide
    646      */
    647     @UnsupportedAppUsage
    648     public static final int UNBOND_REASON_AUTH_REJECTED = 2;
    649 
    650     /**
    651      * A bond attempt failed because we canceled the bonding process
    652      *
    653      * @hide
    654      */
    655     public static final int UNBOND_REASON_AUTH_CANCELED = 3;
    656 
    657     /**
    658      * A bond attempt failed because we could not contact the remote device
    659      *
    660      * @hide
    661      */
    662     @UnsupportedAppUsage
    663     public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
    664 
    665     /**
    666      * A bond attempt failed because a discovery is in progress
    667      *
    668      * @hide
    669      */
    670     @UnsupportedAppUsage
    671     public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
    672 
    673     /**
    674      * A bond attempt failed because of authentication timeout
    675      *
    676      * @hide
    677      */
    678     @UnsupportedAppUsage
    679     public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
    680 
    681     /**
    682      * A bond attempt failed because of repeated attempts
    683      *
    684      * @hide
    685      */
    686     @UnsupportedAppUsage
    687     public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
    688 
    689     /**
    690      * A bond attempt failed because we received an Authentication Cancel
    691      * by remote end
    692      *
    693      * @hide
    694      */
    695     @UnsupportedAppUsage
    696     public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8;
    697 
    698     /**
    699      * An existing bond was explicitly revoked
    700      *
    701      * @hide
    702      */
    703     public static final int UNBOND_REASON_REMOVED = 9;
    704 
    705     /**
    706      * The user will be prompted to enter a pin or
    707      * an app will enter a pin for user.
    708      */
    709     public static final int PAIRING_VARIANT_PIN = 0;
    710 
    711     /**
    712      * The user will be prompted to enter a passkey
    713      *
    714      * @hide
    715      */
    716     public static final int PAIRING_VARIANT_PASSKEY = 1;
    717 
    718     /**
    719      * The user will be prompted to confirm the passkey displayed on the screen or
    720      * an app will confirm the passkey for the user.
    721      */
    722     public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
    723 
    724     /**
    725      * The user will be prompted to accept or deny the incoming pairing request
    726      *
    727      * @hide
    728      */
    729     public static final int PAIRING_VARIANT_CONSENT = 3;
    730 
    731     /**
    732      * The user will be prompted to enter the passkey displayed on remote device
    733      * This is used for Bluetooth 2.1 pairing.
    734      *
    735      * @hide
    736      */
    737     public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
    738 
    739     /**
    740      * The user will be prompted to enter the PIN displayed on remote device.
    741      * This is used for Bluetooth 2.0 pairing.
    742      *
    743      * @hide
    744      */
    745     public static final int PAIRING_VARIANT_DISPLAY_PIN = 5;
    746 
    747     /**
    748      * The user will be prompted to accept or deny the OOB pairing request
    749      *
    750      * @hide
    751      */
    752     public static final int PAIRING_VARIANT_OOB_CONSENT = 6;
    753 
    754     /**
    755      * The user will be prompted to enter a 16 digit pin or
    756      * an app will enter a 16 digit pin for user.
    757      *
    758      * @hide
    759      */
    760     public static final int PAIRING_VARIANT_PIN_16_DIGITS = 7;
    761 
    762     /**
    763      * Used as an extra field in {@link #ACTION_UUID} intents,
    764      * Contains the {@link android.os.ParcelUuid}s of the remote device which
    765      * is a parcelable version of {@link UUID}.
    766      */
    767     public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
    768 
    769     /** @hide */
    770     public static final String EXTRA_SDP_RECORD =
    771             "android.bluetooth.device.extra.SDP_RECORD";
    772 
    773     /** @hide */
    774     @UnsupportedAppUsage
    775     public static final String EXTRA_SDP_SEARCH_STATUS =
    776             "android.bluetooth.device.extra.SDP_SEARCH_STATUS";
    777     /**
    778      * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
    779      * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
    780      *
    781      * @hide
    782      */
    783     @SystemApi
    784     public static final int ACCESS_UNKNOWN = 0;
    785 
    786     /**
    787      * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
    788      * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
    789      *
    790      * @hide
    791      */
    792     @SystemApi
    793     public static final int ACCESS_ALLOWED = 1;
    794 
    795     /**
    796      * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
    797      * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
    798      *
    799      * @hide
    800      */
    801     @SystemApi
    802     public static final int ACCESS_REJECTED = 2;
    803 
    804     /**
    805      * No preference of physical transport for GATT connections to remote dual-mode devices
    806      */
    807     public static final int TRANSPORT_AUTO = 0;
    808 
    809     /**
    810      * Prefer BR/EDR transport for GATT connections to remote dual-mode devices
    811      */
    812     public static final int TRANSPORT_BREDR = 1;
    813 
    814     /**
    815      * Prefer LE transport for GATT connections to remote dual-mode devices
    816      */
    817     public static final int TRANSPORT_LE = 2;
    818 
    819     /**
    820      * Bluetooth LE 1M PHY. Used to refer to LE 1M Physical Channel for advertising, scanning or
    821      * connection.
    822      */
    823     public static final int PHY_LE_1M = 1;
    824 
    825     /**
    826      * Bluetooth LE 2M PHY. Used to refer to LE 2M Physical Channel for advertising, scanning or
    827      * connection.
    828      */
    829     public static final int PHY_LE_2M = 2;
    830 
    831     /**
    832      * Bluetooth LE Coded PHY. Used to refer to LE Coded Physical Channel for advertising, scanning
    833      * or connection.
    834      */
    835     public static final int PHY_LE_CODED = 3;
    836 
    837     /**
    838      * Bluetooth LE 1M PHY mask. Used to specify LE 1M Physical Channel as one of many available
    839      * options in a bitmask.
    840      */
    841     public static final int PHY_LE_1M_MASK = 1;
    842 
    843     /**
    844      * Bluetooth LE 2M PHY mask. Used to specify LE 2M Physical Channel as one of many available
    845      * options in a bitmask.
    846      */
    847     public static final int PHY_LE_2M_MASK = 2;
    848 
    849     /**
    850      * Bluetooth LE Coded PHY mask. Used to specify LE Coded Physical Channel as one of many
    851      * available options in a bitmask.
    852      */
    853     public static final int PHY_LE_CODED_MASK = 4;
    854 
    855     /**
    856      * No preferred coding when transmitting on the LE Coded PHY.
    857      */
    858     public static final int PHY_OPTION_NO_PREFERRED = 0;
    859 
    860     /**
    861      * Prefer the S=2 coding to be used when transmitting on the LE Coded PHY.
    862      */
    863     public static final int PHY_OPTION_S2 = 1;
    864 
    865     /**
    866      * Prefer the S=8 coding to be used when transmitting on the LE Coded PHY.
    867      */
    868     public static final int PHY_OPTION_S8 = 2;
    869 
    870 
    871     /** @hide */
    872     public static final String EXTRA_MAS_INSTANCE =
    873             "android.bluetooth.device.extra.MAS_INSTANCE";
    874 
    875     /**
    876      * Lazy initialization. Guaranteed final after first object constructed, or
    877      * getService() called.
    878      * TODO: Unify implementation of sService amongst BluetoothFoo API's
    879      */
    880     private static volatile IBluetooth sService;
    881 
    882     private final String mAddress;
    883 
    884     /*package*/
    885     @UnsupportedAppUsage
    886     static IBluetooth getService() {
    887         synchronized (BluetoothDevice.class) {
    888             if (sService == null) {
    889                 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    890                 sService = adapter.getBluetoothService(sStateChangeCallback);
    891             }
    892         }
    893         return sService;
    894     }
    895 
    896     static IBluetoothManagerCallback sStateChangeCallback = new IBluetoothManagerCallback.Stub() {
    897 
    898         public void onBluetoothServiceUp(IBluetooth bluetoothService)
    899                 throws RemoteException {
    900             synchronized (BluetoothDevice.class) {
    901                 if (sService == null) {
    902                     sService = bluetoothService;
    903                 }
    904             }
    905         }
    906 
    907         public void onBluetoothServiceDown()
    908                 throws RemoteException {
    909             synchronized (BluetoothDevice.class) {
    910                 sService = null;
    911             }
    912         }
    913 
    914         public void onBrEdrDown() {
    915             if (DBG) Log.d(TAG, "onBrEdrDown: reached BLE ON state");
    916         }
    917     };
    918 
    919     /**
    920      * Create a new BluetoothDevice
    921      * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB",
    922      * and is validated in this constructor.
    923      *
    924      * @param address valid Bluetooth MAC address
    925      * @throws RuntimeException Bluetooth is not available on this platform
    926      * @throws IllegalArgumentException address is invalid
    927      * @hide
    928      */
    929     @UnsupportedAppUsage
    930     /*package*/ BluetoothDevice(String address) {
    931         getService();  // ensures sService is initialized
    932         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
    933             throw new IllegalArgumentException(address + " is not a valid Bluetooth address");
    934         }
    935 
    936         mAddress = address;
    937     }
    938 
    939     @Override
    940     public boolean equals(Object o) {
    941         if (o instanceof BluetoothDevice) {
    942             return mAddress.equals(((BluetoothDevice) o).getAddress());
    943         }
    944         return false;
    945     }
    946 
    947     @Override
    948     public int hashCode() {
    949         return mAddress.hashCode();
    950     }
    951 
    952     /**
    953      * Returns a string representation of this BluetoothDevice.
    954      * <p>Currently this is the Bluetooth hardware address, for example
    955      * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress}
    956      * if you explicitly require the Bluetooth hardware address in case the
    957      * {@link #toString} representation changes in the future.
    958      *
    959      * @return string representation of this BluetoothDevice
    960      */
    961     @Override
    962     public String toString() {
    963         return mAddress;
    964     }
    965 
    966     @Override
    967     public int describeContents() {
    968         return 0;
    969     }
    970 
    971     public static final @android.annotation.NonNull Parcelable.Creator<BluetoothDevice> CREATOR =
    972             new Parcelable.Creator<BluetoothDevice>() {
    973                 public BluetoothDevice createFromParcel(Parcel in) {
    974                     return new BluetoothDevice(in.readString());
    975                 }
    976 
    977                 public BluetoothDevice[] newArray(int size) {
    978                     return new BluetoothDevice[size];
    979                 }
    980             };
    981 
    982     @Override
    983     public void writeToParcel(Parcel out, int flags) {
    984         out.writeString(mAddress);
    985     }
    986 
    987     /**
    988      * Returns the hardware address of this BluetoothDevice.
    989      * <p> For example, "00:11:22:AA:BB:CC".
    990      *
    991      * @return Bluetooth hardware address as string
    992      */
    993     public String getAddress() {
    994         if (DBG) Log.d(TAG, "mAddress: " + mAddress);
    995         return mAddress;
    996     }
    997 
    998     /**
    999      * Get the friendly Bluetooth name of the remote device.
   1000      *
   1001      * <p>The local adapter will automatically retrieve remote names when
   1002      * performing a device scan, and will cache them. This method just returns
   1003      * the name for this device from the cache.
   1004      *
   1005      * @return the Bluetooth name, or null if there was a problem.
   1006      */
   1007     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1008     public String getName() {
   1009         final IBluetooth service = sService;
   1010         if (service == null) {
   1011             Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
   1012             return null;
   1013         }
   1014         try {
   1015             String name = service.getRemoteName(this);
   1016             if (name != null) {
   1017                 return name.replaceAll("[\\t\\n\\r]+", " ");
   1018             }
   1019             return null;
   1020         } catch (RemoteException e) {
   1021             Log.e(TAG, "", e);
   1022         }
   1023         return null;
   1024     }
   1025 
   1026     /**
   1027      * Get the Bluetooth device type of the remote device.
   1028      *
   1029      * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} {@link
   1030      * #DEVICE_TYPE_DUAL}. {@link #DEVICE_TYPE_UNKNOWN} if it's not available
   1031      */
   1032     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1033     public int getType() {
   1034         final IBluetooth service = sService;
   1035         if (service == null) {
   1036             Log.e(TAG, "BT not enabled. Cannot get Remote Device type");
   1037             return DEVICE_TYPE_UNKNOWN;
   1038         }
   1039         try {
   1040             return service.getRemoteType(this);
   1041         } catch (RemoteException e) {
   1042             Log.e(TAG, "", e);
   1043         }
   1044         return DEVICE_TYPE_UNKNOWN;
   1045     }
   1046 
   1047     /**
   1048      * Get the Bluetooth alias of the remote device.
   1049      * <p>Alias is the locally modified name of a remote device.
   1050      *
   1051      * @return the Bluetooth alias, or null if no alias or there was a problem
   1052      * @hide
   1053      */
   1054     @UnsupportedAppUsage
   1055     public String getAlias() {
   1056         final IBluetooth service = sService;
   1057         if (service == null) {
   1058             Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
   1059             return null;
   1060         }
   1061         try {
   1062             return service.getRemoteAlias(this);
   1063         } catch (RemoteException e) {
   1064             Log.e(TAG, "", e);
   1065         }
   1066         return null;
   1067     }
   1068 
   1069     /**
   1070      * Set the Bluetooth alias of the remote device.
   1071      * <p>Alias is the locally modified name of a remote device.
   1072      * <p>This methoid overwrites the alias. The changed
   1073      * alias is saved in the local storage so that the change
   1074      * is preserved over power cycle.
   1075      *
   1076      * @return true on success, false on error
   1077      * @hide
   1078      */
   1079     @UnsupportedAppUsage
   1080     public boolean setAlias(String alias) {
   1081         final IBluetooth service = sService;
   1082         if (service == null) {
   1083             Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
   1084             return false;
   1085         }
   1086         try {
   1087             return service.setRemoteAlias(this, alias);
   1088         } catch (RemoteException e) {
   1089             Log.e(TAG, "", e);
   1090         }
   1091         return false;
   1092     }
   1093 
   1094     /**
   1095      * Get the Bluetooth alias of the remote device.
   1096      * If Alias is null, get the Bluetooth name instead.
   1097      *
   1098      * @return the Bluetooth alias, or null if no alias or there was a problem
   1099      * @hide
   1100      * @see #getAlias()
   1101      * @see #getName()
   1102      */
   1103     @UnsupportedAppUsage
   1104     public String getAliasName() {
   1105         String name = getAlias();
   1106         if (name == null) {
   1107             name = getName();
   1108         }
   1109         return name;
   1110     }
   1111 
   1112     /**
   1113      * Get the most recent identified battery level of this Bluetooth device
   1114      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
   1115      *
   1116      * @return Battery level in percents from 0 to 100, or {@link #BATTERY_LEVEL_UNKNOWN} if
   1117      * Bluetooth is disabled, or device is disconnected, or does not have any battery reporting
   1118      * service, or return value is invalid
   1119      * @hide
   1120      */
   1121     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1122     @UnsupportedAppUsage
   1123     public int getBatteryLevel() {
   1124         final IBluetooth service = sService;
   1125         if (service == null) {
   1126             Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level");
   1127             return BATTERY_LEVEL_UNKNOWN;
   1128         }
   1129         try {
   1130             return service.getBatteryLevel(this);
   1131         } catch (RemoteException e) {
   1132             Log.e(TAG, "", e);
   1133         }
   1134         return BATTERY_LEVEL_UNKNOWN;
   1135     }
   1136 
   1137     /**
   1138      * Start the bonding (pairing) process with the remote device.
   1139      * <p>This is an asynchronous call, it will return immediately. Register
   1140      * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
   1141      * the bonding process completes, and its result.
   1142      * <p>Android system services will handle the necessary user interactions
   1143      * to confirm and complete the bonding process.
   1144      *
   1145      * @return false on immediate error, true if bonding will begin
   1146      */
   1147     @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
   1148     public boolean createBond() {
   1149         final IBluetooth service = sService;
   1150         if (service == null) {
   1151             Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
   1152             return false;
   1153         }
   1154         try {
   1155             Log.i(TAG, "createBond() for device " + getAddress()
   1156                     + " called by pid: " + Process.myPid()
   1157                     + " tid: " + Process.myTid());
   1158             return service.createBond(this, TRANSPORT_AUTO);
   1159         } catch (RemoteException e) {
   1160             Log.e(TAG, "", e);
   1161         }
   1162         return false;
   1163     }
   1164 
   1165     /**
   1166      * Start the bonding (pairing) process with the remote device using the
   1167      * specified transport.
   1168      *
   1169      * <p>This is an asynchronous call, it will return immediately. Register
   1170      * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
   1171      * the bonding process completes, and its result.
   1172      * <p>Android system services will handle the necessary user interactions
   1173      * to confirm and complete the bonding process.
   1174      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
   1175      *
   1176      * @param transport The transport to use for the pairing procedure.
   1177      * @return false on immediate error, true if bonding will begin
   1178      * @throws IllegalArgumentException if an invalid transport was specified
   1179      * @hide
   1180      */
   1181     @UnsupportedAppUsage
   1182     public boolean createBond(int transport) {
   1183         final IBluetooth service = sService;
   1184         if (service == null) {
   1185             Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
   1186             return false;
   1187         }
   1188         if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) {
   1189             throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport");
   1190         }
   1191         try {
   1192             Log.i(TAG, "createBond() for device " + getAddress()
   1193                     + " called by pid: " + Process.myPid()
   1194                     + " tid: " + Process.myTid());
   1195             return service.createBond(this, transport);
   1196         } catch (RemoteException e) {
   1197             Log.e(TAG, "", e);
   1198         }
   1199         return false;
   1200     }
   1201 
   1202     /**
   1203      * Start the bonding (pairing) process with the remote device using the
   1204      * Out Of Band mechanism.
   1205      *
   1206      * <p>This is an asynchronous call, it will return immediately. Register
   1207      * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
   1208      * the bonding process completes, and its result.
   1209      *
   1210      * <p>Android system services will handle the necessary user interactions
   1211      * to confirm and complete the bonding process.
   1212      *
   1213      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
   1214      *
   1215      * @param transport - Transport to use
   1216      * @param oobData - Out Of Band data
   1217      * @return false on immediate error, true if bonding will begin
   1218      * @hide
   1219      */
   1220     public boolean createBondOutOfBand(int transport, OobData oobData) {
   1221         final IBluetooth service = sService;
   1222         if (service == null) {
   1223             Log.w(TAG, "BT not enabled, createBondOutOfBand failed");
   1224             return false;
   1225         }
   1226         try {
   1227             return service.createBondOutOfBand(this, transport, oobData);
   1228         } catch (RemoteException e) {
   1229             Log.e(TAG, "", e);
   1230         }
   1231         return false;
   1232     }
   1233 
   1234     /** @hide */
   1235     @UnsupportedAppUsage
   1236     public boolean isBondingInitiatedLocally() {
   1237         final IBluetooth service = sService;
   1238         if (service == null) {
   1239             Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed");
   1240             return false;
   1241         }
   1242         try {
   1243             return service.isBondingInitiatedLocally(this);
   1244         } catch (RemoteException e) {
   1245             Log.e(TAG, "", e);
   1246         }
   1247         return false;
   1248     }
   1249 
   1250     /**
   1251      * Set the Out Of Band data for a remote device to be used later
   1252      * in the pairing mechanism. Users can obtain this data through other
   1253      * trusted channels
   1254      *
   1255      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
   1256      *
   1257      * @param hash Simple Secure pairing hash
   1258      * @param randomizer The random key obtained using OOB
   1259      * @return false on error; true otherwise
   1260      * @hide
   1261      */
   1262     public boolean setDeviceOutOfBandData(byte[] hash, byte[] randomizer) {
   1263         //TODO(BT)
   1264       /*
   1265       try {
   1266         return sService.setDeviceOutOfBandData(this, hash, randomizer);
   1267       } catch (RemoteException e) {Log.e(TAG, "", e);} */
   1268         return false;
   1269     }
   1270 
   1271     /**
   1272      * Cancel an in-progress bonding request started with {@link #createBond}.
   1273      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
   1274      *
   1275      * @return true on success, false on error
   1276      * @hide
   1277      */
   1278     @SystemApi
   1279     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
   1280     public boolean cancelBondProcess() {
   1281         final IBluetooth service = sService;
   1282         if (service == null) {
   1283             Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond");
   1284             return false;
   1285         }
   1286         try {
   1287             Log.i(TAG, "cancelBondProcess() for device " + getAddress()
   1288                     + " called by pid: " + Process.myPid()
   1289                     + " tid: " + Process.myTid());
   1290             return service.cancelBondProcess(this);
   1291         } catch (RemoteException e) {
   1292             Log.e(TAG, "", e);
   1293         }
   1294         return false;
   1295     }
   1296 
   1297     /**
   1298      * Remove bond (pairing) with the remote device.
   1299      * <p>Delete the link key associated with the remote device, and
   1300      * immediately terminate connections to that device that require
   1301      * authentication and encryption.
   1302      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
   1303      *
   1304      * @return true on success, false on error
   1305      * @hide
   1306      */
   1307     @SystemApi
   1308     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
   1309     public boolean removeBond() {
   1310         final IBluetooth service = sService;
   1311         if (service == null) {
   1312             Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond");
   1313             return false;
   1314         }
   1315         try {
   1316             Log.i(TAG, "removeBond() for device " + getAddress()
   1317                     + " called by pid: " + Process.myPid()
   1318                     + " tid: " + Process.myTid());
   1319             return service.removeBond(this);
   1320         } catch (RemoteException e) {
   1321             Log.e(TAG, "", e);
   1322         }
   1323         return false;
   1324     }
   1325 
   1326     /**
   1327      * Get the bond state of the remote device.
   1328      * <p>Possible values for the bond state are:
   1329      * {@link #BOND_NONE},
   1330      * {@link #BOND_BONDING},
   1331      * {@link #BOND_BONDED}.
   1332      *
   1333      * @return the bond state
   1334      */
   1335     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1336     public int getBondState() {
   1337         final IBluetooth service = sService;
   1338         if (service == null) {
   1339             Log.e(TAG, "BT not enabled. Cannot get bond state");
   1340             return BOND_NONE;
   1341         }
   1342         try {
   1343             return service.getBondState(this);
   1344         } catch (RemoteException e) {
   1345             Log.e(TAG, "", e);
   1346         }
   1347         return BOND_NONE;
   1348     }
   1349 
   1350     /**
   1351      * Returns whether there is an open connection to this device.
   1352      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
   1353      *
   1354      * @return True if there is at least one open connection to this device.
   1355      * @hide
   1356      */
   1357     @SystemApi
   1358     @RequiresPermission(android.Manifest.permission.BLUETOOTH)
   1359     public boolean isConnected() {
   1360         final IBluetooth service = sService;
   1361         if (service == null) {
   1362             // BT is not enabled, we cannot be connected.
   1363             return false;
   1364         }
   1365         try {
   1366             return service.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED;
   1367         } catch (RemoteException e) {
   1368             Log.e(TAG, "", e);
   1369             return false;
   1370         }
   1371     }
   1372 
   1373     /**
   1374      * Returns whether there is an open connection to this device
   1375      * that has been encrypted.
   1376      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
   1377      *
   1378      * @return True if there is at least one encrypted connection to this device.
   1379      * @hide
   1380      */
   1381     @SystemApi
   1382     @RequiresPermission(android.Manifest.permission.BLUETOOTH)
   1383     public boolean isEncrypted() {
   1384         final IBluetooth service = sService;
   1385         if (service == null) {
   1386             // BT is not enabled, we cannot be connected.
   1387             return false;
   1388         }
   1389         try {
   1390             return service.getConnectionState(this) > CONNECTION_STATE_CONNECTED;
   1391         } catch (RemoteException e) {
   1392             Log.e(TAG, "", e);
   1393             return false;
   1394         }
   1395     }
   1396 
   1397     /**
   1398      * Get the Bluetooth class of the remote device.
   1399      *
   1400      * @return Bluetooth class object, or null on error
   1401      */
   1402     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1403     public BluetoothClass getBluetoothClass() {
   1404         final IBluetooth service = sService;
   1405         if (service == null) {
   1406             Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
   1407             return null;
   1408         }
   1409         try {
   1410             int classInt = service.getRemoteClass(this);
   1411             if (classInt == BluetoothClass.ERROR) return null;
   1412             return new BluetoothClass(classInt);
   1413         } catch (RemoteException e) {
   1414             Log.e(TAG, "", e);
   1415         }
   1416         return null;
   1417     }
   1418 
   1419     /**
   1420      * Returns the supported features (UUIDs) of the remote device.
   1421      *
   1422      * <p>This method does not start a service discovery procedure to retrieve the UUIDs
   1423      * from the remote device. Instead, the local cached copy of the service
   1424      * UUIDs are returned.
   1425      * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired.
   1426      *
   1427      * @return the supported features (UUIDs) of the remote device, or null on error
   1428      */
   1429     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1430     public ParcelUuid[] getUuids() {
   1431         final IBluetooth service = sService;
   1432         if (service == null || !isBluetoothEnabled()) {
   1433             Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
   1434             return null;
   1435         }
   1436         try {
   1437             return service.getRemoteUuids(this);
   1438         } catch (RemoteException e) {
   1439             Log.e(TAG, "", e);
   1440         }
   1441         return null;
   1442     }
   1443 
   1444     /**
   1445      * Perform a service discovery on the remote device to get the UUIDs supported.
   1446      *
   1447      * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent,
   1448      * with the UUIDs supported by the remote end. If there is an error
   1449      * in getting the SDP records or if the process takes a long time,
   1450      * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently
   1451      * present in the cache. Clients should use the {@link #getUuids} to get UUIDs
   1452      * if service discovery is not to be performed.
   1453      *
   1454      * @return False if the sanity check fails, True if the process of initiating an ACL connection
   1455      * to the remote device was started.
   1456      */
   1457     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1458     public boolean fetchUuidsWithSdp() {
   1459         final IBluetooth service = sService;
   1460         if (service == null || !isBluetoothEnabled()) {
   1461             Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp");
   1462             return false;
   1463         }
   1464         try {
   1465             return service.fetchRemoteUuids(this);
   1466         } catch (RemoteException e) {
   1467             Log.e(TAG, "", e);
   1468         }
   1469         return false;
   1470     }
   1471 
   1472     /**
   1473      * Perform a service discovery on the remote device to get the SDP records associated
   1474      * with the specified UUID.
   1475      *
   1476      * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent,
   1477      * with the SDP records found on the remote end. If there is an error
   1478      * in getting the SDP records or if the process takes a long time,
   1479      * {@link #ACTION_SDP_RECORD} intent is sent with an status value in
   1480      * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0.
   1481      * Detailed status error codes can be found by members of the Bluetooth package in
   1482      * the AbstractionLayer class.
   1483      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
   1484      * The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}.
   1485      * The object type will match one of the SdpXxxRecord types, depending on the UUID searched
   1486      * for.
   1487      *
   1488      * @return False if the sanity check fails, True if the process
   1489      *               of initiating an ACL connection to the remote device
   1490      *               was started.
   1491      */
   1492     /** @hide */
   1493     public boolean sdpSearch(ParcelUuid uuid) {
   1494         final IBluetooth service = sService;
   1495         if (service == null) {
   1496             Log.e(TAG, "BT not enabled. Cannot query remote device sdp records");
   1497             return false;
   1498         }
   1499         try {
   1500             return service.sdpSearch(this, uuid);
   1501         } catch (RemoteException e) {
   1502             Log.e(TAG, "", e);
   1503         }
   1504         return false;
   1505     }
   1506 
   1507     /**
   1508      * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
   1509      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
   1510      *
   1511      * @return true pin has been set false for error
   1512      */
   1513     public boolean setPin(byte[] pin) {
   1514         final IBluetooth service = sService;
   1515         if (service == null) {
   1516             Log.e(TAG, "BT not enabled. Cannot set Remote Device pin");
   1517             return false;
   1518         }
   1519         try {
   1520             return service.setPin(this, true, pin.length, pin);
   1521         } catch (RemoteException e) {
   1522             Log.e(TAG, "", e);
   1523         }
   1524         return false;
   1525     }
   1526 
   1527     /** @hide */
   1528     @UnsupportedAppUsage
   1529     public boolean setPasskey(int passkey) {
   1530         //TODO(BT)
   1531         /*
   1532         try {
   1533             return sService.setPasskey(this, true, 4, passkey);
   1534         } catch (RemoteException e) {Log.e(TAG, "", e);}*/
   1535         return false;
   1536     }
   1537 
   1538     /**
   1539      * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing.
   1540      *
   1541      * @return true confirmation has been sent out false for error
   1542      */
   1543     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
   1544     public boolean setPairingConfirmation(boolean confirm) {
   1545         final IBluetooth service = sService;
   1546         if (service == null) {
   1547             Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
   1548             return false;
   1549         }
   1550         try {
   1551             return service.setPairingConfirmation(this, confirm);
   1552         } catch (RemoteException e) {
   1553             Log.e(TAG, "", e);
   1554         }
   1555         return false;
   1556     }
   1557 
   1558     /** @hide */
   1559     public boolean setRemoteOutOfBandData() {
   1560         // TODO(BT)
   1561         /*
   1562         try {
   1563           return sService.setRemoteOutOfBandData(this);
   1564       } catch (RemoteException e) {Log.e(TAG, "", e);}*/
   1565         return false;
   1566     }
   1567 
   1568     /** @hide */
   1569     @UnsupportedAppUsage
   1570     public boolean cancelPairingUserInput() {
   1571         final IBluetooth service = sService;
   1572         if (service == null) {
   1573             Log.e(TAG, "BT not enabled. Cannot create pairing user input");
   1574             return false;
   1575         }
   1576         try {
   1577             return service.cancelBondProcess(this);
   1578         } catch (RemoteException e) {
   1579             Log.e(TAG, "", e);
   1580         }
   1581         return false;
   1582     }
   1583 
   1584     /** @hide */
   1585     @UnsupportedAppUsage
   1586     public boolean isBluetoothDock() {
   1587         // TODO(BT)
   1588         /*
   1589         try {
   1590             return sService.isBluetoothDock(this);
   1591         } catch (RemoteException e) {Log.e(TAG, "", e);}*/
   1592         return false;
   1593     }
   1594 
   1595     boolean isBluetoothEnabled() {
   1596         boolean ret = false;
   1597         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   1598         if (adapter != null && adapter.isEnabled()) {
   1599             ret = true;
   1600         }
   1601         return ret;
   1602     }
   1603 
   1604     /**
   1605      * Requires {@link android.Manifest.permission#BLUETOOTH}.
   1606      *
   1607      * @return Whether the phonebook access is allowed to this device. Can be {@link
   1608      * #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
   1609      * @hide
   1610      */
   1611     @UnsupportedAppUsage
   1612     public int getPhonebookAccessPermission() {
   1613         final IBluetooth service = sService;
   1614         if (service == null) {
   1615             return ACCESS_UNKNOWN;
   1616         }
   1617         try {
   1618             return service.getPhonebookAccessPermission(this);
   1619         } catch (RemoteException e) {
   1620             Log.e(TAG, "", e);
   1621         }
   1622         return ACCESS_UNKNOWN;
   1623     }
   1624 
   1625     /**
   1626      * Sets whether the {@link BluetoothDevice} enters silence mode. Audio will not
   1627      * be routed to the {@link BluetoothDevice} if set to {@code true}.
   1628      *
   1629      * When the {@link BluetoothDevice} enters silence mode, and the {@link BluetoothDevice}
   1630      * is an active device (for A2DP or HFP), the active device for that profile
   1631      * will be set to null.
   1632      * If the {@link BluetoothDevice} exits silence mode while the A2DP or HFP
   1633      * active device is null, the {@link BluetoothDevice} will be set as the
   1634      * active device for that profile.
   1635      * If the {@link BluetoothDevice} is disconnected, it exits silence mode.
   1636      * If the {@link BluetoothDevice} is set as the active device for A2DP or
   1637      * HFP, while silence mode is enabled, then the device will exit silence mode.
   1638      * If the {@link BluetoothDevice} is in silence mode, AVRCP position change
   1639      * event and HFP AG indicators will be disabled.
   1640      * If the {@link BluetoothDevice} is not connected with A2DP or HFP, it cannot
   1641      * enter silence mode.
   1642      *
   1643      * <p> Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
   1644      *
   1645      * @param silence true to enter silence mode, false to exit
   1646      * @return true on success, false on error.
   1647      * @throws IllegalStateException if Bluetooth is not turned ON.
   1648      * @hide
   1649      */
   1650     @SystemApi
   1651     @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
   1652     public boolean setSilenceMode(boolean silence) {
   1653         final IBluetooth service = sService;
   1654         if (service == null) {
   1655             throw new IllegalStateException("Bluetooth is not turned ON");
   1656         }
   1657         try {
   1658             return service.setSilenceMode(this, silence);
   1659         } catch (RemoteException e) {
   1660             Log.e(TAG, "setSilenceMode fail", e);
   1661             return false;
   1662         }
   1663     }
   1664 
   1665     /**
   1666      * Check whether the {@link BluetoothDevice} is in silence mode
   1667      *
   1668      * <p> Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
   1669      *
   1670      * @return true on device in silence mode, otherwise false.
   1671      * @throws IllegalStateException if Bluetooth is not turned ON.
   1672      * @hide
   1673      */
   1674     @SystemApi
   1675     @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
   1676     public boolean isInSilenceMode() {
   1677         final IBluetooth service = sService;
   1678         if (service == null) {
   1679             throw new IllegalStateException("Bluetooth is not turned ON");
   1680         }
   1681         try {
   1682             return service.getSilenceMode(this);
   1683         } catch (RemoteException e) {
   1684             Log.e(TAG, "isInSilenceMode fail", e);
   1685             return false;
   1686         }
   1687     }
   1688 
   1689     /**
   1690      * Sets whether the phonebook access is allowed to this device.
   1691      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
   1692      *
   1693      * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
   1694      * #ACCESS_REJECTED}.
   1695      * @return Whether the value has been successfully set.
   1696      * @hide
   1697      */
   1698     @SystemApi
   1699     @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
   1700     public boolean setPhonebookAccessPermission(int value) {
   1701         final IBluetooth service = sService;
   1702         if (service == null) {
   1703             return false;
   1704         }
   1705         try {
   1706             return service.setPhonebookAccessPermission(this, value);
   1707         } catch (RemoteException e) {
   1708             Log.e(TAG, "", e);
   1709         }
   1710         return false;
   1711     }
   1712 
   1713     /**
   1714      * Requires {@link android.Manifest.permission#BLUETOOTH}.
   1715      *
   1716      * @return Whether the message access is allowed to this device. Can be {@link #ACCESS_UNKNOWN},
   1717      * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
   1718      * @hide
   1719      */
   1720     @UnsupportedAppUsage
   1721     public int getMessageAccessPermission() {
   1722         final IBluetooth service = sService;
   1723         if (service == null) {
   1724             return ACCESS_UNKNOWN;
   1725         }
   1726         try {
   1727             return service.getMessageAccessPermission(this);
   1728         } catch (RemoteException e) {
   1729             Log.e(TAG, "", e);
   1730         }
   1731         return ACCESS_UNKNOWN;
   1732     }
   1733 
   1734     /**
   1735      * Sets whether the message access is allowed to this device.
   1736      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
   1737      *
   1738      * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
   1739      * #ACCESS_REJECTED}.
   1740      * @return Whether the value has been successfully set.
   1741      * @hide
   1742      */
   1743     @UnsupportedAppUsage
   1744     public boolean setMessageAccessPermission(int value) {
   1745         final IBluetooth service = sService;
   1746         if (service == null) {
   1747             return false;
   1748         }
   1749         try {
   1750             return service.setMessageAccessPermission(this, value);
   1751         } catch (RemoteException e) {
   1752             Log.e(TAG, "", e);
   1753         }
   1754         return false;
   1755     }
   1756 
   1757     /**
   1758      * Requires {@link android.Manifest.permission#BLUETOOTH}.
   1759      *
   1760      * @return Whether the Sim access is allowed to this device. Can be {@link #ACCESS_UNKNOWN},
   1761      * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}.
   1762      * @hide
   1763      */
   1764     public int getSimAccessPermission() {
   1765         final IBluetooth service = sService;
   1766         if (service == null) {
   1767             return ACCESS_UNKNOWN;
   1768         }
   1769         try {
   1770             return service.getSimAccessPermission(this);
   1771         } catch (RemoteException e) {
   1772             Log.e(TAG, "", e);
   1773         }
   1774         return ACCESS_UNKNOWN;
   1775     }
   1776 
   1777     /**
   1778      * Sets whether the Sim access is allowed to this device.
   1779      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
   1780      *
   1781      * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link
   1782      * #ACCESS_REJECTED}.
   1783      * @return Whether the value has been successfully set.
   1784      * @hide
   1785      */
   1786     @UnsupportedAppUsage
   1787     public boolean setSimAccessPermission(int value) {
   1788         final IBluetooth service = sService;
   1789         if (service == null) {
   1790             return false;
   1791         }
   1792         try {
   1793             return service.setSimAccessPermission(this, value);
   1794         } catch (RemoteException e) {
   1795             Log.e(TAG, "", e);
   1796         }
   1797         return false;
   1798     }
   1799 
   1800     /**
   1801      * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
   1802      * outgoing connection to this remote device on given channel.
   1803      * <p>The remote device will be authenticated and communication on this
   1804      * socket will be encrypted.
   1805      * <p> Use this socket only if an authenticated socket link is possible.
   1806      * Authentication refers to the authentication of the link key to
   1807      * prevent man-in-the-middle type of attacks.
   1808      * For example, for Bluetooth 2.1 devices, if any of the devices does not
   1809      * have an input and output capability or just has the ability to
   1810      * display a numeric key, a secure socket connection is not possible.
   1811      * In such a case, use {@link createInsecureRfcommSocket}.
   1812      * For more details, refer to the Security Model section 5.2 (vol 3) of
   1813      * Bluetooth Core Specification version 2.1 + EDR.
   1814      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
   1815      * connection.
   1816      * <p>Valid RFCOMM channels are in range 1 to 30.
   1817      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
   1818      *
   1819      * @param channel RFCOMM channel to connect to
   1820      * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
   1821      * @throws IOException on error, for example Bluetooth not available, or insufficient
   1822      * permissions
   1823      * @hide
   1824      */
   1825     @UnsupportedAppUsage
   1826     public BluetoothSocket createRfcommSocket(int channel) throws IOException {
   1827         if (!isBluetoothEnabled()) {
   1828             Log.e(TAG, "Bluetooth is not enabled");
   1829             throw new IOException();
   1830         }
   1831         return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel,
   1832                 null);
   1833     }
   1834 
   1835     /**
   1836      * Create an L2cap {@link BluetoothSocket} ready to start a secure
   1837      * outgoing connection to this remote device on given channel.
   1838      * <p>The remote device will be authenticated and communication on this
   1839      * socket will be encrypted.
   1840      * <p> Use this socket only if an authenticated socket link is possible.
   1841      * Authentication refers to the authentication of the link key to
   1842      * prevent man-in-the-middle type of attacks.
   1843      * For example, for Bluetooth 2.1 devices, if any of the devices does not
   1844      * have an input and output capability or just has the ability to
   1845      * display a numeric key, a secure socket connection is not possible.
   1846      * In such a case, use {@link createInsecureRfcommSocket}.
   1847      * For more details, refer to the Security Model section 5.2 (vol 3) of
   1848      * Bluetooth Core Specification version 2.1 + EDR.
   1849      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
   1850      * connection.
   1851      * <p>Valid L2CAP PSM channels are in range 1 to 2^16.
   1852      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
   1853      *
   1854      * @param channel L2cap PSM/channel to connect to
   1855      * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
   1856      * @throws IOException on error, for example Bluetooth not available, or insufficient
   1857      * permissions
   1858      * @hide
   1859      */
   1860     public BluetoothSocket createL2capSocket(int channel) throws IOException {
   1861         return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, true, true, this, channel,
   1862                 null);
   1863     }
   1864 
   1865     /**
   1866      * Create an L2cap {@link BluetoothSocket} ready to start an insecure
   1867      * outgoing connection to this remote device on given channel.
   1868      * <p>The remote device will be not authenticated and communication on this
   1869      * socket will not be encrypted.
   1870      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
   1871      * connection.
   1872      * <p>Valid L2CAP PSM channels are in range 1 to 2^16.
   1873      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
   1874      *
   1875      * @param channel L2cap PSM/channel to connect to
   1876      * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
   1877      * @throws IOException on error, for example Bluetooth not available, or insufficient
   1878      * permissions
   1879      * @hide
   1880      */
   1881     public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException {
   1882         return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false, false, this, channel,
   1883                 null);
   1884     }
   1885 
   1886     /**
   1887      * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
   1888      * outgoing connection to this remote device using SDP lookup of uuid.
   1889      * <p>This is designed to be used with {@link
   1890      * BluetoothAdapter#listenUsingRfcommWithServiceRecord} for peer-peer
   1891      * Bluetooth applications.
   1892      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
   1893      * connection. This will also perform an SDP lookup of the given uuid to
   1894      * determine which channel to connect to.
   1895      * <p>The remote device will be authenticated and communication on this
   1896      * socket will be encrypted.
   1897      * <p> Use this socket only if an authenticated socket link is possible.
   1898      * Authentication refers to the authentication of the link key to
   1899      * prevent man-in-the-middle type of attacks.
   1900      * For example, for Bluetooth 2.1 devices, if any of the devices does not
   1901      * have an input and output capability or just has the ability to
   1902      * display a numeric key, a secure socket connection is not possible.
   1903      * In such a case, use {@link #createInsecureRfcommSocketToServiceRecord}.
   1904      * For more details, refer to the Security Model section 5.2 (vol 3) of
   1905      * Bluetooth Core Specification version 2.1 + EDR.
   1906      * <p>Hint: If you are connecting to a Bluetooth serial board then try
   1907      * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
   1908      * However if you are connecting to an Android peer then please generate
   1909      * your own unique UUID.
   1910      *
   1911      * @param uuid service record uuid to lookup RFCOMM channel
   1912      * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
   1913      * @throws IOException on error, for example Bluetooth not available, or insufficient
   1914      * permissions
   1915      */
   1916     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1917     public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
   1918         if (!isBluetoothEnabled()) {
   1919             Log.e(TAG, "Bluetooth is not enabled");
   1920             throw new IOException();
   1921         }
   1922 
   1923         return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1,
   1924                 new ParcelUuid(uuid));
   1925     }
   1926 
   1927     /**
   1928      * Create an RFCOMM {@link BluetoothSocket} socket ready to start an insecure
   1929      * outgoing connection to this remote device using SDP lookup of uuid.
   1930      * <p> The communication channel will not have an authenticated link key
   1931      * i.e it will be subject to man-in-the-middle attacks. For Bluetooth 2.1
   1932      * devices, the link key will be encrypted, as encryption is mandatory.
   1933      * For legacy devices (pre Bluetooth 2.1 devices) the link key will
   1934      * be not be encrypted. Use {@link #createRfcommSocketToServiceRecord} if an
   1935      * encrypted and authenticated communication channel is desired.
   1936      * <p>This is designed to be used with {@link
   1937      * BluetoothAdapter#listenUsingInsecureRfcommWithServiceRecord} for peer-peer
   1938      * Bluetooth applications.
   1939      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
   1940      * connection. This will also perform an SDP lookup of the given uuid to
   1941      * determine which channel to connect to.
   1942      * <p>The remote device will be authenticated and communication on this
   1943      * socket will be encrypted.
   1944      * <p>Hint: If you are connecting to a Bluetooth serial board then try
   1945      * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
   1946      * However if you are connecting to an Android peer then please generate
   1947      * your own unique UUID.
   1948      *
   1949      * @param uuid service record uuid to lookup RFCOMM channel
   1950      * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
   1951      * @throws IOException on error, for example Bluetooth not available, or insufficient
   1952      * permissions
   1953      */
   1954     @RequiresPermission(Manifest.permission.BLUETOOTH)
   1955     public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
   1956         if (!isBluetoothEnabled()) {
   1957             Log.e(TAG, "Bluetooth is not enabled");
   1958             throw new IOException();
   1959         }
   1960         return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1,
   1961                 new ParcelUuid(uuid));
   1962     }
   1963 
   1964     /**
   1965      * Construct an insecure RFCOMM socket ready to start an outgoing
   1966      * connection.
   1967      * Call #connect on the returned #BluetoothSocket to begin the connection.
   1968      * The remote device will not be authenticated and communication on this
   1969      * socket will not be encrypted.
   1970      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
   1971      *
   1972      * @param port remote port
   1973      * @return An RFCOMM BluetoothSocket
   1974      * @throws IOException On error, for example Bluetooth not available, or insufficient
   1975      * permissions.
   1976      * @hide
   1977      */
   1978     @UnsupportedAppUsage
   1979     public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
   1980         if (!isBluetoothEnabled()) {
   1981             Log.e(TAG, "Bluetooth is not enabled");
   1982             throw new IOException();
   1983         }
   1984         return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port,
   1985                 null);
   1986     }
   1987 
   1988     /**
   1989      * Construct a SCO socket ready to start an outgoing connection.
   1990      * Call #connect on the returned #BluetoothSocket to begin the connection.
   1991      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
   1992      *
   1993      * @return a SCO BluetoothSocket
   1994      * @throws IOException on error, for example Bluetooth not available, or insufficient
   1995      * permissions.
   1996      * @hide
   1997      */
   1998     @UnsupportedAppUsage
   1999     public BluetoothSocket createScoSocket() throws IOException {
   2000         if (!isBluetoothEnabled()) {
   2001             Log.e(TAG, "Bluetooth is not enabled");
   2002             throw new IOException();
   2003         }
   2004         return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null);
   2005     }
   2006 
   2007     /**
   2008      * Check that a pin is valid and convert to byte array.
   2009      *
   2010      * Bluetooth pin's are 1 to 16 bytes of UTF-8 characters.
   2011      *
   2012      * @param pin pin as java String
   2013      * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin.
   2014      * @hide
   2015      */
   2016     @UnsupportedAppUsage
   2017     public static byte[] convertPinToBytes(String pin) {
   2018         if (pin == null) {
   2019             return null;
   2020         }
   2021         byte[] pinBytes;
   2022         try {
   2023             pinBytes = pin.getBytes("UTF-8");
   2024         } catch (UnsupportedEncodingException uee) {
   2025             Log.e(TAG, "UTF-8 not supported?!?");  // this should not happen
   2026             return null;
   2027         }
   2028         if (pinBytes.length <= 0 || pinBytes.length > 16) {
   2029             return null;
   2030         }
   2031         return pinBytes;
   2032     }
   2033 
   2034     /**
   2035      * Connect to GATT Server hosted by this device. Caller acts as GATT client.
   2036      * The callback is used to deliver results to Caller, such as connection status as well
   2037      * as any further GATT client operations.
   2038      * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
   2039      * GATT client operations.
   2040      *
   2041      * @param callback GATT callback handler that will receive asynchronous callbacks.
   2042      * @param autoConnect Whether to directly connect to the remote device (false) or to
   2043      * automatically connect as soon as the remote device becomes available (true).
   2044      * @throws IllegalArgumentException if callback is null
   2045      */
   2046     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
   2047             BluetoothGattCallback callback) {
   2048         return (connectGatt(context, autoConnect, callback, TRANSPORT_AUTO));
   2049     }
   2050 
   2051     /**
   2052      * Connect to GATT Server hosted by this device. Caller acts as GATT client.
   2053      * The callback is used to deliver results to Caller, such as connection status as well
   2054      * as any further GATT client operations.
   2055      * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
   2056      * GATT client operations.
   2057      *
   2058      * @param callback GATT callback handler that will receive asynchronous callbacks.
   2059      * @param autoConnect Whether to directly connect to the remote device (false) or to
   2060      * automatically connect as soon as the remote device becomes available (true).
   2061      * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
   2062      * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
   2063      * BluetoothDevice#TRANSPORT_LE}
   2064      * @throws IllegalArgumentException if callback is null
   2065      */
   2066     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
   2067             BluetoothGattCallback callback, int transport) {
   2068         return (connectGatt(context, autoConnect, callback, transport, PHY_LE_1M_MASK));
   2069     }
   2070 
   2071     /**
   2072      * Connect to GATT Server hosted by this device. Caller acts as GATT client.
   2073      * The callback is used to deliver results to Caller, such as connection status as well
   2074      * as any further GATT client operations.
   2075      * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
   2076      * GATT client operations.
   2077      *
   2078      * @param callback GATT callback handler that will receive asynchronous callbacks.
   2079      * @param autoConnect Whether to directly connect to the remote device (false) or to
   2080      * automatically connect as soon as the remote device becomes available (true).
   2081      * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
   2082      * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
   2083      * BluetoothDevice#TRANSPORT_LE}
   2084      * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
   2085      * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link
   2086      * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
   2087      * is set to true.
   2088      * @throws NullPointerException if callback is null
   2089      */
   2090     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
   2091             BluetoothGattCallback callback, int transport, int phy) {
   2092         return connectGatt(context, autoConnect, callback, transport, phy, null);
   2093     }
   2094 
   2095     /**
   2096      * Connect to GATT Server hosted by this device. Caller acts as GATT client.
   2097      * The callback is used to deliver results to Caller, such as connection status as well
   2098      * as any further GATT client operations.
   2099      * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
   2100      * GATT client operations.
   2101      *
   2102      * @param callback GATT callback handler that will receive asynchronous callbacks.
   2103      * @param autoConnect Whether to directly connect to the remote device (false) or to
   2104      * automatically connect as soon as the remote device becomes available (true).
   2105      * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
   2106      * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
   2107      * BluetoothDevice#TRANSPORT_LE}
   2108      * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
   2109      * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link
   2110      * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
   2111      * is set to true.
   2112      * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on
   2113      * an un-specified background thread.
   2114      * @throws NullPointerException if callback is null
   2115      */
   2116     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
   2117             BluetoothGattCallback callback, int transport, int phy,
   2118             Handler handler) {
   2119         return connectGatt(context, autoConnect, callback, transport, false, phy, handler);
   2120     }
   2121 
   2122     /**
   2123      * Connect to GATT Server hosted by this device. Caller acts as GATT client.
   2124      * The callback is used to deliver results to Caller, such as connection status as well
   2125      * as any further GATT client operations.
   2126      * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
   2127      * GATT client operations.
   2128      *
   2129      * @param callback GATT callback handler that will receive asynchronous callbacks.
   2130      * @param autoConnect Whether to directly connect to the remote device (false) or to
   2131      * automatically connect as soon as the remote device becomes available (true).
   2132      * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
   2133      * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
   2134      * BluetoothDevice#TRANSPORT_LE}
   2135      * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client
   2136      * does not hold a GATT connection. It automatically disconnects when no other GATT connections
   2137      * are active for the remote device.
   2138      * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
   2139      * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link
   2140      * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
   2141      * is set to true.
   2142      * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on
   2143      * an un-specified background thread.
   2144      * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client
   2145      * operations.
   2146      * @hide
   2147      */
   2148     @UnsupportedAppUsage
   2149     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
   2150             BluetoothGattCallback callback, int transport,
   2151             boolean opportunistic, int phy, Handler handler) {
   2152         if (callback == null) {
   2153             throw new NullPointerException("callback is null");
   2154         }
   2155 
   2156         // TODO(Bluetooth) check whether platform support BLE
   2157         //     Do the check here or in GattServer?
   2158         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
   2159         IBluetoothManager managerService = adapter.getBluetoothManager();
   2160         try {
   2161             IBluetoothGatt iGatt = managerService.getBluetoothGatt();
   2162             if (iGatt == null) {
   2163                 // BLE is not supported
   2164                 return null;
   2165             }
   2166             BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy);
   2167             gatt.connect(autoConnect, callback, handler);
   2168             return gatt;
   2169         } catch (RemoteException e) {
   2170             Log.e(TAG, "", e);
   2171         }
   2172         return null;
   2173     }
   2174 
   2175     /**
   2176      * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
   2177      * be used to start a secure outgoing connection to the remote device with the same dynamic
   2178      * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
   2179      * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capChannel()} for
   2180      * peer-peer Bluetooth applications.
   2181      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
   2182      * <p>Application using this API is responsible for obtaining PSM value from remote device.
   2183      * <p>The remote device will be authenticated and communication on this socket will be
   2184      * encrypted.
   2185      * <p> Use this socket if an authenticated socket link is possible. Authentication refers
   2186      * to the authentication of the link key to prevent man-in-the-middle type of attacks.
   2187      *
   2188      * @param psm dynamic PSM value from remote device
   2189      * @return a CoC #BluetoothSocket ready for an outgoing connection
   2190      * @throws IOException on error, for example Bluetooth not available, or insufficient
   2191      * permissions
   2192      */
   2193     @RequiresPermission(Manifest.permission.BLUETOOTH)
   2194     public @NonNull BluetoothSocket createL2capChannel(int psm) throws IOException {
   2195         if (!isBluetoothEnabled()) {
   2196             Log.e(TAG, "createL2capChannel: Bluetooth is not enabled");
   2197             throw new IOException();
   2198         }
   2199         if (DBG) Log.d(TAG, "createL2capChannel: psm=" + psm);
   2200         return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm,
   2201                 null);
   2202     }
   2203 
   2204     /**
   2205      * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
   2206      * API name, createL2capChannel.
   2207      * @hide
   2208      */
   2209     @RequiresPermission(Manifest.permission.BLUETOOTH)
   2210     public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
   2211         Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createL2capChannel");
   2212         return createL2capChannel(psm);
   2213     }
   2214 
   2215     /**
   2216      * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
   2217      * be used to start a secure outgoing connection to the remote device with the same dynamic
   2218      * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
   2219      * <p>This is designed to be used with {@link
   2220      * BluetoothAdapter#listenUsingInsecureL2capChannel()} for peer-peer Bluetooth applications.
   2221      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection.
   2222      * <p>Application using this API is responsible for obtaining PSM value from remote device.
   2223      * <p> The communication channel may not have an authenticated link key, i.e. it may be subject
   2224      * to man-in-the-middle attacks. Use {@link #createL2capChannel(int)} if an encrypted and
   2225      * authenticated communication channel is possible.
   2226      *
   2227      * @param psm dynamic PSM value from remote device
   2228      * @return a CoC #BluetoothSocket ready for an outgoing connection
   2229      * @throws IOException on error, for example Bluetooth not available, or insufficient
   2230      * permissions
   2231      */
   2232     @RequiresPermission(Manifest.permission.BLUETOOTH)
   2233     public @NonNull BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
   2234         if (!isBluetoothEnabled()) {
   2235             Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled");
   2236             throw new IOException();
   2237         }
   2238         if (DBG) {
   2239             Log.d(TAG, "createInsecureL2capChannel: psm=" + psm);
   2240         }
   2241         return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm,
   2242                 null);
   2243     }
   2244 
   2245     /**
   2246      * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
   2247      * API name, createInsecureL2capChannel.
   2248      * @hide
   2249      */
   2250     @RequiresPermission(Manifest.permission.BLUETOOTH)
   2251     public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException {
   2252         Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createInsecureL2capChannel");
   2253         return createInsecureL2capChannel(psm);
   2254     }
   2255 
   2256     /**
   2257      * Set a keyed metadata of this {@link BluetoothDevice} to a
   2258      * {@link String} value.
   2259      * Only bonded devices's metadata will be persisted across Bluetooth
   2260      * restart.
   2261      * Metadata will be removed when the device's bond state is moved to
   2262      * {@link #BOND_NONE}.
   2263      *
   2264      * @param key must be within the list of BluetoothDevice.METADATA_*
   2265      * @param value a byte array data to set for key. Must be less than
   2266      * {@link BluetoothAdapter#METADATA_MAX_LENGTH} characters in length
   2267      * @return true on success, false on error
   2268      * @hide
   2269     */
   2270     @SystemApi
   2271     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
   2272     public boolean setMetadata(int key, @NonNull byte[] value) {
   2273         final IBluetooth service = sService;
   2274         if (service == null) {
   2275             Log.e(TAG, "Bluetooth is not enabled. Cannot set metadata");
   2276             return false;
   2277         }
   2278         if (value.length > METADATA_MAX_LENGTH) {
   2279             throw new IllegalArgumentException("value length is " + value.length
   2280                     + ", should not over " + METADATA_MAX_LENGTH);
   2281         }
   2282         try {
   2283             return service.setMetadata(this, key, value);
   2284         } catch (RemoteException e) {
   2285             Log.e(TAG, "setMetadata fail", e);
   2286             return false;
   2287         }
   2288     }
   2289 
   2290     /**
   2291      * Get a keyed metadata for this {@link BluetoothDevice} as {@link String}
   2292      *
   2293      * @param key must be within the list of BluetoothDevice.METADATA_*
   2294      * @return Metadata of the key as byte array, null on error or not found
   2295      * @hide
   2296      */
   2297     @SystemApi
   2298     @Nullable
   2299     @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
   2300     public byte[] getMetadata(int key) {
   2301         final IBluetooth service = sService;
   2302         if (service == null) {
   2303             Log.e(TAG, "Bluetooth is not enabled. Cannot get metadata");
   2304             return null;
   2305         }
   2306         try {
   2307             return service.getMetadata(this, key);
   2308         } catch (RemoteException e) {
   2309             Log.e(TAG, "getMetadata fail", e);
   2310             return null;
   2311         }
   2312     }
   2313 }
   2314