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 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 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 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 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 962 public String toString() { 963 return mAddress; 964 } 965 966 @Override 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 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 */ 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) 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) 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 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 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 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 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) 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 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 */ 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 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 */ 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) 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) 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) 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) 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) 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) 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) 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) 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 */ 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 */ 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 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) 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 */ 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 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 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 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 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) 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) 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) 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 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 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 */ 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 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 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 */ 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 */ 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) 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) 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 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 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 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 */ 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 */ 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 */ 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 */ 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 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) 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) 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) 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) 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) 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) 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