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.annotation.SdkConstant;
     20 import android.annotation.SdkConstant.SdkConstantType;
     21 import android.os.IBinder;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 import android.os.ParcelUuid;
     25 import android.os.RemoteException;
     26 import android.os.ServiceManager;
     27 import android.util.Log;
     28 
     29 import java.io.IOException;
     30 import java.io.UnsupportedEncodingException;
     31 import java.util.UUID;
     32 
     33 /**
     34  * Represents a remote Bluetooth device. A {@link BluetoothDevice} lets you
     35  * create a connection with the respective device or query information about
     36  * it, such as the name, address, class, and bonding state.
     37  *
     38  * <p>This class is really just a thin wrapper for a Bluetooth hardware
     39  * address. Objects of this class are immutable. Operations on this class
     40  * are performed on the remote Bluetooth hardware address, using the
     41  * {@link BluetoothAdapter} that was used to create this {@link
     42  * BluetoothDevice}.
     43  *
     44  * <p>To get a {@link BluetoothDevice}, use
     45  * {@link BluetoothAdapter#getRemoteDevice(String)
     46  * BluetoothAdapter.getRemoteDevice(String)} to create one representing a device
     47  * of a known MAC address (which you can get through device discovery with
     48  * {@link BluetoothAdapter}) or get one from the set of bonded devices
     49  * returned by {@link BluetoothAdapter#getBondedDevices()
     50  * BluetoothAdapter.getBondedDevices()}. You can then open a
     51  * {@link BluetoothSocket} for communication with the remote device, using
     52  * {@link #createRfcommSocketToServiceRecord(UUID)}.
     53  *
     54  * <p class="note"><strong>Note:</strong>
     55  * Requires the {@link android.Manifest.permission#BLUETOOTH} permission.
     56  *
     57  * <div class="special reference">
     58  * <h3>Developer Guides</h3>
     59  * <p>For more information about using Bluetooth, read the
     60  * <a href="{@docRoot}guide/topics/wireless/bluetooth.html">Bluetooth</a> developer guide.</p>
     61  * </div>
     62  *
     63  * {@see BluetoothAdapter}
     64  * {@see BluetoothSocket}
     65  */
     66 public final class BluetoothDevice implements Parcelable {
     67     private static final String TAG = "BluetoothDevice";
     68 
     69     /**
     70      * Sentinel error value for this class. Guaranteed to not equal any other
     71      * integer constant in this class. Provided as a convenience for functions
     72      * that require a sentinel error value, for example:
     73      * <p><code>Intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
     74      * BluetoothDevice.ERROR)</code>
     75      */
     76     public static final int ERROR = Integer.MIN_VALUE;
     77 
     78     /**
     79      * Broadcast Action: Remote device discovered.
     80      * <p>Sent when a remote device is found during discovery.
     81      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
     82      * #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or
     83      * {@link #EXTRA_RSSI} if they are available.
     84      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
     85      */
     86      // TODO: Change API to not broadcast RSSI if not available (incoming connection)
     87     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     88     public static final String ACTION_FOUND =
     89             "android.bluetooth.device.action.FOUND";
     90 
     91     /**
     92      * Broadcast Action: Remote device disappeared.
     93      * <p>Sent when a remote device that was found in the last discovery is not
     94      * found in the current discovery.
     95      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
     96      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
     97      * @hide
     98      */
     99     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    100     public static final String ACTION_DISAPPEARED =
    101             "android.bluetooth.device.action.DISAPPEARED";
    102 
    103     /**
    104      * Broadcast Action: Bluetooth class of a remote device has changed.
    105      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
    106      * #EXTRA_CLASS}.
    107      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    108      * @see {@link BluetoothClass}
    109      */
    110     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    111     public static final String ACTION_CLASS_CHANGED =
    112             "android.bluetooth.device.action.CLASS_CHANGED";
    113 
    114     /**
    115      * Broadcast Action: Indicates a low level (ACL) connection has been
    116      * established with a remote device.
    117      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    118      * <p>ACL connections are managed automatically by the Android Bluetooth
    119      * stack.
    120      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    121      */
    122     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    123     public static final String ACTION_ACL_CONNECTED =
    124             "android.bluetooth.device.action.ACL_CONNECTED";
    125 
    126     /**
    127      * Broadcast Action: Indicates that a low level (ACL) disconnection has
    128      * been requested for a remote device, and it will soon be disconnected.
    129      * <p>This is useful for graceful disconnection. Applications should use
    130      * this intent as a hint to immediately terminate higher level connections
    131      * (RFCOMM, L2CAP, or profile connections) to the remote device.
    132      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    133      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    134      */
    135     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    136     public static final String ACTION_ACL_DISCONNECT_REQUESTED =
    137             "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
    138 
    139     /**
    140      * Broadcast Action: Indicates a low level (ACL) disconnection from a
    141      * remote device.
    142      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    143      * <p>ACL connections are managed automatically by the Android Bluetooth
    144      * stack.
    145      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    146      */
    147     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    148     public static final String ACTION_ACL_DISCONNECTED =
    149             "android.bluetooth.device.action.ACL_DISCONNECTED";
    150 
    151     /**
    152      * Broadcast Action: Indicates the friendly name of a remote device has
    153      * been retrieved for the first time, or changed since the last retrieval.
    154      * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
    155      * #EXTRA_NAME}.
    156      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    157      */
    158     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    159     public static final String ACTION_NAME_CHANGED =
    160             "android.bluetooth.device.action.NAME_CHANGED";
    161 
    162     /**
    163      * Broadcast Action: Indicates the alias of a remote device has been
    164      * changed.
    165      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    166      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    167      *
    168      * @hide
    169      */
    170     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    171     public static final String ACTION_ALIAS_CHANGED =
    172             "android.bluetooth.device.action.ALIAS_CHANGED";
    173 
    174     /**
    175      * Broadcast Action: Indicates a change in the bond state of a remote
    176      * device. For example, if a device is bonded (paired).
    177      * <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link
    178      * #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}.
    179      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    180      */
    181     // Note: When EXTRA_BOND_STATE is BOND_NONE then this will also
    182     // contain a hidden extra field EXTRA_REASON with the result code.
    183     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    184     public static final String ACTION_BOND_STATE_CHANGED =
    185             "android.bluetooth.device.action.BOND_STATE_CHANGED";
    186 
    187     /**
    188      * Used as a Parcelable {@link BluetoothDevice} extra field in every intent
    189      * broadcast by this class. It contains the {@link BluetoothDevice} that
    190      * the intent applies to.
    191      */
    192     public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
    193 
    194     /**
    195      * Used as a String extra field in {@link #ACTION_NAME_CHANGED} and {@link
    196      * #ACTION_FOUND} intents. It contains the friendly Bluetooth name.
    197      */
    198     public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
    199 
    200     /**
    201      * Used as an optional short extra field in {@link #ACTION_FOUND} intents.
    202      * Contains the RSSI value of the remote device as reported by the
    203      * Bluetooth hardware.
    204      */
    205     public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
    206 
    207     /**
    208      * Used as a Parcelable {@link BluetoothClass} extra field in {@link
    209      * #ACTION_FOUND} and {@link #ACTION_CLASS_CHANGED} intents.
    210      */
    211     public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
    212 
    213     /**
    214      * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
    215      * Contains the bond state of the remote device.
    216      * <p>Possible values are:
    217      * {@link #BOND_NONE},
    218      * {@link #BOND_BONDING},
    219      * {@link #BOND_BONDED}.
    220       */
    221     public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
    222     /**
    223      * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
    224      * Contains the previous bond state of the remote device.
    225      * <p>Possible values are:
    226      * {@link #BOND_NONE},
    227      * {@link #BOND_BONDING},
    228      * {@link #BOND_BONDED}.
    229       */
    230     public static final String EXTRA_PREVIOUS_BOND_STATE =
    231             "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
    232     /**
    233      * Indicates the remote device is not bonded (paired).
    234      * <p>There is no shared link key with the remote device, so communication
    235      * (if it is allowed at all) will be unauthenticated and unencrypted.
    236      */
    237     public static final int BOND_NONE = 10;
    238     /**
    239      * Indicates bonding (pairing) is in progress with the remote device.
    240      */
    241     public static final int BOND_BONDING = 11;
    242     /**
    243      * Indicates the remote device is bonded (paired).
    244      * <p>A shared link keys exists locally for the remote device, so
    245      * communication can be authenticated and encrypted.
    246      * <p><i>Being bonded (paired) with a remote device does not necessarily
    247      * mean the device is currently connected. It just means that the pending
    248      * procedure was completed at some earlier time, and the link key is still
    249      * stored locally, ready to use on the next connection.
    250      * </i>
    251      */
    252     public static final int BOND_BONDED = 12;
    253 
    254     /** @hide */
    255     public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON";
    256     /** @hide */
    257     public static final String EXTRA_PAIRING_VARIANT =
    258             "android.bluetooth.device.extra.PAIRING_VARIANT";
    259     /** @hide */
    260     public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
    261 
    262     /**
    263      * Broadcast Action: This intent is used to broadcast the {@link UUID}
    264      * wrapped as a {@link android.os.ParcelUuid} of the remote device after it
    265      * has been fetched. This intent is sent only when the UUIDs of the remote
    266      * device are requested to be fetched using Service Discovery Protocol
    267      * <p> Always contains the extra field {@link #EXTRA_DEVICE}
    268      * <p> Always contains the extra field {@link #EXTRA_UUID}
    269      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    270      */
    271     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    272     public static final String ACTION_UUID =
    273             "android.bluetooth.device.action.UUID";
    274 
    275     /**
    276      * Broadcast Action: Indicates a failure to retrieve the name of a remote
    277      * device.
    278      * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
    279      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
    280      * @hide
    281      */
    282     //TODO: is this actually useful?
    283     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    284     public static final String ACTION_NAME_FAILED =
    285             "android.bluetooth.device.action.NAME_FAILED";
    286 
    287     /** @hide */
    288     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    289     public static final String ACTION_PAIRING_REQUEST =
    290             "android.bluetooth.device.action.PAIRING_REQUEST";
    291     /** @hide */
    292     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    293     public static final String ACTION_PAIRING_CANCEL =
    294             "android.bluetooth.device.action.PAIRING_CANCEL";
    295 
    296     /** @hide */
    297     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    298     public static final String ACTION_CONNECTION_ACCESS_REQUEST =
    299             "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST";
    300 
    301     /** @hide */
    302     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    303     public static final String ACTION_CONNECTION_ACCESS_REPLY =
    304             "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY";
    305 
    306     /** @hide */
    307     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    308     public static final String ACTION_CONNECTION_ACCESS_CANCEL =
    309             "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL";
    310 
    311     /**
    312      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent.
    313      * @hide
    314      */
    315     public static final String EXTRA_ACCESS_REQUEST_TYPE =
    316         "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE";
    317 
    318     /**@hide*/
    319     public static final int REQUEST_TYPE_PROFILE_CONNECTION = 1;
    320 
    321     /**@hide*/
    322     public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2;
    323 
    324     /**
    325      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
    326      * Contains package name to return reply intent to.
    327      * @hide
    328      */
    329     public static final String EXTRA_PACKAGE_NAME = "android.bluetooth.device.extra.PACKAGE_NAME";
    330 
    331     /**
    332      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
    333      * Contains class name to return reply intent to.
    334      * @hide
    335      */
    336     public static final String EXTRA_CLASS_NAME = "android.bluetooth.device.extra.CLASS_NAME";
    337 
    338     /**
    339      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent.
    340      * @hide
    341      */
    342     public static final String EXTRA_CONNECTION_ACCESS_RESULT =
    343         "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT";
    344 
    345     /**@hide*/
    346     public static final int CONNECTION_ACCESS_YES = 1;
    347 
    348     /**@hide*/
    349     public static final int CONNECTION_ACCESS_NO = 2;
    350 
    351     /**
    352      * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intents,
    353      * Contains boolean to indicate if the allowed response is once-for-all so that
    354      * next request will be granted without asking user again.
    355      * @hide
    356      */
    357     public static final String EXTRA_ALWAYS_ALLOWED =
    358         "android.bluetooth.device.extra.ALWAYS_ALLOWED";
    359 
    360     /**
    361      * A bond attempt succeeded
    362      * @hide
    363      */
    364     public static final int BOND_SUCCESS = 0;
    365 
    366     /**
    367      * A bond attempt failed because pins did not match, or remote device did
    368      * not respond to pin request in time
    369      * @hide
    370      */
    371     public static final int UNBOND_REASON_AUTH_FAILED = 1;
    372 
    373     /**
    374      * A bond attempt failed because the other side explicitly rejected
    375      * bonding
    376      * @hide
    377      */
    378     public static final int UNBOND_REASON_AUTH_REJECTED = 2;
    379 
    380     /**
    381      * A bond attempt failed because we canceled the bonding process
    382      * @hide
    383      */
    384     public static final int UNBOND_REASON_AUTH_CANCELED = 3;
    385 
    386     /**
    387      * A bond attempt failed because we could not contact the remote device
    388      * @hide
    389      */
    390     public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
    391 
    392     /**
    393      * A bond attempt failed because a discovery is in progress
    394      * @hide
    395      */
    396     public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
    397 
    398     /**
    399      * A bond attempt failed because of authentication timeout
    400      * @hide
    401      */
    402     public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
    403 
    404     /**
    405      * A bond attempt failed because of repeated attempts
    406      * @hide
    407      */
    408     public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
    409 
    410     /**
    411      * A bond attempt failed because we received an Authentication Cancel
    412      * by remote end
    413      * @hide
    414      */
    415     public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8;
    416 
    417     /**
    418      * An existing bond was explicitly revoked
    419      * @hide
    420      */
    421     public static final int UNBOND_REASON_REMOVED = 9;
    422 
    423     /**
    424      * The user will be prompted to enter a pin
    425      * @hide
    426      */
    427     public static final int PAIRING_VARIANT_PIN = 0;
    428 
    429     /**
    430      * The user will be prompted to enter a passkey
    431      * @hide
    432      */
    433     public static final int PAIRING_VARIANT_PASSKEY = 1;
    434 
    435     /**
    436      * The user will be prompted to confirm the passkey displayed on the screen
    437      * @hide
    438      */
    439     public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
    440 
    441     /**
    442      * The user will be prompted to accept or deny the incoming pairing request
    443      * @hide
    444      */
    445     public static final int PAIRING_VARIANT_CONSENT = 3;
    446 
    447     /**
    448      * The user will be prompted to enter the passkey displayed on remote device
    449      * This is used for Bluetooth 2.1 pairing.
    450      * @hide
    451      */
    452     public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
    453 
    454     /**
    455      * The user will be prompted to enter the PIN displayed on remote device.
    456      * This is used for Bluetooth 2.0 pairing.
    457      * @hide
    458      */
    459     public static final int PAIRING_VARIANT_DISPLAY_PIN = 5;
    460 
    461     /**
    462      * The user will be prompted to accept or deny the OOB pairing request
    463      * @hide
    464      */
    465     public static final int PAIRING_VARIANT_OOB_CONSENT = 6;
    466 
    467     /**
    468      * Used as an extra field in {@link #ACTION_UUID} intents,
    469      * Contains the {@link android.os.ParcelUuid}s of the remote device which
    470      * is a parcelable version of {@link UUID}.
    471      */
    472     public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
    473 
    474     /**
    475      * Lazy initialization. Guaranteed final after first object constructed, or
    476      * getService() called.
    477      * TODO: Unify implementation of sService amongst BluetoothFoo API's
    478      */
    479     private static IBluetooth sService;
    480 
    481     private final String mAddress;
    482 
    483     /*package*/ static IBluetooth getService() {
    484         synchronized (BluetoothDevice.class) {
    485             if (sService == null) {
    486                 IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
    487                 if (b == null) {
    488                     throw new RuntimeException("Bluetooth service not available");
    489                 }
    490                 sService = IBluetooth.Stub.asInterface(b);
    491             }
    492         }
    493         return sService;
    494     }
    495 
    496     /**
    497      * Create a new BluetoothDevice
    498      * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB",
    499      * and is validated in this constructor.
    500      * @param address valid Bluetooth MAC address
    501      * @throws RuntimeException Bluetooth is not available on this platform
    502      * @throws IllegalArgumentException address is invalid
    503      * @hide
    504      */
    505     /*package*/ BluetoothDevice(String address) {
    506         getService();  // ensures sService is initialized
    507         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
    508             throw new IllegalArgumentException(address + " is not a valid Bluetooth address");
    509         }
    510 
    511         mAddress = address;
    512     }
    513 
    514     @Override
    515     public boolean equals(Object o) {
    516         if (o instanceof BluetoothDevice) {
    517             return mAddress.equals(((BluetoothDevice)o).getAddress());
    518         }
    519         return false;
    520     }
    521 
    522     @Override
    523     public int hashCode() {
    524         return mAddress.hashCode();
    525     }
    526 
    527     /**
    528      * Returns a string representation of this BluetoothDevice.
    529      * <p>Currently this is the Bluetooth hardware address, for example
    530      * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress}
    531      * if you explicitly require the Bluetooth hardware address in case the
    532      * {@link #toString} representation changes in the future.
    533      * @return string representation of this BluetoothDevice
    534      */
    535     @Override
    536     public String toString() {
    537         return mAddress;
    538     }
    539 
    540     public int describeContents() {
    541         return 0;
    542     }
    543 
    544     public static final Parcelable.Creator<BluetoothDevice> CREATOR =
    545             new Parcelable.Creator<BluetoothDevice>() {
    546         public BluetoothDevice createFromParcel(Parcel in) {
    547             return new BluetoothDevice(in.readString());
    548         }
    549         public BluetoothDevice[] newArray(int size) {
    550             return new BluetoothDevice[size];
    551         }
    552     };
    553 
    554     public void writeToParcel(Parcel out, int flags) {
    555         out.writeString(mAddress);
    556     }
    557 
    558     /**
    559      * Returns the hardware address of this BluetoothDevice.
    560      * <p> For example, "00:11:22:AA:BB:CC".
    561      * @return Bluetooth hardware address as string
    562      */
    563     public String getAddress() {
    564         return mAddress;
    565     }
    566 
    567     /**
    568      * Get the friendly Bluetooth name of the remote device.
    569      *
    570      * <p>The local adapter will automatically retrieve remote names when
    571      * performing a device scan, and will cache them. This method just returns
    572      * the name for this device from the cache.
    573      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
    574      *
    575      * @return the Bluetooth name, or null if there was a problem.
    576      */
    577     public String getName() {
    578         try {
    579             return sService.getRemoteName(mAddress);
    580         } catch (RemoteException e) {Log.e(TAG, "", e);}
    581         return null;
    582     }
    583 
    584     /**
    585      * Get the Bluetooth alias of the remote device.
    586      * <p>Alias is the locally modified name of a remote device.
    587      *
    588      * @return the Bluetooth alias, or null if no alias or there was a problem
    589      * @hide
    590      */
    591     public String getAlias() {
    592         try {
    593             return sService.getRemoteAlias(mAddress);
    594         } catch (RemoteException e) {Log.e(TAG, "", e);}
    595         return null;
    596     }
    597 
    598     /**
    599      * Set the Bluetooth alias of the remote device.
    600      * <p>Alias is the locally modified name of a remote device.
    601      * <p>This methoid overwrites the alias. The changed
    602      * alias is saved in the local storage so that the change
    603      * is preserved over power cycle.
    604      *
    605      * @return true on success, false on error
    606      * @hide
    607      */
    608     public boolean setAlias(String alias) {
    609         try {
    610             return sService.setRemoteAlias(mAddress, alias);
    611         } catch (RemoteException e) {Log.e(TAG, "", e);}
    612         return false;
    613     }
    614 
    615     /**
    616      * Get the Bluetooth alias of the remote device.
    617      * If Alias is null, get the Bluetooth name instead.
    618      * @see #getAlias()
    619      * @see #getName()
    620      *
    621      * @return the Bluetooth alias, or null if no alias or there was a problem
    622      * @hide
    623      */
    624     public String getAliasName() {
    625         String name = getAlias();
    626         if (name == null) {
    627             name = getName();
    628         }
    629         return name;
    630     }
    631 
    632     /**
    633      * Start the bonding (pairing) process with the remote device.
    634      * <p>This is an asynchronous call, it will return immediately. Register
    635      * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
    636      * the bonding process completes, and its result.
    637      * <p>Android system services will handle the necessary user interactions
    638      * to confirm and complete the bonding process.
    639      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
    640      *
    641      * @return false on immediate error, true if bonding will begin
    642      * @hide
    643      */
    644     public boolean createBond() {
    645         try {
    646             return sService.createBond(mAddress);
    647         } catch (RemoteException e) {Log.e(TAG, "", e);}
    648         return false;
    649     }
    650 
    651     /**
    652      * Start the bonding (pairing) process with the remote device using the
    653      * Out Of Band mechanism.
    654      *
    655      * <p>This is an asynchronous call, it will return immediately. Register
    656      * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when
    657      * the bonding process completes, and its result.
    658      *
    659      * <p>Android system services will handle the necessary user interactions
    660      * to confirm and complete the bonding process.
    661      *
    662      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
    663      *
    664      * @param hash - Simple Secure pairing hash
    665      * @param randomizer - The random key obtained using OOB
    666      * @return false on immediate error, true if bonding will begin
    667      *
    668      * @hide
    669      */
    670     public boolean createBondOutOfBand(byte[] hash, byte[] randomizer) {
    671         try {
    672             return sService.createBondOutOfBand(mAddress, hash, randomizer);
    673         } catch (RemoteException e) {Log.e(TAG, "", e);}
    674         return false;
    675     }
    676 
    677     /**
    678      * Set the Out Of Band data for a remote device to be used later
    679      * in the pairing mechanism. Users can obtain this data through other
    680      * trusted channels
    681      *
    682      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
    683      *
    684      * @param hash Simple Secure pairing hash
    685      * @param randomizer The random key obtained using OOB
    686      * @return false on error; true otherwise
    687      *
    688      * @hide
    689      */
    690     public boolean setDeviceOutOfBandData(byte[] hash, byte[] randomizer) {
    691       try {
    692         return sService.setDeviceOutOfBandData(mAddress, hash, randomizer);
    693       } catch (RemoteException e) {Log.e(TAG, "", e);}
    694       return false;
    695     }
    696 
    697     /**
    698      * Cancel an in-progress bonding request started with {@link #createBond}.
    699      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
    700      *
    701      * @return true on success, false on error
    702      * @hide
    703      */
    704     public boolean cancelBondProcess() {
    705         try {
    706             return sService.cancelBondProcess(mAddress);
    707         } catch (RemoteException e) {Log.e(TAG, "", e);}
    708         return false;
    709     }
    710 
    711     /**
    712      * Remove bond (pairing) with the remote device.
    713      * <p>Delete the link key associated with the remote device, and
    714      * immediately terminate connections to that device that require
    715      * authentication and encryption.
    716      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
    717      *
    718      * @return true on success, false on error
    719      * @hide
    720      */
    721     public boolean removeBond() {
    722         try {
    723             return sService.removeBond(mAddress);
    724         } catch (RemoteException e) {Log.e(TAG, "", e);}
    725         return false;
    726     }
    727 
    728     /**
    729      * Get the bond state of the remote device.
    730      * <p>Possible values for the bond state are:
    731      * {@link #BOND_NONE},
    732      * {@link #BOND_BONDING},
    733      * {@link #BOND_BONDED}.
    734      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
    735      *
    736      * @return the bond state
    737      */
    738     public int getBondState() {
    739         try {
    740             return sService.getBondState(mAddress);
    741         } catch (RemoteException e) {Log.e(TAG, "", e);}
    742         return BOND_NONE;
    743     }
    744 
    745     /**
    746      * Get the Bluetooth class of the remote device.
    747      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
    748      *
    749      * @return Bluetooth class object, or null on error
    750      */
    751     public BluetoothClass getBluetoothClass() {
    752         try {
    753             int classInt = sService.getRemoteClass(mAddress);
    754             if (classInt == BluetoothClass.ERROR) return null;
    755             return new BluetoothClass(classInt);
    756         } catch (RemoteException e) {Log.e(TAG, "", e);}
    757         return null;
    758     }
    759 
    760     /**
    761      * Get trust state of a remote device.
    762      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
    763      * @hide
    764      */
    765     public boolean getTrustState() {
    766         try {
    767             return sService.getTrustState(mAddress);
    768         } catch (RemoteException e) {
    769             Log.e(TAG, "", e);
    770         }
    771         return false;
    772     }
    773 
    774     /**
    775      * Set trust state for a remote device.
    776      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
    777      * @param value the trust state value (true or false)
    778      * @hide
    779      */
    780     public boolean setTrust(boolean value) {
    781         try {
    782             return sService.setTrust(mAddress, value);
    783         } catch (RemoteException e) {
    784             Log.e(TAG, "", e);
    785         }
    786         return false;
    787     }
    788 
    789     /**
    790      * Returns the supported features (UUIDs) of the remote device.
    791      *
    792      * <p>This method does not start a service discovery procedure to retrieve the UUIDs
    793      * from the remote device. Instead, the local cached copy of the service
    794      * UUIDs are returned.
    795      * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired.
    796      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
    797      *
    798      * @return the supported features (UUIDs) of the remote device,
    799      *         or null on error
    800      */
    801      public ParcelUuid[] getUuids() {
    802         try {
    803             return sService.getRemoteUuids(mAddress);
    804         } catch (RemoteException e) {Log.e(TAG, "", e);}
    805         return null;
    806     }
    807 
    808      /**
    809       * Perform a service discovery on the remote device to get the UUIDs supported.
    810       *
    811       * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent,
    812       * with the UUIDs supported by the remote end. If there is an error
    813       * in getting the SDP records or if the process takes a long time,
    814       * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently
    815       * present in the cache. Clients should use the {@link #getUuids} to get UUIDs
    816       * if service discovery is not to be performed.
    817       * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
    818       *
    819       * @return False if the sanity check fails, True if the process
    820       *               of initiating an ACL connection to the remote device
    821       *               was started.
    822       */
    823      public boolean fetchUuidsWithSdp() {
    824         try {
    825             return sService.fetchRemoteUuids(mAddress, null, null);
    826         } catch (RemoteException e) {Log.e(TAG, "", e);}
    827         return false;
    828     }
    829 
    830     /** @hide */
    831     public int getServiceChannel(ParcelUuid uuid) {
    832          try {
    833              return sService.getRemoteServiceChannel(mAddress, uuid);
    834          } catch (RemoteException e) {Log.e(TAG, "", e);}
    835          return BluetoothDevice.ERROR;
    836     }
    837 
    838     /** @hide */
    839     public boolean setPin(byte[] pin) {
    840         try {
    841             return sService.setPin(mAddress, pin);
    842         } catch (RemoteException e) {Log.e(TAG, "", e);}
    843         return false;
    844     }
    845 
    846     /** @hide */
    847     public boolean setPasskey(int passkey) {
    848         try {
    849             return sService.setPasskey(mAddress, passkey);
    850         } catch (RemoteException e) {Log.e(TAG, "", e);}
    851         return false;
    852     }
    853 
    854     /** @hide */
    855     public boolean setPairingConfirmation(boolean confirm) {
    856         try {
    857             return sService.setPairingConfirmation(mAddress, confirm);
    858         } catch (RemoteException e) {Log.e(TAG, "", e);}
    859         return false;
    860     }
    861 
    862     /** @hide */
    863     public boolean setRemoteOutOfBandData() {
    864         try {
    865           return sService.setRemoteOutOfBandData(mAddress);
    866       } catch (RemoteException e) {Log.e(TAG, "", e);}
    867       return false;
    868     }
    869 
    870     /** @hide */
    871     public boolean cancelPairingUserInput() {
    872         try {
    873             return sService.cancelPairingUserInput(mAddress);
    874         } catch (RemoteException e) {Log.e(TAG, "", e);}
    875         return false;
    876     }
    877 
    878     /** @hide */
    879     public boolean isBluetoothDock() {
    880         try {
    881             return sService.isBluetoothDock(mAddress);
    882         } catch (RemoteException e) {Log.e(TAG, "", e);}
    883         return false;
    884     }
    885 
    886     /**
    887      * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
    888      * outgoing connection to this remote device on given channel.
    889      * <p>The remote device will be authenticated and communication on this
    890      * socket will be encrypted.
    891      * <p> Use this socket only if an authenticated socket link is possible.
    892      * Authentication refers to the authentication of the link key to
    893      * prevent man-in-the-middle type of attacks.
    894      * For example, for Bluetooth 2.1 devices, if any of the devices does not
    895      * have an input and output capability or just has the ability to
    896      * display a numeric key, a secure socket connection is not possible.
    897      * In such a case, use {#link createInsecureRfcommSocket}.
    898      * For more details, refer to the Security Model section 5.2 (vol 3) of
    899      * Bluetooth Core Specification version 2.1 + EDR.
    900      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
    901      * connection.
    902      * <p>Valid RFCOMM channels are in range 1 to 30.
    903      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
    904      *
    905      * @param channel RFCOMM channel to connect to
    906      * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
    907      * @throws IOException on error, for example Bluetooth not available, or
    908      *                     insufficient permissions
    909      * @hide
    910      */
    911     public BluetoothSocket createRfcommSocket(int channel) throws IOException {
    912         return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel,
    913                 null);
    914     }
    915 
    916     /**
    917      * Create an RFCOMM {@link BluetoothSocket} ready to start a secure
    918      * outgoing connection to this remote device using SDP lookup of uuid.
    919      * <p>This is designed to be used with {@link
    920      * BluetoothAdapter#listenUsingRfcommWithServiceRecord} for peer-peer
    921      * Bluetooth applications.
    922      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
    923      * connection. This will also perform an SDP lookup of the given uuid to
    924      * determine which channel to connect to.
    925      * <p>The remote device will be authenticated and communication on this
    926      * socket will be encrypted.
    927      * <p> Use this socket only if an authenticated socket link is possible.
    928      * Authentication refers to the authentication of the link key to
    929      * prevent man-in-the-middle type of attacks.
    930      * For example, for Bluetooth 2.1 devices, if any of the devices does not
    931      * have an input and output capability or just has the ability to
    932      * display a numeric key, a secure socket connection is not possible.
    933      * In such a case, use {#link createInsecureRfcommSocketToServiceRecord}.
    934      * For more details, refer to the Security Model section 5.2 (vol 3) of
    935      * Bluetooth Core Specification version 2.1 + EDR.
    936      * <p>Hint: If you are connecting to a Bluetooth serial board then try
    937      * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
    938      * However if you are connecting to an Android peer then please generate
    939      * your own unique UUID.
    940      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
    941      *
    942      * @param uuid service record uuid to lookup RFCOMM channel
    943      * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
    944      * @throws IOException on error, for example Bluetooth not available, or
    945      *                     insufficient permissions
    946      */
    947     public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
    948         return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1,
    949                 new ParcelUuid(uuid));
    950     }
    951 
    952     /**
    953      * Create an RFCOMM {@link BluetoothSocket} socket ready to start an insecure
    954      * outgoing connection to this remote device using SDP lookup of uuid.
    955      * <p> The communication channel will not have an authenticated link key
    956      * i.e it will be subject to man-in-the-middle attacks. For Bluetooth 2.1
    957      * devices, the link key will be encrypted, as encryption is mandatory.
    958      * For legacy devices (pre Bluetooth 2.1 devices) the link key will
    959      * be not be encrypted. Use {@link #createRfcommSocketToServiceRecord} if an
    960      * encrypted and authenticated communication channel is desired.
    961      * <p>This is designed to be used with {@link
    962      * BluetoothAdapter#listenUsingInsecureRfcommWithServiceRecord} for peer-peer
    963      * Bluetooth applications.
    964      * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
    965      * connection. This will also perform an SDP lookup of the given uuid to
    966      * determine which channel to connect to.
    967      * <p>The remote device will be authenticated and communication on this
    968      * socket will be encrypted.
    969      * <p>Hint: If you are connecting to a Bluetooth serial board then try
    970      * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB.
    971      * However if you are connecting to an Android peer then please generate
    972      * your own unique UUID.
    973      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
    974      *
    975      * @param uuid service record uuid to lookup RFCOMM channel
    976      * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
    977      * @throws IOException on error, for example Bluetooth not available, or
    978      *                     insufficient permissions
    979      */
    980     public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
    981         return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1,
    982                 new ParcelUuid(uuid));
    983     }
    984 
    985     /**
    986      * Construct an insecure RFCOMM socket ready to start an outgoing
    987      * connection.
    988      * Call #connect on the returned #BluetoothSocket to begin the connection.
    989      * The remote device will not be authenticated and communication on this
    990      * socket will not be encrypted.
    991      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
    992      *
    993      * @param port    remote port
    994      * @return An RFCOMM BluetoothSocket
    995      * @throws IOException On error, for example Bluetooth not available, or
    996      *                     insufficient permissions.
    997      * @hide
    998      */
    999     public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
   1000         return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port,
   1001                 null);
   1002     }
   1003 
   1004     /**
   1005      * Construct a SCO socket ready to start an outgoing connection.
   1006      * Call #connect on the returned #BluetoothSocket to begin the connection.
   1007      * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
   1008      *
   1009      * @return a SCO BluetoothSocket
   1010      * @throws IOException on error, for example Bluetooth not available, or
   1011      *                     insufficient permissions.
   1012      * @hide
   1013      */
   1014     public BluetoothSocket createScoSocket() throws IOException {
   1015         return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null);
   1016     }
   1017 
   1018     /**
   1019      * Check that a pin is valid and convert to byte array.
   1020      *
   1021      * Bluetooth pin's are 1 to 16 bytes of UTF-8 characters.
   1022      * @param pin pin as java String
   1023      * @return the pin code as a UTF-8 byte array, or null if it is an invalid
   1024      *         Bluetooth pin.
   1025      * @hide
   1026      */
   1027     public static byte[] convertPinToBytes(String pin) {
   1028         if (pin == null) {
   1029             return null;
   1030         }
   1031         byte[] pinBytes;
   1032         try {
   1033             pinBytes = pin.getBytes("UTF-8");
   1034         } catch (UnsupportedEncodingException uee) {
   1035             Log.e(TAG, "UTF-8 not supported?!?");  // this should not happen
   1036             return null;
   1037         }
   1038         if (pinBytes.length <= 0 || pinBytes.length > 16) {
   1039             return null;
   1040         }
   1041         return pinBytes;
   1042     }
   1043 
   1044 }
   1045