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