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