1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.bluetooth; 18 19 import android.Manifest; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SdkConstant; 24 import android.annotation.SdkConstant.SdkConstantType; 25 import android.annotation.SystemApi; 26 import android.annotation.UnsupportedAppUsage; 27 import android.content.Context; 28 import android.os.Handler; 29 import android.os.Parcel; 30 import android.os.ParcelUuid; 31 import android.os.Parcelable; 32 import android.os.Process; 33 import android.os.RemoteException; 34 import android.util.Log; 35 36 import java.io.IOException; 37 import java.io.UnsupportedEncodingException; 38 import java.util.UUID; 39 40 /** 41 * Represents a remote Bluetooth device. A {@link BluetoothDevice} lets you 42 * create a connection with the respective device or query information about 43 * it, such as the name, address, class, and bonding state. 44 * 45 * <p>This class is really just a thin wrapper for a Bluetooth hardware 46 * address. Objects of this class are immutable. Operations on this class 47 * are performed on the remote Bluetooth hardware address, using the 48 * {@link BluetoothAdapter} that was used to create this {@link 49 * BluetoothDevice}. 50 * 51 * <p>To get a {@link BluetoothDevice}, use 52 * {@link BluetoothAdapter#getRemoteDevice(String) 53 * BluetoothAdapter.getRemoteDevice(String)} to create one representing a device 54 * of a known MAC address (which you can get through device discovery with 55 * {@link BluetoothAdapter}) or get one from the set of bonded devices 56 * returned by {@link BluetoothAdapter#getBondedDevices() 57 * BluetoothAdapter.getBondedDevices()}. You can then open a 58 * {@link BluetoothSocket} for communication with the remote device, using 59 * {@link #createRfcommSocketToServiceRecord(UUID)} over Bluetooth BR/EDR or using 60 * {@link #createL2capChannel(int)} over Bluetooth LE. 61 * 62 * <p class="note"><strong>Note:</strong> 63 * Requires the {@link android.Manifest.permission#BLUETOOTH} permission. 64 * 65 * <div class="special reference"> 66 * <h3>Developer Guides</h3> 67 * <p> 68 * For more information about using Bluetooth, read the <a href= 69 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer 70 * guide. 71 * </p> 72 * </div> 73 * 74 * {@see BluetoothAdapter} 75 * {@see BluetoothSocket} 76 */ 77 public final class BluetoothDevice implements Parcelable { 78 private static final String TAG = "BluetoothDevice"; 79 private static final boolean DBG = false; 80 81 /** 82 * Connection state bitmask as returned by getConnectionState. 83 */ 84 private static final int CONNECTION_STATE_DISCONNECTED = 0; 85 private static final int CONNECTION_STATE_CONNECTED = 1; 86 private static final int CONNECTION_STATE_ENCRYPTED_BREDR = 2; 87 private static final int CONNECTION_STATE_ENCRYPTED_LE = 4; 88 89 /** 90 * Sentinel error value for this class. Guaranteed to not equal any other 91 * integer constant in this class. Provided as a convenience for functions 92 * that require a sentinel error value, for example: 93 * <p><code>Intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, 94 * BluetoothDevice.ERROR)</code> 95 */ 96 public static final int ERROR = Integer.MIN_VALUE; 97 98 /** 99 * Broadcast Action: Remote device discovered. 100 * <p>Sent when a remote device is found during discovery. 101 * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link 102 * #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or 103 * {@link #EXTRA_RSSI} if they are available. 104 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} and 105 * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to receive. 106 */ 107 // TODO: Change API to not broadcast RSSI if not available (incoming connection) 108 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 109 public static final String ACTION_FOUND = 110 "android.bluetooth.device.action.FOUND"; 111 112 /** 113 * Broadcast Action: Bluetooth class of a remote device has changed. 114 * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link 115 * #EXTRA_CLASS}. 116 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 117 * {@see BluetoothClass} 118 */ 119 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 120 public static final String ACTION_CLASS_CHANGED = 121 "android.bluetooth.device.action.CLASS_CHANGED"; 122 123 /** 124 * Broadcast Action: Indicates a low level (ACL) connection has been 125 * established with a remote device. 126 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 127 * <p>ACL connections are managed automatically by the Android Bluetooth 128 * stack. 129 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 130 */ 131 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 132 public static final String ACTION_ACL_CONNECTED = 133 "android.bluetooth.device.action.ACL_CONNECTED"; 134 135 /** 136 * Broadcast Action: Indicates that a low level (ACL) disconnection has 137 * been requested for a remote device, and it will soon be disconnected. 138 * <p>This is useful for graceful disconnection. Applications should use 139 * this intent as a hint to immediately terminate higher level connections 140 * (RFCOMM, L2CAP, or profile connections) to the remote device. 141 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 142 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 143 */ 144 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 145 public static final String ACTION_ACL_DISCONNECT_REQUESTED = 146 "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED"; 147 148 /** 149 * Broadcast Action: Indicates a low level (ACL) disconnection from a 150 * remote device. 151 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 152 * <p>ACL connections are managed automatically by the Android Bluetooth 153 * stack. 154 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 155 */ 156 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 157 public static final String ACTION_ACL_DISCONNECTED = 158 "android.bluetooth.device.action.ACL_DISCONNECTED"; 159 160 /** 161 * Broadcast Action: Indicates the friendly name of a remote device has 162 * been retrieved for the first time, or changed since the last retrieval. 163 * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link 164 * #EXTRA_NAME}. 165 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 166 */ 167 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 168 public static final String ACTION_NAME_CHANGED = 169 "android.bluetooth.device.action.NAME_CHANGED"; 170 171 /** 172 * Broadcast Action: Indicates the alias of a remote device has been 173 * changed. 174 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 175 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 176 * 177 * @hide 178 */ 179 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 180 @UnsupportedAppUsage 181 public static final String ACTION_ALIAS_CHANGED = 182 "android.bluetooth.device.action.ALIAS_CHANGED"; 183 184 /** 185 * Broadcast Action: Indicates a change in the bond state of a remote 186 * device. For example, if a device is bonded (paired). 187 * <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link 188 * #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}. 189 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 190 */ 191 // Note: When EXTRA_BOND_STATE is BOND_NONE then this will also 192 // contain a hidden extra field EXTRA_REASON with the result code. 193 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 194 public static final String ACTION_BOND_STATE_CHANGED = 195 "android.bluetooth.device.action.BOND_STATE_CHANGED"; 196 197 /** 198 * Broadcast Action: Indicates the battery level of a remote device has 199 * been retrieved for the first time, or changed since the last retrieval 200 * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link 201 * #EXTRA_BATTERY_LEVEL}. 202 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 203 * 204 * @hide 205 */ 206 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 207 public static final String ACTION_BATTERY_LEVEL_CHANGED = 208 "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED"; 209 210 /** 211 * Used as an Integer extra field in {@link #ACTION_BATTERY_LEVEL_CHANGED} 212 * intent. It contains the most recently retrieved battery level information 213 * ranging from 0% to 100% for a remote device, {@link #BATTERY_LEVEL_UNKNOWN} 214 * when the valid is unknown or there is an error 215 * 216 * @hide 217 */ 218 public static final String EXTRA_BATTERY_LEVEL = 219 "android.bluetooth.device.extra.BATTERY_LEVEL"; 220 221 /** 222 * Used as the unknown value for {@link #EXTRA_BATTERY_LEVEL} and {@link #getBatteryLevel()} 223 * 224 * @hide 225 */ 226 public static final int BATTERY_LEVEL_UNKNOWN = -1; 227 228 /** 229 * Used as a Parcelable {@link BluetoothDevice} extra field in every intent 230 * broadcast by this class. It contains the {@link BluetoothDevice} that 231 * the intent applies to. 232 */ 233 public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE"; 234 235 /** 236 * Used as a String extra field in {@link #ACTION_NAME_CHANGED} and {@link 237 * #ACTION_FOUND} intents. It contains the friendly Bluetooth name. 238 */ 239 public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME"; 240 241 /** 242 * Used as an optional short extra field in {@link #ACTION_FOUND} intents. 243 * Contains the RSSI value of the remote device as reported by the 244 * Bluetooth hardware. 245 */ 246 public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI"; 247 248 /** 249 * Used as a Parcelable {@link BluetoothClass} extra field in {@link 250 * #ACTION_FOUND} and {@link #ACTION_CLASS_CHANGED} intents. 251 */ 252 public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS"; 253 254 /** 255 * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents. 256 * Contains the bond state of the remote device. 257 * <p>Possible values are: 258 * {@link #BOND_NONE}, 259 * {@link #BOND_BONDING}, 260 * {@link #BOND_BONDED}. 261 */ 262 public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE"; 263 /** 264 * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents. 265 * Contains the previous bond state of the remote device. 266 * <p>Possible values are: 267 * {@link #BOND_NONE}, 268 * {@link #BOND_BONDING}, 269 * {@link #BOND_BONDED}. 270 */ 271 public static final String EXTRA_PREVIOUS_BOND_STATE = 272 "android.bluetooth.device.extra.PREVIOUS_BOND_STATE"; 273 /** 274 * Indicates the remote device is not bonded (paired). 275 * <p>There is no shared link key with the remote device, so communication 276 * (if it is allowed at all) will be unauthenticated and unencrypted. 277 */ 278 public static final int BOND_NONE = 10; 279 /** 280 * Indicates bonding (pairing) is in progress with the remote device. 281 */ 282 public static final int BOND_BONDING = 11; 283 /** 284 * Indicates the remote device is bonded (paired). 285 * <p>A shared link keys exists locally for the remote device, so 286 * communication can be authenticated and encrypted. 287 * <p><i>Being bonded (paired) with a remote device does not necessarily 288 * mean the device is currently connected. It just means that the pending 289 * procedure was completed at some earlier time, and the link key is still 290 * stored locally, ready to use on the next connection. 291 * </i> 292 */ 293 public static final int BOND_BONDED = 12; 294 295 /** 296 * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST} 297 * intents for unbond reason. 298 * 299 * @hide 300 */ 301 @UnsupportedAppUsage 302 public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON"; 303 304 /** 305 * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST} 306 * intents to indicate pairing method used. Possible values are: 307 * {@link #PAIRING_VARIANT_PIN}, 308 * {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION}, 309 */ 310 public static final String EXTRA_PAIRING_VARIANT = 311 "android.bluetooth.device.extra.PAIRING_VARIANT"; 312 313 /** 314 * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST} 315 * intents as the value of passkey. 316 */ 317 public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY"; 318 319 /** 320 * Bluetooth device type, Unknown 321 */ 322 public static final int DEVICE_TYPE_UNKNOWN = 0; 323 324 /** 325 * Bluetooth device type, Classic - BR/EDR devices 326 */ 327 public static final int DEVICE_TYPE_CLASSIC = 1; 328 329 /** 330 * Bluetooth device type, Low Energy - LE-only 331 */ 332 public static final int DEVICE_TYPE_LE = 2; 333 334 /** 335 * Bluetooth device type, Dual Mode - BR/EDR/LE 336 */ 337 public static final int DEVICE_TYPE_DUAL = 3; 338 339 340 /** @hide */ 341 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 342 @UnsupportedAppUsage 343 public static final String ACTION_SDP_RECORD = 344 "android.bluetooth.device.action.SDP_RECORD"; 345 346 /** 347 * Maximum length of a metadata entry, this is to avoid exploding Bluetooth 348 * disk usage 349 * @hide 350 */ 351 @SystemApi 352 public static final int METADATA_MAX_LENGTH = 2048; 353 354 /** 355 * Manufacturer name of this Bluetooth device 356 * Data type should be {@String} as {@link Byte} array. 357 * @hide 358 */ 359 @SystemApi 360 public static final int METADATA_MANUFACTURER_NAME = 0; 361 362 /** 363 * Model name of this Bluetooth device 364 * Data type should be {@String} as {@link Byte} array. 365 * @hide 366 */ 367 @SystemApi 368 public static final int METADATA_MODEL_NAME = 1; 369 370 /** 371 * Software version of this Bluetooth device 372 * Data type should be {@String} as {@link Byte} array. 373 * @hide 374 */ 375 @SystemApi 376 public static final int METADATA_SOFTWARE_VERSION = 2; 377 378 /** 379 * Hardware version of this Bluetooth device 380 * Data type should be {@String} as {@link Byte} array. 381 * @hide 382 */ 383 @SystemApi 384 public static final int METADATA_HARDWARE_VERSION = 3; 385 386 /** 387 * Package name of the companion app, if any 388 * Data type should be {@String} as {@link Byte} array. 389 * @hide 390 */ 391 @SystemApi 392 public static final int METADATA_COMPANION_APP = 4; 393 394 /** 395 * URI to the main icon shown on the settings UI 396 * Data type should be {@link Byte} array. 397 * @hide 398 */ 399 @SystemApi 400 public static final int METADATA_MAIN_ICON = 5; 401 402 /** 403 * Whether this device is an untethered headset with left, right and case 404 * Data type should be {@String} as {@link Byte} array. 405 * @hide 406 */ 407 @SystemApi 408 public static final int METADATA_IS_UNTETHERED_HEADSET = 6; 409 410 /** 411 * URI to icon of the left headset 412 * Data type should be {@link Byte} array. 413 * @hide 414 */ 415 @SystemApi 416 public static final int METADATA_UNTETHERED_LEFT_ICON = 7; 417 418 /** 419 * URI to icon of the right headset 420 * Data type should be {@link Byte} array. 421 * @hide 422 */ 423 @SystemApi 424 public static final int METADATA_UNTETHERED_RIGHT_ICON = 8; 425 426 /** 427 * URI to icon of the headset charging case 428 * Data type should be {@link Byte} array. 429 * @hide 430 */ 431 @SystemApi 432 public static final int METADATA_UNTETHERED_CASE_ICON = 9; 433 434 /** 435 * Battery level of left headset 436 * Data type should be {@String} 0-100 as {@link Byte} array, otherwise 437 * as invalid. 438 * @hide 439 */ 440 @SystemApi 441 public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10; 442 443 /** 444 * Battery level of rigth headset 445 * Data type should be {@String} 0-100 as {@link Byte} array, otherwise 446 * as invalid. 447 * @hide 448 */ 449 @SystemApi 450 public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11; 451 452 /** 453 * Battery level of the headset charging case 454 * Data type should be {@String} 0-100 as {@link Byte} array, otherwise 455 * as invalid. 456 * @hide 457 */ 458 @SystemApi 459 public static final int METADATA_UNTETHERED_CASE_BATTERY = 12; 460 461 /** 462 * Whether the left headset is charging 463 * Data type should be {@String} as {@link Byte} array. 464 * @hide 465 */ 466 @SystemApi 467 public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13; 468 469 /** 470 * Whether the right headset is charging 471 * Data type should be {@String} as {@link Byte} array. 472 * @hide 473 */ 474 @SystemApi 475 public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14; 476 477 /** 478 * Whether the headset charging case is charging 479 * Data type should be {@String} as {@link Byte} array. 480 * @hide 481 */ 482 @SystemApi 483 public static final int METADATA_UNTETHERED_CASE_CHARGING = 15; 484 485 /** 486 * URI to the enhanced settings UI slice 487 * Data type should be {@String} as {@link Byte} array, null means 488 * the UI does not exist. 489 * @hide 490 */ 491 @SystemApi 492 public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16; 493 494 /** 495 * Broadcast Action: This intent is used to broadcast the {@link UUID} 496 * wrapped as a {@link android.os.ParcelUuid} of the remote device after it 497 * has been fetched. This intent is sent only when the UUIDs of the remote 498 * device are requested to be fetched using Service Discovery Protocol 499 * <p> Always contains the extra field {@link #EXTRA_DEVICE} 500 * <p> Always contains the extra field {@link #EXTRA_UUID} 501 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} to receive. 502 */ 503 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 504 public static final String ACTION_UUID = 505 "android.bluetooth.device.action.UUID"; 506 507 /** @hide */ 508 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 509 public static final String ACTION_MAS_INSTANCE = 510 "android.bluetooth.device.action.MAS_INSTANCE"; 511 512 /** 513 * Broadcast Action: Indicates a failure to retrieve the name of a remote 514 * device. 515 * <p>Always contains the extra field {@link #EXTRA_DEVICE}. 516 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 517 * 518 * @hide 519 */ 520 //TODO: is this actually useful? 521 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 522 public static final String ACTION_NAME_FAILED = 523 "android.bluetooth.device.action.NAME_FAILED"; 524 525 /** 526 * Broadcast Action: This intent is used to broadcast PAIRING REQUEST 527 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} to 528 * receive. 529 */ 530 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 531 public static final String ACTION_PAIRING_REQUEST = 532 "android.bluetooth.device.action.PAIRING_REQUEST"; 533 /** @hide */ 534 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 535 @UnsupportedAppUsage 536 public static final String ACTION_PAIRING_CANCEL = 537 "android.bluetooth.device.action.PAIRING_CANCEL"; 538 539 /** @hide */ 540 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 541 public static final String ACTION_CONNECTION_ACCESS_REQUEST = 542 "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST"; 543 544 /** @hide */ 545 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 546 public static final String ACTION_CONNECTION_ACCESS_REPLY = 547 "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY"; 548 549 /** @hide */ 550 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 551 public static final String ACTION_CONNECTION_ACCESS_CANCEL = 552 "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL"; 553 554 /** 555 * Intent to broadcast silence mode changed. 556 * Alway contains the extra field {@link #EXTRA_DEVICE} 557 * 558 * @hide 559 */ 560 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 561 @SystemApi 562 public static final String ACTION_SILENCE_MODE_CHANGED = 563 "android.bluetooth.device.action.SILENCE_MODE_CHANGED"; 564 565 /** 566 * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent. 567 * 568 * @hide 569 */ 570 public static final String EXTRA_ACCESS_REQUEST_TYPE = 571 "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE"; 572 573 /** @hide */ 574 public static final int REQUEST_TYPE_PROFILE_CONNECTION = 1; 575 576 /** @hide */ 577 public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2; 578 579 /** @hide */ 580 public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3; 581 582 /** @hide */ 583 public static final int REQUEST_TYPE_SIM_ACCESS = 4; 584 585 /** 586 * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents, 587 * Contains package name to return reply intent to. 588 * 589 * @hide 590 */ 591 public static final String EXTRA_PACKAGE_NAME = "android.bluetooth.device.extra.PACKAGE_NAME"; 592 593 /** 594 * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents, 595 * Contains class name to return reply intent to. 596 * 597 * @hide 598 */ 599 public static final String EXTRA_CLASS_NAME = "android.bluetooth.device.extra.CLASS_NAME"; 600 601 /** 602 * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent. 603 * 604 * @hide 605 */ 606 public static final String EXTRA_CONNECTION_ACCESS_RESULT = 607 "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT"; 608 609 /** @hide */ 610 public static final int CONNECTION_ACCESS_YES = 1; 611 612 /** @hide */ 613 public static final int CONNECTION_ACCESS_NO = 2; 614 615 /** 616 * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intents, 617 * Contains boolean to indicate if the allowed response is once-for-all so that 618 * next request will be granted without asking user again. 619 * 620 * @hide 621 */ 622 public static final String EXTRA_ALWAYS_ALLOWED = 623 "android.bluetooth.device.extra.ALWAYS_ALLOWED"; 624 625 /** 626 * A bond attempt succeeded 627 * 628 * @hide 629 */ 630 public static final int BOND_SUCCESS = 0; 631 632 /** 633 * A bond attempt failed because pins did not match, or remote device did 634 * not respond to pin request in time 635 * 636 * @hide 637 */ 638 @UnsupportedAppUsage 639 public static final int UNBOND_REASON_AUTH_FAILED = 1; 640 641 /** 642 * A bond attempt failed because the other side explicitly rejected 643 * bonding 644 * 645 * @hide 646 */ 647 @UnsupportedAppUsage 648 public static final int UNBOND_REASON_AUTH_REJECTED = 2; 649 650 /** 651 * A bond attempt failed because we canceled the bonding process 652 * 653 * @hide 654 */ 655 public static final int UNBOND_REASON_AUTH_CANCELED = 3; 656 657 /** 658 * A bond attempt failed because we could not contact the remote device 659 * 660 * @hide 661 */ 662 @UnsupportedAppUsage 663 public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4; 664 665 /** 666 * A bond attempt failed because a discovery is in progress 667 * 668 * @hide 669 */ 670 @UnsupportedAppUsage 671 public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5; 672 673 /** 674 * A bond attempt failed because of authentication timeout 675 * 676 * @hide 677 */ 678 @UnsupportedAppUsage 679 public static final int UNBOND_REASON_AUTH_TIMEOUT = 6; 680 681 /** 682 * A bond attempt failed because of repeated attempts 683 * 684 * @hide 685 */ 686 @UnsupportedAppUsage 687 public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7; 688 689 /** 690 * A bond attempt failed because we received an Authentication Cancel 691 * by remote end 692 * 693 * @hide 694 */ 695 @UnsupportedAppUsage 696 public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8; 697 698 /** 699 * An existing bond was explicitly revoked 700 * 701 * @hide 702 */ 703 public static final int UNBOND_REASON_REMOVED = 9; 704 705 /** 706 * The user will be prompted to enter a pin or 707 * an app will enter a pin for user. 708 */ 709 public static final int PAIRING_VARIANT_PIN = 0; 710 711 /** 712 * The user will be prompted to enter a passkey 713 * 714 * @hide 715 */ 716 public static final int PAIRING_VARIANT_PASSKEY = 1; 717 718 /** 719 * The user will be prompted to confirm the passkey displayed on the screen or 720 * an app will confirm the passkey for the user. 721 */ 722 public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; 723 724 /** 725 * The user will be prompted to accept or deny the incoming pairing request 726 * 727 * @hide 728 */ 729 public static final int PAIRING_VARIANT_CONSENT = 3; 730 731 /** 732 * The user will be prompted to enter the passkey displayed on remote device 733 * This is used for Bluetooth 2.1 pairing. 734 * 735 * @hide 736 */ 737 public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4; 738 739 /** 740 * The user will be prompted to enter the PIN displayed on remote device. 741 * This is used for Bluetooth 2.0 pairing. 742 * 743 * @hide 744 */ 745 public static final int PAIRING_VARIANT_DISPLAY_PIN = 5; 746 747 /** 748 * The user will be prompted to accept or deny the OOB pairing request 749 * 750 * @hide 751 */ 752 public static final int PAIRING_VARIANT_OOB_CONSENT = 6; 753 754 /** 755 * The user will be prompted to enter a 16 digit pin or 756 * an app will enter a 16 digit pin for user. 757 * 758 * @hide 759 */ 760 public static final int PAIRING_VARIANT_PIN_16_DIGITS = 7; 761 762 /** 763 * Used as an extra field in {@link #ACTION_UUID} intents, 764 * Contains the {@link android.os.ParcelUuid}s of the remote device which 765 * is a parcelable version of {@link UUID}. 766 */ 767 public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID"; 768 769 /** @hide */ 770 public static final String EXTRA_SDP_RECORD = 771 "android.bluetooth.device.extra.SDP_RECORD"; 772 773 /** @hide */ 774 @UnsupportedAppUsage 775 public static final String EXTRA_SDP_SEARCH_STATUS = 776 "android.bluetooth.device.extra.SDP_SEARCH_STATUS"; 777 /** 778 * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, 779 * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. 780 * 781 * @hide 782 */ 783 @SystemApi 784 public static final int ACCESS_UNKNOWN = 0; 785 786 /** 787 * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, 788 * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. 789 * 790 * @hide 791 */ 792 @SystemApi 793 public static final int ACCESS_ALLOWED = 1; 794 795 /** 796 * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission}, 797 * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}. 798 * 799 * @hide 800 */ 801 @SystemApi 802 public static final int ACCESS_REJECTED = 2; 803 804 /** 805 * No preference of physical transport for GATT connections to remote dual-mode devices 806 */ 807 public static final int TRANSPORT_AUTO = 0; 808 809 /** 810 * Prefer BR/EDR transport for GATT connections to remote dual-mode devices 811 */ 812 public static final int TRANSPORT_BREDR = 1; 813 814 /** 815 * Prefer LE transport for GATT connections to remote dual-mode devices 816 */ 817 public static final int TRANSPORT_LE = 2; 818 819 /** 820 * Bluetooth LE 1M PHY. Used to refer to LE 1M Physical Channel for advertising, scanning or 821 * connection. 822 */ 823 public static final int PHY_LE_1M = 1; 824 825 /** 826 * Bluetooth LE 2M PHY. Used to refer to LE 2M Physical Channel for advertising, scanning or 827 * connection. 828 */ 829 public static final int PHY_LE_2M = 2; 830 831 /** 832 * Bluetooth LE Coded PHY. Used to refer to LE Coded Physical Channel for advertising, scanning 833 * or connection. 834 */ 835 public static final int PHY_LE_CODED = 3; 836 837 /** 838 * Bluetooth LE 1M PHY mask. Used to specify LE 1M Physical Channel as one of many available 839 * options in a bitmask. 840 */ 841 public static final int PHY_LE_1M_MASK = 1; 842 843 /** 844 * Bluetooth LE 2M PHY mask. Used to specify LE 2M Physical Channel as one of many available 845 * options in a bitmask. 846 */ 847 public static final int PHY_LE_2M_MASK = 2; 848 849 /** 850 * Bluetooth LE Coded PHY mask. Used to specify LE Coded Physical Channel as one of many 851 * available options in a bitmask. 852 */ 853 public static final int PHY_LE_CODED_MASK = 4; 854 855 /** 856 * No preferred coding when transmitting on the LE Coded PHY. 857 */ 858 public static final int PHY_OPTION_NO_PREFERRED = 0; 859 860 /** 861 * Prefer the S=2 coding to be used when transmitting on the LE Coded PHY. 862 */ 863 public static final int PHY_OPTION_S2 = 1; 864 865 /** 866 * Prefer the S=8 coding to be used when transmitting on the LE Coded PHY. 867 */ 868 public static final int PHY_OPTION_S8 = 2; 869 870 871 /** @hide */ 872 public static final String EXTRA_MAS_INSTANCE = 873 "android.bluetooth.device.extra.MAS_INSTANCE"; 874 875 /** 876 * Lazy initialization. Guaranteed final after first object constructed, or 877 * getService() called. 878 * TODO: Unify implementation of sService amongst BluetoothFoo API's 879 */ 880 private static volatile IBluetooth sService; 881 882 private final String mAddress; 883 884 /*package*/ 885 @UnsupportedAppUsage getService()886 static IBluetooth getService() { 887 synchronized (BluetoothDevice.class) { 888 if (sService == null) { 889 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 890 sService = adapter.getBluetoothService(sStateChangeCallback); 891 } 892 } 893 return sService; 894 } 895 896 static IBluetoothManagerCallback sStateChangeCallback = new IBluetoothManagerCallback.Stub() { 897 898 public void onBluetoothServiceUp(IBluetooth bluetoothService) 899 throws RemoteException { 900 synchronized (BluetoothDevice.class) { 901 if (sService == null) { 902 sService = bluetoothService; 903 } 904 } 905 } 906 907 public void onBluetoothServiceDown() 908 throws RemoteException { 909 synchronized (BluetoothDevice.class) { 910 sService = null; 911 } 912 } 913 914 public void onBrEdrDown() { 915 if (DBG) Log.d(TAG, "onBrEdrDown: reached BLE ON state"); 916 } 917 }; 918 919 /** 920 * Create a new BluetoothDevice 921 * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB", 922 * and is validated in this constructor. 923 * 924 * @param address valid Bluetooth MAC address 925 * @throws RuntimeException Bluetooth is not available on this platform 926 * @throws IllegalArgumentException address is invalid 927 * @hide 928 */ 929 @UnsupportedAppUsage BluetoothDevice(String address)930 /*package*/ BluetoothDevice(String address) { 931 getService(); // ensures sService is initialized 932 if (!BluetoothAdapter.checkBluetoothAddress(address)) { 933 throw new IllegalArgumentException(address + " is not a valid Bluetooth address"); 934 } 935 936 mAddress = address; 937 } 938 939 @Override equals(Object o)940 public boolean equals(Object o) { 941 if (o instanceof BluetoothDevice) { 942 return mAddress.equals(((BluetoothDevice) o).getAddress()); 943 } 944 return false; 945 } 946 947 @Override hashCode()948 public int hashCode() { 949 return mAddress.hashCode(); 950 } 951 952 /** 953 * Returns a string representation of this BluetoothDevice. 954 * <p>Currently this is the Bluetooth hardware address, for example 955 * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress} 956 * if you explicitly require the Bluetooth hardware address in case the 957 * {@link #toString} representation changes in the future. 958 * 959 * @return string representation of this BluetoothDevice 960 */ 961 @Override toString()962 public String toString() { 963 return mAddress; 964 } 965 966 @Override describeContents()967 public int describeContents() { 968 return 0; 969 } 970 971 public static final @android.annotation.NonNull Parcelable.Creator<BluetoothDevice> CREATOR = 972 new Parcelable.Creator<BluetoothDevice>() { 973 public BluetoothDevice createFromParcel(Parcel in) { 974 return new BluetoothDevice(in.readString()); 975 } 976 977 public BluetoothDevice[] newArray(int size) { 978 return new BluetoothDevice[size]; 979 } 980 }; 981 982 @Override writeToParcel(Parcel out, int flags)983 public void writeToParcel(Parcel out, int flags) { 984 out.writeString(mAddress); 985 } 986 987 /** 988 * Returns the hardware address of this BluetoothDevice. 989 * <p> For example, "00:11:22:AA:BB:CC". 990 * 991 * @return Bluetooth hardware address as string 992 */ getAddress()993 public String getAddress() { 994 if (DBG) Log.d(TAG, "mAddress: " + mAddress); 995 return mAddress; 996 } 997 998 /** 999 * Get the friendly Bluetooth name of the remote device. 1000 * 1001 * <p>The local adapter will automatically retrieve remote names when 1002 * performing a device scan, and will cache them. This method just returns 1003 * the name for this device from the cache. 1004 * 1005 * @return the Bluetooth name, or null if there was a problem. 1006 */ 1007 @RequiresPermission(Manifest.permission.BLUETOOTH) getName()1008 public String getName() { 1009 final IBluetooth service = sService; 1010 if (service == null) { 1011 Log.e(TAG, "BT not enabled. Cannot get Remote Device name"); 1012 return null; 1013 } 1014 try { 1015 String name = service.getRemoteName(this); 1016 if (name != null) { 1017 return name.replaceAll("[\\t\\n\\r]+", " "); 1018 } 1019 return null; 1020 } catch (RemoteException e) { 1021 Log.e(TAG, "", e); 1022 } 1023 return null; 1024 } 1025 1026 /** 1027 * Get the Bluetooth device type of the remote device. 1028 * 1029 * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} {@link 1030 * #DEVICE_TYPE_DUAL}. {@link #DEVICE_TYPE_UNKNOWN} if it's not available 1031 */ 1032 @RequiresPermission(Manifest.permission.BLUETOOTH) getType()1033 public int getType() { 1034 final IBluetooth service = sService; 1035 if (service == null) { 1036 Log.e(TAG, "BT not enabled. Cannot get Remote Device type"); 1037 return DEVICE_TYPE_UNKNOWN; 1038 } 1039 try { 1040 return service.getRemoteType(this); 1041 } catch (RemoteException e) { 1042 Log.e(TAG, "", e); 1043 } 1044 return DEVICE_TYPE_UNKNOWN; 1045 } 1046 1047 /** 1048 * Get the Bluetooth alias of the remote device. 1049 * <p>Alias is the locally modified name of a remote device. 1050 * 1051 * @return the Bluetooth alias, or null if no alias or there was a problem 1052 * @hide 1053 */ 1054 @UnsupportedAppUsage getAlias()1055 public String getAlias() { 1056 final IBluetooth service = sService; 1057 if (service == null) { 1058 Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias"); 1059 return null; 1060 } 1061 try { 1062 return service.getRemoteAlias(this); 1063 } catch (RemoteException e) { 1064 Log.e(TAG, "", e); 1065 } 1066 return null; 1067 } 1068 1069 /** 1070 * Set the Bluetooth alias of the remote device. 1071 * <p>Alias is the locally modified name of a remote device. 1072 * <p>This methoid overwrites the alias. The changed 1073 * alias is saved in the local storage so that the change 1074 * is preserved over power cycle. 1075 * 1076 * @return true on success, false on error 1077 * @hide 1078 */ 1079 @UnsupportedAppUsage setAlias(String alias)1080 public boolean setAlias(String alias) { 1081 final IBluetooth service = sService; 1082 if (service == null) { 1083 Log.e(TAG, "BT not enabled. Cannot set Remote Device name"); 1084 return false; 1085 } 1086 try { 1087 return service.setRemoteAlias(this, alias); 1088 } catch (RemoteException e) { 1089 Log.e(TAG, "", e); 1090 } 1091 return false; 1092 } 1093 1094 /** 1095 * Get the Bluetooth alias of the remote device. 1096 * If Alias is null, get the Bluetooth name instead. 1097 * 1098 * @return the Bluetooth alias, or null if no alias or there was a problem 1099 * @hide 1100 * @see #getAlias() 1101 * @see #getName() 1102 */ 1103 @UnsupportedAppUsage getAliasName()1104 public String getAliasName() { 1105 String name = getAlias(); 1106 if (name == null) { 1107 name = getName(); 1108 } 1109 return name; 1110 } 1111 1112 /** 1113 * Get the most recent identified battery level of this Bluetooth device 1114 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1115 * 1116 * @return Battery level in percents from 0 to 100, or {@link #BATTERY_LEVEL_UNKNOWN} if 1117 * Bluetooth is disabled, or device is disconnected, or does not have any battery reporting 1118 * service, or return value is invalid 1119 * @hide 1120 */ 1121 @RequiresPermission(Manifest.permission.BLUETOOTH) 1122 @UnsupportedAppUsage getBatteryLevel()1123 public int getBatteryLevel() { 1124 final IBluetooth service = sService; 1125 if (service == null) { 1126 Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level"); 1127 return BATTERY_LEVEL_UNKNOWN; 1128 } 1129 try { 1130 return service.getBatteryLevel(this); 1131 } catch (RemoteException e) { 1132 Log.e(TAG, "", e); 1133 } 1134 return BATTERY_LEVEL_UNKNOWN; 1135 } 1136 1137 /** 1138 * Start the bonding (pairing) process with the remote device. 1139 * <p>This is an asynchronous call, it will return immediately. Register 1140 * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when 1141 * the bonding process completes, and its result. 1142 * <p>Android system services will handle the necessary user interactions 1143 * to confirm and complete the bonding process. 1144 * 1145 * @return false on immediate error, true if bonding will begin 1146 */ 1147 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) createBond()1148 public boolean createBond() { 1149 final IBluetooth service = sService; 1150 if (service == null) { 1151 Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); 1152 return false; 1153 } 1154 try { 1155 Log.i(TAG, "createBond() for device " + getAddress() 1156 + " called by pid: " + Process.myPid() 1157 + " tid: " + Process.myTid()); 1158 return service.createBond(this, TRANSPORT_AUTO); 1159 } catch (RemoteException e) { 1160 Log.e(TAG, "", e); 1161 } 1162 return false; 1163 } 1164 1165 /** 1166 * Start the bonding (pairing) process with the remote device using the 1167 * specified transport. 1168 * 1169 * <p>This is an asynchronous call, it will return immediately. Register 1170 * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when 1171 * the bonding process completes, and its result. 1172 * <p>Android system services will handle the necessary user interactions 1173 * to confirm and complete the bonding process. 1174 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1175 * 1176 * @param transport The transport to use for the pairing procedure. 1177 * @return false on immediate error, true if bonding will begin 1178 * @throws IllegalArgumentException if an invalid transport was specified 1179 * @hide 1180 */ 1181 @UnsupportedAppUsage createBond(int transport)1182 public boolean createBond(int transport) { 1183 final IBluetooth service = sService; 1184 if (service == null) { 1185 Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); 1186 return false; 1187 } 1188 if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) { 1189 throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport"); 1190 } 1191 try { 1192 Log.i(TAG, "createBond() for device " + getAddress() 1193 + " called by pid: " + Process.myPid() 1194 + " tid: " + Process.myTid()); 1195 return service.createBond(this, transport); 1196 } catch (RemoteException e) { 1197 Log.e(TAG, "", e); 1198 } 1199 return false; 1200 } 1201 1202 /** 1203 * Start the bonding (pairing) process with the remote device using the 1204 * Out Of Band mechanism. 1205 * 1206 * <p>This is an asynchronous call, it will return immediately. Register 1207 * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when 1208 * the bonding process completes, and its result. 1209 * 1210 * <p>Android system services will handle the necessary user interactions 1211 * to confirm and complete the bonding process. 1212 * 1213 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1214 * 1215 * @param transport - Transport to use 1216 * @param oobData - Out Of Band data 1217 * @return false on immediate error, true if bonding will begin 1218 * @hide 1219 */ createBondOutOfBand(int transport, OobData oobData)1220 public boolean createBondOutOfBand(int transport, OobData oobData) { 1221 final IBluetooth service = sService; 1222 if (service == null) { 1223 Log.w(TAG, "BT not enabled, createBondOutOfBand failed"); 1224 return false; 1225 } 1226 try { 1227 return service.createBondOutOfBand(this, transport, oobData); 1228 } catch (RemoteException e) { 1229 Log.e(TAG, "", e); 1230 } 1231 return false; 1232 } 1233 1234 /** @hide */ 1235 @UnsupportedAppUsage isBondingInitiatedLocally()1236 public boolean isBondingInitiatedLocally() { 1237 final IBluetooth service = sService; 1238 if (service == null) { 1239 Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed"); 1240 return false; 1241 } 1242 try { 1243 return service.isBondingInitiatedLocally(this); 1244 } catch (RemoteException e) { 1245 Log.e(TAG, "", e); 1246 } 1247 return false; 1248 } 1249 1250 /** 1251 * Set the Out Of Band data for a remote device to be used later 1252 * in the pairing mechanism. Users can obtain this data through other 1253 * trusted channels 1254 * 1255 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1256 * 1257 * @param hash Simple Secure pairing hash 1258 * @param randomizer The random key obtained using OOB 1259 * @return false on error; true otherwise 1260 * @hide 1261 */ setDeviceOutOfBandData(byte[] hash, byte[] randomizer)1262 public boolean setDeviceOutOfBandData(byte[] hash, byte[] randomizer) { 1263 //TODO(BT) 1264 /* 1265 try { 1266 return sService.setDeviceOutOfBandData(this, hash, randomizer); 1267 } catch (RemoteException e) {Log.e(TAG, "", e);} */ 1268 return false; 1269 } 1270 1271 /** 1272 * Cancel an in-progress bonding request started with {@link #createBond}. 1273 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1274 * 1275 * @return true on success, false on error 1276 * @hide 1277 */ 1278 @SystemApi 1279 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) cancelBondProcess()1280 public boolean cancelBondProcess() { 1281 final IBluetooth service = sService; 1282 if (service == null) { 1283 Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond"); 1284 return false; 1285 } 1286 try { 1287 Log.i(TAG, "cancelBondProcess() for device " + getAddress() 1288 + " called by pid: " + Process.myPid() 1289 + " tid: " + Process.myTid()); 1290 return service.cancelBondProcess(this); 1291 } catch (RemoteException e) { 1292 Log.e(TAG, "", e); 1293 } 1294 return false; 1295 } 1296 1297 /** 1298 * Remove bond (pairing) with the remote device. 1299 * <p>Delete the link key associated with the remote device, and 1300 * immediately terminate connections to that device that require 1301 * authentication and encryption. 1302 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1303 * 1304 * @return true on success, false on error 1305 * @hide 1306 */ 1307 @SystemApi 1308 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) removeBond()1309 public boolean removeBond() { 1310 final IBluetooth service = sService; 1311 if (service == null) { 1312 Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond"); 1313 return false; 1314 } 1315 try { 1316 Log.i(TAG, "removeBond() for device " + getAddress() 1317 + " called by pid: " + Process.myPid() 1318 + " tid: " + Process.myTid()); 1319 return service.removeBond(this); 1320 } catch (RemoteException e) { 1321 Log.e(TAG, "", e); 1322 } 1323 return false; 1324 } 1325 1326 /** 1327 * Get the bond state of the remote device. 1328 * <p>Possible values for the bond state are: 1329 * {@link #BOND_NONE}, 1330 * {@link #BOND_BONDING}, 1331 * {@link #BOND_BONDED}. 1332 * 1333 * @return the bond state 1334 */ 1335 @RequiresPermission(Manifest.permission.BLUETOOTH) getBondState()1336 public int getBondState() { 1337 final IBluetooth service = sService; 1338 if (service == null) { 1339 Log.e(TAG, "BT not enabled. Cannot get bond state"); 1340 return BOND_NONE; 1341 } 1342 try { 1343 return service.getBondState(this); 1344 } catch (RemoteException e) { 1345 Log.e(TAG, "", e); 1346 } 1347 return BOND_NONE; 1348 } 1349 1350 /** 1351 * Returns whether there is an open connection to this device. 1352 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1353 * 1354 * @return True if there is at least one open connection to this device. 1355 * @hide 1356 */ 1357 @SystemApi 1358 @RequiresPermission(android.Manifest.permission.BLUETOOTH) isConnected()1359 public boolean isConnected() { 1360 final IBluetooth service = sService; 1361 if (service == null) { 1362 // BT is not enabled, we cannot be connected. 1363 return false; 1364 } 1365 try { 1366 return service.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED; 1367 } catch (RemoteException e) { 1368 Log.e(TAG, "", e); 1369 return false; 1370 } 1371 } 1372 1373 /** 1374 * Returns whether there is an open connection to this device 1375 * that has been encrypted. 1376 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1377 * 1378 * @return True if there is at least one encrypted connection to this device. 1379 * @hide 1380 */ 1381 @SystemApi 1382 @RequiresPermission(android.Manifest.permission.BLUETOOTH) isEncrypted()1383 public boolean isEncrypted() { 1384 final IBluetooth service = sService; 1385 if (service == null) { 1386 // BT is not enabled, we cannot be connected. 1387 return false; 1388 } 1389 try { 1390 return service.getConnectionState(this) > CONNECTION_STATE_CONNECTED; 1391 } catch (RemoteException e) { 1392 Log.e(TAG, "", e); 1393 return false; 1394 } 1395 } 1396 1397 /** 1398 * Get the Bluetooth class of the remote device. 1399 * 1400 * @return Bluetooth class object, or null on error 1401 */ 1402 @RequiresPermission(Manifest.permission.BLUETOOTH) getBluetoothClass()1403 public BluetoothClass getBluetoothClass() { 1404 final IBluetooth service = sService; 1405 if (service == null) { 1406 Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class"); 1407 return null; 1408 } 1409 try { 1410 int classInt = service.getRemoteClass(this); 1411 if (classInt == BluetoothClass.ERROR) return null; 1412 return new BluetoothClass(classInt); 1413 } catch (RemoteException e) { 1414 Log.e(TAG, "", e); 1415 } 1416 return null; 1417 } 1418 1419 /** 1420 * Returns the supported features (UUIDs) of the remote device. 1421 * 1422 * <p>This method does not start a service discovery procedure to retrieve the UUIDs 1423 * from the remote device. Instead, the local cached copy of the service 1424 * UUIDs are returned. 1425 * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired. 1426 * 1427 * @return the supported features (UUIDs) of the remote device, or null on error 1428 */ 1429 @RequiresPermission(Manifest.permission.BLUETOOTH) getUuids()1430 public ParcelUuid[] getUuids() { 1431 final IBluetooth service = sService; 1432 if (service == null || !isBluetoothEnabled()) { 1433 Log.e(TAG, "BT not enabled. Cannot get remote device Uuids"); 1434 return null; 1435 } 1436 try { 1437 return service.getRemoteUuids(this); 1438 } catch (RemoteException e) { 1439 Log.e(TAG, "", e); 1440 } 1441 return null; 1442 } 1443 1444 /** 1445 * Perform a service discovery on the remote device to get the UUIDs supported. 1446 * 1447 * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent, 1448 * with the UUIDs supported by the remote end. If there is an error 1449 * in getting the SDP records or if the process takes a long time, 1450 * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently 1451 * present in the cache. Clients should use the {@link #getUuids} to get UUIDs 1452 * if service discovery is not to be performed. 1453 * 1454 * @return False if the sanity check fails, True if the process of initiating an ACL connection 1455 * to the remote device was started. 1456 */ 1457 @RequiresPermission(Manifest.permission.BLUETOOTH) fetchUuidsWithSdp()1458 public boolean fetchUuidsWithSdp() { 1459 final IBluetooth service = sService; 1460 if (service == null || !isBluetoothEnabled()) { 1461 Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp"); 1462 return false; 1463 } 1464 try { 1465 return service.fetchRemoteUuids(this); 1466 } catch (RemoteException e) { 1467 Log.e(TAG, "", e); 1468 } 1469 return false; 1470 } 1471 1472 /** 1473 * Perform a service discovery on the remote device to get the SDP records associated 1474 * with the specified UUID. 1475 * 1476 * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent, 1477 * with the SDP records found on the remote end. If there is an error 1478 * in getting the SDP records or if the process takes a long time, 1479 * {@link #ACTION_SDP_RECORD} intent is sent with an status value in 1480 * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0. 1481 * Detailed status error codes can be found by members of the Bluetooth package in 1482 * the AbstractionLayer class. 1483 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1484 * The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}. 1485 * The object type will match one of the SdpXxxRecord types, depending on the UUID searched 1486 * for. 1487 * 1488 * @return False if the sanity check fails, True if the process 1489 * of initiating an ACL connection to the remote device 1490 * was started. 1491 */ 1492 /** @hide */ sdpSearch(ParcelUuid uuid)1493 public boolean sdpSearch(ParcelUuid uuid) { 1494 final IBluetooth service = sService; 1495 if (service == null) { 1496 Log.e(TAG, "BT not enabled. Cannot query remote device sdp records"); 1497 return false; 1498 } 1499 try { 1500 return service.sdpSearch(this, uuid); 1501 } catch (RemoteException e) { 1502 Log.e(TAG, "", e); 1503 } 1504 return false; 1505 } 1506 1507 /** 1508 * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN} 1509 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1510 * 1511 * @return true pin has been set false for error 1512 */ setPin(byte[] pin)1513 public boolean setPin(byte[] pin) { 1514 final IBluetooth service = sService; 1515 if (service == null) { 1516 Log.e(TAG, "BT not enabled. Cannot set Remote Device pin"); 1517 return false; 1518 } 1519 try { 1520 return service.setPin(this, true, pin.length, pin); 1521 } catch (RemoteException e) { 1522 Log.e(TAG, "", e); 1523 } 1524 return false; 1525 } 1526 1527 /** @hide */ 1528 @UnsupportedAppUsage setPasskey(int passkey)1529 public boolean setPasskey(int passkey) { 1530 //TODO(BT) 1531 /* 1532 try { 1533 return sService.setPasskey(this, true, 4, passkey); 1534 } catch (RemoteException e) {Log.e(TAG, "", e);}*/ 1535 return false; 1536 } 1537 1538 /** 1539 * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing. 1540 * 1541 * @return true confirmation has been sent out false for error 1542 */ 1543 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) setPairingConfirmation(boolean confirm)1544 public boolean setPairingConfirmation(boolean confirm) { 1545 final IBluetooth service = sService; 1546 if (service == null) { 1547 Log.e(TAG, "BT not enabled. Cannot set pairing confirmation"); 1548 return false; 1549 } 1550 try { 1551 return service.setPairingConfirmation(this, confirm); 1552 } catch (RemoteException e) { 1553 Log.e(TAG, "", e); 1554 } 1555 return false; 1556 } 1557 1558 /** @hide */ setRemoteOutOfBandData()1559 public boolean setRemoteOutOfBandData() { 1560 // TODO(BT) 1561 /* 1562 try { 1563 return sService.setRemoteOutOfBandData(this); 1564 } catch (RemoteException e) {Log.e(TAG, "", e);}*/ 1565 return false; 1566 } 1567 1568 /** @hide */ 1569 @UnsupportedAppUsage cancelPairingUserInput()1570 public boolean cancelPairingUserInput() { 1571 final IBluetooth service = sService; 1572 if (service == null) { 1573 Log.e(TAG, "BT not enabled. Cannot create pairing user input"); 1574 return false; 1575 } 1576 try { 1577 return service.cancelBondProcess(this); 1578 } catch (RemoteException e) { 1579 Log.e(TAG, "", e); 1580 } 1581 return false; 1582 } 1583 1584 /** @hide */ 1585 @UnsupportedAppUsage isBluetoothDock()1586 public boolean isBluetoothDock() { 1587 // TODO(BT) 1588 /* 1589 try { 1590 return sService.isBluetoothDock(this); 1591 } catch (RemoteException e) {Log.e(TAG, "", e);}*/ 1592 return false; 1593 } 1594 isBluetoothEnabled()1595 boolean isBluetoothEnabled() { 1596 boolean ret = false; 1597 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 1598 if (adapter != null && adapter.isEnabled()) { 1599 ret = true; 1600 } 1601 return ret; 1602 } 1603 1604 /** 1605 * Requires {@link android.Manifest.permission#BLUETOOTH}. 1606 * 1607 * @return Whether the phonebook access is allowed to this device. Can be {@link 1608 * #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. 1609 * @hide 1610 */ 1611 @UnsupportedAppUsage getPhonebookAccessPermission()1612 public int getPhonebookAccessPermission() { 1613 final IBluetooth service = sService; 1614 if (service == null) { 1615 return ACCESS_UNKNOWN; 1616 } 1617 try { 1618 return service.getPhonebookAccessPermission(this); 1619 } catch (RemoteException e) { 1620 Log.e(TAG, "", e); 1621 } 1622 return ACCESS_UNKNOWN; 1623 } 1624 1625 /** 1626 * Sets whether the {@link BluetoothDevice} enters silence mode. Audio will not 1627 * be routed to the {@link BluetoothDevice} if set to {@code true}. 1628 * 1629 * When the {@link BluetoothDevice} enters silence mode, and the {@link BluetoothDevice} 1630 * is an active device (for A2DP or HFP), the active device for that profile 1631 * will be set to null. 1632 * If the {@link BluetoothDevice} exits silence mode while the A2DP or HFP 1633 * active device is null, the {@link BluetoothDevice} will be set as the 1634 * active device for that profile. 1635 * If the {@link BluetoothDevice} is disconnected, it exits silence mode. 1636 * If the {@link BluetoothDevice} is set as the active device for A2DP or 1637 * HFP, while silence mode is enabled, then the device will exit silence mode. 1638 * If the {@link BluetoothDevice} is in silence mode, AVRCP position change 1639 * event and HFP AG indicators will be disabled. 1640 * If the {@link BluetoothDevice} is not connected with A2DP or HFP, it cannot 1641 * enter silence mode. 1642 * 1643 * <p> Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. 1644 * 1645 * @param silence true to enter silence mode, false to exit 1646 * @return true on success, false on error. 1647 * @throws IllegalStateException if Bluetooth is not turned ON. 1648 * @hide 1649 */ 1650 @SystemApi 1651 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) setSilenceMode(boolean silence)1652 public boolean setSilenceMode(boolean silence) { 1653 final IBluetooth service = sService; 1654 if (service == null) { 1655 throw new IllegalStateException("Bluetooth is not turned ON"); 1656 } 1657 try { 1658 return service.setSilenceMode(this, silence); 1659 } catch (RemoteException e) { 1660 Log.e(TAG, "setSilenceMode fail", e); 1661 return false; 1662 } 1663 } 1664 1665 /** 1666 * Check whether the {@link BluetoothDevice} is in silence mode 1667 * 1668 * <p> Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. 1669 * 1670 * @return true on device in silence mode, otherwise false. 1671 * @throws IllegalStateException if Bluetooth is not turned ON. 1672 * @hide 1673 */ 1674 @SystemApi 1675 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) isInSilenceMode()1676 public boolean isInSilenceMode() { 1677 final IBluetooth service = sService; 1678 if (service == null) { 1679 throw new IllegalStateException("Bluetooth is not turned ON"); 1680 } 1681 try { 1682 return service.getSilenceMode(this); 1683 } catch (RemoteException e) { 1684 Log.e(TAG, "isInSilenceMode fail", e); 1685 return false; 1686 } 1687 } 1688 1689 /** 1690 * Sets whether the phonebook access is allowed to this device. 1691 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. 1692 * 1693 * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link 1694 * #ACCESS_REJECTED}. 1695 * @return Whether the value has been successfully set. 1696 * @hide 1697 */ 1698 @SystemApi 1699 @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) setPhonebookAccessPermission(int value)1700 public boolean setPhonebookAccessPermission(int value) { 1701 final IBluetooth service = sService; 1702 if (service == null) { 1703 return false; 1704 } 1705 try { 1706 return service.setPhonebookAccessPermission(this, value); 1707 } catch (RemoteException e) { 1708 Log.e(TAG, "", e); 1709 } 1710 return false; 1711 } 1712 1713 /** 1714 * Requires {@link android.Manifest.permission#BLUETOOTH}. 1715 * 1716 * @return Whether the message access is allowed to this device. Can be {@link #ACCESS_UNKNOWN}, 1717 * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. 1718 * @hide 1719 */ 1720 @UnsupportedAppUsage getMessageAccessPermission()1721 public int getMessageAccessPermission() { 1722 final IBluetooth service = sService; 1723 if (service == null) { 1724 return ACCESS_UNKNOWN; 1725 } 1726 try { 1727 return service.getMessageAccessPermission(this); 1728 } catch (RemoteException e) { 1729 Log.e(TAG, "", e); 1730 } 1731 return ACCESS_UNKNOWN; 1732 } 1733 1734 /** 1735 * Sets whether the message access is allowed to this device. 1736 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. 1737 * 1738 * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link 1739 * #ACCESS_REJECTED}. 1740 * @return Whether the value has been successfully set. 1741 * @hide 1742 */ 1743 @UnsupportedAppUsage setMessageAccessPermission(int value)1744 public boolean setMessageAccessPermission(int value) { 1745 final IBluetooth service = sService; 1746 if (service == null) { 1747 return false; 1748 } 1749 try { 1750 return service.setMessageAccessPermission(this, value); 1751 } catch (RemoteException e) { 1752 Log.e(TAG, "", e); 1753 } 1754 return false; 1755 } 1756 1757 /** 1758 * Requires {@link android.Manifest.permission#BLUETOOTH}. 1759 * 1760 * @return Whether the Sim access is allowed to this device. Can be {@link #ACCESS_UNKNOWN}, 1761 * {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. 1762 * @hide 1763 */ getSimAccessPermission()1764 public int getSimAccessPermission() { 1765 final IBluetooth service = sService; 1766 if (service == null) { 1767 return ACCESS_UNKNOWN; 1768 } 1769 try { 1770 return service.getSimAccessPermission(this); 1771 } catch (RemoteException e) { 1772 Log.e(TAG, "", e); 1773 } 1774 return ACCESS_UNKNOWN; 1775 } 1776 1777 /** 1778 * Sets whether the Sim access is allowed to this device. 1779 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. 1780 * 1781 * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link 1782 * #ACCESS_REJECTED}. 1783 * @return Whether the value has been successfully set. 1784 * @hide 1785 */ 1786 @UnsupportedAppUsage setSimAccessPermission(int value)1787 public boolean setSimAccessPermission(int value) { 1788 final IBluetooth service = sService; 1789 if (service == null) { 1790 return false; 1791 } 1792 try { 1793 return service.setSimAccessPermission(this, value); 1794 } catch (RemoteException e) { 1795 Log.e(TAG, "", e); 1796 } 1797 return false; 1798 } 1799 1800 /** 1801 * Create an RFCOMM {@link BluetoothSocket} ready to start a secure 1802 * outgoing connection to this remote device on given channel. 1803 * <p>The remote device will be authenticated and communication on this 1804 * socket will be encrypted. 1805 * <p> Use this socket only if an authenticated socket link is possible. 1806 * Authentication refers to the authentication of the link key to 1807 * prevent man-in-the-middle type of attacks. 1808 * For example, for Bluetooth 2.1 devices, if any of the devices does not 1809 * have an input and output capability or just has the ability to 1810 * display a numeric key, a secure socket connection is not possible. 1811 * In such a case, use {@link createInsecureRfcommSocket}. 1812 * For more details, refer to the Security Model section 5.2 (vol 3) of 1813 * Bluetooth Core Specification version 2.1 + EDR. 1814 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1815 * connection. 1816 * <p>Valid RFCOMM channels are in range 1 to 30. 1817 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1818 * 1819 * @param channel RFCOMM channel to connect to 1820 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1821 * @throws IOException on error, for example Bluetooth not available, or insufficient 1822 * permissions 1823 * @hide 1824 */ 1825 @UnsupportedAppUsage createRfcommSocket(int channel)1826 public BluetoothSocket createRfcommSocket(int channel) throws IOException { 1827 if (!isBluetoothEnabled()) { 1828 Log.e(TAG, "Bluetooth is not enabled"); 1829 throw new IOException(); 1830 } 1831 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel, 1832 null); 1833 } 1834 1835 /** 1836 * Create an L2cap {@link BluetoothSocket} ready to start a secure 1837 * outgoing connection to this remote device on given channel. 1838 * <p>The remote device will be authenticated and communication on this 1839 * socket will be encrypted. 1840 * <p> Use this socket only if an authenticated socket link is possible. 1841 * Authentication refers to the authentication of the link key to 1842 * prevent man-in-the-middle type of attacks. 1843 * For example, for Bluetooth 2.1 devices, if any of the devices does not 1844 * have an input and output capability or just has the ability to 1845 * display a numeric key, a secure socket connection is not possible. 1846 * In such a case, use {@link createInsecureRfcommSocket}. 1847 * For more details, refer to the Security Model section 5.2 (vol 3) of 1848 * Bluetooth Core Specification version 2.1 + EDR. 1849 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1850 * connection. 1851 * <p>Valid L2CAP PSM channels are in range 1 to 2^16. 1852 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1853 * 1854 * @param channel L2cap PSM/channel to connect to 1855 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1856 * @throws IOException on error, for example Bluetooth not available, or insufficient 1857 * permissions 1858 * @hide 1859 */ createL2capSocket(int channel)1860 public BluetoothSocket createL2capSocket(int channel) throws IOException { 1861 return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, true, true, this, channel, 1862 null); 1863 } 1864 1865 /** 1866 * Create an L2cap {@link BluetoothSocket} ready to start an insecure 1867 * outgoing connection to this remote device on given channel. 1868 * <p>The remote device will be not authenticated and communication on this 1869 * socket will not be encrypted. 1870 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1871 * connection. 1872 * <p>Valid L2CAP PSM channels are in range 1 to 2^16. 1873 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1874 * 1875 * @param channel L2cap PSM/channel to connect to 1876 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1877 * @throws IOException on error, for example Bluetooth not available, or insufficient 1878 * permissions 1879 * @hide 1880 */ createInsecureL2capSocket(int channel)1881 public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException { 1882 return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false, false, this, channel, 1883 null); 1884 } 1885 1886 /** 1887 * Create an RFCOMM {@link BluetoothSocket} ready to start a secure 1888 * outgoing connection to this remote device using SDP lookup of uuid. 1889 * <p>This is designed to be used with {@link 1890 * BluetoothAdapter#listenUsingRfcommWithServiceRecord} for peer-peer 1891 * Bluetooth applications. 1892 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1893 * connection. This will also perform an SDP lookup of the given uuid to 1894 * determine which channel to connect to. 1895 * <p>The remote device will be authenticated and communication on this 1896 * socket will be encrypted. 1897 * <p> Use this socket only if an authenticated socket link is possible. 1898 * Authentication refers to the authentication of the link key to 1899 * prevent man-in-the-middle type of attacks. 1900 * For example, for Bluetooth 2.1 devices, if any of the devices does not 1901 * have an input and output capability or just has the ability to 1902 * display a numeric key, a secure socket connection is not possible. 1903 * In such a case, use {@link #createInsecureRfcommSocketToServiceRecord}. 1904 * For more details, refer to the Security Model section 5.2 (vol 3) of 1905 * Bluetooth Core Specification version 2.1 + EDR. 1906 * <p>Hint: If you are connecting to a Bluetooth serial board then try 1907 * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. 1908 * However if you are connecting to an Android peer then please generate 1909 * your own unique UUID. 1910 * 1911 * @param uuid service record uuid to lookup RFCOMM channel 1912 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1913 * @throws IOException on error, for example Bluetooth not available, or insufficient 1914 * permissions 1915 */ 1916 @RequiresPermission(Manifest.permission.BLUETOOTH) createRfcommSocketToServiceRecord(UUID uuid)1917 public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException { 1918 if (!isBluetoothEnabled()) { 1919 Log.e(TAG, "Bluetooth is not enabled"); 1920 throw new IOException(); 1921 } 1922 1923 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1, 1924 new ParcelUuid(uuid)); 1925 } 1926 1927 /** 1928 * Create an RFCOMM {@link BluetoothSocket} socket ready to start an insecure 1929 * outgoing connection to this remote device using SDP lookup of uuid. 1930 * <p> The communication channel will not have an authenticated link key 1931 * i.e it will be subject to man-in-the-middle attacks. For Bluetooth 2.1 1932 * devices, the link key will be encrypted, as encryption is mandatory. 1933 * For legacy devices (pre Bluetooth 2.1 devices) the link key will 1934 * be not be encrypted. Use {@link #createRfcommSocketToServiceRecord} if an 1935 * encrypted and authenticated communication channel is desired. 1936 * <p>This is designed to be used with {@link 1937 * BluetoothAdapter#listenUsingInsecureRfcommWithServiceRecord} for peer-peer 1938 * Bluetooth applications. 1939 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1940 * connection. This will also perform an SDP lookup of the given uuid to 1941 * determine which channel to connect to. 1942 * <p>The remote device will be authenticated and communication on this 1943 * socket will be encrypted. 1944 * <p>Hint: If you are connecting to a Bluetooth serial board then try 1945 * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. 1946 * However if you are connecting to an Android peer then please generate 1947 * your own unique UUID. 1948 * 1949 * @param uuid service record uuid to lookup RFCOMM channel 1950 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1951 * @throws IOException on error, for example Bluetooth not available, or insufficient 1952 * permissions 1953 */ 1954 @RequiresPermission(Manifest.permission.BLUETOOTH) createInsecureRfcommSocketToServiceRecord(UUID uuid)1955 public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException { 1956 if (!isBluetoothEnabled()) { 1957 Log.e(TAG, "Bluetooth is not enabled"); 1958 throw new IOException(); 1959 } 1960 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1, 1961 new ParcelUuid(uuid)); 1962 } 1963 1964 /** 1965 * Construct an insecure RFCOMM socket ready to start an outgoing 1966 * connection. 1967 * Call #connect on the returned #BluetoothSocket to begin the connection. 1968 * The remote device will not be authenticated and communication on this 1969 * socket will not be encrypted. 1970 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1971 * 1972 * @param port remote port 1973 * @return An RFCOMM BluetoothSocket 1974 * @throws IOException On error, for example Bluetooth not available, or insufficient 1975 * permissions. 1976 * @hide 1977 */ 1978 @UnsupportedAppUsage createInsecureRfcommSocket(int port)1979 public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException { 1980 if (!isBluetoothEnabled()) { 1981 Log.e(TAG, "Bluetooth is not enabled"); 1982 throw new IOException(); 1983 } 1984 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port, 1985 null); 1986 } 1987 1988 /** 1989 * Construct a SCO socket ready to start an outgoing connection. 1990 * Call #connect on the returned #BluetoothSocket to begin the connection. 1991 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1992 * 1993 * @return a SCO BluetoothSocket 1994 * @throws IOException on error, for example Bluetooth not available, or insufficient 1995 * permissions. 1996 * @hide 1997 */ 1998 @UnsupportedAppUsage createScoSocket()1999 public BluetoothSocket createScoSocket() throws IOException { 2000 if (!isBluetoothEnabled()) { 2001 Log.e(TAG, "Bluetooth is not enabled"); 2002 throw new IOException(); 2003 } 2004 return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null); 2005 } 2006 2007 /** 2008 * Check that a pin is valid and convert to byte array. 2009 * 2010 * Bluetooth pin's are 1 to 16 bytes of UTF-8 characters. 2011 * 2012 * @param pin pin as java String 2013 * @return the pin code as a UTF-8 byte array, or null if it is an invalid Bluetooth pin. 2014 * @hide 2015 */ 2016 @UnsupportedAppUsage convertPinToBytes(String pin)2017 public static byte[] convertPinToBytes(String pin) { 2018 if (pin == null) { 2019 return null; 2020 } 2021 byte[] pinBytes; 2022 try { 2023 pinBytes = pin.getBytes("UTF-8"); 2024 } catch (UnsupportedEncodingException uee) { 2025 Log.e(TAG, "UTF-8 not supported?!?"); // this should not happen 2026 return null; 2027 } 2028 if (pinBytes.length <= 0 || pinBytes.length > 16) { 2029 return null; 2030 } 2031 return pinBytes; 2032 } 2033 2034 /** 2035 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 2036 * The callback is used to deliver results to Caller, such as connection status as well 2037 * as any further GATT client operations. 2038 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 2039 * GATT client operations. 2040 * 2041 * @param callback GATT callback handler that will receive asynchronous callbacks. 2042 * @param autoConnect Whether to directly connect to the remote device (false) or to 2043 * automatically connect as soon as the remote device becomes available (true). 2044 * @throws IllegalArgumentException if callback is null 2045 */ connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)2046 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 2047 BluetoothGattCallback callback) { 2048 return (connectGatt(context, autoConnect, callback, TRANSPORT_AUTO)); 2049 } 2050 2051 /** 2052 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 2053 * The callback is used to deliver results to Caller, such as connection status as well 2054 * as any further GATT client operations. 2055 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 2056 * GATT client operations. 2057 * 2058 * @param callback GATT callback handler that will receive asynchronous callbacks. 2059 * @param autoConnect Whether to directly connect to the remote device (false) or to 2060 * automatically connect as soon as the remote device becomes available (true). 2061 * @param transport preferred transport for GATT connections to remote dual-mode devices {@link 2062 * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link 2063 * BluetoothDevice#TRANSPORT_LE} 2064 * @throws IllegalArgumentException if callback is null 2065 */ connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport)2066 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 2067 BluetoothGattCallback callback, int transport) { 2068 return (connectGatt(context, autoConnect, callback, transport, PHY_LE_1M_MASK)); 2069 } 2070 2071 /** 2072 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 2073 * The callback is used to deliver results to Caller, such as connection status as well 2074 * as any further GATT client operations. 2075 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 2076 * GATT client operations. 2077 * 2078 * @param callback GATT callback handler that will receive asynchronous callbacks. 2079 * @param autoConnect Whether to directly connect to the remote device (false) or to 2080 * automatically connect as soon as the remote device becomes available (true). 2081 * @param transport preferred transport for GATT connections to remote dual-mode devices {@link 2082 * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link 2083 * BluetoothDevice#TRANSPORT_LE} 2084 * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link 2085 * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, and {@link 2086 * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} 2087 * is set to true. 2088 * @throws NullPointerException if callback is null 2089 */ connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, int phy)2090 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 2091 BluetoothGattCallback callback, int transport, int phy) { 2092 return connectGatt(context, autoConnect, callback, transport, phy, null); 2093 } 2094 2095 /** 2096 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 2097 * The callback is used to deliver results to Caller, such as connection status as well 2098 * as any further GATT client operations. 2099 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 2100 * GATT client operations. 2101 * 2102 * @param callback GATT callback handler that will receive asynchronous callbacks. 2103 * @param autoConnect Whether to directly connect to the remote device (false) or to 2104 * automatically connect as soon as the remote device becomes available (true). 2105 * @param transport preferred transport for GATT connections to remote dual-mode devices {@link 2106 * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link 2107 * BluetoothDevice#TRANSPORT_LE} 2108 * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link 2109 * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link 2110 * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} 2111 * is set to true. 2112 * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on 2113 * an un-specified background thread. 2114 * @throws NullPointerException if callback is null 2115 */ connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, int phy, Handler handler)2116 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 2117 BluetoothGattCallback callback, int transport, int phy, 2118 Handler handler) { 2119 return connectGatt(context, autoConnect, callback, transport, false, phy, handler); 2120 } 2121 2122 /** 2123 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 2124 * The callback is used to deliver results to Caller, such as connection status as well 2125 * as any further GATT client operations. 2126 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 2127 * GATT client operations. 2128 * 2129 * @param callback GATT callback handler that will receive asynchronous callbacks. 2130 * @param autoConnect Whether to directly connect to the remote device (false) or to 2131 * automatically connect as soon as the remote device becomes available (true). 2132 * @param transport preferred transport for GATT connections to remote dual-mode devices {@link 2133 * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link 2134 * BluetoothDevice#TRANSPORT_LE} 2135 * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client 2136 * does not hold a GATT connection. It automatically disconnects when no other GATT connections 2137 * are active for the remote device. 2138 * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link 2139 * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link 2140 * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect} 2141 * is set to true. 2142 * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on 2143 * an un-specified background thread. 2144 * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client 2145 * operations. 2146 * @hide 2147 */ 2148 @UnsupportedAppUsage connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback, int transport, boolean opportunistic, int phy, Handler handler)2149 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 2150 BluetoothGattCallback callback, int transport, 2151 boolean opportunistic, int phy, Handler handler) { 2152 if (callback == null) { 2153 throw new NullPointerException("callback is null"); 2154 } 2155 2156 // TODO(Bluetooth) check whether platform support BLE 2157 // Do the check here or in GattServer? 2158 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 2159 IBluetoothManager managerService = adapter.getBluetoothManager(); 2160 try { 2161 IBluetoothGatt iGatt = managerService.getBluetoothGatt(); 2162 if (iGatt == null) { 2163 // BLE is not supported 2164 return null; 2165 } 2166 BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy); 2167 gatt.connect(autoConnect, callback, handler); 2168 return gatt; 2169 } catch (RemoteException e) { 2170 Log.e(TAG, "", e); 2171 } 2172 return null; 2173 } 2174 2175 /** 2176 * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can 2177 * be used to start a secure outgoing connection to the remote device with the same dynamic 2178 * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only. 2179 * <p>This is designed to be used with {@link BluetoothAdapter#listenUsingL2capChannel()} for 2180 * peer-peer Bluetooth applications. 2181 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection. 2182 * <p>Application using this API is responsible for obtaining PSM value from remote device. 2183 * <p>The remote device will be authenticated and communication on this socket will be 2184 * encrypted. 2185 * <p> Use this socket if an authenticated socket link is possible. Authentication refers 2186 * to the authentication of the link key to prevent man-in-the-middle type of attacks. 2187 * 2188 * @param psm dynamic PSM value from remote device 2189 * @return a CoC #BluetoothSocket ready for an outgoing connection 2190 * @throws IOException on error, for example Bluetooth not available, or insufficient 2191 * permissions 2192 */ 2193 @RequiresPermission(Manifest.permission.BLUETOOTH) createL2capChannel(int psm)2194 public @NonNull BluetoothSocket createL2capChannel(int psm) throws IOException { 2195 if (!isBluetoothEnabled()) { 2196 Log.e(TAG, "createL2capChannel: Bluetooth is not enabled"); 2197 throw new IOException(); 2198 } 2199 if (DBG) Log.d(TAG, "createL2capChannel: psm=" + psm); 2200 return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, true, true, this, psm, 2201 null); 2202 } 2203 2204 /** 2205 * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new 2206 * API name, createL2capChannel. 2207 * @hide 2208 */ 2209 @RequiresPermission(Manifest.permission.BLUETOOTH) createL2capCocSocket(int transport, int psm)2210 public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException { 2211 Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createL2capChannel"); 2212 return createL2capChannel(psm); 2213 } 2214 2215 /** 2216 * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can 2217 * be used to start a secure outgoing connection to the remote device with the same dynamic 2218 * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only. 2219 * <p>This is designed to be used with {@link 2220 * BluetoothAdapter#listenUsingInsecureL2capChannel()} for peer-peer Bluetooth applications. 2221 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing connection. 2222 * <p>Application using this API is responsible for obtaining PSM value from remote device. 2223 * <p> The communication channel may not have an authenticated link key, i.e. it may be subject 2224 * to man-in-the-middle attacks. Use {@link #createL2capChannel(int)} if an encrypted and 2225 * authenticated communication channel is possible. 2226 * 2227 * @param psm dynamic PSM value from remote device 2228 * @return a CoC #BluetoothSocket ready for an outgoing connection 2229 * @throws IOException on error, for example Bluetooth not available, or insufficient 2230 * permissions 2231 */ 2232 @RequiresPermission(Manifest.permission.BLUETOOTH) createInsecureL2capChannel(int psm)2233 public @NonNull BluetoothSocket createInsecureL2capChannel(int psm) throws IOException { 2234 if (!isBluetoothEnabled()) { 2235 Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled"); 2236 throw new IOException(); 2237 } 2238 if (DBG) { 2239 Log.d(TAG, "createInsecureL2capChannel: psm=" + psm); 2240 } 2241 return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP_LE, -1, false, false, this, psm, 2242 null); 2243 } 2244 2245 /** 2246 * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new 2247 * API name, createInsecureL2capChannel. 2248 * @hide 2249 */ 2250 @RequiresPermission(Manifest.permission.BLUETOOTH) createInsecureL2capCocSocket(int transport, int psm)2251 public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException { 2252 Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createInsecureL2capChannel"); 2253 return createInsecureL2capChannel(psm); 2254 } 2255 2256 /** 2257 * Set a keyed metadata of this {@link BluetoothDevice} to a 2258 * {@link String} value. 2259 * Only bonded devices's metadata will be persisted across Bluetooth 2260 * restart. 2261 * Metadata will be removed when the device's bond state is moved to 2262 * {@link #BOND_NONE}. 2263 * 2264 * @param key must be within the list of BluetoothDevice.METADATA_* 2265 * @param value a byte array data to set for key. Must be less than 2266 * {@link BluetoothAdapter#METADATA_MAX_LENGTH} characters in length 2267 * @return true on success, false on error 2268 * @hide 2269 */ 2270 @SystemApi 2271 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) setMetadata(int key, @NonNull byte[] value)2272 public boolean setMetadata(int key, @NonNull byte[] value) { 2273 final IBluetooth service = sService; 2274 if (service == null) { 2275 Log.e(TAG, "Bluetooth is not enabled. Cannot set metadata"); 2276 return false; 2277 } 2278 if (value.length > METADATA_MAX_LENGTH) { 2279 throw new IllegalArgumentException("value length is " + value.length 2280 + ", should not over " + METADATA_MAX_LENGTH); 2281 } 2282 try { 2283 return service.setMetadata(this, key, value); 2284 } catch (RemoteException e) { 2285 Log.e(TAG, "setMetadata fail", e); 2286 return false; 2287 } 2288 } 2289 2290 /** 2291 * Get a keyed metadata for this {@link BluetoothDevice} as {@link String} 2292 * 2293 * @param key must be within the list of BluetoothDevice.METADATA_* 2294 * @return Metadata of the key as byte array, null on error or not found 2295 * @hide 2296 */ 2297 @SystemApi 2298 @Nullable 2299 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) getMetadata(int key)2300 public byte[] getMetadata(int key) { 2301 final IBluetooth service = sService; 2302 if (service == null) { 2303 Log.e(TAG, "Bluetooth is not enabled. Cannot get metadata"); 2304 return null; 2305 } 2306 try { 2307 return service.getMetadata(this, key); 2308 } catch (RemoteException e) { 2309 Log.e(TAG, "getMetadata fail", e); 2310 return null; 2311 } 2312 } 2313 } 2314