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