1 /* 2 * Copyright 2009-2016 The Android Open Source Project 3 * Copyright 2015 Samsung LSI 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package android.bluetooth; 19 20 import android.Manifest; 21 import android.annotation.IntDef; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SdkConstant; 24 import android.annotation.SdkConstant.SdkConstantType; 25 import android.annotation.SystemApi; 26 import android.app.ActivityThread; 27 import android.bluetooth.le.BluetoothLeAdvertiser; 28 import android.bluetooth.le.BluetoothLeScanner; 29 import android.bluetooth.le.PeriodicAdvertisingManager; 30 import android.bluetooth.le.ScanCallback; 31 import android.bluetooth.le.ScanFilter; 32 import android.bluetooth.le.ScanRecord; 33 import android.bluetooth.le.ScanResult; 34 import android.bluetooth.le.ScanSettings; 35 import android.content.Context; 36 import android.os.BatteryStats; 37 import android.os.Binder; 38 import android.os.IBinder; 39 import android.os.ParcelUuid; 40 import android.os.RemoteException; 41 import android.os.ResultReceiver; 42 import android.os.ServiceManager; 43 import android.os.SynchronousResultReceiver; 44 import android.os.SystemProperties; 45 import android.util.Log; 46 import android.util.Pair; 47 48 import java.io.IOException; 49 import java.lang.annotation.Retention; 50 import java.lang.annotation.RetentionPolicy; 51 import java.util.ArrayList; 52 import java.util.Arrays; 53 import java.util.Collections; 54 import java.util.HashMap; 55 import java.util.HashSet; 56 import java.util.List; 57 import java.util.Locale; 58 import java.util.Map; 59 import java.util.Set; 60 import java.util.UUID; 61 import java.util.concurrent.TimeoutException; 62 import java.util.concurrent.locks.ReentrantReadWriteLock; 63 64 /** 65 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter} 66 * lets you perform fundamental Bluetooth tasks, such as initiate 67 * device discovery, query a list of bonded (paired) devices, 68 * instantiate a {@link BluetoothDevice} using a known MAC address, and create 69 * a {@link BluetoothServerSocket} to listen for connection requests from other 70 * devices, and start a scan for Bluetooth LE devices. 71 * 72 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth 73 * adapter, call the {@link BluetoothManager#getAdapter} function on {@link BluetoothManager}. 74 * On JELLY_BEAN_MR1 and below you will need to use the static {@link #getDefaultAdapter} 75 * method instead. 76 * </p><p> 77 * Fundamentally, this is your starting point for all 78 * Bluetooth actions. Once you have the local adapter, you can get a set of 79 * {@link BluetoothDevice} objects representing all paired devices with 80 * {@link #getBondedDevices()}; start device discovery with 81 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to 82 * listen for incoming RFComm connection requests with {@link 83 * #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for 84 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}. 85 * </p> 86 * <p>This class is thread safe.</p> 87 * <p class="note"><strong>Note:</strong> 88 * Most methods require the {@link android.Manifest.permission#BLUETOOTH} 89 * permission and some also require the 90 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. 91 * </p> 92 * <div class="special reference"> 93 * <h3>Developer Guides</h3> 94 * <p> 95 * For more information about using Bluetooth, read the <a href= 96 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer 97 * guide. 98 * </p> 99 * </div> 100 * 101 * {@see BluetoothDevice} 102 * {@see BluetoothServerSocket} 103 */ 104 public final class BluetoothAdapter { 105 private static final String TAG = "BluetoothAdapter"; 106 private static final boolean DBG = true; 107 private static final boolean VDBG = false; 108 109 /** 110 * Default MAC address reported to a client that does not have the 111 * android.permission.LOCAL_MAC_ADDRESS permission. 112 * 113 * @hide 114 */ 115 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00"; 116 117 /** 118 * Sentinel error value for this class. Guaranteed to not equal any other 119 * integer constant in this class. Provided as a convenience for functions 120 * that require a sentinel error value, for example: 121 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 122 * BluetoothAdapter.ERROR)</code> 123 */ 124 public static final int ERROR = Integer.MIN_VALUE; 125 126 /** 127 * Broadcast Action: The state of the local Bluetooth adapter has been 128 * changed. 129 * <p>For example, Bluetooth has been turned on or off. 130 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link 131 * #EXTRA_PREVIOUS_STATE} containing the new and old states 132 * respectively. 133 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 134 */ 135 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String 136 ACTION_STATE_CHANGED = "android.bluetooth.adapter.action.STATE_CHANGED"; 137 138 /** 139 * Used as an int extra field in {@link #ACTION_STATE_CHANGED} 140 * intents to request the current power state. Possible values are: 141 * {@link #STATE_OFF}, 142 * {@link #STATE_TURNING_ON}, 143 * {@link #STATE_ON}, 144 * {@link #STATE_TURNING_OFF}, 145 */ 146 public static final String EXTRA_STATE = "android.bluetooth.adapter.extra.STATE"; 147 /** 148 * Used as an int extra field in {@link #ACTION_STATE_CHANGED} 149 * intents to request the previous power state. Possible values are: 150 * {@link #STATE_OFF}, 151 * {@link #STATE_TURNING_ON}, 152 * {@link #STATE_ON}, 153 * {@link #STATE_TURNING_OFF} 154 */ 155 public static final String EXTRA_PREVIOUS_STATE = 156 "android.bluetooth.adapter.extra.PREVIOUS_STATE"; 157 158 /** @hide */ 159 @IntDef(prefix = { "STATE_" }, value = { 160 STATE_OFF, 161 STATE_TURNING_ON, 162 STATE_ON, 163 STATE_TURNING_OFF, 164 STATE_BLE_TURNING_ON, 165 STATE_BLE_ON, 166 STATE_BLE_TURNING_OFF 167 }) 168 @Retention(RetentionPolicy.SOURCE) 169 public @interface AdapterState {} 170 171 /** 172 * Indicates the local Bluetooth adapter is off. 173 */ 174 public static final int STATE_OFF = 10; 175 /** 176 * Indicates the local Bluetooth adapter is turning on. However local 177 * clients should wait for {@link #STATE_ON} before attempting to 178 * use the adapter. 179 */ 180 public static final int STATE_TURNING_ON = 11; 181 /** 182 * Indicates the local Bluetooth adapter is on, and ready for use. 183 */ 184 public static final int STATE_ON = 12; 185 /** 186 * Indicates the local Bluetooth adapter is turning off. Local clients 187 * should immediately attempt graceful disconnection of any remote links. 188 */ 189 public static final int STATE_TURNING_OFF = 13; 190 191 /** 192 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on. 193 * 194 * @hide 195 */ 196 public static final int STATE_BLE_TURNING_ON = 14; 197 198 /** 199 * Indicates the local Bluetooth adapter is in LE only mode. 200 * 201 * @hide 202 */ 203 public static final int STATE_BLE_ON = 15; 204 205 /** 206 * Indicates the local Bluetooth adapter is turning off LE only mode. 207 * 208 * @hide 209 */ 210 public static final int STATE_BLE_TURNING_OFF = 16; 211 212 /** 213 * UUID of the GATT Read Characteristics for LE_PSM value. 214 * 215 * @hide 216 */ 217 public static final UUID LE_PSM_CHARACTERISTIC_UUID = 218 UUID.fromString("2d410339-82b6-42aa-b34e-e2e01df8cc1a"); 219 220 /** 221 * Human-readable string helper for AdapterState 222 * 223 * @hide 224 */ nameForState(@dapterState int state)225 public static String nameForState(@AdapterState int state) { 226 switch (state) { 227 case STATE_OFF: 228 return "OFF"; 229 case STATE_TURNING_ON: 230 return "TURNING_ON"; 231 case STATE_ON: 232 return "ON"; 233 case STATE_TURNING_OFF: 234 return "TURNING_OFF"; 235 case STATE_BLE_TURNING_ON: 236 return "BLE_TURNING_ON"; 237 case STATE_BLE_ON: 238 return "BLE_ON"; 239 case STATE_BLE_TURNING_OFF: 240 return "BLE_TURNING_OFF"; 241 default: 242 return "?!?!? (" + state + ")"; 243 } 244 } 245 246 /** 247 * Activity Action: Show a system activity that requests discoverable mode. 248 * This activity will also request the user to turn on Bluetooth if it 249 * is not currently enabled. 250 * <p>Discoverable mode is equivalent to {@link 251 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see 252 * this Bluetooth adapter when they perform a discovery. 253 * <p>For privacy, Android is not discoverable by default. 254 * <p>The sender of this Intent can optionally use extra field {@link 255 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of 256 * discoverability. Currently the default duration is 120 seconds, and 257 * maximum duration is capped at 300 seconds for each request. 258 * <p>Notification of the result of this activity is posted using the 259 * {@link android.app.Activity#onActivityResult} callback. The 260 * <code>resultCode</code> 261 * will be the duration (in seconds) of discoverability or 262 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected 263 * discoverability or an error has occurred. 264 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED} 265 * for global notification whenever the scan mode changes. For example, an 266 * application can be notified when the device has ended discoverability. 267 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 268 */ 269 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String 270 ACTION_REQUEST_DISCOVERABLE = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE"; 271 272 /** 273 * Used as an optional int extra field in {@link 274 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration 275 * for discoverability in seconds. The current default is 120 seconds, and 276 * requests over 300 seconds will be capped. These values could change. 277 */ 278 public static final String EXTRA_DISCOVERABLE_DURATION = 279 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION"; 280 281 /** 282 * Activity Action: Show a system activity that allows the user to turn on 283 * Bluetooth. 284 * <p>This system activity will return once Bluetooth has completed turning 285 * on, or the user has decided not to turn Bluetooth on. 286 * <p>Notification of the result of this activity is posted using the 287 * {@link android.app.Activity#onActivityResult} callback. The 288 * <code>resultCode</code> 289 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been 290 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user 291 * has rejected the request or an error has occurred. 292 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED} 293 * for global notification whenever Bluetooth is turned on or off. 294 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 295 */ 296 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String 297 ACTION_REQUEST_ENABLE = "android.bluetooth.adapter.action.REQUEST_ENABLE"; 298 299 /** 300 * Activity Action: Show a system activity that allows the user to turn off 301 * Bluetooth. This is used only if permission review is enabled which is for 302 * apps targeting API less than 23 require a permission review before any of 303 * the app's components can run. 304 * <p>This system activity will return once Bluetooth has completed turning 305 * off, or the user has decided not to turn Bluetooth off. 306 * <p>Notification of the result of this activity is posted using the 307 * {@link android.app.Activity#onActivityResult} callback. The 308 * <code>resultCode</code> 309 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been 310 * turned off or {@link android.app.Activity#RESULT_CANCELED} if the user 311 * has rejected the request or an error has occurred. 312 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED} 313 * for global notification whenever Bluetooth is turned on or off. 314 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 315 * 316 * @hide 317 */ 318 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) public static final String 319 ACTION_REQUEST_DISABLE = "android.bluetooth.adapter.action.REQUEST_DISABLE"; 320 321 /** 322 * Activity Action: Show a system activity that allows user to enable BLE scans even when 323 * Bluetooth is turned off.<p> 324 * 325 * Notification of result of this activity is posted using 326 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be 327 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or 328 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an 329 * error occurred. 330 * 331 * @hide 332 */ 333 @SystemApi 334 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 335 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = 336 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE"; 337 338 /** 339 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter 340 * has changed. 341 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link 342 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes 343 * respectively. 344 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 345 */ 346 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String 347 ACTION_SCAN_MODE_CHANGED = "android.bluetooth.adapter.action.SCAN_MODE_CHANGED"; 348 349 /** 350 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED} 351 * intents to request the current scan mode. Possible values are: 352 * {@link #SCAN_MODE_NONE}, 353 * {@link #SCAN_MODE_CONNECTABLE}, 354 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}, 355 */ 356 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE"; 357 /** 358 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED} 359 * intents to request the previous scan mode. Possible values are: 360 * {@link #SCAN_MODE_NONE}, 361 * {@link #SCAN_MODE_CONNECTABLE}, 362 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}, 363 */ 364 public static final String EXTRA_PREVIOUS_SCAN_MODE = 365 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE"; 366 367 /** @hide */ 368 @IntDef(prefix = { "SCAN_" }, value = { 369 SCAN_MODE_NONE, 370 SCAN_MODE_CONNECTABLE, 371 SCAN_MODE_CONNECTABLE_DISCOVERABLE 372 }) 373 @Retention(RetentionPolicy.SOURCE) 374 public @interface ScanMode {} 375 376 /** 377 * Indicates that both inquiry scan and page scan are disabled on the local 378 * Bluetooth adapter. Therefore this device is neither discoverable 379 * nor connectable from remote Bluetooth devices. 380 */ 381 public static final int SCAN_MODE_NONE = 20; 382 /** 383 * Indicates that inquiry scan is disabled, but page scan is enabled on the 384 * local Bluetooth adapter. Therefore this device is not discoverable from 385 * remote Bluetooth devices, but is connectable from remote devices that 386 * have previously discovered this device. 387 */ 388 public static final int SCAN_MODE_CONNECTABLE = 21; 389 /** 390 * Indicates that both inquiry scan and page scan are enabled on the local 391 * Bluetooth adapter. Therefore this device is both discoverable and 392 * connectable from remote Bluetooth devices. 393 */ 394 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; 395 396 /** 397 * Broadcast Action: The local Bluetooth adapter has started the remote 398 * device discovery process. 399 * <p>This usually involves an inquiry scan of about 12 seconds, followed 400 * by a page scan of each new device to retrieve its Bluetooth name. 401 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as 402 * remote Bluetooth devices are found. 403 * <p>Device discovery is a heavyweight procedure. New connections to 404 * remote Bluetooth devices should not be attempted while discovery is in 405 * progress, and existing connections will experience limited bandwidth 406 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing 407 * discovery. 408 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 409 */ 410 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String 411 ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED"; 412 /** 413 * Broadcast Action: The local Bluetooth adapter has finished the device 414 * discovery process. 415 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 416 */ 417 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String 418 ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED"; 419 420 /** 421 * Broadcast Action: The local Bluetooth adapter has changed its friendly 422 * Bluetooth name. 423 * <p>This name is visible to remote Bluetooth devices. 424 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing 425 * the name. 426 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 427 */ 428 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String 429 ACTION_LOCAL_NAME_CHANGED = "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED"; 430 /** 431 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED} 432 * intents to request the local Bluetooth name. 433 */ 434 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME"; 435 436 /** 437 * Intent used to broadcast the change in connection state of the local 438 * Bluetooth adapter to a profile of the remote device. When the adapter is 439 * not connected to any profiles of any remote devices and it attempts a 440 * connection to a profile this intent will be sent. Once connected, this intent 441 * will not be sent for any more connection attempts to any profiles of any 442 * remote device. When the adapter disconnects from the last profile its 443 * connected to of any remote device, this intent will be sent. 444 * 445 * <p> This intent is useful for applications that are only concerned about 446 * whether the local adapter is connected to any profile of any device and 447 * are not really concerned about which profile. For example, an application 448 * which displays an icon to display whether Bluetooth is connected or not 449 * can use this intent. 450 * 451 * <p>This intent will have 3 extras: 452 * {@link #EXTRA_CONNECTION_STATE} - The current connection state. 453 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state. 454 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. 455 * 456 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE} 457 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, 458 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. 459 * 460 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 461 */ 462 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String 463 ACTION_CONNECTION_STATE_CHANGED = 464 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED"; 465 466 /** 467 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED} 468 * 469 * This extra represents the current connection state. 470 */ 471 public static final String EXTRA_CONNECTION_STATE = 472 "android.bluetooth.adapter.extra.CONNECTION_STATE"; 473 474 /** 475 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED} 476 * 477 * This extra represents the previous connection state. 478 */ 479 public static final String EXTRA_PREVIOUS_CONNECTION_STATE = 480 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE"; 481 482 /** 483 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode. 484 * 485 * @hide 486 */ 487 @SystemApi public static final String ACTION_BLE_STATE_CHANGED = 488 "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; 489 490 /** 491 * Intent used to broadcast the change in the Bluetooth address 492 * of the local Bluetooth adapter. 493 * <p>Always contains the extra field {@link 494 * #EXTRA_BLUETOOTH_ADDRESS} containing the Bluetooth address. 495 * 496 * Note: only system level processes are allowed to send this 497 * defined broadcast. 498 * 499 * @hide 500 */ 501 public static final String ACTION_BLUETOOTH_ADDRESS_CHANGED = 502 "android.bluetooth.adapter.action.BLUETOOTH_ADDRESS_CHANGED"; 503 504 /** 505 * Used as a String extra field in {@link 506 * #ACTION_BLUETOOTH_ADDRESS_CHANGED} intent to store the local 507 * Bluetooth address. 508 * 509 * @hide 510 */ 511 public static final String EXTRA_BLUETOOTH_ADDRESS = 512 "android.bluetooth.adapter.extra.BLUETOOTH_ADDRESS"; 513 514 /** 515 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be 516 * by BLE Always on enabled application to know the ACL_CONNECTED event 517 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection 518 * as Bluetooth LE is the only feature available in STATE_BLE_ON 519 * 520 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which 521 * works in Bluetooth state STATE_ON 522 * 523 * @hide 524 */ 525 public static final String ACTION_BLE_ACL_CONNECTED = 526 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED"; 527 528 /** 529 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be 530 * by BLE Always on enabled application to know the ACL_DISCONNECTED event 531 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth 532 * LE is the only feature available in STATE_BLE_ON 533 * 534 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which 535 * works in Bluetooth state STATE_ON 536 * 537 * @hide 538 */ 539 public static final String ACTION_BLE_ACL_DISCONNECTED = 540 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED"; 541 542 /** The profile is in disconnected state */ 543 public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED; 544 /** The profile is in connecting state */ 545 public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING; 546 /** The profile is in connected state */ 547 public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED; 548 /** The profile is in disconnecting state */ 549 public static final int STATE_DISCONNECTING = 550 BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING; 551 552 /** @hide */ 553 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager"; 554 private final IBinder mToken; 555 556 557 /** 558 * When creating a ServerSocket using listenUsingRfcommOn() or 559 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create 560 * a ServerSocket that auto assigns a channel number to the first 561 * bluetooth socket. 562 * The channel number assigned to this first Bluetooth Socket will 563 * be stored in the ServerSocket, and reused for subsequent Bluetooth 564 * sockets. 565 * 566 * @hide 567 */ 568 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2; 569 570 571 private static final int ADDRESS_LENGTH = 17; 572 573 /** 574 * Lazily initialized singleton. Guaranteed final after first object 575 * constructed. 576 */ 577 private static BluetoothAdapter sAdapter; 578 579 private static BluetoothLeScanner sBluetoothLeScanner; 580 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser; 581 private static PeriodicAdvertisingManager sPeriodicAdvertisingManager; 582 583 private final IBluetoothManager mManagerService; 584 private IBluetooth mService; 585 private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); 586 587 private final Object mLock = new Object(); 588 private final Map<LeScanCallback, ScanCallback> mLeScanClients; 589 590 /** 591 * Get a handle to the default local Bluetooth adapter. 592 * <p>Currently Android only supports one Bluetooth adapter, but the API 593 * could be extended to support more. This will always return the default 594 * adapter. 595 * </p> 596 * 597 * @return the default local adapter, or null if Bluetooth is not supported on this hardware 598 * platform 599 */ getDefaultAdapter()600 public static synchronized BluetoothAdapter getDefaultAdapter() { 601 if (sAdapter == null) { 602 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE); 603 if (b != null) { 604 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b); 605 sAdapter = new BluetoothAdapter(managerService); 606 } else { 607 Log.e(TAG, "Bluetooth binder is null"); 608 } 609 } 610 return sAdapter; 611 } 612 613 /** 614 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance. 615 */ BluetoothAdapter(IBluetoothManager managerService)616 BluetoothAdapter(IBluetoothManager managerService) { 617 618 if (managerService == null) { 619 throw new IllegalArgumentException("bluetooth manager service is null"); 620 } 621 try { 622 mServiceLock.writeLock().lock(); 623 mService = managerService.registerAdapter(mManagerCallback); 624 } catch (RemoteException e) { 625 Log.e(TAG, "", e); 626 } finally { 627 mServiceLock.writeLock().unlock(); 628 } 629 mManagerService = managerService; 630 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>(); 631 mToken = new Binder(); 632 } 633 634 /** 635 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware 636 * address. 637 * <p>Valid Bluetooth hardware addresses must be upper case, in a format 638 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is 639 * available to validate a Bluetooth address. 640 * <p>A {@link BluetoothDevice} will always be returned for a valid 641 * hardware address, even if this adapter has never seen that device. 642 * 643 * @param address valid Bluetooth MAC address 644 * @throws IllegalArgumentException if address is invalid 645 */ getRemoteDevice(String address)646 public BluetoothDevice getRemoteDevice(String address) { 647 return new BluetoothDevice(address); 648 } 649 650 /** 651 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware 652 * address. 653 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method 654 * expects the address in network byte order (MSB first). 655 * <p>A {@link BluetoothDevice} will always be returned for a valid 656 * hardware address, even if this adapter has never seen that device. 657 * 658 * @param address Bluetooth MAC address (6 bytes) 659 * @throws IllegalArgumentException if address is invalid 660 */ getRemoteDevice(byte[] address)661 public BluetoothDevice getRemoteDevice(byte[] address) { 662 if (address == null || address.length != 6) { 663 throw new IllegalArgumentException("Bluetooth address must have 6 bytes"); 664 } 665 return new BluetoothDevice( 666 String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1], 667 address[2], address[3], address[4], address[5])); 668 } 669 670 /** 671 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations. 672 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not 673 * supported on this device. 674 * <p> 675 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported 676 * on this device before calling this method. 677 */ getBluetoothLeAdvertiser()678 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() { 679 if (!getLeAccess()) { 680 return null; 681 } 682 synchronized (mLock) { 683 if (sBluetoothLeAdvertiser == null) { 684 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService); 685 } 686 } 687 return sBluetoothLeAdvertiser; 688 } 689 690 /** 691 * Returns a {@link PeriodicAdvertisingManager} object for Bluetooth LE Periodic Advertising 692 * operations. Will return null if Bluetooth is turned off or if Bluetooth LE Periodic 693 * Advertising is not supported on this device. 694 * <p> 695 * Use {@link #isLePeriodicAdvertisingSupported()} to check whether LE Periodic Advertising is 696 * supported on this device before calling this method. 697 * 698 * @hide 699 */ getPeriodicAdvertisingManager()700 public PeriodicAdvertisingManager getPeriodicAdvertisingManager() { 701 if (!getLeAccess()) { 702 return null; 703 } 704 705 if (!isLePeriodicAdvertisingSupported()) { 706 return null; 707 } 708 709 synchronized (mLock) { 710 if (sPeriodicAdvertisingManager == null) { 711 sPeriodicAdvertisingManager = new PeriodicAdvertisingManager(mManagerService); 712 } 713 } 714 return sPeriodicAdvertisingManager; 715 } 716 717 /** 718 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations. 719 */ getBluetoothLeScanner()720 public BluetoothLeScanner getBluetoothLeScanner() { 721 if (!getLeAccess()) { 722 return null; 723 } 724 synchronized (mLock) { 725 if (sBluetoothLeScanner == null) { 726 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService); 727 } 728 } 729 return sBluetoothLeScanner; 730 } 731 732 /** 733 * Return true if Bluetooth is currently enabled and ready for use. 734 * <p>Equivalent to: 735 * <code>getBluetoothState() == STATE_ON</code> 736 * 737 * @return true if the local adapter is turned on 738 */ 739 @RequiresPermission(Manifest.permission.BLUETOOTH) isEnabled()740 public boolean isEnabled() { 741 try { 742 mServiceLock.readLock().lock(); 743 if (mService != null) { 744 return mService.isEnabled(); 745 } 746 } catch (RemoteException e) { 747 Log.e(TAG, "", e); 748 } finally { 749 mServiceLock.readLock().unlock(); 750 } 751 752 return false; 753 } 754 755 /** 756 * Return true if Bluetooth LE(Always BLE On feature) is currently 757 * enabled and ready for use 758 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON 759 * 760 * @return true if the local Bluetooth LE adapter is turned on 761 * @hide 762 */ 763 @SystemApi isLeEnabled()764 public boolean isLeEnabled() { 765 final int state = getLeState(); 766 if (DBG) { 767 Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state)); 768 } 769 return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON); 770 } 771 772 /** 773 * Turns off Bluetooth LE which was earlier turned on by calling enableBLE(). 774 * 775 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition 776 * to STATE_OFF and completely shut-down Bluetooth 777 * 778 * <p> If the Adapter state is STATE_ON, This would unregister the existance of 779 * special Bluetooth LE application and hence the further turning off of Bluetooth 780 * from UI would ensure the complete turn-off of Bluetooth rather than staying back 781 * BLE only state 782 * 783 * <p>This is an asynchronous call: it will return immediately, and 784 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED} 785 * to be notified of subsequent adapter state changes If this call returns 786 * true, then the adapter state will immediately transition from {@link 787 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time 788 * later transition to either {@link #STATE_BLE_ON} or {@link 789 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications 790 * If this call returns false then there was an 791 * immediate problem that will prevent the QAdapter from being turned off - 792 * such as the QAadapter already being turned off. 793 * 794 * @return true to indicate success, or false on immediate error 795 * @hide 796 */ 797 @SystemApi disableBLE()798 public boolean disableBLE() { 799 if (!isBleScanAlwaysAvailable()) { 800 return false; 801 } 802 803 int state = getLeState(); 804 if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON) { 805 String packageName = ActivityThread.currentPackageName(); 806 if (DBG) { 807 Log.d(TAG, "disableBLE(): de-registering " + packageName); 808 } 809 try { 810 mManagerService.updateBleAppCount(mToken, false, packageName); 811 } catch (RemoteException e) { 812 Log.e(TAG, "", e); 813 } 814 return true; 815 } 816 817 if (DBG) { 818 Log.d(TAG, "disableBLE(): Already disabled"); 819 } 820 return false; 821 } 822 823 /** 824 * Applications who want to only use Bluetooth Low Energy (BLE) can call enableBLE. 825 * 826 * enableBLE registers the existence of an app using only LE functions. 827 * 828 * enableBLE may enable Bluetooth to an LE only mode so that an app can use 829 * LE related features (BluetoothGatt or BluetoothGattServer classes) 830 * 831 * If the user disables Bluetooth while an app is registered to use LE only features, 832 * Bluetooth will remain on in LE only mode for the app. 833 * 834 * When Bluetooth is in LE only mode, it is not shown as ON to the UI. 835 * 836 * <p>This is an asynchronous call: it returns immediately, and 837 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED} 838 * to be notified of adapter state changes. 839 * 840 * If this call returns * true, then the adapter state is either in a mode where 841 * LE is available, or will transition from {@link #STATE_OFF} to {@link #STATE_BLE_TURNING_ON}, 842 * and some time later transition to either {@link #STATE_OFF} or {@link #STATE_BLE_ON}. 843 * 844 * If this call returns false then there was an immediate problem that prevents the 845 * adapter from being turned on - such as Airplane mode. 846 * 847 * {@link #ACTION_BLE_STATE_CHANGED} returns the Bluetooth Adapter's various 848 * states, It includes all the classic Bluetooth Adapter states along with 849 * internal BLE only states 850 * 851 * @return true to indicate Bluetooth LE will be available, or false on immediate error 852 * @hide 853 */ 854 @SystemApi enableBLE()855 public boolean enableBLE() { 856 if (!isBleScanAlwaysAvailable()) { 857 return false; 858 } 859 860 try { 861 String packageName = ActivityThread.currentPackageName(); 862 mManagerService.updateBleAppCount(mToken, true, packageName); 863 if (isLeEnabled()) { 864 if (DBG) { 865 Log.d(TAG, "enableBLE(): Bluetooth already enabled"); 866 } 867 return true; 868 } 869 if (DBG) { 870 Log.d(TAG, "enableBLE(): Calling enable"); 871 } 872 return mManagerService.enable(packageName); 873 } catch (RemoteException e) { 874 Log.e(TAG, "", e); 875 } 876 877 return false; 878 } 879 880 /** 881 * Get the current state of the local Bluetooth adapter. 882 * <p>Possible return values are 883 * {@link #STATE_OFF}, 884 * {@link #STATE_TURNING_ON}, 885 * {@link #STATE_ON}, 886 * {@link #STATE_TURNING_OFF}. 887 * 888 * @return current state of Bluetooth adapter 889 */ 890 @RequiresPermission(Manifest.permission.BLUETOOTH) 891 @AdapterState getState()892 public int getState() { 893 int state = BluetoothAdapter.STATE_OFF; 894 895 try { 896 mServiceLock.readLock().lock(); 897 if (mService != null) { 898 state = mService.getState(); 899 } 900 } catch (RemoteException e) { 901 Log.e(TAG, "", e); 902 } finally { 903 mServiceLock.readLock().unlock(); 904 } 905 906 // Consider all internal states as OFF 907 if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON 908 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) { 909 if (VDBG) { 910 Log.d(TAG, "Consider " + BluetoothAdapter.nameForState(state) + " state as OFF"); 911 } 912 state = BluetoothAdapter.STATE_OFF; 913 } 914 if (VDBG) { 915 Log.d(TAG, "" + hashCode() + ": getState(). Returning " + BluetoothAdapter.nameForState( 916 state)); 917 } 918 return state; 919 } 920 921 /** 922 * Get the current state of the local Bluetooth adapter 923 * <p>This returns current internal state of Adapter including LE ON/OFF 924 * 925 * <p>Possible return values are 926 * {@link #STATE_OFF}, 927 * {@link #STATE_BLE_TURNING_ON}, 928 * {@link #STATE_BLE_ON}, 929 * {@link #STATE_TURNING_ON}, 930 * {@link #STATE_ON}, 931 * {@link #STATE_TURNING_OFF}, 932 * {@link #STATE_BLE_TURNING_OFF}. 933 * 934 * @return current state of Bluetooth adapter 935 * @hide 936 */ 937 @RequiresPermission(Manifest.permission.BLUETOOTH) 938 @AdapterState getLeState()939 public int getLeState() { 940 int state = BluetoothAdapter.STATE_OFF; 941 942 try { 943 mServiceLock.readLock().lock(); 944 if (mService != null) { 945 state = mService.getState(); 946 } 947 } catch (RemoteException e) { 948 Log.e(TAG, "", e); 949 } finally { 950 mServiceLock.readLock().unlock(); 951 } 952 953 if (VDBG) { 954 Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state)); 955 } 956 return state; 957 } 958 getLeAccess()959 boolean getLeAccess() { 960 if (getLeState() == STATE_ON) { 961 return true; 962 } else if (getLeState() == STATE_BLE_ON) { 963 return true; // TODO: FILTER SYSTEM APPS HERE <-- 964 } 965 966 return false; 967 } 968 969 /** 970 * Turn on the local Bluetooth adapter—do not use without explicit 971 * user action to turn on Bluetooth. 972 * <p>This powers on the underlying Bluetooth hardware, and starts all 973 * Bluetooth system services. 974 * <p class="caution"><strong>Bluetooth should never be enabled without 975 * direct user consent</strong>. If you want to turn on Bluetooth in order 976 * to create a wireless connection, you should use the {@link 977 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests 978 * user permission to turn on Bluetooth. The {@link #enable()} method is 979 * provided only for applications that include a user interface for changing 980 * system settings, such as a "power manager" app.</p> 981 * <p>This is an asynchronous call: it will return immediately, and 982 * clients should listen for {@link #ACTION_STATE_CHANGED} 983 * to be notified of subsequent adapter state changes. If this call returns 984 * true, then the adapter state will immediately transition from {@link 985 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time 986 * later transition to either {@link #STATE_OFF} or {@link 987 * #STATE_ON}. If this call returns false then there was an 988 * immediate problem that will prevent the adapter from being turned on - 989 * such as Airplane mode, or the adapter is already turned on. 990 * 991 * @return true to indicate adapter startup has begun, or false on immediate error 992 */ 993 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) enable()994 public boolean enable() { 995 if (isEnabled()) { 996 if (DBG) { 997 Log.d(TAG, "enable(): BT already enabled!"); 998 } 999 return true; 1000 } 1001 try { 1002 return mManagerService.enable(ActivityThread.currentPackageName()); 1003 } catch (RemoteException e) { 1004 Log.e(TAG, "", e); 1005 } 1006 return false; 1007 } 1008 1009 /** 1010 * Turn off the local Bluetooth adapter—do not use without explicit 1011 * user action to turn off Bluetooth. 1012 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth 1013 * system services, and powers down the underlying Bluetooth hardware. 1014 * <p class="caution"><strong>Bluetooth should never be disabled without 1015 * direct user consent</strong>. The {@link #disable()} method is 1016 * provided only for applications that include a user interface for changing 1017 * system settings, such as a "power manager" app.</p> 1018 * <p>This is an asynchronous call: it will return immediately, and 1019 * clients should listen for {@link #ACTION_STATE_CHANGED} 1020 * to be notified of subsequent adapter state changes. If this call returns 1021 * true, then the adapter state will immediately transition from {@link 1022 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time 1023 * later transition to either {@link #STATE_OFF} or {@link 1024 * #STATE_ON}. If this call returns false then there was an 1025 * immediate problem that will prevent the adapter from being turned off - 1026 * such as the adapter already being turned off. 1027 * 1028 * @return true to indicate adapter shutdown has begun, or false on immediate error 1029 */ 1030 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) disable()1031 public boolean disable() { 1032 try { 1033 return mManagerService.disable(ActivityThread.currentPackageName(), true); 1034 } catch (RemoteException e) { 1035 Log.e(TAG, "", e); 1036 } 1037 return false; 1038 } 1039 1040 /** 1041 * Turn off the local Bluetooth adapter and don't persist the setting. 1042 * 1043 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1044 * permission 1045 * 1046 * @return true to indicate adapter shutdown has begun, or false on immediate error 1047 * @hide 1048 */ disable(boolean persist)1049 public boolean disable(boolean persist) { 1050 1051 try { 1052 return mManagerService.disable(ActivityThread.currentPackageName(), persist); 1053 } catch (RemoteException e) { 1054 Log.e(TAG, "", e); 1055 } 1056 return false; 1057 } 1058 1059 /** 1060 * Returns the hardware address of the local Bluetooth adapter. 1061 * <p>For example, "00:11:22:AA:BB:CC". 1062 * 1063 * @return Bluetooth hardware address as string 1064 */ 1065 @RequiresPermission(Manifest.permission.BLUETOOTH) getAddress()1066 public String getAddress() { 1067 try { 1068 return mManagerService.getAddress(); 1069 } catch (RemoteException e) { 1070 Log.e(TAG, "", e); 1071 } 1072 return null; 1073 } 1074 1075 /** 1076 * Get the friendly Bluetooth name of the local Bluetooth adapter. 1077 * <p>This name is visible to remote Bluetooth devices. 1078 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1079 * 1080 * @return the Bluetooth name, or null on error 1081 */ getName()1082 public String getName() { 1083 try { 1084 return mManagerService.getName(); 1085 } catch (RemoteException e) { 1086 Log.e(TAG, "", e); 1087 } 1088 return null; 1089 } 1090 1091 /** 1092 * Factory reset bluetooth settings. 1093 * 1094 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} 1095 * permission 1096 * 1097 * @return true to indicate that the config file was successfully cleared 1098 * @hide 1099 */ factoryReset()1100 public boolean factoryReset() { 1101 try { 1102 mServiceLock.readLock().lock(); 1103 if (mService != null) { 1104 return mService.factoryReset(); 1105 } 1106 SystemProperties.set("persist.bluetooth.factoryreset", "true"); 1107 } catch (RemoteException e) { 1108 Log.e(TAG, "", e); 1109 } finally { 1110 mServiceLock.readLock().unlock(); 1111 } 1112 return false; 1113 } 1114 1115 /** 1116 * Get the UUIDs supported by the local Bluetooth adapter. 1117 * 1118 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1119 * 1120 * @return the UUIDs supported by the local Bluetooth Adapter. 1121 * @hide 1122 */ getUuids()1123 public ParcelUuid[] getUuids() { 1124 if (getState() != STATE_ON) { 1125 return null; 1126 } 1127 try { 1128 mServiceLock.readLock().lock(); 1129 if (mService != null) { 1130 return mService.getUuids(); 1131 } 1132 } catch (RemoteException e) { 1133 Log.e(TAG, "", e); 1134 } finally { 1135 mServiceLock.readLock().unlock(); 1136 } 1137 return null; 1138 } 1139 1140 /** 1141 * Set the friendly Bluetooth name of the local Bluetooth adapter. 1142 * <p>This name is visible to remote Bluetooth devices. 1143 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8 1144 * encoding, although many remote devices can only display the first 1145 * 40 characters, and some may be limited to just 20. 1146 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1147 * will return false. After turning on Bluetooth, 1148 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1149 * to get the updated value. 1150 * 1151 * @param name a valid Bluetooth name 1152 * @return true if the name was set, false otherwise 1153 */ 1154 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) setName(String name)1155 public boolean setName(String name) { 1156 if (getState() != STATE_ON) { 1157 return false; 1158 } 1159 try { 1160 mServiceLock.readLock().lock(); 1161 if (mService != null) { 1162 return mService.setName(name); 1163 } 1164 } catch (RemoteException e) { 1165 Log.e(TAG, "", e); 1166 } finally { 1167 mServiceLock.readLock().unlock(); 1168 } 1169 return false; 1170 } 1171 1172 /** 1173 * Returns the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth 1174 * adapter. 1175 * 1176 * @return {@link BluetoothClass} Bluetooth CoD of local Bluetooth device. 1177 * 1178 * @hide 1179 */ 1180 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) getBluetoothClass()1181 public BluetoothClass getBluetoothClass() { 1182 if (getState() != STATE_ON) { 1183 return null; 1184 } 1185 try { 1186 mServiceLock.readLock().lock(); 1187 if (mService != null) { 1188 return mService.getBluetoothClass(); 1189 } 1190 } catch (RemoteException e) { 1191 Log.e(TAG, "", e); 1192 } finally { 1193 mServiceLock.readLock().unlock(); 1194 } 1195 return null; 1196 } 1197 1198 /** 1199 * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of the local Bluetooth 1200 * adapter. 1201 * 1202 * <p>Note: This value persists across system reboot. 1203 * 1204 * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to. 1205 * @return true if successful, false if unsuccessful. 1206 * 1207 * @hide 1208 */ 1209 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) setBluetoothClass(BluetoothClass bluetoothClass)1210 public boolean setBluetoothClass(BluetoothClass bluetoothClass) { 1211 if (getState() != STATE_ON) { 1212 return false; 1213 } 1214 try { 1215 mServiceLock.readLock().lock(); 1216 if (mService != null) { 1217 return mService.setBluetoothClass(bluetoothClass); 1218 } 1219 } catch (RemoteException e) { 1220 Log.e(TAG, "", e); 1221 } finally { 1222 mServiceLock.readLock().unlock(); 1223 } 1224 return false; 1225 } 1226 1227 /** 1228 * Get the current Bluetooth scan mode of the local Bluetooth adapter. 1229 * <p>The Bluetooth scan mode determines if the local adapter is 1230 * connectable and/or discoverable from remote Bluetooth devices. 1231 * <p>Possible values are: 1232 * {@link #SCAN_MODE_NONE}, 1233 * {@link #SCAN_MODE_CONNECTABLE}, 1234 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. 1235 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1236 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth, 1237 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1238 * to get the updated value. 1239 * 1240 * @return scan mode 1241 */ 1242 @RequiresPermission(Manifest.permission.BLUETOOTH) 1243 @ScanMode getScanMode()1244 public int getScanMode() { 1245 if (getState() != STATE_ON) { 1246 return SCAN_MODE_NONE; 1247 } 1248 try { 1249 mServiceLock.readLock().lock(); 1250 if (mService != null) { 1251 return mService.getScanMode(); 1252 } 1253 } catch (RemoteException e) { 1254 Log.e(TAG, "", e); 1255 } finally { 1256 mServiceLock.readLock().unlock(); 1257 } 1258 return SCAN_MODE_NONE; 1259 } 1260 1261 /** 1262 * Set the Bluetooth scan mode of the local Bluetooth adapter. 1263 * <p>The Bluetooth scan mode determines if the local adapter is 1264 * connectable and/or discoverable from remote Bluetooth devices. 1265 * <p>For privacy reasons, discoverable mode is automatically turned off 1266 * after <code>duration</code> seconds. For example, 120 seconds should be 1267 * enough for a remote device to initiate and complete its discovery 1268 * process. 1269 * <p>Valid scan mode values are: 1270 * {@link #SCAN_MODE_NONE}, 1271 * {@link #SCAN_MODE_CONNECTABLE}, 1272 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. 1273 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1274 * will return false. After turning on Bluetooth, 1275 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1276 * to get the updated value. 1277 * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} 1278 * <p>Applications cannot set the scan mode. They should use 1279 * <code>startActivityForResult( 1280 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE}) 1281 * </code>instead. 1282 * 1283 * @param mode valid scan mode 1284 * @param duration time in seconds to apply scan mode, only used for {@link 1285 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE} 1286 * @return true if the scan mode was set, false otherwise 1287 * @hide 1288 */ setScanMode(@canMode int mode, int duration)1289 public boolean setScanMode(@ScanMode int mode, int duration) { 1290 if (getState() != STATE_ON) { 1291 return false; 1292 } 1293 try { 1294 mServiceLock.readLock().lock(); 1295 if (mService != null) { 1296 return mService.setScanMode(mode, duration); 1297 } 1298 } catch (RemoteException e) { 1299 Log.e(TAG, "", e); 1300 } finally { 1301 mServiceLock.readLock().unlock(); 1302 } 1303 return false; 1304 } 1305 1306 /** @hide */ setScanMode(int mode)1307 public boolean setScanMode(int mode) { 1308 if (getState() != STATE_ON) { 1309 return false; 1310 } 1311 /* getDiscoverableTimeout() to use the latest from NV than use 0 */ 1312 return setScanMode(mode, getDiscoverableTimeout()); 1313 } 1314 1315 /** @hide */ getDiscoverableTimeout()1316 public int getDiscoverableTimeout() { 1317 if (getState() != STATE_ON) { 1318 return -1; 1319 } 1320 try { 1321 mServiceLock.readLock().lock(); 1322 if (mService != null) { 1323 return mService.getDiscoverableTimeout(); 1324 } 1325 } catch (RemoteException e) { 1326 Log.e(TAG, "", e); 1327 } finally { 1328 mServiceLock.readLock().unlock(); 1329 } 1330 return -1; 1331 } 1332 1333 /** @hide */ setDiscoverableTimeout(int timeout)1334 public void setDiscoverableTimeout(int timeout) { 1335 if (getState() != STATE_ON) { 1336 return; 1337 } 1338 try { 1339 mServiceLock.readLock().lock(); 1340 if (mService != null) { 1341 mService.setDiscoverableTimeout(timeout); 1342 } 1343 } catch (RemoteException e) { 1344 Log.e(TAG, "", e); 1345 } finally { 1346 mServiceLock.readLock().unlock(); 1347 } 1348 } 1349 1350 /** 1351 * Get the end time of the latest remote device discovery process. 1352 * 1353 * @return the latest time that the bluetooth adapter was/will be in discovery mode, in 1354 * milliseconds since the epoch. This time can be in the future if {@link #startDiscovery()} has 1355 * been called recently. 1356 * @hide 1357 */ getDiscoveryEndMillis()1358 public long getDiscoveryEndMillis() { 1359 try { 1360 mServiceLock.readLock().lock(); 1361 if (mService != null) { 1362 return mService.getDiscoveryEndMillis(); 1363 } 1364 } catch (RemoteException e) { 1365 Log.e(TAG, "", e); 1366 } finally { 1367 mServiceLock.readLock().unlock(); 1368 } 1369 return -1; 1370 } 1371 1372 /** 1373 * Start the remote device discovery process. 1374 * <p>The discovery process usually involves an inquiry scan of about 12 1375 * seconds, followed by a page scan of each new device to retrieve its 1376 * Bluetooth name. 1377 * <p>This is an asynchronous call, it will return immediately. Register 1378 * for {@link #ACTION_DISCOVERY_STARTED} and {@link 1379 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the 1380 * discovery starts and completes. Register for {@link 1381 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices 1382 * are found. 1383 * <p>Device discovery is a heavyweight procedure. New connections to 1384 * remote Bluetooth devices should not be attempted while discovery is in 1385 * progress, and existing connections will experience limited bandwidth 1386 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing 1387 * discovery. Discovery is not managed by the Activity, 1388 * but is run as a system service, so an application should always call 1389 * {@link BluetoothAdapter#cancelDiscovery()} even if it 1390 * did not directly request a discovery, just to be sure. 1391 * <p>Device discovery will only find remote devices that are currently 1392 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are 1393 * not discoverable by default, and need to be entered into a special mode. 1394 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1395 * will return false. After turning on Bluetooth, 1396 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1397 * to get the updated value. 1398 * 1399 * @return true on success, false on error 1400 */ 1401 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) startDiscovery()1402 public boolean startDiscovery() { 1403 if (getState() != STATE_ON) { 1404 return false; 1405 } 1406 try { 1407 mServiceLock.readLock().lock(); 1408 if (mService != null) { 1409 return mService.startDiscovery(); 1410 } 1411 } catch (RemoteException e) { 1412 Log.e(TAG, "", e); 1413 } finally { 1414 mServiceLock.readLock().unlock(); 1415 } 1416 return false; 1417 } 1418 1419 /** 1420 * Cancel the current device discovery process. 1421 * <p>Because discovery is a heavyweight procedure for the Bluetooth 1422 * adapter, this method should always be called before attempting to connect 1423 * to a remote device with {@link 1424 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by 1425 * the Activity, but is run as a system service, so an application should 1426 * always call cancel discovery even if it did not directly request a 1427 * discovery, just to be sure. 1428 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1429 * will return false. After turning on Bluetooth, 1430 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1431 * to get the updated value. 1432 * 1433 * @return true on success, false on error 1434 */ 1435 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) cancelDiscovery()1436 public boolean cancelDiscovery() { 1437 if (getState() != STATE_ON) { 1438 return false; 1439 } 1440 try { 1441 mServiceLock.readLock().lock(); 1442 if (mService != null) { 1443 return mService.cancelDiscovery(); 1444 } 1445 } catch (RemoteException e) { 1446 Log.e(TAG, "", e); 1447 } finally { 1448 mServiceLock.readLock().unlock(); 1449 } 1450 return false; 1451 } 1452 1453 /** 1454 * Return true if the local Bluetooth adapter is currently in the device 1455 * discovery process. 1456 * <p>Device discovery is a heavyweight procedure. New connections to 1457 * remote Bluetooth devices should not be attempted while discovery is in 1458 * progress, and existing connections will experience limited bandwidth 1459 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing 1460 * discovery. 1461 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED} 1462 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery 1463 * starts or completes. 1464 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1465 * will return false. After turning on Bluetooth, 1466 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1467 * to get the updated value. 1468 * 1469 * @return true if discovering 1470 */ 1471 @RequiresPermission(Manifest.permission.BLUETOOTH) isDiscovering()1472 public boolean isDiscovering() { 1473 if (getState() != STATE_ON) { 1474 return false; 1475 } 1476 try { 1477 mServiceLock.readLock().lock(); 1478 if (mService != null) { 1479 return mService.isDiscovering(); 1480 } 1481 } catch (RemoteException e) { 1482 Log.e(TAG, "", e); 1483 } finally { 1484 mServiceLock.readLock().unlock(); 1485 } 1486 return false; 1487 } 1488 1489 /** 1490 * Return true if the multi advertisement is supported by the chipset 1491 * 1492 * @return true if Multiple Advertisement feature is supported 1493 */ isMultipleAdvertisementSupported()1494 public boolean isMultipleAdvertisementSupported() { 1495 if (getState() != STATE_ON) { 1496 return false; 1497 } 1498 try { 1499 mServiceLock.readLock().lock(); 1500 if (mService != null) { 1501 return mService.isMultiAdvertisementSupported(); 1502 } 1503 } catch (RemoteException e) { 1504 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e); 1505 } finally { 1506 mServiceLock.readLock().unlock(); 1507 } 1508 return false; 1509 } 1510 1511 /** 1512 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p> 1513 * 1514 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and 1515 * fetch scan results even when Bluetooth is turned off.<p> 1516 * 1517 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}. 1518 * 1519 * @hide 1520 */ 1521 @SystemApi isBleScanAlwaysAvailable()1522 public boolean isBleScanAlwaysAvailable() { 1523 try { 1524 return mManagerService.isBleScanAlwaysAvailable(); 1525 } catch (RemoteException e) { 1526 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e); 1527 return false; 1528 } 1529 } 1530 1531 /** 1532 * Return true if offloaded filters are supported 1533 * 1534 * @return true if chipset supports on-chip filtering 1535 */ isOffloadedFilteringSupported()1536 public boolean isOffloadedFilteringSupported() { 1537 if (!getLeAccess()) { 1538 return false; 1539 } 1540 try { 1541 mServiceLock.readLock().lock(); 1542 if (mService != null) { 1543 return mService.isOffloadedFilteringSupported(); 1544 } 1545 } catch (RemoteException e) { 1546 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e); 1547 } finally { 1548 mServiceLock.readLock().unlock(); 1549 } 1550 return false; 1551 } 1552 1553 /** 1554 * Return true if offloaded scan batching is supported 1555 * 1556 * @return true if chipset supports on-chip scan batching 1557 */ isOffloadedScanBatchingSupported()1558 public boolean isOffloadedScanBatchingSupported() { 1559 if (!getLeAccess()) { 1560 return false; 1561 } 1562 try { 1563 mServiceLock.readLock().lock(); 1564 if (mService != null) { 1565 return mService.isOffloadedScanBatchingSupported(); 1566 } 1567 } catch (RemoteException e) { 1568 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e); 1569 } finally { 1570 mServiceLock.readLock().unlock(); 1571 } 1572 return false; 1573 } 1574 1575 /** 1576 * Return true if LE 2M PHY feature is supported. 1577 * 1578 * @return true if chipset supports LE 2M PHY feature 1579 */ isLe2MPhySupported()1580 public boolean isLe2MPhySupported() { 1581 if (!getLeAccess()) { 1582 return false; 1583 } 1584 try { 1585 mServiceLock.readLock().lock(); 1586 if (mService != null) { 1587 return mService.isLe2MPhySupported(); 1588 } 1589 } catch (RemoteException e) { 1590 Log.e(TAG, "failed to get isExtendedAdvertisingSupported, error: ", e); 1591 } finally { 1592 mServiceLock.readLock().unlock(); 1593 } 1594 return false; 1595 } 1596 1597 /** 1598 * Return true if LE Coded PHY feature is supported. 1599 * 1600 * @return true if chipset supports LE Coded PHY feature 1601 */ isLeCodedPhySupported()1602 public boolean isLeCodedPhySupported() { 1603 if (!getLeAccess()) { 1604 return false; 1605 } 1606 try { 1607 mServiceLock.readLock().lock(); 1608 if (mService != null) { 1609 return mService.isLeCodedPhySupported(); 1610 } 1611 } catch (RemoteException e) { 1612 Log.e(TAG, "failed to get isLeCodedPhySupported, error: ", e); 1613 } finally { 1614 mServiceLock.readLock().unlock(); 1615 } 1616 return false; 1617 } 1618 1619 /** 1620 * Return true if LE Extended Advertising feature is supported. 1621 * 1622 * @return true if chipset supports LE Extended Advertising feature 1623 */ isLeExtendedAdvertisingSupported()1624 public boolean isLeExtendedAdvertisingSupported() { 1625 if (!getLeAccess()) { 1626 return false; 1627 } 1628 try { 1629 mServiceLock.readLock().lock(); 1630 if (mService != null) { 1631 return mService.isLeExtendedAdvertisingSupported(); 1632 } 1633 } catch (RemoteException e) { 1634 Log.e(TAG, "failed to get isLeExtendedAdvertisingSupported, error: ", e); 1635 } finally { 1636 mServiceLock.readLock().unlock(); 1637 } 1638 return false; 1639 } 1640 1641 /** 1642 * Return true if LE Periodic Advertising feature is supported. 1643 * 1644 * @return true if chipset supports LE Periodic Advertising feature 1645 */ isLePeriodicAdvertisingSupported()1646 public boolean isLePeriodicAdvertisingSupported() { 1647 if (!getLeAccess()) { 1648 return false; 1649 } 1650 try { 1651 mServiceLock.readLock().lock(); 1652 if (mService != null) { 1653 return mService.isLePeriodicAdvertisingSupported(); 1654 } 1655 } catch (RemoteException e) { 1656 Log.e(TAG, "failed to get isLePeriodicAdvertisingSupported, error: ", e); 1657 } finally { 1658 mServiceLock.readLock().unlock(); 1659 } 1660 return false; 1661 } 1662 1663 /** 1664 * Return the maximum LE advertising data length in bytes, 1665 * if LE Extended Advertising feature is supported, 0 otherwise. 1666 * 1667 * @return the maximum LE advertising data length. 1668 */ getLeMaximumAdvertisingDataLength()1669 public int getLeMaximumAdvertisingDataLength() { 1670 if (!getLeAccess()) { 1671 return 0; 1672 } 1673 try { 1674 mServiceLock.readLock().lock(); 1675 if (mService != null) { 1676 return mService.getLeMaximumAdvertisingDataLength(); 1677 } 1678 } catch (RemoteException e) { 1679 Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e); 1680 } finally { 1681 mServiceLock.readLock().unlock(); 1682 } 1683 return 0; 1684 } 1685 1686 /** 1687 * Get the maximum number of connected audio devices. 1688 * 1689 * @return the maximum number of connected audio devices 1690 * @hide 1691 */ 1692 @RequiresPermission(Manifest.permission.BLUETOOTH) getMaxConnectedAudioDevices()1693 public int getMaxConnectedAudioDevices() { 1694 try { 1695 mServiceLock.readLock().lock(); 1696 if (mService != null) { 1697 return mService.getMaxConnectedAudioDevices(); 1698 } 1699 } catch (RemoteException e) { 1700 Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e); 1701 } finally { 1702 mServiceLock.readLock().unlock(); 1703 } 1704 return 1; 1705 } 1706 1707 /** 1708 * Return true if hardware has entries available for matching beacons 1709 * 1710 * @return true if there are hw entries available for matching beacons 1711 * @hide 1712 */ isHardwareTrackingFiltersAvailable()1713 public boolean isHardwareTrackingFiltersAvailable() { 1714 if (!getLeAccess()) { 1715 return false; 1716 } 1717 try { 1718 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); 1719 if (iGatt == null) { 1720 // BLE is not supported 1721 return false; 1722 } 1723 return (iGatt.numHwTrackFiltersAvailable() != 0); 1724 } catch (RemoteException e) { 1725 Log.e(TAG, "", e); 1726 } 1727 return false; 1728 } 1729 1730 /** 1731 * Return the record of {@link BluetoothActivityEnergyInfo} object that 1732 * has the activity and energy info. This can be used to ascertain what 1733 * the controller has been up to, since the last sample. 1734 * 1735 * @param updateType Type of info, cached vs refreshed. 1736 * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or 1737 * unsupported 1738 * @hide 1739 * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)} 1740 * instead. 1741 */ 1742 @Deprecated getControllerActivityEnergyInfo(int updateType)1743 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { 1744 SynchronousResultReceiver receiver = new SynchronousResultReceiver(); 1745 requestControllerActivityEnergyInfo(receiver); 1746 try { 1747 SynchronousResultReceiver.Result result = receiver.awaitResult(1000); 1748 if (result.bundle != null) { 1749 return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY); 1750 } 1751 } catch (TimeoutException e) { 1752 Log.e(TAG, "getControllerActivityEnergyInfo timed out"); 1753 } 1754 return null; 1755 } 1756 1757 /** 1758 * Request the record of {@link BluetoothActivityEnergyInfo} object that 1759 * has the activity and energy info. This can be used to ascertain what 1760 * the controller has been up to, since the last sample. 1761 * 1762 * A null value for the activity info object may be sent if the bluetooth service is 1763 * unreachable or the device does not support reporting such information. 1764 * 1765 * @param result The callback to which to send the activity info. 1766 * @hide 1767 */ requestControllerActivityEnergyInfo(ResultReceiver result)1768 public void requestControllerActivityEnergyInfo(ResultReceiver result) { 1769 try { 1770 mServiceLock.readLock().lock(); 1771 if (mService != null) { 1772 mService.requestActivityInfo(result); 1773 result = null; 1774 } 1775 } catch (RemoteException e) { 1776 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); 1777 } finally { 1778 mServiceLock.readLock().unlock(); 1779 if (result != null) { 1780 // Only send an immediate result if we failed. 1781 result.send(0, null); 1782 } 1783 } 1784 } 1785 1786 /** 1787 * Return the set of {@link BluetoothDevice} objects that are bonded 1788 * (paired) to the local adapter. 1789 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1790 * will return an empty set. After turning on Bluetooth, 1791 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1792 * to get the updated value. 1793 * 1794 * @return unmodifiable set of {@link BluetoothDevice}, or null on error 1795 */ 1796 @RequiresPermission(Manifest.permission.BLUETOOTH) getBondedDevices()1797 public Set<BluetoothDevice> getBondedDevices() { 1798 if (getState() != STATE_ON) { 1799 return toDeviceSet(new BluetoothDevice[0]); 1800 } 1801 try { 1802 mServiceLock.readLock().lock(); 1803 if (mService != null) { 1804 return toDeviceSet(mService.getBondedDevices()); 1805 } 1806 return toDeviceSet(new BluetoothDevice[0]); 1807 } catch (RemoteException e) { 1808 Log.e(TAG, "", e); 1809 } finally { 1810 mServiceLock.readLock().unlock(); 1811 } 1812 return null; 1813 } 1814 1815 /** 1816 * Gets the currently supported profiles by the adapter. 1817 * 1818 * <p> This can be used to check whether a profile is supported before attempting 1819 * to connect to its respective proxy. 1820 * 1821 * @return a list of integers indicating the ids of supported profiles as defined in {@link 1822 * BluetoothProfile}. 1823 * @hide 1824 */ getSupportedProfiles()1825 public List<Integer> getSupportedProfiles() { 1826 final ArrayList<Integer> supportedProfiles = new ArrayList<Integer>(); 1827 1828 try { 1829 synchronized (mManagerCallback) { 1830 if (mService != null) { 1831 final long supportedProfilesBitMask = mService.getSupportedProfiles(); 1832 1833 for (int i = 0; i <= BluetoothProfile.MAX_PROFILE_ID; i++) { 1834 if ((supportedProfilesBitMask & (1 << i)) != 0) { 1835 supportedProfiles.add(i); 1836 } 1837 } 1838 } 1839 } 1840 } catch (RemoteException e) { 1841 Log.e(TAG, "getSupportedProfiles:", e); 1842 } 1843 return supportedProfiles; 1844 } 1845 1846 /** 1847 * Get the current connection state of the local Bluetooth adapter. 1848 * This can be used to check whether the local Bluetooth adapter is connected 1849 * to any profile of any other remote Bluetooth Device. 1850 * 1851 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED} 1852 * intent to get the connection state of the adapter. 1853 * 1854 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, {@link 1855 * #STATE_CONNECTING} or {@link #STATE_DISCONNECTED} 1856 * @hide 1857 */ getConnectionState()1858 public int getConnectionState() { 1859 if (getState() != STATE_ON) { 1860 return BluetoothAdapter.STATE_DISCONNECTED; 1861 } 1862 try { 1863 mServiceLock.readLock().lock(); 1864 if (mService != null) { 1865 return mService.getAdapterConnectionState(); 1866 } 1867 } catch (RemoteException e) { 1868 Log.e(TAG, "getConnectionState:", e); 1869 } finally { 1870 mServiceLock.readLock().unlock(); 1871 } 1872 return BluetoothAdapter.STATE_DISCONNECTED; 1873 } 1874 1875 /** 1876 * Get the current connection state of a profile. 1877 * This function can be used to check whether the local Bluetooth adapter 1878 * is connected to any remote device for a specific profile. 1879 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET}, 1880 * {@link BluetoothProfile#A2DP}. 1881 * 1882 * <p> Return value can be one of 1883 * {@link BluetoothProfile#STATE_DISCONNECTED}, 1884 * {@link BluetoothProfile#STATE_CONNECTING}, 1885 * {@link BluetoothProfile#STATE_CONNECTED}, 1886 * {@link BluetoothProfile#STATE_DISCONNECTING} 1887 */ 1888 @RequiresPermission(Manifest.permission.BLUETOOTH) getProfileConnectionState(int profile)1889 public int getProfileConnectionState(int profile) { 1890 if (getState() != STATE_ON) { 1891 return BluetoothProfile.STATE_DISCONNECTED; 1892 } 1893 try { 1894 mServiceLock.readLock().lock(); 1895 if (mService != null) { 1896 return mService.getProfileConnectionState(profile); 1897 } 1898 } catch (RemoteException e) { 1899 Log.e(TAG, "getProfileConnectionState:", e); 1900 } finally { 1901 mServiceLock.readLock().unlock(); 1902 } 1903 return BluetoothProfile.STATE_DISCONNECTED; 1904 } 1905 1906 /** 1907 * Create a listening, secure RFCOMM Bluetooth socket. 1908 * <p>A remote device connecting to this socket will be authenticated and 1909 * communication on this socket will be encrypted. 1910 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 1911 * connections from a listening {@link BluetoothServerSocket}. 1912 * <p>Valid RFCOMM channels are in range 1 to 30. 1913 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1914 * 1915 * @param channel RFCOMM channel to listen on 1916 * @return a listening RFCOMM BluetoothServerSocket 1917 * @throws IOException on error, for example Bluetooth not available, or insufficient 1918 * permissions, or channel in use. 1919 * @hide 1920 */ listenUsingRfcommOn(int channel)1921 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException { 1922 return listenUsingRfcommOn(channel, false, false); 1923 } 1924 1925 /** 1926 * Create a listening, secure RFCOMM Bluetooth socket. 1927 * <p>A remote device connecting to this socket will be authenticated and 1928 * communication on this socket will be encrypted. 1929 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 1930 * connections from a listening {@link BluetoothServerSocket}. 1931 * <p>Valid RFCOMM channels are in range 1 to 30. 1932 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1933 * <p>To auto assign a channel without creating a SDP record use 1934 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number. 1935 * 1936 * @param channel RFCOMM channel to listen on 1937 * @param mitm enforce man-in-the-middle protection for authentication. 1938 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 1939 * connections. 1940 * @return a listening RFCOMM BluetoothServerSocket 1941 * @throws IOException on error, for example Bluetooth not available, or insufficient 1942 * permissions, or channel in use. 1943 * @hide 1944 */ listenUsingRfcommOn(int channel, boolean mitm, boolean min16DigitPin)1945 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm, 1946 boolean min16DigitPin) throws IOException { 1947 BluetoothServerSocket socket = 1948 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm, 1949 min16DigitPin); 1950 int errno = socket.mSocket.bindListen(); 1951 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 1952 socket.setChannel(socket.mSocket.getPort()); 1953 } 1954 if (errno != 0) { 1955 //TODO(BT): Throw the same exception error code 1956 // that the previous code was using. 1957 //socket.mSocket.throwErrnoNative(errno); 1958 throw new IOException("Error: " + errno); 1959 } 1960 return socket; 1961 } 1962 1963 /** 1964 * Create a listening, secure RFCOMM Bluetooth socket with Service Record. 1965 * <p>A remote device connecting to this socket will be authenticated and 1966 * communication on this socket will be encrypted. 1967 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 1968 * connections from a listening {@link BluetoothServerSocket}. 1969 * <p>The system will assign an unused RFCOMM channel to listen on. 1970 * <p>The system will also register a Service Discovery 1971 * Protocol (SDP) record with the local SDP server containing the specified 1972 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices 1973 * can use the same UUID to query our SDP server and discover which channel 1974 * to connect to. This SDP record will be removed when this socket is 1975 * closed, or if this application closes unexpectedly. 1976 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to 1977 * connect to this socket from another device using the same {@link UUID}. 1978 * 1979 * @param name service name for SDP record 1980 * @param uuid uuid for SDP record 1981 * @return a listening RFCOMM BluetoothServerSocket 1982 * @throws IOException on error, for example Bluetooth not available, or insufficient 1983 * permissions, or channel in use. 1984 */ 1985 @RequiresPermission(Manifest.permission.BLUETOOTH) listenUsingRfcommWithServiceRecord(String name, UUID uuid)1986 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) 1987 throws IOException { 1988 return createNewRfcommSocketAndRecord(name, uuid, true, true); 1989 } 1990 1991 /** 1992 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record. 1993 * <p>The link key is not required to be authenticated, i.e the communication may be 1994 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices, 1995 * the link will be encrypted, as encryption is mandartory. 1996 * For legacy devices (pre Bluetooth 2.1 devices) the link will not 1997 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an 1998 * encrypted and authenticated communication channel is desired. 1999 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 2000 * connections from a listening {@link BluetoothServerSocket}. 2001 * <p>The system will assign an unused RFCOMM channel to listen on. 2002 * <p>The system will also register a Service Discovery 2003 * Protocol (SDP) record with the local SDP server containing the specified 2004 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices 2005 * can use the same UUID to query our SDP server and discover which channel 2006 * to connect to. This SDP record will be removed when this socket is 2007 * closed, or if this application closes unexpectedly. 2008 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to 2009 * connect to this socket from another device using the same {@link UUID}. 2010 * 2011 * @param name service name for SDP record 2012 * @param uuid uuid for SDP record 2013 * @return a listening RFCOMM BluetoothServerSocket 2014 * @throws IOException on error, for example Bluetooth not available, or insufficient 2015 * permissions, or channel in use. 2016 */ 2017 @RequiresPermission(Manifest.permission.BLUETOOTH) listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)2018 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid) 2019 throws IOException { 2020 return createNewRfcommSocketAndRecord(name, uuid, false, false); 2021 } 2022 2023 /** 2024 * Create a listening, encrypted, 2025 * RFCOMM Bluetooth socket with Service Record. 2026 * <p>The link will be encrypted, but the link key is not required to be authenticated 2027 * i.e the communication is vulnerable to Man In the Middle attacks. Use 2028 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key. 2029 * <p> Use this socket if authentication of link key is not possible. 2030 * For example, for Bluetooth 2.1 devices, if any of the devices does not have 2031 * an input and output capability or just has the ability to display a numeric key, 2032 * a secure socket connection is not possible and this socket can be used. 2033 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required. 2034 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory. 2035 * For more details, refer to the Security Model section 5.2 (vol 3) of 2036 * Bluetooth Core Specification version 2.1 + EDR. 2037 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 2038 * connections from a listening {@link BluetoothServerSocket}. 2039 * <p>The system will assign an unused RFCOMM channel to listen on. 2040 * <p>The system will also register a Service Discovery 2041 * Protocol (SDP) record with the local SDP server containing the specified 2042 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices 2043 * can use the same UUID to query our SDP server and discover which channel 2044 * to connect to. This SDP record will be removed when this socket is 2045 * closed, or if this application closes unexpectedly. 2046 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to 2047 * connect to this socket from another device using the same {@link UUID}. 2048 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 2049 * 2050 * @param name service name for SDP record 2051 * @param uuid uuid for SDP record 2052 * @return a listening RFCOMM BluetoothServerSocket 2053 * @throws IOException on error, for example Bluetooth not available, or insufficient 2054 * permissions, or channel in use. 2055 * @hide 2056 */ listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid)2057 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord(String name, UUID uuid) 2058 throws IOException { 2059 return createNewRfcommSocketAndRecord(name, uuid, false, true); 2060 } 2061 2062 createNewRfcommSocketAndRecord(String name, UUID uuid, boolean auth, boolean encrypt)2063 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid, 2064 boolean auth, boolean encrypt) throws IOException { 2065 BluetoothServerSocket socket; 2066 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, encrypt, 2067 new ParcelUuid(uuid)); 2068 socket.setServiceName(name); 2069 int errno = socket.mSocket.bindListen(); 2070 if (errno != 0) { 2071 //TODO(BT): Throw the same exception error code 2072 // that the previous code was using. 2073 //socket.mSocket.throwErrnoNative(errno); 2074 throw new IOException("Error: " + errno); 2075 } 2076 return socket; 2077 } 2078 2079 /** 2080 * Construct an unencrypted, unauthenticated, RFCOMM server socket. 2081 * Call #accept to retrieve connections to this socket. 2082 * 2083 * @return An RFCOMM BluetoothServerSocket 2084 * @throws IOException On error, for example Bluetooth not available, or insufficient 2085 * permissions. 2086 * @hide 2087 */ listenUsingInsecureRfcommOn(int port)2088 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException { 2089 BluetoothServerSocket socket = 2090 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, false, port); 2091 int errno = socket.mSocket.bindListen(); 2092 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 2093 socket.setChannel(socket.mSocket.getPort()); 2094 } 2095 if (errno != 0) { 2096 //TODO(BT): Throw the same exception error code 2097 // that the previous code was using. 2098 //socket.mSocket.throwErrnoNative(errno); 2099 throw new IOException("Error: " + errno); 2100 } 2101 return socket; 2102 } 2103 2104 /** 2105 * Construct an encrypted, RFCOMM server socket. 2106 * Call #accept to retrieve connections to this socket. 2107 * 2108 * @return An RFCOMM BluetoothServerSocket 2109 * @throws IOException On error, for example Bluetooth not available, or insufficient 2110 * permissions. 2111 * @hide 2112 */ listenUsingEncryptedRfcommOn(int port)2113 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port) throws IOException { 2114 BluetoothServerSocket socket = 2115 new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, false, true, port); 2116 int errno = socket.mSocket.bindListen(); 2117 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 2118 socket.setChannel(socket.mSocket.getPort()); 2119 } 2120 if (errno < 0) { 2121 //TODO(BT): Throw the same exception error code 2122 // that the previous code was using. 2123 //socket.mSocket.throwErrnoNative(errno); 2124 throw new IOException("Error: " + errno); 2125 } 2126 return socket; 2127 } 2128 2129 /** 2130 * Construct a SCO server socket. 2131 * Call #accept to retrieve connections to this socket. 2132 * 2133 * @return A SCO BluetoothServerSocket 2134 * @throws IOException On error, for example Bluetooth not available, or insufficient 2135 * permissions. 2136 * @hide 2137 */ listenUsingScoOn()2138 public static BluetoothServerSocket listenUsingScoOn() throws IOException { 2139 BluetoothServerSocket socket = 2140 new BluetoothServerSocket(BluetoothSocket.TYPE_SCO, false, false, -1); 2141 int errno = socket.mSocket.bindListen(); 2142 if (errno < 0) { 2143 //TODO(BT): Throw the same exception error code 2144 // that the previous code was using. 2145 //socket.mSocket.throwErrnoNative(errno); 2146 } 2147 return socket; 2148 } 2149 2150 /** 2151 * Construct an encrypted, authenticated, L2CAP server socket. 2152 * Call #accept to retrieve connections to this socket. 2153 * <p>To auto assign a port without creating a SDP record use 2154 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number. 2155 * 2156 * @param port the PSM to listen on 2157 * @param mitm enforce man-in-the-middle protection for authentication. 2158 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 2159 * connections. 2160 * @return An L2CAP BluetoothServerSocket 2161 * @throws IOException On error, for example Bluetooth not available, or insufficient 2162 * permissions. 2163 * @hide 2164 */ listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)2165 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin) 2166 throws IOException { 2167 BluetoothServerSocket socket = 2168 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, true, true, port, mitm, 2169 min16DigitPin); 2170 int errno = socket.mSocket.bindListen(); 2171 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 2172 int assignedChannel = socket.mSocket.getPort(); 2173 if (DBG) Log.d(TAG, "listenUsingL2capOn: set assigned channel to " + assignedChannel); 2174 socket.setChannel(assignedChannel); 2175 } 2176 if (errno != 0) { 2177 //TODO(BT): Throw the same exception error code 2178 // that the previous code was using. 2179 //socket.mSocket.throwErrnoNative(errno); 2180 throw new IOException("Error: " + errno); 2181 } 2182 return socket; 2183 } 2184 2185 /** 2186 * Construct an encrypted, authenticated, L2CAP server socket. 2187 * Call #accept to retrieve connections to this socket. 2188 * <p>To auto assign a port without creating a SDP record use 2189 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number. 2190 * 2191 * @param port the PSM to listen on 2192 * @return An L2CAP BluetoothServerSocket 2193 * @throws IOException On error, for example Bluetooth not available, or insufficient 2194 * permissions. 2195 * @hide 2196 */ listenUsingL2capOn(int port)2197 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException { 2198 return listenUsingL2capOn(port, false, false); 2199 } 2200 2201 2202 /** 2203 * Construct an insecure L2CAP server socket. 2204 * Call #accept to retrieve connections to this socket. 2205 * <p>To auto assign a port without creating a SDP record use 2206 * {@link #SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number. 2207 * 2208 * @param port the PSM to listen on 2209 * @return An L2CAP BluetoothServerSocket 2210 * @throws IOException On error, for example Bluetooth not available, or insufficient 2211 * permissions. 2212 * @hide 2213 */ listenUsingInsecureL2capOn(int port)2214 public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException { 2215 Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port); 2216 BluetoothServerSocket socket = 2217 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP, false, false, port, false, 2218 false); 2219 int errno = socket.mSocket.bindListen(); 2220 if (port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 2221 int assignedChannel = socket.mSocket.getPort(); 2222 if (DBG) { 2223 Log.d(TAG, "listenUsingInsecureL2capOn: set assigned channel to " 2224 + assignedChannel); 2225 } 2226 socket.setChannel(assignedChannel); 2227 } 2228 if (errno != 0) { 2229 //TODO(BT): Throw the same exception error code 2230 // that the previous code was using. 2231 //socket.mSocket.throwErrnoNative(errno); 2232 throw new IOException("Error: " + errno); 2233 } 2234 return socket; 2235 2236 } 2237 2238 /** 2239 * Read the local Out of Band Pairing Data 2240 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 2241 * 2242 * @return Pair<byte[], byte[]> of Hash and Randomizer 2243 * @hide 2244 */ readOutOfBandData()2245 public Pair<byte[], byte[]> readOutOfBandData() { 2246 return null; 2247 } 2248 2249 /** 2250 * Get the profile proxy object associated with the profile. 2251 * 2252 * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET}, 2253 * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or 2254 * {@link BluetoothProfile#GATT_SERVER}. Clients must implement 2255 * {@link BluetoothProfile.ServiceListener} to get notified of 2256 * the connection status and to get the proxy object. 2257 * 2258 * @param context Context of the application 2259 * @param listener The service Listener for connection callbacks. 2260 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH}, {@link 2261 * BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}. {@link BluetoothProfile#GATT} or 2262 * {@link BluetoothProfile#GATT_SERVER}. 2263 * @return true on success, false on error 2264 */ getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile)2265 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, 2266 int profile) { 2267 if (context == null || listener == null) { 2268 return false; 2269 } 2270 2271 if (profile == BluetoothProfile.HEADSET) { 2272 BluetoothHeadset headset = new BluetoothHeadset(context, listener); 2273 return true; 2274 } else if (profile == BluetoothProfile.A2DP) { 2275 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener); 2276 return true; 2277 } else if (profile == BluetoothProfile.A2DP_SINK) { 2278 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener); 2279 return true; 2280 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) { 2281 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener); 2282 return true; 2283 } else if (profile == BluetoothProfile.HID_HOST) { 2284 BluetoothHidHost iDev = new BluetoothHidHost(context, listener); 2285 return true; 2286 } else if (profile == BluetoothProfile.PAN) { 2287 BluetoothPan pan = new BluetoothPan(context, listener); 2288 return true; 2289 } else if (profile == BluetoothProfile.HEALTH) { 2290 BluetoothHealth health = new BluetoothHealth(context, listener); 2291 return true; 2292 } else if (profile == BluetoothProfile.MAP) { 2293 BluetoothMap map = new BluetoothMap(context, listener); 2294 return true; 2295 } else if (profile == BluetoothProfile.HEADSET_CLIENT) { 2296 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener); 2297 return true; 2298 } else if (profile == BluetoothProfile.SAP) { 2299 BluetoothSap sap = new BluetoothSap(context, listener); 2300 return true; 2301 } else if (profile == BluetoothProfile.PBAP_CLIENT) { 2302 BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener); 2303 return true; 2304 } else if (profile == BluetoothProfile.MAP_CLIENT) { 2305 BluetoothMapClient mapClient = new BluetoothMapClient(context, listener); 2306 return true; 2307 } else if (profile == BluetoothProfile.HID_DEVICE) { 2308 BluetoothHidDevice hidDevice = new BluetoothHidDevice(context, listener); 2309 return true; 2310 } else if (profile == BluetoothProfile.HEARING_AID) { 2311 BluetoothHearingAid hearingAid = new BluetoothHearingAid(context, listener); 2312 return true; 2313 } else { 2314 return false; 2315 } 2316 } 2317 2318 /** 2319 * Close the connection of the profile proxy to the Service. 2320 * 2321 * <p> Clients should call this when they are no longer using 2322 * the proxy obtained from {@link #getProfileProxy}. 2323 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or 2324 * {@link BluetoothProfile#A2DP} 2325 * 2326 * @param profile 2327 * @param proxy Profile proxy object 2328 */ closeProfileProxy(int profile, BluetoothProfile proxy)2329 public void closeProfileProxy(int profile, BluetoothProfile proxy) { 2330 if (proxy == null) { 2331 return; 2332 } 2333 2334 switch (profile) { 2335 case BluetoothProfile.HEADSET: 2336 BluetoothHeadset headset = (BluetoothHeadset) proxy; 2337 headset.close(); 2338 break; 2339 case BluetoothProfile.A2DP: 2340 BluetoothA2dp a2dp = (BluetoothA2dp) proxy; 2341 a2dp.close(); 2342 break; 2343 case BluetoothProfile.A2DP_SINK: 2344 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink) proxy; 2345 a2dpSink.close(); 2346 break; 2347 case BluetoothProfile.AVRCP_CONTROLLER: 2348 BluetoothAvrcpController avrcp = (BluetoothAvrcpController) proxy; 2349 avrcp.close(); 2350 break; 2351 case BluetoothProfile.HID_HOST: 2352 BluetoothHidHost iDev = (BluetoothHidHost) proxy; 2353 iDev.close(); 2354 break; 2355 case BluetoothProfile.PAN: 2356 BluetoothPan pan = (BluetoothPan) proxy; 2357 pan.close(); 2358 break; 2359 case BluetoothProfile.HEALTH: 2360 BluetoothHealth health = (BluetoothHealth) proxy; 2361 health.close(); 2362 break; 2363 case BluetoothProfile.GATT: 2364 BluetoothGatt gatt = (BluetoothGatt) proxy; 2365 gatt.close(); 2366 break; 2367 case BluetoothProfile.GATT_SERVER: 2368 BluetoothGattServer gattServer = (BluetoothGattServer) proxy; 2369 gattServer.close(); 2370 break; 2371 case BluetoothProfile.MAP: 2372 BluetoothMap map = (BluetoothMap) proxy; 2373 map.close(); 2374 break; 2375 case BluetoothProfile.HEADSET_CLIENT: 2376 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient) proxy; 2377 headsetClient.close(); 2378 break; 2379 case BluetoothProfile.SAP: 2380 BluetoothSap sap = (BluetoothSap) proxy; 2381 sap.close(); 2382 break; 2383 case BluetoothProfile.PBAP_CLIENT: 2384 BluetoothPbapClient pbapClient = (BluetoothPbapClient) proxy; 2385 pbapClient.close(); 2386 break; 2387 case BluetoothProfile.MAP_CLIENT: 2388 BluetoothMapClient mapClient = (BluetoothMapClient) proxy; 2389 mapClient.close(); 2390 break; 2391 case BluetoothProfile.HID_DEVICE: 2392 BluetoothHidDevice hidDevice = (BluetoothHidDevice) proxy; 2393 hidDevice.close(); 2394 break; 2395 case BluetoothProfile.HEARING_AID: 2396 BluetoothHearingAid hearingAid = (BluetoothHearingAid) proxy; 2397 hearingAid.close(); 2398 } 2399 } 2400 2401 private final IBluetoothManagerCallback mManagerCallback = 2402 new IBluetoothManagerCallback.Stub() { 2403 public void onBluetoothServiceUp(IBluetooth bluetoothService) { 2404 if (DBG) { 2405 Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); 2406 } 2407 2408 mServiceLock.writeLock().lock(); 2409 mService = bluetoothService; 2410 mServiceLock.writeLock().unlock(); 2411 2412 synchronized (mProxyServiceStateCallbacks) { 2413 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) { 2414 try { 2415 if (cb != null) { 2416 cb.onBluetoothServiceUp(bluetoothService); 2417 } else { 2418 Log.d(TAG, "onBluetoothServiceUp: cb is null!"); 2419 } 2420 } catch (Exception e) { 2421 Log.e(TAG, "", e); 2422 } 2423 } 2424 } 2425 } 2426 2427 public void onBluetoothServiceDown() { 2428 if (DBG) { 2429 Log.d(TAG, "onBluetoothServiceDown: " + mService); 2430 } 2431 2432 try { 2433 mServiceLock.writeLock().lock(); 2434 mService = null; 2435 if (mLeScanClients != null) { 2436 mLeScanClients.clear(); 2437 } 2438 if (sBluetoothLeAdvertiser != null) { 2439 sBluetoothLeAdvertiser.cleanup(); 2440 } 2441 if (sBluetoothLeScanner != null) { 2442 sBluetoothLeScanner.cleanup(); 2443 } 2444 } finally { 2445 mServiceLock.writeLock().unlock(); 2446 } 2447 2448 synchronized (mProxyServiceStateCallbacks) { 2449 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks) { 2450 try { 2451 if (cb != null) { 2452 cb.onBluetoothServiceDown(); 2453 } else { 2454 Log.d(TAG, "onBluetoothServiceDown: cb is null!"); 2455 } 2456 } catch (Exception e) { 2457 Log.e(TAG, "", e); 2458 } 2459 } 2460 } 2461 } 2462 2463 public void onBrEdrDown() { 2464 if (VDBG) { 2465 Log.i(TAG, "onBrEdrDown: " + mService); 2466 } 2467 } 2468 }; 2469 2470 /** 2471 * Enable the Bluetooth Adapter, but don't auto-connect devices 2472 * and don't persist state. Only for use by system applications. 2473 * 2474 * @hide 2475 */ 2476 @SystemApi 2477 @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) enableNoAutoConnect()2478 public boolean enableNoAutoConnect() { 2479 if (isEnabled()) { 2480 if (DBG) { 2481 Log.d(TAG, "enableNoAutoConnect(): BT already enabled!"); 2482 } 2483 return true; 2484 } 2485 try { 2486 return mManagerService.enableNoAutoConnect(ActivityThread.currentPackageName()); 2487 } catch (RemoteException e) { 2488 Log.e(TAG, "", e); 2489 } 2490 return false; 2491 } 2492 2493 /** 2494 * Enable control of the Bluetooth Adapter for a single application. 2495 * 2496 * <p>Some applications need to use Bluetooth for short periods of time to 2497 * transfer data but don't want all the associated implications like 2498 * automatic connection to headsets etc. 2499 * 2500 * <p> Multiple applications can call this. This is reference counted and 2501 * Bluetooth disabled only when no one else is using it. There will be no UI 2502 * shown to the user while bluetooth is being enabled. Any user action will 2503 * override this call. For example, if user wants Bluetooth on and the last 2504 * user of this API wanted to disable Bluetooth, Bluetooth will not be 2505 * turned off. 2506 * 2507 * <p> This API is only meant to be used by internal applications. Third 2508 * party applications but use {@link #enable} and {@link #disable} APIs. 2509 * 2510 * <p> If this API returns true, it means the callback will be called. 2511 * The callback will be called with the current state of Bluetooth. 2512 * If the state is not what was requested, an internal error would be the 2513 * reason. If Bluetooth is already on and if this function is called to turn 2514 * it on, the api will return true and a callback will be called. 2515 * 2516 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 2517 * 2518 * @param on True for on, false for off. 2519 * @param callback The callback to notify changes to the state. 2520 * @hide 2521 */ changeApplicationBluetoothState(boolean on, BluetoothStateChangeCallback callback)2522 public boolean changeApplicationBluetoothState(boolean on, 2523 BluetoothStateChangeCallback callback) { 2524 return false; 2525 } 2526 2527 /** 2528 * @hide 2529 */ 2530 public interface BluetoothStateChangeCallback { 2531 /** 2532 * @hide 2533 */ onBluetoothStateChange(boolean on)2534 void onBluetoothStateChange(boolean on); 2535 } 2536 2537 /** 2538 * @hide 2539 */ 2540 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub { 2541 private BluetoothStateChangeCallback mCallback; 2542 StateChangeCallbackWrapper(BluetoothStateChangeCallback callback)2543 StateChangeCallbackWrapper(BluetoothStateChangeCallback callback) { 2544 mCallback = callback; 2545 } 2546 2547 @Override onBluetoothStateChange(boolean on)2548 public void onBluetoothStateChange(boolean on) { 2549 mCallback.onBluetoothStateChange(on); 2550 } 2551 } 2552 toDeviceSet(BluetoothDevice[] devices)2553 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) { 2554 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices)); 2555 return Collections.unmodifiableSet(deviceSet); 2556 } 2557 finalize()2558 protected void finalize() throws Throwable { 2559 try { 2560 mManagerService.unregisterAdapter(mManagerCallback); 2561 } catch (RemoteException e) { 2562 Log.e(TAG, "", e); 2563 } finally { 2564 super.finalize(); 2565 } 2566 } 2567 2568 2569 /** 2570 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0" 2571 * <p>Alphabetic characters must be uppercase to be valid. 2572 * 2573 * @param address Bluetooth address as string 2574 * @return true if the address is valid, false otherwise 2575 */ checkBluetoothAddress(String address)2576 public static boolean checkBluetoothAddress(String address) { 2577 if (address == null || address.length() != ADDRESS_LENGTH) { 2578 return false; 2579 } 2580 for (int i = 0; i < ADDRESS_LENGTH; i++) { 2581 char c = address.charAt(i); 2582 switch (i % 3) { 2583 case 0: 2584 case 1: 2585 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { 2586 // hex character, OK 2587 break; 2588 } 2589 return false; 2590 case 2: 2591 if (c == ':') { 2592 break; // OK 2593 } 2594 return false; 2595 } 2596 } 2597 return true; 2598 } 2599 getBluetoothManager()2600 /*package*/ IBluetoothManager getBluetoothManager() { 2601 return mManagerService; 2602 } 2603 2604 private final ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = 2605 new ArrayList<IBluetoothManagerCallback>(); 2606 getBluetoothService(IBluetoothManagerCallback cb)2607 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) { 2608 synchronized (mProxyServiceStateCallbacks) { 2609 if (cb == null) { 2610 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback"); 2611 } else if (!mProxyServiceStateCallbacks.contains(cb)) { 2612 mProxyServiceStateCallbacks.add(cb); 2613 } 2614 } 2615 return mService; 2616 } 2617 removeServiceStateCallback(IBluetoothManagerCallback cb)2618 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) { 2619 synchronized (mProxyServiceStateCallbacks) { 2620 mProxyServiceStateCallbacks.remove(cb); 2621 } 2622 } 2623 2624 /** 2625 * Callback interface used to deliver LE scan results. 2626 * 2627 * @see #startLeScan(LeScanCallback) 2628 * @see #startLeScan(UUID[], LeScanCallback) 2629 */ 2630 public interface LeScanCallback { 2631 /** 2632 * Callback reporting an LE device found during a device scan initiated 2633 * by the {@link BluetoothAdapter#startLeScan} function. 2634 * 2635 * @param device Identifies the remote device 2636 * @param rssi The RSSI value for the remote device as reported by the Bluetooth hardware. 0 2637 * if no RSSI value is available. 2638 * @param scanRecord The content of the advertisement record offered by the remote device. 2639 */ onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)2640 void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord); 2641 } 2642 2643 /** 2644 * Starts a scan for Bluetooth LE devices. 2645 * 2646 * <p>Results of the scan are reported using the 2647 * {@link LeScanCallback#onLeScan} callback. 2648 * 2649 * @param callback the callback LE scan results are delivered 2650 * @return true, if the scan was started successfully 2651 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} 2652 * instead. 2653 */ 2654 @Deprecated 2655 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) startLeScan(LeScanCallback callback)2656 public boolean startLeScan(LeScanCallback callback) { 2657 return startLeScan(null, callback); 2658 } 2659 2660 /** 2661 * Starts a scan for Bluetooth LE devices, looking for devices that 2662 * advertise given services. 2663 * 2664 * <p>Devices which advertise all specified services are reported using the 2665 * {@link LeScanCallback#onLeScan} callback. 2666 * 2667 * @param serviceUuids Array of services to look for 2668 * @param callback the callback LE scan results are delivered 2669 * @return true, if the scan was started successfully 2670 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} 2671 * instead. 2672 */ 2673 @Deprecated 2674 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) startLeScan(final UUID[] serviceUuids, final LeScanCallback callback)2675 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) { 2676 if (DBG) { 2677 Log.d(TAG, "startLeScan(): " + Arrays.toString(serviceUuids)); 2678 } 2679 if (callback == null) { 2680 if (DBG) { 2681 Log.e(TAG, "startLeScan: null callback"); 2682 } 2683 return false; 2684 } 2685 BluetoothLeScanner scanner = getBluetoothLeScanner(); 2686 if (scanner == null) { 2687 if (DBG) { 2688 Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner"); 2689 } 2690 return false; 2691 } 2692 2693 synchronized (mLeScanClients) { 2694 if (mLeScanClients.containsKey(callback)) { 2695 if (DBG) { 2696 Log.e(TAG, "LE Scan has already started"); 2697 } 2698 return false; 2699 } 2700 2701 try { 2702 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); 2703 if (iGatt == null) { 2704 // BLE is not supported 2705 return false; 2706 } 2707 2708 ScanCallback scanCallback = new ScanCallback() { 2709 @Override 2710 public void onScanResult(int callbackType, ScanResult result) { 2711 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) { 2712 // Should not happen. 2713 Log.e(TAG, "LE Scan has already started"); 2714 return; 2715 } 2716 ScanRecord scanRecord = result.getScanRecord(); 2717 if (scanRecord == null) { 2718 return; 2719 } 2720 if (serviceUuids != null) { 2721 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>(); 2722 for (UUID uuid : serviceUuids) { 2723 uuids.add(new ParcelUuid(uuid)); 2724 } 2725 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids(); 2726 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) { 2727 if (DBG) { 2728 Log.d(TAG, "uuids does not match"); 2729 } 2730 return; 2731 } 2732 } 2733 callback.onLeScan(result.getDevice(), result.getRssi(), 2734 scanRecord.getBytes()); 2735 } 2736 }; 2737 ScanSettings settings = new ScanSettings.Builder().setCallbackType( 2738 ScanSettings.CALLBACK_TYPE_ALL_MATCHES) 2739 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) 2740 .build(); 2741 2742 List<ScanFilter> filters = new ArrayList<ScanFilter>(); 2743 if (serviceUuids != null && serviceUuids.length > 0) { 2744 // Note scan filter does not support matching an UUID array so we put one 2745 // UUID to hardware and match the whole array in callback. 2746 ScanFilter filter = 2747 new ScanFilter.Builder().setServiceUuid(new ParcelUuid(serviceUuids[0])) 2748 .build(); 2749 filters.add(filter); 2750 } 2751 scanner.startScan(filters, settings, scanCallback); 2752 2753 mLeScanClients.put(callback, scanCallback); 2754 return true; 2755 2756 } catch (RemoteException e) { 2757 Log.e(TAG, "", e); 2758 } 2759 } 2760 return false; 2761 } 2762 2763 /** 2764 * Stops an ongoing Bluetooth LE device scan. 2765 * 2766 * @param callback used to identify which scan to stop must be the same handle used to start the 2767 * scan 2768 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead. 2769 */ 2770 @Deprecated 2771 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) stopLeScan(LeScanCallback callback)2772 public void stopLeScan(LeScanCallback callback) { 2773 if (DBG) { 2774 Log.d(TAG, "stopLeScan()"); 2775 } 2776 BluetoothLeScanner scanner = getBluetoothLeScanner(); 2777 if (scanner == null) { 2778 return; 2779 } 2780 synchronized (mLeScanClients) { 2781 ScanCallback scanCallback = mLeScanClients.remove(callback); 2782 if (scanCallback == null) { 2783 if (DBG) { 2784 Log.d(TAG, "scan not started yet"); 2785 } 2786 return; 2787 } 2788 scanner.stopScan(scanCallback); 2789 } 2790 } 2791 2792 /** 2793 * Create a secure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and 2794 * assign a dynamic protocol/service multiplexer (PSM) value. This socket can be used to listen 2795 * for incoming connections. 2796 * <p>A remote device connecting to this socket will be authenticated and communication on this 2797 * socket will be encrypted. 2798 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening 2799 * {@link BluetoothServerSocket}. 2800 * <p>The system will assign a dynamic PSM value. This PSM value can be read from the {#link 2801 * BluetoothServerSocket#getPsm()} and this value will be released when this server socket is 2802 * closed, Bluetooth is turned off, or the application exits unexpectedly. 2803 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is 2804 * defined and performed by the application. 2805 * <p>Use {@link BluetoothDevice#createL2capCocSocket(int, int)} to connect to this server 2806 * socket from another Android device that is given the PSM value. 2807 * 2808 * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE} 2809 * @return an L2CAP CoC BluetoothServerSocket 2810 * @throws IOException on error, for example Bluetooth not available, or insufficient 2811 * permissions, or unable to start this CoC 2812 * @hide 2813 */ 2814 @RequiresPermission(Manifest.permission.BLUETOOTH) listenUsingL2capCoc(int transport)2815 public BluetoothServerSocket listenUsingL2capCoc(int transport) 2816 throws IOException { 2817 if (transport != BluetoothDevice.TRANSPORT_LE) { 2818 throw new IllegalArgumentException("Unsupported transport: " + transport); 2819 } 2820 BluetoothServerSocket socket = 2821 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true, 2822 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false); 2823 int errno = socket.mSocket.bindListen(); 2824 if (errno != 0) { 2825 throw new IOException("Error: " + errno); 2826 } 2827 2828 int assignedPsm = socket.mSocket.getPort(); 2829 if (assignedPsm == 0) { 2830 throw new IOException("Error: Unable to assign PSM value"); 2831 } 2832 if (DBG) { 2833 Log.d(TAG, "listenUsingL2capCoc: set assigned PSM to " 2834 + assignedPsm); 2835 } 2836 socket.setChannel(assignedPsm); 2837 2838 return socket; 2839 } 2840 2841 /** 2842 * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and 2843 * assign a dynamic PSM value. This socket can be used to listen for incoming connections. 2844 * <p>The link key is not required to be authenticated, i.e the communication may be vulnerable 2845 * to man-in-the-middle attacks. Use {@link #listenUsingL2capCoc}, if an encrypted and 2846 * authenticated communication channel is desired. 2847 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming connections from a listening 2848 * {@link BluetoothServerSocket}. 2849 * <p>The system will assign a dynamic protocol/service multiplexer (PSM) value. This PSM value 2850 * can be read from the {#link BluetoothServerSocket#getPsm()} and this value will be released 2851 * when this server socket is closed, Bluetooth is turned off, or the application exits 2852 * unexpectedly. 2853 * <p>The mechanism of disclosing the assigned dynamic PSM value to the initiating peer is 2854 * defined and performed by the application. 2855 * <p>Use {@link BluetoothDevice#createInsecureL2capCocSocket(int, int)} to connect to this 2856 * server socket from another Android device that is given the PSM value. 2857 * 2858 * @param transport Bluetooth transport to use, must be {@link BluetoothDevice#TRANSPORT_LE} 2859 * @return an L2CAP CoC BluetoothServerSocket 2860 * @throws IOException on error, for example Bluetooth not available, or insufficient 2861 * permissions, or unable to start this CoC 2862 * @hide 2863 */ 2864 @RequiresPermission(Manifest.permission.BLUETOOTH) listenUsingInsecureL2capCoc(int transport)2865 public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport) 2866 throws IOException { 2867 if (transport != BluetoothDevice.TRANSPORT_LE) { 2868 throw new IllegalArgumentException("Unsupported transport: " + transport); 2869 } 2870 BluetoothServerSocket socket = 2871 new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false, 2872 SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false, false); 2873 int errno = socket.mSocket.bindListen(); 2874 if (errno != 0) { 2875 throw new IOException("Error: " + errno); 2876 } 2877 2878 int assignedPsm = socket.mSocket.getPort(); 2879 if (assignedPsm == 0) { 2880 throw new IOException("Error: Unable to assign PSM value"); 2881 } 2882 if (DBG) { 2883 Log.d(TAG, "listenUsingInsecureL2capOn: set assigned PSM to " 2884 + assignedPsm); 2885 } 2886 socket.setChannel(assignedPsm); 2887 2888 return socket; 2889 } 2890 } 2891