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