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