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