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 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 */ 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 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 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 762 public String toString() { 763 return mAddress; 764 } 765 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 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 */ 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) 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 return service.getRemoteName(this); 812 } catch (RemoteException e) { 813 Log.e(TAG, "", e); 814 } 815 return null; 816 } 817 818 /** 819 * Get the Bluetooth device type of the remote device. 820 * 821 * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} 822 * {@link #DEVICE_TYPE_DUAL}. 823 * {@link #DEVICE_TYPE_UNKNOWN} if it's not available 824 */ 825 @RequiresPermission(Manifest.permission.BLUETOOTH) 826 public int getType() { 827 final IBluetooth service = sService; 828 if (service == null) { 829 Log.e(TAG, "BT not enabled. Cannot get Remote Device type"); 830 return DEVICE_TYPE_UNKNOWN; 831 } 832 try { 833 return service.getRemoteType(this); 834 } catch (RemoteException e) { 835 Log.e(TAG, "", e); 836 } 837 return DEVICE_TYPE_UNKNOWN; 838 } 839 840 /** 841 * Get the Bluetooth alias of the remote device. 842 * <p>Alias is the locally modified name of a remote device. 843 * 844 * @return the Bluetooth alias, or null if no alias or there was a problem 845 * @hide 846 */ 847 public String getAlias() { 848 final IBluetooth service = sService; 849 if (service == null) { 850 Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias"); 851 return null; 852 } 853 try { 854 return service.getRemoteAlias(this); 855 } catch (RemoteException e) { 856 Log.e(TAG, "", e); 857 } 858 return null; 859 } 860 861 /** 862 * Set the Bluetooth alias of the remote device. 863 * <p>Alias is the locally modified name of a remote device. 864 * <p>This methoid overwrites the alias. The changed 865 * alias is saved in the local storage so that the change 866 * is preserved over power cycle. 867 * 868 * @return true on success, false on error 869 * @hide 870 */ 871 public boolean setAlias(String alias) { 872 final IBluetooth service = sService; 873 if (service == null) { 874 Log.e(TAG, "BT not enabled. Cannot set Remote Device name"); 875 return false; 876 } 877 try { 878 return service.setRemoteAlias(this, alias); 879 } catch (RemoteException e) { 880 Log.e(TAG, "", e); 881 } 882 return false; 883 } 884 885 /** 886 * Get the Bluetooth alias of the remote device. 887 * If Alias is null, get the Bluetooth name instead. 888 * @see #getAlias() 889 * @see #getName() 890 * 891 * @return the Bluetooth alias, or null if no alias or there was a problem 892 * @hide 893 */ 894 public String getAliasName() { 895 String name = getAlias(); 896 if (name == null) { 897 name = getName(); 898 } 899 return name; 900 } 901 902 /** 903 * Get the most recent identified battery level of this Bluetooth device 904 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 905 * 906 * @return Battery level in percents from 0 to 100, or {@link #BATTERY_LEVEL_UNKNOWN} if 907 * Bluetooth is disabled, or device is disconnected, or does not have any battery 908 * reporting service, or return value is invalid 909 * @hide 910 */ 911 @RequiresPermission(Manifest.permission.BLUETOOTH) 912 public int getBatteryLevel() { 913 final IBluetooth service = sService; 914 if (service == null) { 915 Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level"); 916 return BATTERY_LEVEL_UNKNOWN; 917 } 918 try { 919 return service.getBatteryLevel(this); 920 } catch (RemoteException e) { 921 Log.e(TAG, "", e); 922 } 923 return BATTERY_LEVEL_UNKNOWN; 924 } 925 926 /** 927 * Start the bonding (pairing) process with the remote device. 928 * <p>This is an asynchronous call, it will return immediately. Register 929 * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when 930 * the bonding process completes, and its result. 931 * <p>Android system services will handle the necessary user interactions 932 * to confirm and complete the bonding process. 933 * 934 * @return false on immediate error, true if bonding will begin 935 */ 936 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 937 public boolean createBond() { 938 final IBluetooth service = sService; 939 if (service == null) { 940 Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); 941 return false; 942 } 943 try { 944 Log.i(TAG, "createBond() for device " + getAddress() 945 + " called by pid: " + Process.myPid() 946 + " tid: " + Process.myTid()); 947 return service.createBond(this, TRANSPORT_AUTO); 948 } catch (RemoteException e) { 949 Log.e(TAG, "", e); 950 } 951 return false; 952 } 953 954 /** 955 * Start the bonding (pairing) process with the remote device using the 956 * specified transport. 957 * 958 * <p>This is an asynchronous call, it will return immediately. Register 959 * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when 960 * the bonding process completes, and its result. 961 * <p>Android system services will handle the necessary user interactions 962 * to confirm and complete the bonding process. 963 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 964 * 965 * @param transport The transport to use for the pairing procedure. 966 * @return false on immediate error, true if bonding will begin 967 * @throws IllegalArgumentException if an invalid transport was specified 968 * @hide 969 */ 970 public boolean createBond(int transport) { 971 final IBluetooth service = sService; 972 if (service == null) { 973 Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device"); 974 return false; 975 } 976 if (TRANSPORT_AUTO > transport || transport > TRANSPORT_LE) 977 { 978 throw new IllegalArgumentException(transport + " is not a valid Bluetooth transport"); 979 } 980 try { 981 Log.i(TAG, "createBond() for device " + getAddress() 982 + " called by pid: " + Process.myPid() 983 + " tid: " + Process.myTid()); 984 return service.createBond(this, transport); 985 } catch (RemoteException e) { 986 Log.e(TAG, "", e); 987 } 988 return false; 989 } 990 991 /** 992 * Start the bonding (pairing) process with the remote device using the 993 * Out Of Band mechanism. 994 * 995 * <p>This is an asynchronous call, it will return immediately. Register 996 * for {@link #ACTION_BOND_STATE_CHANGED} intents to be notified when 997 * the bonding process completes, and its result. 998 * 999 * <p>Android system services will handle the necessary user interactions 1000 * to confirm and complete the bonding process. 1001 * 1002 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1003 * 1004 * @param transport - Transport to use 1005 * @param oobData - Out Of Band data 1006 * @return false on immediate error, true if bonding will begin 1007 * 1008 * @hide 1009 */ 1010 public boolean createBondOutOfBand(int transport, OobData oobData) { 1011 final IBluetooth service = sService; 1012 if (service == null) { 1013 Log.w(TAG, "BT not enabled, createBondOutOfBand failed"); 1014 return false; 1015 } 1016 try { 1017 return service.createBondOutOfBand(this, transport, oobData); 1018 } catch (RemoteException e) { 1019 Log.e(TAG, "", e); 1020 } 1021 return false; 1022 } 1023 1024 /** @hide */ 1025 public boolean isBondingInitiatedLocally() { 1026 final IBluetooth service = sService; 1027 if (service == null) { 1028 Log.w(TAG, "BT not enabled, isBondingInitiatedLocally failed"); 1029 return false; 1030 } 1031 try { 1032 return service.isBondingInitiatedLocally(this); 1033 } catch (RemoteException e) { 1034 Log.e(TAG, "", e); 1035 } 1036 return false; 1037 } 1038 1039 /** 1040 * Set the Out Of Band data for a remote device to be used later 1041 * in the pairing mechanism. Users can obtain this data through other 1042 * trusted channels 1043 * 1044 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1045 * 1046 * @param hash Simple Secure pairing hash 1047 * @param randomizer The random key obtained using OOB 1048 * @return false on error; true otherwise 1049 * 1050 * @hide 1051 */ 1052 public boolean setDeviceOutOfBandData(byte[] hash, byte[] randomizer) { 1053 //TODO(BT) 1054 /* 1055 try { 1056 return sService.setDeviceOutOfBandData(this, hash, randomizer); 1057 } catch (RemoteException e) {Log.e(TAG, "", e);} */ 1058 return false; 1059 } 1060 1061 /** 1062 * Cancel an in-progress bonding request started with {@link #createBond}. 1063 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1064 * 1065 * @return true on success, false on error 1066 * @hide 1067 */ 1068 public boolean cancelBondProcess() { 1069 final IBluetooth service = sService; 1070 if (service == null) { 1071 Log.e(TAG, "BT not enabled. Cannot cancel Remote Device bond"); 1072 return false; 1073 } 1074 try { 1075 Log.i(TAG, "cancelBondProcess() for device " + getAddress() 1076 + " called by pid: " + Process.myPid() 1077 + " tid: " + Process.myTid()); 1078 return service.cancelBondProcess(this); 1079 } catch (RemoteException e) { 1080 Log.e(TAG, "", e); 1081 } 1082 return false; 1083 } 1084 1085 /** 1086 * Remove bond (pairing) with the remote device. 1087 * <p>Delete the link key associated with the remote device, and 1088 * immediately terminate connections to that device that require 1089 * authentication and encryption. 1090 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1091 * 1092 * @return true on success, false on error 1093 * @hide 1094 */ 1095 public boolean removeBond() { 1096 final IBluetooth service = sService; 1097 if (service == null) { 1098 Log.e(TAG, "BT not enabled. Cannot remove Remote Device bond"); 1099 return false; 1100 } 1101 try { 1102 Log.i(TAG, "removeBond() for device " + getAddress() 1103 + " called by pid: " + Process.myPid() 1104 + " tid: " + Process.myTid()); 1105 return service.removeBond(this); 1106 } catch (RemoteException e) { 1107 Log.e(TAG, "", e); 1108 } 1109 return false; 1110 } 1111 1112 /** 1113 * Get the bond state of the remote device. 1114 * <p>Possible values for the bond state are: 1115 * {@link #BOND_NONE}, 1116 * {@link #BOND_BONDING}, 1117 * {@link #BOND_BONDED}. 1118 * 1119 * @return the bond state 1120 */ 1121 @RequiresPermission(Manifest.permission.BLUETOOTH) 1122 public int getBondState() { 1123 final IBluetooth service = sService; 1124 if (service == null) { 1125 Log.e(TAG, "BT not enabled. Cannot get bond state"); 1126 return BOND_NONE; 1127 } 1128 try { 1129 return service.getBondState(this); 1130 } catch (RemoteException e) { 1131 Log.e(TAG, "", e); 1132 } 1133 return BOND_NONE; 1134 } 1135 1136 /** 1137 * Returns whether there is an open connection to this device. 1138 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1139 * 1140 * @return True if there is at least one open connection to this device. 1141 * @hide 1142 */ 1143 @SystemApi 1144 public boolean isConnected() { 1145 final IBluetooth service = sService; 1146 if (service == null) { 1147 // BT is not enabled, we cannot be connected. 1148 return false; 1149 } 1150 try { 1151 return service.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED; 1152 } catch (RemoteException e) { 1153 Log.e(TAG, "", e); 1154 return false; 1155 } 1156 } 1157 1158 /** 1159 * Returns whether there is an open connection to this device 1160 * that has been encrypted. 1161 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1162 * 1163 * @return True if there is at least one encrypted connection to this device. 1164 * @hide 1165 */ 1166 @SystemApi 1167 public boolean isEncrypted() { 1168 final IBluetooth service = sService; 1169 if (service == null) { 1170 // BT is not enabled, we cannot be connected. 1171 return false; 1172 } 1173 try { 1174 return service.getConnectionState(this) > CONNECTION_STATE_CONNECTED; 1175 } catch (RemoteException e) { 1176 Log.e(TAG, "", e); 1177 return false; 1178 } 1179 } 1180 1181 /** 1182 * Get the Bluetooth class of the remote device. 1183 * 1184 * @return Bluetooth class object, or null on error 1185 */ 1186 @RequiresPermission(Manifest.permission.BLUETOOTH) 1187 public BluetoothClass getBluetoothClass() { 1188 final IBluetooth service = sService; 1189 if (service == null) { 1190 Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class"); 1191 return null; 1192 } 1193 try { 1194 int classInt = service.getRemoteClass(this); 1195 if (classInt == BluetoothClass.ERROR) return null; 1196 return new BluetoothClass(classInt); 1197 } catch (RemoteException e) {Log.e(TAG, "", e);} 1198 return null; 1199 } 1200 1201 /** 1202 * Returns the supported features (UUIDs) of the remote device. 1203 * 1204 * <p>This method does not start a service discovery procedure to retrieve the UUIDs 1205 * from the remote device. Instead, the local cached copy of the service 1206 * UUIDs are returned. 1207 * <p>Use {@link #fetchUuidsWithSdp} if fresh UUIDs are desired. 1208 * 1209 * @return the supported features (UUIDs) of the remote device, 1210 * or null on error 1211 */ 1212 @RequiresPermission(Manifest.permission.BLUETOOTH) 1213 public ParcelUuid[] getUuids() { 1214 final IBluetooth service = sService; 1215 if (service == null || !isBluetoothEnabled()) { 1216 Log.e(TAG, "BT not enabled. Cannot get remote device Uuids"); 1217 return null; 1218 } 1219 try { 1220 return service.getRemoteUuids(this); 1221 } catch (RemoteException e) { 1222 Log.e(TAG, "", e); 1223 } 1224 return null; 1225 } 1226 1227 /** 1228 * Perform a service discovery on the remote device to get the UUIDs supported. 1229 * 1230 * <p>This API is asynchronous and {@link #ACTION_UUID} intent is sent, 1231 * with the UUIDs supported by the remote end. If there is an error 1232 * in getting the SDP records or if the process takes a long time, 1233 * {@link #ACTION_UUID} intent is sent with the UUIDs that is currently 1234 * present in the cache. Clients should use the {@link #getUuids} to get UUIDs 1235 * if service discovery is not to be performed. 1236 * 1237 * @return False if the sanity check fails, True if the process of initiating an ACL connection 1238 * to the remote device was started. 1239 */ 1240 @RequiresPermission(Manifest.permission.BLUETOOTH) 1241 public boolean fetchUuidsWithSdp() { 1242 final IBluetooth service = sService; 1243 if (service == null || !isBluetoothEnabled()) { 1244 Log.e(TAG, "BT not enabled. Cannot fetchUuidsWithSdp"); 1245 return false; 1246 } 1247 try { 1248 return service.fetchRemoteUuids(this); 1249 } catch (RemoteException e) { 1250 Log.e(TAG, "", e); 1251 } 1252 return false; 1253 } 1254 1255 /** 1256 * Perform a service discovery on the remote device to get the SDP records associated 1257 * with the specified UUID. 1258 * 1259 * <p>This API is asynchronous and {@link #ACTION_SDP_RECORD} intent is sent, 1260 * with the SDP records found on the remote end. If there is an error 1261 * in getting the SDP records or if the process takes a long time, 1262 * {@link #ACTION_SDP_RECORD} intent is sent with an status value in 1263 * {@link #EXTRA_SDP_SEARCH_STATUS} different from 0. 1264 * Detailed status error codes can be found by members of the Bluetooth package in 1265 * the AbstractionLayer class. 1266 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1267 * The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}. 1268 * The object type will match one of the SdpXxxRecord types, depending on the UUID searched 1269 * for. 1270 * 1271 * @return False if the sanity check fails, True if the process 1272 * of initiating an ACL connection to the remote device 1273 * was started. 1274 */ 1275 /** @hide */ 1276 public boolean sdpSearch(ParcelUuid uuid) { 1277 final IBluetooth service = sService; 1278 if (service == null) { 1279 Log.e(TAG, "BT not enabled. Cannot query remote device sdp records"); 1280 return false; 1281 } 1282 try { 1283 return service.sdpSearch(this, uuid); 1284 } catch (RemoteException e) { 1285 Log.e(TAG, "", e); 1286 } 1287 return false; 1288 } 1289 1290 /** 1291 * Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN} 1292 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1293 * 1294 * @return true pin has been set 1295 * false for error 1296 */ 1297 public boolean setPin(byte[] pin) { 1298 final IBluetooth service = sService; 1299 if (service == null) { 1300 Log.e(TAG, "BT not enabled. Cannot set Remote Device pin"); 1301 return false; 1302 } 1303 try { 1304 return service.setPin(this, true, pin.length, pin); 1305 } catch (RemoteException e) { 1306 Log.e(TAG, "", e); 1307 } 1308 return false; 1309 } 1310 1311 /** @hide */ 1312 public boolean setPasskey(int passkey) { 1313 //TODO(BT) 1314 /* 1315 try { 1316 return sService.setPasskey(this, true, 4, passkey); 1317 } catch (RemoteException e) {Log.e(TAG, "", e);}*/ 1318 return false; 1319 } 1320 1321 /** 1322 * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing. 1323 * 1324 * @return true confirmation has been sent out 1325 * false for error 1326 */ 1327 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) 1328 public boolean setPairingConfirmation(boolean confirm) { 1329 final IBluetooth service = sService; 1330 if (service == null) { 1331 Log.e(TAG, "BT not enabled. Cannot set pairing confirmation"); 1332 return false; 1333 } 1334 try { 1335 return service.setPairingConfirmation(this, confirm); 1336 } catch (RemoteException e) { 1337 Log.e(TAG, "", e); 1338 } 1339 return false; 1340 } 1341 1342 /** @hide */ 1343 public boolean setRemoteOutOfBandData() { 1344 // TODO(BT) 1345 /* 1346 try { 1347 return sService.setRemoteOutOfBandData(this); 1348 } catch (RemoteException e) {Log.e(TAG, "", e);}*/ 1349 return false; 1350 } 1351 1352 /** @hide */ 1353 public boolean cancelPairingUserInput() { 1354 final IBluetooth service = sService; 1355 if (service == null) { 1356 Log.e(TAG, "BT not enabled. Cannot create pairing user input"); 1357 return false; 1358 } 1359 try { 1360 return service.cancelBondProcess(this); 1361 } catch (RemoteException e) { 1362 Log.e(TAG, "", e); 1363 } 1364 return false; 1365 } 1366 1367 /** @hide */ 1368 public boolean isBluetoothDock() { 1369 // TODO(BT) 1370 /* 1371 try { 1372 return sService.isBluetoothDock(this); 1373 } catch (RemoteException e) {Log.e(TAG, "", e);}*/ 1374 return false; 1375 } 1376 1377 boolean isBluetoothEnabled() { 1378 boolean ret = false; 1379 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 1380 if (adapter != null && adapter.isEnabled() == true) { 1381 ret = true; 1382 } 1383 return ret; 1384 } 1385 1386 /** 1387 * Requires {@link android.Manifest.permission#BLUETOOTH}. 1388 * @return Whether the phonebook access is allowed to this device. Can be 1389 * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. 1390 * @hide 1391 */ 1392 public int getPhonebookAccessPermission() { 1393 final IBluetooth service = sService; 1394 if (service == null) { 1395 return ACCESS_UNKNOWN; 1396 } 1397 try { 1398 return service.getPhonebookAccessPermission(this); 1399 } catch (RemoteException e) { 1400 Log.e(TAG, "", e); 1401 } 1402 return ACCESS_UNKNOWN; 1403 } 1404 1405 /** 1406 * Sets whether the phonebook access is allowed to this device. 1407 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. 1408 * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or 1409 * {@link #ACCESS_REJECTED}. 1410 * @return Whether the value has been successfully set. 1411 * @hide 1412 */ 1413 public boolean setPhonebookAccessPermission(int value) { 1414 final IBluetooth service = sService; 1415 if (service == null) { 1416 return false; 1417 } 1418 try { 1419 return service.setPhonebookAccessPermission(this, value); 1420 } catch (RemoteException e) { 1421 Log.e(TAG, "", e); 1422 } 1423 return false; 1424 } 1425 1426 /** 1427 * Requires {@link android.Manifest.permission#BLUETOOTH}. 1428 * @return Whether the message access is allowed to this device. Can be 1429 * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. 1430 * @hide 1431 */ 1432 public int getMessageAccessPermission() { 1433 final IBluetooth service = sService; 1434 if (service == null) { 1435 return ACCESS_UNKNOWN; 1436 } 1437 try { 1438 return service.getMessageAccessPermission(this); 1439 } catch (RemoteException e) { 1440 Log.e(TAG, "", e); 1441 } 1442 return ACCESS_UNKNOWN; 1443 } 1444 1445 /** 1446 * Sets whether the message access is allowed to this device. 1447 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. 1448 * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or 1449 * {@link #ACCESS_REJECTED}. 1450 * @return Whether the value has been successfully set. 1451 * @hide 1452 */ 1453 public boolean setMessageAccessPermission(int value) { 1454 final IBluetooth service = sService; 1455 if (service == null) { 1456 return false; 1457 } 1458 try { 1459 return service.setMessageAccessPermission(this, value); 1460 } catch (RemoteException e) { 1461 Log.e(TAG, "", e); 1462 } 1463 return false; 1464 } 1465 1466 /** 1467 * Requires {@link android.Manifest.permission#BLUETOOTH}. 1468 * @return Whether the Sim access is allowed to this device. Can be 1469 * {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or {@link #ACCESS_REJECTED}. 1470 * @hide 1471 */ 1472 public int getSimAccessPermission() { 1473 final IBluetooth service = sService; 1474 if (service == null) { 1475 return ACCESS_UNKNOWN; 1476 } 1477 try { 1478 return service.getSimAccessPermission(this); 1479 } catch (RemoteException e) { 1480 Log.e(TAG, "", e); 1481 } 1482 return ACCESS_UNKNOWN; 1483 } 1484 1485 /** 1486 * Sets whether the Sim access is allowed to this device. 1487 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. 1488 * @param value Can be {@link #ACCESS_UNKNOWN}, {@link #ACCESS_ALLOWED} or 1489 * {@link #ACCESS_REJECTED}. 1490 * @return Whether the value has been successfully set. 1491 * @hide 1492 */ 1493 public boolean setSimAccessPermission(int value) { 1494 final IBluetooth service = sService; 1495 if (service == null) { 1496 return false; 1497 } 1498 try { 1499 return service.setSimAccessPermission(this, value); 1500 } catch (RemoteException e) { 1501 Log.e(TAG, "", e); 1502 } 1503 return false; 1504 } 1505 1506 /** 1507 * Create an RFCOMM {@link BluetoothSocket} ready to start a secure 1508 * outgoing connection to this remote device on given channel. 1509 * <p>The remote device will be authenticated and communication on this 1510 * socket will be encrypted. 1511 * <p> Use this socket only if an authenticated socket link is possible. 1512 * Authentication refers to the authentication of the link key to 1513 * prevent man-in-the-middle type of attacks. 1514 * For example, for Bluetooth 2.1 devices, if any of the devices does not 1515 * have an input and output capability or just has the ability to 1516 * display a numeric key, a secure socket connection is not possible. 1517 * In such a case, use {#link createInsecureRfcommSocket}. 1518 * For more details, refer to the Security Model section 5.2 (vol 3) of 1519 * Bluetooth Core Specification version 2.1 + EDR. 1520 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1521 * connection. 1522 * <p>Valid RFCOMM channels are in range 1 to 30. 1523 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1524 * 1525 * @param channel RFCOMM channel to connect to 1526 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1527 * @throws IOException on error, for example Bluetooth not available, or 1528 * insufficient permissions 1529 * @hide 1530 */ 1531 public BluetoothSocket createRfcommSocket(int channel) throws IOException { 1532 if (isBluetoothEnabled() == false) { 1533 Log.e(TAG, "Bluetooth is not enabled"); 1534 throw new IOException(); 1535 } 1536 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel, 1537 null); 1538 } 1539 1540 /** 1541 * Create an L2cap {@link BluetoothSocket} ready to start a secure 1542 * outgoing connection to this remote device on given channel. 1543 * <p>The remote device will be authenticated and communication on this 1544 * socket will be encrypted. 1545 * <p> Use this socket only if an authenticated socket link is possible. 1546 * Authentication refers to the authentication of the link key to 1547 * prevent man-in-the-middle type of attacks. 1548 * For example, for Bluetooth 2.1 devices, if any of the devices does not 1549 * have an input and output capability or just has the ability to 1550 * display a numeric key, a secure socket connection is not possible. 1551 * In such a case, use {#link createInsecureRfcommSocket}. 1552 * For more details, refer to the Security Model section 5.2 (vol 3) of 1553 * Bluetooth Core Specification version 2.1 + EDR. 1554 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1555 * connection. 1556 * <p>Valid L2CAP PSM channels are in range 1 to 2^16. 1557 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1558 * 1559 * @param channel L2cap PSM/channel to connect to 1560 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1561 * @throws IOException on error, for example Bluetooth not available, or 1562 * insufficient permissions 1563 * @hide 1564 */ 1565 public BluetoothSocket createL2capSocket(int channel) throws IOException { 1566 return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, true, true, this, channel, 1567 null); 1568 } 1569 1570 /** 1571 * Create an L2cap {@link BluetoothSocket} ready to start an insecure 1572 * outgoing connection to this remote device on given channel. 1573 * <p>The remote device will be not authenticated and communication on this 1574 * socket will not be encrypted. 1575 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1576 * connection. 1577 * <p>Valid L2CAP PSM channels are in range 1 to 2^16. 1578 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1579 * 1580 * @param channel L2cap PSM/channel to connect to 1581 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1582 * @throws IOException on error, for example Bluetooth not available, or 1583 * insufficient permissions 1584 * @hide 1585 */ 1586 public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException { 1587 return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false, false, this, channel, 1588 null); 1589 } 1590 1591 /** 1592 * Create an RFCOMM {@link BluetoothSocket} ready to start a secure 1593 * outgoing connection to this remote device using SDP lookup of uuid. 1594 * <p>This is designed to be used with {@link 1595 * BluetoothAdapter#listenUsingRfcommWithServiceRecord} for peer-peer 1596 * Bluetooth applications. 1597 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1598 * connection. This will also perform an SDP lookup of the given uuid to 1599 * determine which channel to connect to. 1600 * <p>The remote device will be authenticated and communication on this 1601 * socket will be encrypted. 1602 * <p> Use this socket only if an authenticated socket link is possible. 1603 * Authentication refers to the authentication of the link key to 1604 * prevent man-in-the-middle type of attacks. 1605 * For example, for Bluetooth 2.1 devices, if any of the devices does not 1606 * have an input and output capability or just has the ability to 1607 * display a numeric key, a secure socket connection is not possible. 1608 * In such a case, use {#link createInsecureRfcommSocketToServiceRecord}. 1609 * For more details, refer to the Security Model section 5.2 (vol 3) of 1610 * Bluetooth Core Specification version 2.1 + EDR. 1611 * <p>Hint: If you are connecting to a Bluetooth serial board then try 1612 * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. 1613 * However if you are connecting to an Android peer then please generate 1614 * your own unique UUID. 1615 * 1616 * @param uuid service record uuid to lookup RFCOMM channel 1617 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1618 * @throws IOException on error, for example Bluetooth not available, or 1619 * insufficient permissions 1620 */ 1621 @RequiresPermission(Manifest.permission.BLUETOOTH) 1622 public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException { 1623 if (isBluetoothEnabled() == false) { 1624 Log.e(TAG, "Bluetooth is not enabled"); 1625 throw new IOException(); 1626 } 1627 1628 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1, 1629 new ParcelUuid(uuid)); 1630 } 1631 1632 /** 1633 * Create an RFCOMM {@link BluetoothSocket} socket ready to start an insecure 1634 * outgoing connection to this remote device using SDP lookup of uuid. 1635 * <p> The communication channel will not have an authenticated link key 1636 * i.e it will be subject to man-in-the-middle attacks. For Bluetooth 2.1 1637 * devices, the link key will be encrypted, as encryption is mandatory. 1638 * For legacy devices (pre Bluetooth 2.1 devices) the link key will 1639 * be not be encrypted. Use {@link #createRfcommSocketToServiceRecord} if an 1640 * encrypted and authenticated communication channel is desired. 1641 * <p>This is designed to be used with {@link 1642 * BluetoothAdapter#listenUsingInsecureRfcommWithServiceRecord} for peer-peer 1643 * Bluetooth applications. 1644 * <p>Use {@link BluetoothSocket#connect} to initiate the outgoing 1645 * connection. This will also perform an SDP lookup of the given uuid to 1646 * determine which channel to connect to. 1647 * <p>The remote device will be authenticated and communication on this 1648 * socket will be encrypted. 1649 * <p>Hint: If you are connecting to a Bluetooth serial board then try 1650 * using the well-known SPP UUID 00001101-0000-1000-8000-00805F9B34FB. 1651 * However if you are connecting to an Android peer then please generate 1652 * your own unique UUID. 1653 * 1654 * @param uuid service record uuid to lookup RFCOMM channel 1655 * @return a RFCOMM BluetoothServerSocket ready for an outgoing connection 1656 * @throws IOException on error, for example Bluetooth not available, or 1657 * insufficient permissions 1658 */ 1659 @RequiresPermission(Manifest.permission.BLUETOOTH) 1660 public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException { 1661 if (isBluetoothEnabled() == false) { 1662 Log.e(TAG, "Bluetooth is not enabled"); 1663 throw new IOException(); 1664 } 1665 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1, 1666 new ParcelUuid(uuid)); 1667 } 1668 1669 /** 1670 * Construct an insecure RFCOMM socket ready to start an outgoing 1671 * connection. 1672 * Call #connect on the returned #BluetoothSocket to begin the connection. 1673 * The remote device will not be authenticated and communication on this 1674 * socket will not be encrypted. 1675 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1676 * 1677 * @param port remote port 1678 * @return An RFCOMM BluetoothSocket 1679 * @throws IOException On error, for example Bluetooth not available, or 1680 * insufficient permissions. 1681 * @hide 1682 */ 1683 public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException { 1684 1685 if (isBluetoothEnabled() == false) { 1686 Log.e(TAG, "Bluetooth is not enabled"); 1687 throw new IOException(); 1688 } 1689 return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port, 1690 null); 1691 } 1692 1693 /** 1694 * Construct a SCO socket ready to start an outgoing connection. 1695 * Call #connect on the returned #BluetoothSocket to begin the connection. 1696 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1697 * 1698 * @return a SCO BluetoothSocket 1699 * @throws IOException on error, for example Bluetooth not available, or 1700 * insufficient permissions. 1701 * @hide 1702 */ 1703 public BluetoothSocket createScoSocket() throws IOException { 1704 1705 if (isBluetoothEnabled() == false) { 1706 Log.e(TAG, "Bluetooth is not enabled"); 1707 throw new IOException(); 1708 } 1709 return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null); 1710 } 1711 1712 /** 1713 * Check that a pin is valid and convert to byte array. 1714 * 1715 * Bluetooth pin's are 1 to 16 bytes of UTF-8 characters. 1716 * @param pin pin as java String 1717 * @return the pin code as a UTF-8 byte array, or null if it is an invalid 1718 * Bluetooth pin. 1719 * @hide 1720 */ 1721 public static byte[] convertPinToBytes(String pin) { 1722 if (pin == null) { 1723 return null; 1724 } 1725 byte[] pinBytes; 1726 try { 1727 pinBytes = pin.getBytes("UTF-8"); 1728 } catch (UnsupportedEncodingException uee) { 1729 Log.e(TAG, "UTF-8 not supported?!?"); // this should not happen 1730 return null; 1731 } 1732 if (pinBytes.length <= 0 || pinBytes.length > 16) { 1733 return null; 1734 } 1735 return pinBytes; 1736 } 1737 1738 /** 1739 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 1740 * The callback is used to deliver results to Caller, such as connection status as well 1741 * as any further GATT client operations. 1742 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 1743 * GATT client operations. 1744 * @param callback GATT callback handler that will receive asynchronous callbacks. 1745 * @param autoConnect Whether to directly connect to the remote device (false) 1746 * or to automatically connect as soon as the remote 1747 * device becomes available (true). 1748 * @throws IllegalArgumentException if callback is null 1749 */ 1750 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 1751 BluetoothGattCallback callback) { 1752 return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO)); 1753 } 1754 1755 /** 1756 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 1757 * The callback is used to deliver results to Caller, such as connection status as well 1758 * as any further GATT client operations. 1759 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 1760 * GATT client operations. 1761 * @param callback GATT callback handler that will receive asynchronous callbacks. 1762 * @param autoConnect Whether to directly connect to the remote device (false) 1763 * or to automatically connect as soon as the remote 1764 * device becomes available (true). 1765 * @param transport preferred transport for GATT connections to remote dual-mode devices 1766 * {@link BluetoothDevice#TRANSPORT_AUTO} or 1767 * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} 1768 * @throws IllegalArgumentException if callback is null 1769 */ 1770 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 1771 BluetoothGattCallback callback, int transport) { 1772 return (connectGatt(context, autoConnect,callback, transport, PHY_LE_1M_MASK)); 1773 } 1774 1775 /** 1776 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 1777 * The callback is used to deliver results to Caller, such as connection status as well 1778 * as any further GATT client operations. 1779 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 1780 * GATT client operations. 1781 * @param callback GATT callback handler that will receive asynchronous callbacks. 1782 * @param autoConnect Whether to directly connect to the remote device (false) 1783 * or to automatically connect as soon as the remote 1784 * device becomes available (true). 1785 * @param transport preferred transport for GATT connections to remote dual-mode devices 1786 * {@link BluetoothDevice#TRANSPORT_AUTO} or 1787 * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} 1788 * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of 1789 * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, 1790 * and {@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect 1791 * if {@code autoConnect} is set to true. 1792 * @throws NullPointerException if callback is null 1793 */ 1794 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 1795 BluetoothGattCallback callback, int transport, int phy) { 1796 return connectGatt(context, autoConnect,callback, transport, phy, null); 1797 } 1798 1799 /** 1800 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 1801 * The callback is used to deliver results to Caller, such as connection status as well 1802 * as any further GATT client operations. 1803 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 1804 * GATT client operations. 1805 * @param callback GATT callback handler that will receive asynchronous callbacks. 1806 * @param autoConnect Whether to directly connect to the remote device (false) 1807 * or to automatically connect as soon as the remote 1808 * device becomes available (true). 1809 * @param transport preferred transport for GATT connections to remote dual-mode devices 1810 * {@link BluetoothDevice#TRANSPORT_AUTO} or 1811 * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} 1812 * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of 1813 * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, 1814 * an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect 1815 * if {@code autoConnect} is set to true. 1816 * @param handler The handler to use for the callback. If {@code null}, callbacks will happen 1817 * on an un-specified background thread. 1818 * @throws NullPointerException if callback is null 1819 */ 1820 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 1821 BluetoothGattCallback callback, int transport, int phy, 1822 Handler handler) { 1823 return connectGatt(context, autoConnect, callback, transport, false, phy, handler); 1824 } 1825 1826 /** 1827 * Connect to GATT Server hosted by this device. Caller acts as GATT client. 1828 * The callback is used to deliver results to Caller, such as connection status as well 1829 * as any further GATT client operations. 1830 * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct 1831 * GATT client operations. 1832 * @param callback GATT callback handler that will receive asynchronous callbacks. 1833 * @param autoConnect Whether to directly connect to the remote device (false) 1834 * or to automatically connect as soon as the remote 1835 * device becomes available (true). 1836 * @param transport preferred transport for GATT connections to remote dual-mode devices 1837 * {@link BluetoothDevice#TRANSPORT_AUTO} or 1838 * {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE} 1839 * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client 1840 * does not hold a GATT connection. It automatically disconnects when no 1841 * other GATT connections are active for the remote device. 1842 * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of 1843 * {@link BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, 1844 * an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect 1845 * if {@code autoConnect} is set to true. 1846 * @param handler The handler to use for the callback. If {@code null}, callbacks will happen 1847 * on an un-specified background thread. 1848 * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client 1849 * operations. 1850 * @hide 1851 */ 1852 public BluetoothGatt connectGatt(Context context, boolean autoConnect, 1853 BluetoothGattCallback callback, int transport, 1854 boolean opportunistic, int phy, Handler handler) { 1855 if (callback == null) 1856 throw new NullPointerException("callback is null"); 1857 1858 // TODO(Bluetooth) check whether platform support BLE 1859 // Do the check here or in GattServer? 1860 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 1861 IBluetoothManager managerService = adapter.getBluetoothManager(); 1862 try { 1863 IBluetoothGatt iGatt = managerService.getBluetoothGatt(); 1864 if (iGatt == null) { 1865 // BLE is not supported 1866 return null; 1867 } 1868 BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy); 1869 gatt.connect(autoConnect, callback, handler); 1870 return gatt; 1871 } catch (RemoteException e) {Log.e(TAG, "", e);} 1872 return null; 1873 } 1874 } 1875