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