BluetoothAdapter.java revision 3b3d1fea94318a4892fbd4353269749af417a81a
1/* 2 * Copyright (C) 2009-2015 The Android Open Source Project 3 * Copyright (C) 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.bluetooth.le.BluetoothLeAdvertiser; 27import android.bluetooth.le.BluetoothLeScanner; 28import android.bluetooth.le.ScanCallback; 29import android.bluetooth.le.ScanFilter; 30import android.bluetooth.le.ScanRecord; 31import android.bluetooth.le.ScanResult; 32import android.bluetooth.le.ScanSettings; 33import android.content.Context; 34import android.os.Binder; 35import android.os.IBinder; 36import android.os.ParcelUuid; 37import android.os.RemoteException; 38import android.os.ServiceManager; 39import android.util.Log; 40import android.util.Pair; 41 42import java.io.IOException; 43import java.lang.annotation.Retention; 44import java.lang.annotation.RetentionPolicy; 45import java.util.ArrayList; 46import java.util.Arrays; 47import java.util.Collections; 48import java.util.HashMap; 49import java.util.HashSet; 50import java.util.List; 51import java.util.Locale; 52import java.util.Map; 53import java.util.Set; 54import java.util.UUID; 55 56/** 57 * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter} 58 * lets you perform fundamental Bluetooth tasks, such as initiate 59 * device discovery, query a list of bonded (paired) devices, 60 * instantiate a {@link BluetoothDevice} using a known MAC address, and create 61 * a {@link BluetoothServerSocket} to listen for connection requests from other 62 * devices, and start a scan for Bluetooth LE devices. 63 * 64 * <p>To get a {@link BluetoothAdapter} representing the local Bluetooth 65 * adapter, when running on JELLY_BEAN_MR1 and below, call the 66 * static {@link #getDefaultAdapter} method; when running on JELLY_BEAN_MR2 and 67 * higher, retrieve it through 68 * {@link android.content.Context#getSystemService} with 69 * {@link android.content.Context#BLUETOOTH_SERVICE}. 70 * Fundamentally, this is your starting point for all 71 * Bluetooth actions. Once you have the local adapter, you can get a set of 72 * {@link BluetoothDevice} objects representing all paired devices with 73 * {@link #getBondedDevices()}; start device discovery with 74 * {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to 75 * listen for incoming connection requests with 76 * {@link #listenUsingRfcommWithServiceRecord(String,UUID)}; or start a scan for 77 * Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}. 78 * 79 * <p class="note"><strong>Note:</strong> 80 * Most methods require the {@link android.Manifest.permission#BLUETOOTH} 81 * permission and some also require the 82 * {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. 83 * 84 * <div class="special reference"> 85 * <h3>Developer Guides</h3> 86 * <p>For more information about using Bluetooth, read the 87 * <a href="{@docRoot}guide/topics/wireless/bluetooth.html">Bluetooth</a> developer guide.</p> 88 * </div> 89 * 90 * {@see BluetoothDevice} 91 * {@see BluetoothServerSocket} 92 */ 93public final class BluetoothAdapter { 94 private static final String TAG = "BluetoothAdapter"; 95 private static final boolean DBG = true; 96 private static final boolean VDBG = false; 97 98 /** 99 * Default MAC address reported to a client that does not have the 100 * android.permission.LOCAL_MAC_ADDRESS permission. 101 * 102 * @hide 103 */ 104 public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00"; 105 106 /** 107 * Sentinel error value for this class. Guaranteed to not equal any other 108 * integer constant in this class. Provided as a convenience for functions 109 * that require a sentinel error value, for example: 110 * <p><code>Intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 111 * BluetoothAdapter.ERROR)</code> 112 */ 113 public static final int ERROR = Integer.MIN_VALUE; 114 115 /** 116 * Broadcast Action: The state of the local Bluetooth adapter has been 117 * changed. 118 * <p>For example, Bluetooth has been turned on or off. 119 * <p>Always contains the extra fields {@link #EXTRA_STATE} and {@link 120 * #EXTRA_PREVIOUS_STATE} containing the new and old states 121 * respectively. 122 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 123 */ 124 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 125 public static final String ACTION_STATE_CHANGED = 126 "android.bluetooth.adapter.action.STATE_CHANGED"; 127 128 /** 129 * Used as an int extra field in {@link #ACTION_STATE_CHANGED} 130 * intents to request the current power state. Possible values are: 131 * {@link #STATE_OFF}, 132 * {@link #STATE_TURNING_ON}, 133 * {@link #STATE_ON}, 134 * {@link #STATE_TURNING_OFF}, 135 */ 136 public static final String EXTRA_STATE = 137 "android.bluetooth.adapter.extra.STATE"; 138 /** 139 * Used as an int extra field in {@link #ACTION_STATE_CHANGED} 140 * intents to request the previous power state. Possible values are: 141 * {@link #STATE_OFF}, 142 * {@link #STATE_TURNING_ON}, 143 * {@link #STATE_ON}, 144 * {@link #STATE_TURNING_OFF} 145 */ 146 public static final String EXTRA_PREVIOUS_STATE = 147 "android.bluetooth.adapter.extra.PREVIOUS_STATE"; 148 149 /** @hide */ 150 @IntDef({STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON, 151 STATE_BLE_ON, STATE_BLE_TURNING_OFF}) 152 @Retention(RetentionPolicy.SOURCE) 153 public @interface AdapterState {} 154 155 /** 156 * Indicates the local Bluetooth adapter is off. 157 */ 158 public static final int STATE_OFF = 10; 159 /** 160 * Indicates the local Bluetooth adapter is turning on. However local 161 * clients should wait for {@link #STATE_ON} before attempting to 162 * use the adapter. 163 */ 164 public static final int STATE_TURNING_ON = 11; 165 /** 166 * Indicates the local Bluetooth adapter is on, and ready for use. 167 */ 168 public static final int STATE_ON = 12; 169 /** 170 * Indicates the local Bluetooth adapter is turning off. Local clients 171 * should immediately attempt graceful disconnection of any remote links. 172 */ 173 public static final int STATE_TURNING_OFF = 13; 174 175 /** 176 * Indicates the local Bluetooth adapter is turning Bluetooth LE mode on. 177 * @hide 178 */ 179 public static final int STATE_BLE_TURNING_ON = 14; 180 181 /** 182 * Indicates the local Bluetooth adapter is in LE only mode. 183 * @hide 184 */ 185 public static final int STATE_BLE_ON = 15; 186 187 /** 188 * Indicates the local Bluetooth adapter is turning off LE only mode. 189 * @hide 190 */ 191 public static final int STATE_BLE_TURNING_OFF = 16; 192 193 /** 194 * Activity Action: Show a system activity that requests discoverable mode. 195 * This activity will also request the user to turn on Bluetooth if it 196 * is not currently enabled. 197 * <p>Discoverable mode is equivalent to {@link 198 * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. It allows remote devices to see 199 * this Bluetooth adapter when they perform a discovery. 200 * <p>For privacy, Android is not discoverable by default. 201 * <p>The sender of this Intent can optionally use extra field {@link 202 * #EXTRA_DISCOVERABLE_DURATION} to request the duration of 203 * discoverability. Currently the default duration is 120 seconds, and 204 * maximum duration is capped at 300 seconds for each request. 205 * <p>Notification of the result of this activity is posted using the 206 * {@link android.app.Activity#onActivityResult} callback. The 207 * <code>resultCode</code> 208 * will be the duration (in seconds) of discoverability or 209 * {@link android.app.Activity#RESULT_CANCELED} if the user rejected 210 * discoverability or an error has occurred. 211 * <p>Applications can also listen for {@link #ACTION_SCAN_MODE_CHANGED} 212 * for global notification whenever the scan mode changes. For example, an 213 * application can be notified when the device has ended discoverability. 214 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 215 */ 216 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 217 public static final String ACTION_REQUEST_DISCOVERABLE = 218 "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE"; 219 220 /** 221 * Used as an optional int extra field in {@link 222 * #ACTION_REQUEST_DISCOVERABLE} intents to request a specific duration 223 * for discoverability in seconds. The current default is 120 seconds, and 224 * requests over 300 seconds will be capped. These values could change. 225 */ 226 public static final String EXTRA_DISCOVERABLE_DURATION = 227 "android.bluetooth.adapter.extra.DISCOVERABLE_DURATION"; 228 229 /** 230 * Activity Action: Show a system activity that allows the user to turn on 231 * Bluetooth. 232 * <p>This system activity will return once Bluetooth has completed turning 233 * on, or the user has decided not to turn Bluetooth on. 234 * <p>Notification of the result of this activity is posted using the 235 * {@link android.app.Activity#onActivityResult} callback. The 236 * <code>resultCode</code> 237 * will be {@link android.app.Activity#RESULT_OK} if Bluetooth has been 238 * turned on or {@link android.app.Activity#RESULT_CANCELED} if the user 239 * has rejected the request or an error has occurred. 240 * <p>Applications can also listen for {@link #ACTION_STATE_CHANGED} 241 * for global notification whenever Bluetooth is turned on or off. 242 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 243 */ 244 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 245 public static final String ACTION_REQUEST_ENABLE = 246 "android.bluetooth.adapter.action.REQUEST_ENABLE"; 247 248 /** 249 * Activity Action: Show a system activity that allows user to enable BLE scans even when 250 * Bluetooth is turned off.<p> 251 * 252 * Notification of result of this activity is posted using 253 * {@link android.app.Activity#onActivityResult}. The <code>resultCode</code> will be 254 * {@link android.app.Activity#RESULT_OK} if BLE scan always available setting is turned on or 255 * {@link android.app.Activity#RESULT_CANCELED} if the user has rejected the request or an 256 * error occurred. 257 * 258 * @hide 259 */ 260 @SystemApi 261 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 262 public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = 263 "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE"; 264 265 /** 266 * Broadcast Action: Indicates the Bluetooth scan mode of the local Adapter 267 * has changed. 268 * <p>Always contains the extra fields {@link #EXTRA_SCAN_MODE} and {@link 269 * #EXTRA_PREVIOUS_SCAN_MODE} containing the new and old scan modes 270 * respectively. 271 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 272 */ 273 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 274 public static final String ACTION_SCAN_MODE_CHANGED = 275 "android.bluetooth.adapter.action.SCAN_MODE_CHANGED"; 276 277 /** 278 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED} 279 * intents to request the current scan mode. Possible values are: 280 * {@link #SCAN_MODE_NONE}, 281 * {@link #SCAN_MODE_CONNECTABLE}, 282 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}, 283 */ 284 public static final String EXTRA_SCAN_MODE = "android.bluetooth.adapter.extra.SCAN_MODE"; 285 /** 286 * Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED} 287 * intents to request the previous scan mode. Possible values are: 288 * {@link #SCAN_MODE_NONE}, 289 * {@link #SCAN_MODE_CONNECTABLE}, 290 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}, 291 */ 292 public static final String EXTRA_PREVIOUS_SCAN_MODE = 293 "android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE"; 294 295 /** @hide */ 296 @IntDef({SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE}) 297 @Retention(RetentionPolicy.SOURCE) 298 public @interface ScanMode {} 299 300 /** 301 * Indicates that both inquiry scan and page scan are disabled on the local 302 * Bluetooth adapter. Therefore this device is neither discoverable 303 * nor connectable from remote Bluetooth devices. 304 */ 305 public static final int SCAN_MODE_NONE = 20; 306 /** 307 * Indicates that inquiry scan is disabled, but page scan is enabled on the 308 * local Bluetooth adapter. Therefore this device is not discoverable from 309 * remote Bluetooth devices, but is connectable from remote devices that 310 * have previously discovered this device. 311 */ 312 public static final int SCAN_MODE_CONNECTABLE = 21; 313 /** 314 * Indicates that both inquiry scan and page scan are enabled on the local 315 * Bluetooth adapter. Therefore this device is both discoverable and 316 * connectable from remote Bluetooth devices. 317 */ 318 public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23; 319 320 /** 321 * Broadcast Action: The local Bluetooth adapter has started the remote 322 * device discovery process. 323 * <p>This usually involves an inquiry scan of about 12 seconds, followed 324 * by a page scan of each new device to retrieve its Bluetooth name. 325 * <p>Register for {@link BluetoothDevice#ACTION_FOUND} to be notified as 326 * remote Bluetooth devices are found. 327 * <p>Device discovery is a heavyweight procedure. New connections to 328 * remote Bluetooth devices should not be attempted while discovery is in 329 * progress, and existing connections will experience limited bandwidth 330 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing 331 * discovery. 332 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 333 */ 334 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 335 public static final String ACTION_DISCOVERY_STARTED = 336 "android.bluetooth.adapter.action.DISCOVERY_STARTED"; 337 /** 338 * Broadcast Action: The local Bluetooth adapter has finished the device 339 * discovery process. 340 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 341 */ 342 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 343 public static final String ACTION_DISCOVERY_FINISHED = 344 "android.bluetooth.adapter.action.DISCOVERY_FINISHED"; 345 346 /** 347 * Broadcast Action: The local Bluetooth adapter has changed its friendly 348 * Bluetooth name. 349 * <p>This name is visible to remote Bluetooth devices. 350 * <p>Always contains the extra field {@link #EXTRA_LOCAL_NAME} containing 351 * the name. 352 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 353 */ 354 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 355 public static final String ACTION_LOCAL_NAME_CHANGED = 356 "android.bluetooth.adapter.action.LOCAL_NAME_CHANGED"; 357 /** 358 * Used as a String extra field in {@link #ACTION_LOCAL_NAME_CHANGED} 359 * intents to request the local Bluetooth name. 360 */ 361 public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME"; 362 363 /** 364 * Intent used to broadcast the change in connection state of the local 365 * Bluetooth adapter to a profile of the remote device. When the adapter is 366 * not connected to any profiles of any remote devices and it attempts a 367 * connection to a profile this intent will sent. Once connected, this intent 368 * will not be sent for any more connection attempts to any profiles of any 369 * remote device. When the adapter disconnects from the last profile its 370 * connected to of any remote device, this intent will be sent. 371 * 372 * <p> This intent is useful for applications that are only concerned about 373 * whether the local adapter is connected to any profile of any device and 374 * are not really concerned about which profile. For example, an application 375 * which displays an icon to display whether Bluetooth is connected or not 376 * can use this intent. 377 * 378 * <p>This intent will have 3 extras: 379 * {@link #EXTRA_CONNECTION_STATE} - The current connection state. 380 * {@link #EXTRA_PREVIOUS_CONNECTION_STATE}- The previous connection state. 381 * {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. 382 * 383 * {@link #EXTRA_CONNECTION_STATE} or {@link #EXTRA_PREVIOUS_CONNECTION_STATE} 384 * can be any of {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING}, 385 * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}. 386 * 387 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive. 388 */ 389 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 390 public static final String ACTION_CONNECTION_STATE_CHANGED = 391 "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED"; 392 393 /** 394 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED} 395 * 396 * This extra represents the current connection state. 397 */ 398 public static final String EXTRA_CONNECTION_STATE = 399 "android.bluetooth.adapter.extra.CONNECTION_STATE"; 400 401 /** 402 * Extra used by {@link #ACTION_CONNECTION_STATE_CHANGED} 403 * 404 * This extra represents the previous connection state. 405 */ 406 public static final String EXTRA_PREVIOUS_CONNECTION_STATE = 407 "android.bluetooth.adapter.extra.PREVIOUS_CONNECTION_STATE"; 408 409 /** 410 * Broadcast Action: The Bluetooth adapter state has changed in LE only mode. 411 * @hide 412 */ 413 @SystemApi 414 public static final String ACTION_BLE_STATE_CHANGED = 415 "android.bluetooth.adapter.action.BLE_STATE_CHANGED"; 416 417 /** 418 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be 419 * by BLE Always on enabled application to know the ACL_CONNECTED event 420 * when Bluetooth state in STATE_BLE_ON. This denotes GATT connection 421 * as Bluetooth LE is the only feature available in STATE_BLE_ON 422 * 423 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_CONNECTED} which 424 * works in Bluetooth state STATE_ON 425 * @hide 426 */ 427 public static final String ACTION_BLE_ACL_CONNECTED = 428 "android.bluetooth.adapter.action.BLE_ACL_CONNECTED"; 429 430 /** 431 * Broadcast Action: The notifys Bluetooth ACL connected event. This will be 432 * by BLE Always on enabled application to know the ACL_DISCONNECTED event 433 * when Bluetooth state in STATE_BLE_ON. This denotes GATT disconnection as Bluetooth 434 * LE is the only feature available in STATE_BLE_ON 435 * 436 * This is counterpart of {@link BluetoothDevice#ACTION_ACL_DISCONNECTED} which 437 * works in Bluetooth state STATE_ON 438 * @hide 439 */ 440 public static final String ACTION_BLE_ACL_DISCONNECTED = 441 "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED"; 442 443 /** The profile is in disconnected state */ 444 public static final int STATE_DISCONNECTED = 0; 445 /** The profile is in connecting state */ 446 public static final int STATE_CONNECTING = 1; 447 /** The profile is in connected state */ 448 public static final int STATE_CONNECTED = 2; 449 /** The profile is in disconnecting state */ 450 public static final int STATE_DISCONNECTING = 3; 451 452 /** @hide */ 453 public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager"; 454 private final IBinder mToken; 455 456 457 /** When creating a ServerSocket using listenUsingRfcommOn() or 458 * listenUsingL2capOn() use SOCKET_CHANNEL_AUTO_STATIC to create 459 * a ServerSocket that auto assigns a channel number to the first 460 * bluetooth socket. 461 * The channel number assigned to this first Bluetooth Socket will 462 * be stored in the ServerSocket, and reused for subsequent Bluetooth 463 * sockets. 464 * @hide */ 465 public static final int SOCKET_CHANNEL_AUTO_STATIC_NO_SDP = -2; 466 467 468 private static final int ADDRESS_LENGTH = 17; 469 470 private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; 471 /** @hide */ 472 public static final int ACTIVITY_ENERGY_INFO_CACHED = 0; 473 /** @hide */ 474 public static final int ACTIVITY_ENERGY_INFO_REFRESHED = 1; 475 476 /** 477 * Lazily initialized singleton. Guaranteed final after first object 478 * constructed. 479 */ 480 private static BluetoothAdapter sAdapter; 481 482 private static BluetoothLeScanner sBluetoothLeScanner; 483 private static BluetoothLeAdvertiser sBluetoothLeAdvertiser; 484 485 private final IBluetoothManager mManagerService; 486 private IBluetooth mService; 487 488 private final Object mLock = new Object(); 489 private final Map<LeScanCallback, ScanCallback> mLeScanClients; 490 491 /** 492 * Get a handle to the default local Bluetooth adapter. 493 * <p>Currently Android only supports one Bluetooth adapter, but the API 494 * could be extended to support more. This will always return the default 495 * adapter. 496 * @return the default local adapter, or null if Bluetooth is not supported 497 * on this hardware platform 498 */ 499 public static synchronized BluetoothAdapter getDefaultAdapter() { 500 if (sAdapter == null) { 501 IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE); 502 if (b != null) { 503 IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b); 504 sAdapter = new BluetoothAdapter(managerService); 505 } else { 506 Log.e(TAG, "Bluetooth binder is null"); 507 } 508 } 509 return sAdapter; 510 } 511 512 /** 513 * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance. 514 */ 515 BluetoothAdapter(IBluetoothManager managerService) { 516 517 if (managerService == null) { 518 throw new IllegalArgumentException("bluetooth manager service is null"); 519 } 520 try { 521 mService = managerService.registerAdapter(mManagerCallback); 522 } catch (RemoteException e) {Log.e(TAG, "", e);} 523 mManagerService = managerService; 524 mLeScanClients = new HashMap<LeScanCallback, ScanCallback>(); 525 mToken = new Binder(); 526 } 527 528 /** 529 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware 530 * address. 531 * <p>Valid Bluetooth hardware addresses must be upper case, in a format 532 * such as "00:11:22:33:AA:BB". The helper {@link #checkBluetoothAddress} is 533 * available to validate a Bluetooth address. 534 * <p>A {@link BluetoothDevice} will always be returned for a valid 535 * hardware address, even if this adapter has never seen that device. 536 * 537 * @param address valid Bluetooth MAC address 538 * @throws IllegalArgumentException if address is invalid 539 */ 540 public BluetoothDevice getRemoteDevice(String address) { 541 return new BluetoothDevice(address); 542 } 543 544 /** 545 * Get a {@link BluetoothDevice} object for the given Bluetooth hardware 546 * address. 547 * <p>Valid Bluetooth hardware addresses must be 6 bytes. This method 548 * expects the address in network byte order (MSB first). 549 * <p>A {@link BluetoothDevice} will always be returned for a valid 550 * hardware address, even if this adapter has never seen that device. 551 * 552 * @param address Bluetooth MAC address (6 bytes) 553 * @throws IllegalArgumentException if address is invalid 554 */ 555 public BluetoothDevice getRemoteDevice(byte[] address) { 556 if (address == null || address.length != 6) { 557 throw new IllegalArgumentException("Bluetooth address must have 6 bytes"); 558 } 559 return new BluetoothDevice(String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", 560 address[0], address[1], address[2], address[3], address[4], address[5])); 561 } 562 563 /** 564 * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations. 565 * Will return null if Bluetooth is turned off or if Bluetooth LE Advertising is not 566 * supported on this device. 567 * <p> 568 * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported 569 * on this device before calling this method. 570 */ 571 public BluetoothLeAdvertiser getBluetoothLeAdvertiser() { 572 if (!getLeAccess()) return null; 573 if (!isMultipleAdvertisementSupported() && !isPeripheralModeSupported()) { 574 Log.e(TAG, "Bluetooth LE advertising not supported"); 575 return null; 576 } 577 synchronized(mLock) { 578 if (sBluetoothLeAdvertiser == null) { 579 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService); 580 } 581 } 582 return sBluetoothLeAdvertiser; 583 } 584 585 /** 586 * Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations. 587 */ 588 public BluetoothLeScanner getBluetoothLeScanner() { 589 if (!getLeAccess()) return null; 590 synchronized(mLock) { 591 if (sBluetoothLeScanner == null) { 592 sBluetoothLeScanner = new BluetoothLeScanner(mManagerService); 593 } 594 } 595 return sBluetoothLeScanner; 596 } 597 598 /** 599 * Return true if Bluetooth is currently enabled and ready for use. 600 * <p>Equivalent to: 601 * <code>getBluetoothState() == STATE_ON</code> 602 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 603 * 604 * @return true if the local adapter is turned on 605 */ 606 @RequiresPermission(Manifest.permission.BLUETOOTH) 607 public boolean isEnabled() { 608 try { 609 synchronized(mManagerCallback) { 610 if (mService != null) return mService.isEnabled(); 611 } 612 } catch (RemoteException e) {Log.e(TAG, "", e);} 613 return false; 614 } 615 616 /** 617 * Return true if Bluetooth LE(Always BLE On feature) is currently 618 * enabled and ready for use 619 * <p>This returns true if current state is either STATE_ON or STATE_BLE_ON 620 * 621 * @return true if the local Bluetooth LE adapter is turned on 622 * @hide 623 */ 624 @SystemApi 625 public boolean isLeEnabled() { 626 final int state = getLeState(); 627 if (state == BluetoothAdapter.STATE_ON) { 628 if (DBG) Log.d (TAG, "STATE_ON"); 629 } else if (state == BluetoothAdapter.STATE_BLE_ON) { 630 if (DBG) Log.d (TAG, "STATE_BLE_ON"); 631 } else { 632 if (DBG) Log.d (TAG, "STATE_OFF"); 633 return false; 634 } 635 return true; 636 } 637 638 /** 639 * Performs action based on user action to turn BT ON 640 * or OFF if BT is in BLE_ON state 641 */ 642 private void notifyUserAction(boolean enable) { 643 if (mService == null) { 644 Log.e(TAG, "mService is null"); 645 return; 646 } 647 648 try { 649 if (enable) { 650 mService.onLeServiceUp(); //NA:TODO implementation pending 651 } else { 652 mService.onBrEdrDown(); //NA:TODO implementation pending 653 } 654 } catch (RemoteException e) { 655 Log.e(TAG, "", e); 656 } 657 } 658 659 /** 660 * Turns off Bluetooth LE which was earlier turned on by calling EnableBLE(). 661 * 662 * <p> If the internal Adapter state is STATE_BLE_ON, this would trigger the transition 663 * to STATE_OFF and completely shut-down Bluetooth 664 * 665 * <p> If the Adapter state is STATE_ON, This would unregister the existance of 666 * special Bluetooth LE application and hence the further turning off of Bluetooth 667 * from UI would ensure the complete turn-off of Bluetooth rather than staying back 668 * BLE only state 669 * 670 * <p>This is an asynchronous call: it will return immediately, and 671 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED} 672 * to be notified of subsequent adapter state changes If this call returns 673 * true, then the adapter state will immediately transition from {@link 674 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time 675 * later transition to either {@link #STATE_BLE_ON} or {@link 676 * #STATE_OFF} based on the existance of the further Always BLE ON enabled applications 677 * If this call returns false then there was an 678 * immediate problem that will prevent the QAdapter from being turned off - 679 * such as the QAadapter already being turned off. 680 * 681 * @return true to indicate success, or false on 682 * immediate error 683 * @hide 684 */ 685 @SystemApi 686 public boolean disableBLE() { 687 if (!isBleScanAlwaysAvailable()) return false; 688 689 int state = getLeState(); 690 if (state == BluetoothAdapter.STATE_ON) { 691 if (DBG) Log.d (TAG, "STATE_ON: shouldn't disable"); 692 try { 693 mManagerService.updateBleAppCount(mToken, false); 694 } catch (RemoteException e) { 695 Log.e(TAG, "", e); 696 } 697 return true; 698 699 } else if (state == BluetoothAdapter.STATE_BLE_ON) { 700 if (DBG) Log.d (TAG, "STATE_BLE_ON"); 701 int bleAppCnt = 0; 702 try { 703 bleAppCnt = mManagerService.updateBleAppCount(mToken, false); 704 } catch (RemoteException e) { 705 Log.e(TAG, "", e); 706 } 707 if (bleAppCnt == 0) { 708 // Disable only if there are no other clients 709 notifyUserAction(false); 710 } 711 return true; 712 } 713 714 if (DBG) Log.d (TAG, "STATE_OFF: Already disabled"); 715 return false; 716 } 717 718 /** 719 * Special Applications who want to only turn on Bluetooth Low Energy (BLE) would 720 * EnableBLE, EnableBLE brings-up Bluetooth so that application can access 721 * only LE related feature (Bluetooth GATT layers interfaces using the respective class) 722 * EnableBLE in turn registers the existance of a special App which wants to 723 * turn on Bluetooth Low enrgy part without making it visible at the settings UI 724 * as Bluetooth ON. 725 * <p>Invoking EnableBLE when Bluetooth is already in ON state, would just registers 726 * the existance of special Application and doesn't do anything to current BT state. 727 * when user turn OFF Bluetooth from UI, if there is an existance of special app, Bluetooth 728 * would stay in BLE_ON state so that LE features are still acessible to the special 729 * Applications. 730 * 731 * <p>This is an asynchronous call: it will return immediately, and 732 * clients should listen for {@link #ACTION_BLE_STATE_CHANGED} 733 * to be notified of subsequent adapter state changes. If this call returns 734 * true, then the adapter state will immediately transition from {@link 735 * #STATE_OFF} to {@link #STATE_BLE_TURNING_ON}, and some time 736 * later transition to either {@link #STATE_OFF} or {@link 737 * #STATE_BLE_ON}. If this call returns false then there was an 738 * immediate problem that will prevent the adapter from being turned on - 739 * such as Airplane mode, or the adapter is already turned on. 740 * (@link #ACTION_BLE_STATE_CHANGED) returns the Bluetooth Adapter's various 741 * states, It includes all the classic Bluetooth Adapter states along with 742 * internal BLE only states 743 * 744 * @return true to indicate Bluetooth LE start-up has begun, or false on 745 * immediate error 746 * @hide 747 */ 748 @SystemApi 749 public boolean enableBLE() { 750 if (!isBleScanAlwaysAvailable()) return false; 751 752 if (isLeEnabled() == true) { 753 if (DBG) Log.d(TAG, "enableBLE(): BT is already enabled..!"); 754 try { 755 mManagerService.updateBleAppCount(mToken, true); 756 } catch (RemoteException e) { 757 Log.e(TAG, "", e); 758 } 759 return true; 760 } 761 762 try { 763 if (DBG) Log.d(TAG, "Calling enableBLE"); 764 mManagerService.updateBleAppCount(mToken, true); 765 return mManagerService.enable(); 766 } catch (RemoteException e) { 767 Log.e(TAG, "", e); 768 } 769 770 return false; 771 } 772 773 /** 774 * Get the current state of the local Bluetooth adapter. 775 * <p>Possible return values are 776 * {@link #STATE_OFF}, 777 * {@link #STATE_TURNING_ON}, 778 * {@link #STATE_ON}, 779 * {@link #STATE_TURNING_OFF}. 780 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 781 * 782 * @return current state of Bluetooth adapter 783 */ 784 @RequiresPermission(Manifest.permission.BLUETOOTH) 785 @AdapterState 786 public int getState() { 787 try { 788 synchronized(mManagerCallback) { 789 if (mService != null) 790 { 791 int state= mService.getState(); 792 if (VDBG) Log.d(TAG, "" + hashCode() + ": getState(). Returning " + state); 793 //consider all internal states as OFF 794 if (state == BluetoothAdapter.STATE_BLE_ON 795 || state == BluetoothAdapter.STATE_BLE_TURNING_ON 796 || state == BluetoothAdapter.STATE_BLE_TURNING_OFF) { 797 if (VDBG) Log.d(TAG, "Consider internal state as OFF"); 798 state = BluetoothAdapter.STATE_OFF; 799 } 800 return state; 801 } 802 // TODO(BT) there might be a small gap during STATE_TURNING_ON that 803 // mService is null, handle that case 804 } 805 } catch (RemoteException e) {Log.e(TAG, "", e);} 806 return STATE_OFF; 807 } 808 809 /** 810 * Get the current state of the local Bluetooth adapter 811 * <p>This returns current internal state of Adapter including LE ON/OFF 812 * 813 * <p>Possible return values are 814 * {@link #STATE_OFF}, 815 * {@link #STATE_BLE_TURNING_ON}, 816 * {@link #STATE_BLE_ON}, 817 * {@link #STATE_TURNING_ON}, 818 * {@link #STATE_ON}, 819 * {@link #STATE_TURNING_OFF}, 820 * {@link #STATE_BLE_TURNING_OFF}. 821 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 822 * 823 * @return current state of Bluetooth adapter 824 * @hide 825 */ 826 @RequiresPermission(Manifest.permission.BLUETOOTH) 827 @AdapterState 828 public int getLeState() { 829 try { 830 synchronized(mManagerCallback) { 831 if (mService != null) 832 { 833 int state= mService.getState(); 834 if (VDBG) Log.d(TAG,"getLeState() returning " + state); 835 return state; 836 } 837 } 838 } catch (RemoteException e) { 839 Log.e(TAG, "", e); 840 } 841 return BluetoothAdapter.STATE_OFF; 842 } 843 844 boolean getLeAccess() { 845 if(getLeState() == STATE_ON) 846 return true; 847 848 else if (getLeState() == STATE_BLE_ON) 849 return true; // TODO: FILTER SYSTEM APPS HERE <-- 850 851 return false; 852 } 853 854 /** 855 * Turn on the local Bluetooth adapter—do not use without explicit 856 * user action to turn on Bluetooth. 857 * <p>This powers on the underlying Bluetooth hardware, and starts all 858 * Bluetooth system services. 859 * <p class="caution"><strong>Bluetooth should never be enabled without 860 * direct user consent</strong>. If you want to turn on Bluetooth in order 861 * to create a wireless connection, you should use the {@link 862 * #ACTION_REQUEST_ENABLE} Intent, which will raise a dialog that requests 863 * user permission to turn on Bluetooth. The {@link #enable()} method is 864 * provided only for applications that include a user interface for changing 865 * system settings, such as a "power manager" app.</p> 866 * <p>This is an asynchronous call: it will return immediately, and 867 * clients should listen for {@link #ACTION_STATE_CHANGED} 868 * to be notified of subsequent adapter state changes. If this call returns 869 * true, then the adapter state will immediately transition from {@link 870 * #STATE_OFF} to {@link #STATE_TURNING_ON}, and some time 871 * later transition to either {@link #STATE_OFF} or {@link 872 * #STATE_ON}. If this call returns false then there was an 873 * immediate problem that will prevent the adapter from being turned on - 874 * such as Airplane mode, or the adapter is already turned on. 875 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN} 876 * permission 877 * 878 * @return true to indicate adapter startup has begun, or false on 879 * immediate error 880 */ 881 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 882 public boolean enable() { 883 int state = STATE_OFF; 884 if (isEnabled() == true){ 885 if (DBG) Log.d(TAG, "enable(): BT is already enabled..!"); 886 return true; 887 } 888 //Use service interface to get the exact state 889 if (mService != null) { 890 try { 891 state = mService.getState(); 892 } catch (RemoteException e) {Log.e(TAG, "", e);} 893 } 894 895 if (state == BluetoothAdapter.STATE_BLE_ON) { 896 Log.e(TAG, "BT is in BLE_ON State"); 897 notifyUserAction(true); 898 return true; 899 } 900 try { 901 return mManagerService.enable(); 902 } catch (RemoteException e) {Log.e(TAG, "", e);} 903 return false; 904 } 905 906 /** 907 * Turn off the local Bluetooth adapter—do not use without explicit 908 * user action to turn off Bluetooth. 909 * <p>This gracefully shuts down all Bluetooth connections, stops Bluetooth 910 * system services, and powers down the underlying Bluetooth hardware. 911 * <p class="caution"><strong>Bluetooth should never be disabled without 912 * direct user consent</strong>. The {@link #disable()} method is 913 * provided only for applications that include a user interface for changing 914 * system settings, such as a "power manager" app.</p> 915 * <p>This is an asynchronous call: it will return immediately, and 916 * clients should listen for {@link #ACTION_STATE_CHANGED} 917 * to be notified of subsequent adapter state changes. If this call returns 918 * true, then the adapter state will immediately transition from {@link 919 * #STATE_ON} to {@link #STATE_TURNING_OFF}, and some time 920 * later transition to either {@link #STATE_OFF} or {@link 921 * #STATE_ON}. If this call returns false then there was an 922 * immediate problem that will prevent the adapter from being turned off - 923 * such as the adapter already being turned off. 924 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN} 925 * permission 926 * 927 * @return true to indicate adapter shutdown has begun, or false on 928 * immediate error 929 */ 930 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 931 public boolean disable() { 932 try { 933 return mManagerService.disable(true); 934 } catch (RemoteException e) {Log.e(TAG, "", e);} 935 return false; 936 } 937 938 /** 939 * Turn off the local Bluetooth adapter and don't persist the setting. 940 * 941 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN} 942 * permission 943 * 944 * @return true to indicate adapter shutdown has begun, or false on 945 * immediate error 946 * @hide 947 */ 948 public boolean disable(boolean persist) { 949 950 try { 951 return mManagerService.disable(persist); 952 } catch (RemoteException e) {Log.e(TAG, "", e);} 953 return false; 954 } 955 956 /** 957 * Returns the hardware address of the local Bluetooth adapter. 958 * <p>For example, "00:11:22:AA:BB:CC". 959 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 960 * 961 * @return Bluetooth hardware address as string 962 */ 963 @RequiresPermission(Manifest.permission.BLUETOOTH) 964 public String getAddress() { 965 try { 966 return mManagerService.getAddress(); 967 } catch (RemoteException e) {Log.e(TAG, "", e);} 968 return null; 969 } 970 971 /** 972 * Get the friendly Bluetooth name of the local Bluetooth adapter. 973 * <p>This name is visible to remote Bluetooth devices. 974 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 975 * 976 * @return the Bluetooth name, or null on error 977 */ 978 public String getName() { 979 try { 980 return mManagerService.getName(); 981 } catch (RemoteException e) {Log.e(TAG, "", e);} 982 return null; 983 } 984 985 /** 986 * enable or disable Bluetooth HCI snoop log. 987 * 988 * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_ADMIN} 989 * permission 990 * 991 * @return true to indicate configure HCI log successfully, or false on 992 * immediate error 993 * @hide 994 */ 995 public boolean configHciSnoopLog(boolean enable) { 996 try { 997 synchronized(mManagerCallback) { 998 if (mService != null) return mService.configHciSnoopLog(enable); 999 } 1000 } catch (RemoteException e) {Log.e(TAG, "", e);} 1001 return false; 1002 } 1003 1004 /** 1005 * Get the UUIDs supported by the local Bluetooth adapter. 1006 * 1007 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1008 * 1009 * @return the UUIDs supported by the local Bluetooth Adapter. 1010 * @hide 1011 */ 1012 public ParcelUuid[] getUuids() { 1013 if (getState() != STATE_ON) return null; 1014 try { 1015 synchronized(mManagerCallback) { 1016 if (mService != null) return mService.getUuids(); 1017 } 1018 } catch (RemoteException e) {Log.e(TAG, "", e);} 1019 return null; 1020 } 1021 1022 /** 1023 * Set the friendly Bluetooth name of the local Bluetooth adapter. 1024 * <p>This name is visible to remote Bluetooth devices. 1025 * <p>Valid Bluetooth names are a maximum of 248 bytes using UTF-8 1026 * encoding, although many remote devices can only display the first 1027 * 40 characters, and some may be limited to just 20. 1028 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1029 * will return false. After turning on Bluetooth, 1030 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1031 * to get the updated value. 1032 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1033 * 1034 * @param name a valid Bluetooth name 1035 * @return true if the name was set, false otherwise 1036 */ 1037 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 1038 public boolean setName(String name) { 1039 if (getState() != STATE_ON) return false; 1040 try { 1041 synchronized(mManagerCallback) { 1042 if (mService != null) return mService.setName(name); 1043 } 1044 } catch (RemoteException e) {Log.e(TAG, "", e);} 1045 return false; 1046 } 1047 1048 /** 1049 * Get the current Bluetooth scan mode of the local Bluetooth adapter. 1050 * <p>The Bluetooth scan mode determines if the local adapter is 1051 * connectable and/or discoverable from remote Bluetooth devices. 1052 * <p>Possible values are: 1053 * {@link #SCAN_MODE_NONE}, 1054 * {@link #SCAN_MODE_CONNECTABLE}, 1055 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. 1056 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1057 * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth, 1058 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1059 * to get the updated value. 1060 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1061 * 1062 * @return scan mode 1063 */ 1064 @RequiresPermission(Manifest.permission.BLUETOOTH) 1065 @ScanMode 1066 public int getScanMode() { 1067 if (getState() != STATE_ON) return SCAN_MODE_NONE; 1068 try { 1069 synchronized(mManagerCallback) { 1070 if (mService != null) return mService.getScanMode(); 1071 } 1072 } catch (RemoteException e) {Log.e(TAG, "", e);} 1073 return SCAN_MODE_NONE; 1074 } 1075 1076 /** 1077 * Set the Bluetooth scan mode of the local Bluetooth adapter. 1078 * <p>The Bluetooth scan mode determines if the local adapter is 1079 * connectable and/or discoverable from remote Bluetooth devices. 1080 * <p>For privacy reasons, discoverable mode is automatically turned off 1081 * after <code>duration</code> seconds. For example, 120 seconds should be 1082 * enough for a remote device to initiate and complete its discovery 1083 * process. 1084 * <p>Valid scan mode values are: 1085 * {@link #SCAN_MODE_NONE}, 1086 * {@link #SCAN_MODE_CONNECTABLE}, 1087 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. 1088 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1089 * will return false. After turning on Bluetooth, 1090 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1091 * to get the updated value. 1092 * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} 1093 * <p>Applications cannot set the scan mode. They should use 1094 * <code>startActivityForResult( 1095 * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE}) 1096 * </code>instead. 1097 * 1098 * @param mode valid scan mode 1099 * @param duration time in seconds to apply scan mode, only used for 1100 * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE} 1101 * @return true if the scan mode was set, false otherwise 1102 * @hide 1103 */ 1104 public boolean setScanMode(@ScanMode int mode, int duration) { 1105 if (getState() != STATE_ON) return false; 1106 try { 1107 synchronized(mManagerCallback) { 1108 if (mService != null) return mService.setScanMode(mode, duration); 1109 } 1110 } catch (RemoteException e) {Log.e(TAG, "", e);} 1111 return false; 1112 } 1113 1114 /** @hide */ 1115 public boolean setScanMode(int mode) { 1116 if (getState() != STATE_ON) return false; 1117 /* getDiscoverableTimeout() to use the latest from NV than use 0 */ 1118 return setScanMode(mode, getDiscoverableTimeout()); 1119 } 1120 1121 /** @hide */ 1122 public int getDiscoverableTimeout() { 1123 if (getState() != STATE_ON) return -1; 1124 try { 1125 synchronized(mManagerCallback) { 1126 if (mService != null) return mService.getDiscoverableTimeout(); 1127 } 1128 } catch (RemoteException e) {Log.e(TAG, "", e);} 1129 return -1; 1130 } 1131 1132 /** @hide */ 1133 public void setDiscoverableTimeout(int timeout) { 1134 if (getState() != STATE_ON) return; 1135 try { 1136 synchronized(mManagerCallback) { 1137 if (mService != null) mService.setDiscoverableTimeout(timeout); 1138 } 1139 } catch (RemoteException e) {Log.e(TAG, "", e);} 1140 } 1141 1142 /** 1143 * Start the remote device discovery process. 1144 * <p>The discovery process usually involves an inquiry scan of about 12 1145 * seconds, followed by a page scan of each new device to retrieve its 1146 * Bluetooth name. 1147 * <p>This is an asynchronous call, it will return immediately. Register 1148 * for {@link #ACTION_DISCOVERY_STARTED} and {@link 1149 * #ACTION_DISCOVERY_FINISHED} intents to determine exactly when the 1150 * discovery starts and completes. Register for {@link 1151 * BluetoothDevice#ACTION_FOUND} to be notified as remote Bluetooth devices 1152 * are found. 1153 * <p>Device discovery is a heavyweight procedure. New connections to 1154 * remote Bluetooth devices should not be attempted while discovery is in 1155 * progress, and existing connections will experience limited bandwidth 1156 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing 1157 * discovery. Discovery is not managed by the Activity, 1158 * but is run as a system service, so an application should always call 1159 * {@link BluetoothAdapter#cancelDiscovery()} even if it 1160 * did not directly request a discovery, just to be sure. 1161 * <p>Device discovery will only find remote devices that are currently 1162 * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are 1163 * not discoverable by default, and need to be entered into a special mode. 1164 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1165 * will return false. After turning on Bluetooth, 1166 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1167 * to get the updated value. 1168 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1169 * 1170 * @return true on success, false on error 1171 */ 1172 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 1173 public boolean startDiscovery() { 1174 if (getState() != STATE_ON) return false; 1175 try { 1176 synchronized(mManagerCallback) { 1177 if (mService != null) return mService.startDiscovery(); 1178 } 1179 } catch (RemoteException e) {Log.e(TAG, "", e);} 1180 return false; 1181 } 1182 1183 /** 1184 * Cancel the current device discovery process. 1185 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. 1186 * <p>Because discovery is a heavyweight procedure for the Bluetooth 1187 * adapter, this method should always be called before attempting to connect 1188 * to a remote device with {@link 1189 * android.bluetooth.BluetoothSocket#connect()}. Discovery is not managed by 1190 * the Activity, but is run as a system service, so an application should 1191 * always call cancel discovery even if it did not directly request a 1192 * discovery, just to be sure. 1193 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1194 * will return false. After turning on Bluetooth, 1195 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1196 * to get the updated value. 1197 * 1198 * @return true on success, false on error 1199 */ 1200 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 1201 public boolean cancelDiscovery() { 1202 if (getState() != STATE_ON) return false; 1203 try { 1204 synchronized(mManagerCallback) { 1205 if (mService != null) return mService.cancelDiscovery(); 1206 } 1207 } catch (RemoteException e) {Log.e(TAG, "", e);} 1208 return false; 1209 } 1210 1211 /** 1212 * Return true if the local Bluetooth adapter is currently in the device 1213 * discovery process. 1214 * <p>Device discovery is a heavyweight procedure. New connections to 1215 * remote Bluetooth devices should not be attempted while discovery is in 1216 * progress, and existing connections will experience limited bandwidth 1217 * and high latency. Use {@link #cancelDiscovery()} to cancel an ongoing 1218 * discovery. 1219 * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED} 1220 * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery 1221 * starts or completes. 1222 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1223 * will return false. After turning on Bluetooth, 1224 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1225 * to get the updated value. 1226 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1227 * 1228 * @return true if discovering 1229 */ 1230 @RequiresPermission(Manifest.permission.BLUETOOTH) 1231 public boolean isDiscovering() { 1232 if (getState() != STATE_ON) return false; 1233 try { 1234 synchronized(mManagerCallback) { 1235 if (mService != null ) return mService.isDiscovering(); 1236 } 1237 } catch (RemoteException e) {Log.e(TAG, "", e);} 1238 return false; 1239 } 1240 1241 /** 1242 * Return true if the multi advertisement is supported by the chipset 1243 * 1244 * @return true if Multiple Advertisement feature is supported 1245 */ 1246 public boolean isMultipleAdvertisementSupported() { 1247 if (getState() != STATE_ON) return false; 1248 try { 1249 return mService.isMultiAdvertisementSupported(); 1250 } catch (RemoteException e) { 1251 Log.e(TAG, "failed to get isMultipleAdvertisementSupported, error: ", e); 1252 } 1253 return false; 1254 } 1255 1256 /** 1257 * Returns {@code true} if BLE scan is always available, {@code false} otherwise. <p> 1258 * 1259 * If this returns {@code true}, application can issue {@link BluetoothLeScanner#startScan} and 1260 * fetch scan results even when Bluetooth is turned off.<p> 1261 * 1262 * To change this setting, use {@link #ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE}. 1263 * 1264 * @hide 1265 */ 1266 @SystemApi 1267 public boolean isBleScanAlwaysAvailable() { 1268 try { 1269 return mManagerService.isBleScanAlwaysAvailable(); 1270 } catch (RemoteException e) { 1271 Log.e(TAG, "remote expection when calling isBleScanAlwaysAvailable", e); 1272 return false; 1273 } 1274 } 1275 1276 /** 1277 * Returns whether peripheral mode is supported. 1278 * 1279 * @hide 1280 */ 1281 public boolean isPeripheralModeSupported() { 1282 if (getState() != STATE_ON) return false; 1283 try { 1284 return mService.isPeripheralModeSupported(); 1285 } catch (RemoteException e) { 1286 Log.e(TAG, "failed to get peripheral mode capability: ", e); 1287 } 1288 return false; 1289 } 1290 1291 /** 1292 * Return true if offloaded filters are supported 1293 * 1294 * @return true if chipset supports on-chip filtering 1295 */ 1296 public boolean isOffloadedFilteringSupported() { 1297 if (!getLeAccess()) return false; 1298 try { 1299 return mService.isOffloadedFilteringSupported(); 1300 } catch (RemoteException e) { 1301 Log.e(TAG, "failed to get isOffloadedFilteringSupported, error: ", e); 1302 } 1303 return false; 1304 } 1305 1306 /** 1307 * Return true if offloaded scan batching is supported 1308 * 1309 * @return true if chipset supports on-chip scan batching 1310 */ 1311 public boolean isOffloadedScanBatchingSupported() { 1312 if (!getLeAccess()) return false; 1313 try { 1314 return mService.isOffloadedScanBatchingSupported(); 1315 } catch (RemoteException e) { 1316 Log.e(TAG, "failed to get isOffloadedScanBatchingSupported, error: ", e); 1317 } 1318 return false; 1319 } 1320 1321 /** 1322 * Return true if hardware has entries available for matching beacons 1323 * 1324 * @return true if there are hw entries available for matching beacons 1325 * @hide 1326 */ 1327 public boolean isHardwareTrackingFiltersAvailable() { 1328 if (!getLeAccess()) return false; 1329 try { 1330 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); 1331 if (iGatt == null) { 1332 // BLE is not supported 1333 return false; 1334 } 1335 return (iGatt.numHwTrackFiltersAvailable() != 0); 1336 } catch (RemoteException e) { 1337 Log.e(TAG, "", e); 1338 } 1339 return false; 1340 } 1341 1342 /** 1343 * Return the record of {@link BluetoothActivityEnergyInfo} object that 1344 * has the activity and energy info. This can be used to ascertain what 1345 * the controller has been up to, since the last sample. 1346 * @param updateType Type of info, cached vs refreshed. 1347 * 1348 * @return a record with {@link BluetoothActivityEnergyInfo} or null if 1349 * report is unavailable or unsupported 1350 * @hide 1351 */ 1352 public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { 1353 if (getState() != STATE_ON) return null; 1354 try { 1355 BluetoothActivityEnergyInfo record; 1356 if (!mService.isActivityAndEnergyReportingSupported()) { 1357 return null; 1358 } 1359 synchronized(this) { 1360 if (updateType == ACTIVITY_ENERGY_INFO_REFRESHED) { 1361 mService.getActivityEnergyInfoFromController(); 1362 wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS); 1363 } 1364 record = mService.reportActivityInfo(); 1365 if (record.isValid()) { 1366 return record; 1367 } else { 1368 return null; 1369 } 1370 } 1371 } catch (InterruptedException e) { 1372 Log.e(TAG, "getControllerActivityEnergyInfoCallback wait interrupted: " + e); 1373 } catch (RemoteException e) { 1374 Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); 1375 } 1376 return null; 1377 } 1378 1379 /** 1380 * Return the set of {@link BluetoothDevice} objects that are bonded 1381 * (paired) to the local adapter. 1382 * <p>If Bluetooth state is not {@link #STATE_ON}, this API 1383 * will return an empty set. After turning on Bluetooth, 1384 * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} 1385 * to get the updated value. 1386 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1387 * 1388 * @return unmodifiable set of {@link BluetoothDevice}, or null on error 1389 */ 1390 @RequiresPermission(Manifest.permission.BLUETOOTH) 1391 public Set<BluetoothDevice> getBondedDevices() { 1392 if (getState() != STATE_ON) { 1393 return toDeviceSet(new BluetoothDevice[0]); 1394 } 1395 try { 1396 synchronized(mManagerCallback) { 1397 if (mService != null) return toDeviceSet(mService.getBondedDevices()); 1398 } 1399 return toDeviceSet(new BluetoothDevice[0]); 1400 } catch (RemoteException e) {Log.e(TAG, "", e);} 1401 return null; 1402 } 1403 1404 /** 1405 * Get the current connection state of the local Bluetooth adapter. 1406 * This can be used to check whether the local Bluetooth adapter is connected 1407 * to any profile of any other remote Bluetooth Device. 1408 * 1409 * <p> Use this function along with {@link #ACTION_CONNECTION_STATE_CHANGED} 1410 * intent to get the connection state of the adapter. 1411 * 1412 * @return One of {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTED}, 1413 * {@link #STATE_CONNECTING} or {@link #STATE_DISCONNECTED} 1414 * 1415 * @hide 1416 */ 1417 public int getConnectionState() { 1418 if (getState() != STATE_ON) return BluetoothAdapter.STATE_DISCONNECTED; 1419 try { 1420 synchronized(mManagerCallback) { 1421 if (mService != null) return mService.getAdapterConnectionState(); 1422 } 1423 } catch (RemoteException e) {Log.e(TAG, "getConnectionState:", e);} 1424 return BluetoothAdapter.STATE_DISCONNECTED; 1425 } 1426 1427 /** 1428 * Get the current connection state of a profile. 1429 * This function can be used to check whether the local Bluetooth adapter 1430 * is connected to any remote device for a specific profile. 1431 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET}, 1432 * {@link BluetoothProfile#A2DP}. 1433 * 1434 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. 1435 * 1436 * <p> Return value can be one of 1437 * {@link BluetoothProfile#STATE_DISCONNECTED}, 1438 * {@link BluetoothProfile#STATE_CONNECTING}, 1439 * {@link BluetoothProfile#STATE_CONNECTED}, 1440 * {@link BluetoothProfile#STATE_DISCONNECTING} 1441 */ 1442 @RequiresPermission(Manifest.permission.BLUETOOTH) 1443 public int getProfileConnectionState(int profile) { 1444 if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED; 1445 try { 1446 synchronized(mManagerCallback) { 1447 if (mService != null) return mService.getProfileConnectionState(profile); 1448 } 1449 } catch (RemoteException e) { 1450 Log.e(TAG, "getProfileConnectionState:", e); 1451 } 1452 return BluetoothProfile.STATE_DISCONNECTED; 1453 } 1454 1455 /** 1456 * Create a listening, secure RFCOMM Bluetooth socket. 1457 * <p>A remote device connecting to this socket will be authenticated and 1458 * communication on this socket will be encrypted. 1459 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 1460 * connections from a listening {@link BluetoothServerSocket}. 1461 * <p>Valid RFCOMM channels are in range 1 to 30. 1462 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1463 * @param channel RFCOMM channel to listen on 1464 * @return a listening RFCOMM BluetoothServerSocket 1465 * @throws IOException on error, for example Bluetooth not available, or 1466 * insufficient permissions, or channel in use. 1467 * @hide 1468 */ 1469 public BluetoothServerSocket listenUsingRfcommOn(int channel) throws IOException { 1470 return listenUsingRfcommOn(channel, false, false); 1471 } 1472 1473 /** 1474 * Create a listening, secure RFCOMM Bluetooth socket. 1475 * <p>A remote device connecting to this socket will be authenticated and 1476 * communication on this socket will be encrypted. 1477 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 1478 * connections from a listening {@link BluetoothServerSocket}. 1479 * <p>Valid RFCOMM channels are in range 1 to 30. 1480 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} 1481 * <p>To auto assign a channel without creating a SDP record use 1482 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as channel number. 1483 * @param channel RFCOMM channel to listen on 1484 * @param mitm enforce man-in-the-middle protection for authentication. 1485 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections. 1486 * @return a listening RFCOMM BluetoothServerSocket 1487 * @throws IOException on error, for example Bluetooth not available, or 1488 * insufficient permissions, or channel in use. 1489 * @hide 1490 */ 1491 public BluetoothServerSocket listenUsingRfcommOn(int channel, boolean mitm, 1492 boolean min16DigitPin) 1493 throws IOException { 1494 BluetoothServerSocket socket = new BluetoothServerSocket( 1495 BluetoothSocket.TYPE_RFCOMM, true, true, channel, mitm, min16DigitPin); 1496 int errno = socket.mSocket.bindListen(); 1497 if (channel == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 1498 socket.setChannel(socket.mSocket.getPort()); 1499 } 1500 if (errno != 0) { 1501 //TODO(BT): Throw the same exception error code 1502 // that the previous code was using. 1503 //socket.mSocket.throwErrnoNative(errno); 1504 throw new IOException("Error: " + errno); 1505 } 1506 return socket; 1507 } 1508 1509 /** 1510 * Create a listening, secure RFCOMM Bluetooth socket with Service Record. 1511 * <p>A remote device connecting to this socket will be authenticated and 1512 * communication on this socket will be encrypted. 1513 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 1514 * connections from a listening {@link BluetoothServerSocket}. 1515 * <p>The system will assign an unused RFCOMM channel to listen on. 1516 * <p>The system will also register a Service Discovery 1517 * Protocol (SDP) record with the local SDP server containing the specified 1518 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices 1519 * can use the same UUID to query our SDP server and discover which channel 1520 * to connect to. This SDP record will be removed when this socket is 1521 * closed, or if this application closes unexpectedly. 1522 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to 1523 * connect to this socket from another device using the same {@link UUID}. 1524 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1525 * @param name service name for SDP record 1526 * @param uuid uuid for SDP record 1527 * @return a listening RFCOMM BluetoothServerSocket 1528 * @throws IOException on error, for example Bluetooth not available, or 1529 * insufficient permissions, or channel in use. 1530 */ 1531 @RequiresPermission(Manifest.permission.BLUETOOTH) 1532 public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid) 1533 throws IOException { 1534 return createNewRfcommSocketAndRecord(name, uuid, true, true); 1535 } 1536 1537 /** 1538 * Create a listening, insecure RFCOMM Bluetooth socket with Service Record. 1539 * <p>The link key is not required to be authenticated, i.e the communication may be 1540 * vulnerable to Man In the Middle attacks. For Bluetooth 2.1 devices, 1541 * the link will be encrypted, as encryption is mandartory. 1542 * For legacy devices (pre Bluetooth 2.1 devices) the link will not 1543 * be encrypted. Use {@link #listenUsingRfcommWithServiceRecord}, if an 1544 * encrypted and authenticated communication channel is desired. 1545 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 1546 * connections from a listening {@link BluetoothServerSocket}. 1547 * <p>The system will assign an unused RFCOMM channel to listen on. 1548 * <p>The system will also register a Service Discovery 1549 * Protocol (SDP) record with the local SDP server containing the specified 1550 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices 1551 * can use the same UUID to query our SDP server and discover which channel 1552 * to connect to. This SDP record will be removed when this socket is 1553 * closed, or if this application closes unexpectedly. 1554 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to 1555 * connect to this socket from another device using the same {@link UUID}. 1556 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1557 * @param name service name for SDP record 1558 * @param uuid uuid for SDP record 1559 * @return a listening RFCOMM BluetoothServerSocket 1560 * @throws IOException on error, for example Bluetooth not available, or 1561 * insufficient permissions, or channel in use. 1562 */ 1563 @RequiresPermission(Manifest.permission.BLUETOOTH) 1564 public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid) 1565 throws IOException { 1566 return createNewRfcommSocketAndRecord(name, uuid, false, false); 1567 } 1568 1569 /** 1570 * Create a listening, encrypted, 1571 * RFCOMM Bluetooth socket with Service Record. 1572 * <p>The link will be encrypted, but the link key is not required to be authenticated 1573 * i.e the communication is vulnerable to Man In the Middle attacks. Use 1574 * {@link #listenUsingRfcommWithServiceRecord}, to ensure an authenticated link key. 1575 * <p> Use this socket if authentication of link key is not possible. 1576 * For example, for Bluetooth 2.1 devices, if any of the devices does not have 1577 * an input and output capability or just has the ability to display a numeric key, 1578 * a secure socket connection is not possible and this socket can be used. 1579 * Use {@link #listenUsingInsecureRfcommWithServiceRecord}, if encryption is not required. 1580 * For Bluetooth 2.1 devices, the link will be encrypted, as encryption is mandartory. 1581 * For more details, refer to the Security Model section 5.2 (vol 3) of 1582 * Bluetooth Core Specification version 2.1 + EDR. 1583 * <p>Use {@link BluetoothServerSocket#accept} to retrieve incoming 1584 * connections from a listening {@link BluetoothServerSocket}. 1585 * <p>The system will assign an unused RFCOMM channel to listen on. 1586 * <p>The system will also register a Service Discovery 1587 * Protocol (SDP) record with the local SDP server containing the specified 1588 * UUID, service name, and auto-assigned channel. Remote Bluetooth devices 1589 * can use the same UUID to query our SDP server and discover which channel 1590 * to connect to. This SDP record will be removed when this socket is 1591 * closed, or if this application closes unexpectedly. 1592 * <p>Use {@link BluetoothDevice#createRfcommSocketToServiceRecord} to 1593 * connect to this socket from another device using the same {@link UUID}. 1594 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1595 * @param name service name for SDP record 1596 * @param uuid uuid for SDP record 1597 * @return a listening RFCOMM BluetoothServerSocket 1598 * @throws IOException on error, for example Bluetooth not available, or 1599 * insufficient permissions, or channel in use. 1600 * @hide 1601 */ 1602 public BluetoothServerSocket listenUsingEncryptedRfcommWithServiceRecord( 1603 String name, UUID uuid) throws IOException { 1604 return createNewRfcommSocketAndRecord(name, uuid, false, true); 1605 } 1606 1607 1608 private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid, 1609 boolean auth, boolean encrypt) throws IOException { 1610 BluetoothServerSocket socket; 1611 socket = new BluetoothServerSocket(BluetoothSocket.TYPE_RFCOMM, auth, 1612 encrypt, new ParcelUuid(uuid)); 1613 socket.setServiceName(name); 1614 int errno = socket.mSocket.bindListen(); 1615 if (errno != 0) { 1616 //TODO(BT): Throw the same exception error code 1617 // that the previous code was using. 1618 //socket.mSocket.throwErrnoNative(errno); 1619 throw new IOException("Error: " + errno); 1620 } 1621 return socket; 1622 } 1623 1624 /** 1625 * Construct an unencrypted, unauthenticated, RFCOMM server socket. 1626 * Call #accept to retrieve connections to this socket. 1627 * @return An RFCOMM BluetoothServerSocket 1628 * @throws IOException On error, for example Bluetooth not available, or 1629 * insufficient permissions. 1630 * @hide 1631 */ 1632 public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException { 1633 BluetoothServerSocket socket = new BluetoothServerSocket( 1634 BluetoothSocket.TYPE_RFCOMM, false, false, port); 1635 int errno = socket.mSocket.bindListen(); 1636 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 1637 socket.setChannel(socket.mSocket.getPort()); 1638 } 1639 if (errno != 0) { 1640 //TODO(BT): Throw the same exception error code 1641 // that the previous code was using. 1642 //socket.mSocket.throwErrnoNative(errno); 1643 throw new IOException("Error: " + errno); 1644 } 1645 return socket; 1646 } 1647 1648 /** 1649 * Construct an encrypted, RFCOMM server socket. 1650 * Call #accept to retrieve connections to this socket. 1651 * @return An RFCOMM BluetoothServerSocket 1652 * @throws IOException On error, for example Bluetooth not available, or 1653 * insufficient permissions. 1654 * @hide 1655 */ 1656 public BluetoothServerSocket listenUsingEncryptedRfcommOn(int port) 1657 throws IOException { 1658 BluetoothServerSocket socket = new BluetoothServerSocket( 1659 BluetoothSocket.TYPE_RFCOMM, false, true, port); 1660 int errno = socket.mSocket.bindListen(); 1661 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 1662 socket.setChannel(socket.mSocket.getPort()); 1663 } 1664 if (errno < 0) { 1665 //TODO(BT): Throw the same exception error code 1666 // that the previous code was using. 1667 //socket.mSocket.throwErrnoNative(errno); 1668 throw new IOException("Error: " + errno); 1669 } 1670 return socket; 1671 } 1672 1673 /** 1674 * Construct a SCO server socket. 1675 * Call #accept to retrieve connections to this socket. 1676 * @return A SCO BluetoothServerSocket 1677 * @throws IOException On error, for example Bluetooth not available, or 1678 * insufficient permissions. 1679 * @hide 1680 */ 1681 public static BluetoothServerSocket listenUsingScoOn() throws IOException { 1682 BluetoothServerSocket socket = new BluetoothServerSocket( 1683 BluetoothSocket.TYPE_SCO, false, false, -1); 1684 int errno = socket.mSocket.bindListen(); 1685 if (errno < 0) { 1686 //TODO(BT): Throw the same exception error code 1687 // that the previous code was using. 1688 //socket.mSocket.throwErrnoNative(errno); 1689 } 1690 return socket; 1691 } 1692 1693 /** 1694 * Construct an encrypted, authenticated, L2CAP server socket. 1695 * Call #accept to retrieve connections to this socket. 1696 * <p>To auto assign a port without creating a SDP record use 1697 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number. 1698 * @param port the PSM to listen on 1699 * @param mitm enforce man-in-the-middle protection for authentication. 1700 * @param min16DigitPin enforce a pin key length og minimum 16 digit for sec mode 2 connections. 1701 * @return An L2CAP BluetoothServerSocket 1702 * @throws IOException On error, for example Bluetooth not available, or 1703 * insufficient permissions. 1704 * @hide 1705 */ 1706 public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin) 1707 throws IOException { 1708 BluetoothServerSocket socket = new BluetoothServerSocket( 1709 BluetoothSocket.TYPE_L2CAP, true, true, port, mitm, min16DigitPin); 1710 int errno = socket.mSocket.bindListen(); 1711 if(port == SOCKET_CHANNEL_AUTO_STATIC_NO_SDP) { 1712 socket.setChannel(socket.mSocket.getPort()); 1713 } 1714 if (errno != 0) { 1715 //TODO(BT): Throw the same exception error code 1716 // that the previous code was using. 1717 //socket.mSocket.throwErrnoNative(errno); 1718 throw new IOException("Error: " + errno); 1719 } 1720 return socket; 1721 } 1722 1723 /** 1724 * Construct an encrypted, authenticated, L2CAP server socket. 1725 * Call #accept to retrieve connections to this socket. 1726 * <p>To auto assign a port without creating a SDP record use 1727 * {@link SOCKET_CHANNEL_AUTO_STATIC_NO_SDP} as port number. 1728 * @param port the PSM to listen on 1729 * @return An L2CAP BluetoothServerSocket 1730 * @throws IOException On error, for example Bluetooth not available, or 1731 * insufficient permissions. 1732 * @hide 1733 */ 1734 public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException { 1735 return listenUsingL2capOn(port, false, false); 1736 } 1737 1738 /** 1739 * Read the local Out of Band Pairing Data 1740 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1741 * 1742 * @return Pair<byte[], byte[]> of Hash and Randomizer 1743 * 1744 * @hide 1745 */ 1746 public Pair<byte[], byte[]> readOutOfBandData() { 1747 if (getState() != STATE_ON) return null; 1748 //TODO(BT 1749 /* 1750 try { 1751 byte[] hash; 1752 byte[] randomizer; 1753 1754 byte[] ret = mService.readOutOfBandData(); 1755 1756 if (ret == null || ret.length != 32) return null; 1757 1758 hash = Arrays.copyOfRange(ret, 0, 16); 1759 randomizer = Arrays.copyOfRange(ret, 16, 32); 1760 1761 if (DBG) { 1762 Log.d(TAG, "readOutOfBandData:" + Arrays.toString(hash) + 1763 ":" + Arrays.toString(randomizer)); 1764 } 1765 return new Pair<byte[], byte[]>(hash, randomizer); 1766 1767 } catch (RemoteException e) {Log.e(TAG, "", e);}*/ 1768 return null; 1769 } 1770 1771 /** 1772 * Get the profile proxy object associated with the profile. 1773 * 1774 * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET}, 1775 * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or 1776 * {@link BluetoothProfile#GATT_SERVER}. Clients must implement 1777 * {@link BluetoothProfile.ServiceListener} to get notified of 1778 * the connection status and to get the proxy object. 1779 * 1780 * @param context Context of the application 1781 * @param listener The service Listener for connection callbacks. 1782 * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH}, 1783 * {@link BluetoothProfile#HEADSET}, {@link BluetoothProfile#A2DP}. 1784 * {@link BluetoothProfile#GATT} or {@link BluetoothProfile#GATT_SERVER}. 1785 * @return true on success, false on error 1786 */ 1787 public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, 1788 int profile) { 1789 if (context == null || listener == null) return false; 1790 1791 if (profile == BluetoothProfile.HEADSET) { 1792 BluetoothHeadset headset = new BluetoothHeadset(context, listener); 1793 return true; 1794 } else if (profile == BluetoothProfile.A2DP) { 1795 BluetoothA2dp a2dp = new BluetoothA2dp(context, listener); 1796 return true; 1797 } else if (profile == BluetoothProfile.A2DP_SINK) { 1798 BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener); 1799 return true; 1800 } else if (profile == BluetoothProfile.AVRCP_CONTROLLER) { 1801 BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener); 1802 return true; 1803 } else if (profile == BluetoothProfile.INPUT_DEVICE) { 1804 BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener); 1805 return true; 1806 } else if (profile == BluetoothProfile.PAN) { 1807 BluetoothPan pan = new BluetoothPan(context, listener); 1808 return true; 1809 } else if (profile == BluetoothProfile.HEALTH) { 1810 BluetoothHealth health = new BluetoothHealth(context, listener); 1811 return true; 1812 } else if (profile == BluetoothProfile.MAP) { 1813 BluetoothMap map = new BluetoothMap(context, listener); 1814 return true; 1815 } else if (profile == BluetoothProfile.HEADSET_CLIENT) { 1816 BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener); 1817 return true; 1818 } else if (profile == BluetoothProfile.SAP) { 1819 BluetoothSap sap = new BluetoothSap(context, listener); 1820 return true; 1821 } else { 1822 return false; 1823 } 1824 } 1825 1826 /** 1827 * Close the connection of the profile proxy to the Service. 1828 * 1829 * <p> Clients should call this when they are no longer using 1830 * the proxy obtained from {@link #getProfileProxy}. 1831 * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or 1832 * {@link BluetoothProfile#A2DP} 1833 * 1834 * @param profile 1835 * @param proxy Profile proxy object 1836 */ 1837 public void closeProfileProxy(int profile, BluetoothProfile proxy) { 1838 if (proxy == null) return; 1839 1840 switch (profile) { 1841 case BluetoothProfile.HEADSET: 1842 BluetoothHeadset headset = (BluetoothHeadset)proxy; 1843 headset.close(); 1844 break; 1845 case BluetoothProfile.A2DP: 1846 BluetoothA2dp a2dp = (BluetoothA2dp)proxy; 1847 a2dp.close(); 1848 break; 1849 case BluetoothProfile.A2DP_SINK: 1850 BluetoothA2dpSink a2dpSink = (BluetoothA2dpSink)proxy; 1851 a2dpSink.close(); 1852 break; 1853 case BluetoothProfile.AVRCP_CONTROLLER: 1854 BluetoothAvrcpController avrcp = (BluetoothAvrcpController)proxy; 1855 avrcp.close(); 1856 break; 1857 case BluetoothProfile.INPUT_DEVICE: 1858 BluetoothInputDevice iDev = (BluetoothInputDevice)proxy; 1859 iDev.close(); 1860 break; 1861 case BluetoothProfile.PAN: 1862 BluetoothPan pan = (BluetoothPan)proxy; 1863 pan.close(); 1864 break; 1865 case BluetoothProfile.HEALTH: 1866 BluetoothHealth health = (BluetoothHealth)proxy; 1867 health.close(); 1868 break; 1869 case BluetoothProfile.GATT: 1870 BluetoothGatt gatt = (BluetoothGatt)proxy; 1871 gatt.close(); 1872 break; 1873 case BluetoothProfile.GATT_SERVER: 1874 BluetoothGattServer gattServer = (BluetoothGattServer)proxy; 1875 gattServer.close(); 1876 break; 1877 case BluetoothProfile.MAP: 1878 BluetoothMap map = (BluetoothMap)proxy; 1879 map.close(); 1880 break; 1881 case BluetoothProfile.HEADSET_CLIENT: 1882 BluetoothHeadsetClient headsetClient = (BluetoothHeadsetClient)proxy; 1883 headsetClient.close(); 1884 break; 1885 case BluetoothProfile.SAP: 1886 BluetoothSap sap = (BluetoothSap)proxy; 1887 sap.close(); 1888 break; 1889 } 1890 } 1891 1892 final private IBluetoothManagerCallback mManagerCallback = 1893 new IBluetoothManagerCallback.Stub() { 1894 public void onBluetoothServiceUp(IBluetooth bluetoothService) { 1895 if (VDBG) Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); 1896 synchronized (mManagerCallback) { 1897 mService = bluetoothService; 1898 synchronized (mProxyServiceStateCallbacks) { 1899 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ 1900 try { 1901 if (cb != null) { 1902 cb.onBluetoothServiceUp(bluetoothService); 1903 } else { 1904 Log.d(TAG, "onBluetoothServiceUp: cb is null!!!"); 1905 } 1906 } catch (Exception e) { Log.e(TAG,"",e);} 1907 } 1908 } 1909 } 1910 } 1911 1912 public void onBluetoothServiceDown() { 1913 if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService); 1914 synchronized (mManagerCallback) { 1915 mService = null; 1916 if (mLeScanClients != null) mLeScanClients.clear(); 1917 if (sBluetoothLeAdvertiser != null) sBluetoothLeAdvertiser.cleanup(); 1918 if (sBluetoothLeScanner != null) sBluetoothLeScanner.cleanup(); 1919 synchronized (mProxyServiceStateCallbacks) { 1920 for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){ 1921 try { 1922 if (cb != null) { 1923 cb.onBluetoothServiceDown(); 1924 } else { 1925 Log.d(TAG, "onBluetoothServiceDown: cb is null!!!"); 1926 } 1927 } catch (Exception e) { Log.e(TAG,"",e);} 1928 } 1929 } 1930 } 1931 } 1932 1933 public void onBrEdrDown() { 1934 if (VDBG) Log.i(TAG, "on QBrEdrDown: "); 1935 } 1936 }; 1937 1938 /** 1939 * Enable the Bluetooth Adapter, but don't auto-connect devices 1940 * and don't persist state. Only for use by system applications. 1941 * @hide 1942 */ 1943 public boolean enableNoAutoConnect() { 1944 if (isEnabled() == true){ 1945 if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT is already enabled..!"); 1946 return true; 1947 } 1948 try { 1949 return mManagerService.enableNoAutoConnect(); 1950 } catch (RemoteException e) {Log.e(TAG, "", e);} 1951 return false; 1952 } 1953 1954 /** 1955 * Enable control of the Bluetooth Adapter for a single application. 1956 * 1957 * <p>Some applications need to use Bluetooth for short periods of time to 1958 * transfer data but don't want all the associated implications like 1959 * automatic connection to headsets etc. 1960 * 1961 * <p> Multiple applications can call this. This is reference counted and 1962 * Bluetooth disabled only when no one else is using it. There will be no UI 1963 * shown to the user while bluetooth is being enabled. Any user action will 1964 * override this call. For example, if user wants Bluetooth on and the last 1965 * user of this API wanted to disable Bluetooth, Bluetooth will not be 1966 * turned off. 1967 * 1968 * <p> This API is only meant to be used by internal applications. Third 1969 * party applications but use {@link #enable} and {@link #disable} APIs. 1970 * 1971 * <p> If this API returns true, it means the callback will be called. 1972 * The callback will be called with the current state of Bluetooth. 1973 * If the state is not what was requested, an internal error would be the 1974 * reason. If Bluetooth is already on and if this function is called to turn 1975 * it on, the api will return true and a callback will be called. 1976 * 1977 * <p>Requires {@link android.Manifest.permission#BLUETOOTH} 1978 * 1979 * @param on True for on, false for off. 1980 * @param callback The callback to notify changes to the state. 1981 * @hide 1982 */ 1983 public boolean changeApplicationBluetoothState(boolean on, 1984 BluetoothStateChangeCallback callback) { 1985 if (callback == null) return false; 1986 1987 //TODO(BT) 1988 /* 1989 try { 1990 return mService.changeApplicationBluetoothState(on, new 1991 StateChangeCallbackWrapper(callback), new Binder()); 1992 } catch (RemoteException e) { 1993 Log.e(TAG, "changeBluetoothState", e); 1994 }*/ 1995 return false; 1996 } 1997 1998 /** 1999 * @hide 2000 */ 2001 public interface BluetoothStateChangeCallback { 2002 public void onBluetoothStateChange(boolean on); 2003 } 2004 2005 /** 2006 * @hide 2007 */ 2008 public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub { 2009 private BluetoothStateChangeCallback mCallback; 2010 2011 StateChangeCallbackWrapper(BluetoothStateChangeCallback 2012 callback) { 2013 mCallback = callback; 2014 } 2015 2016 @Override 2017 public void onBluetoothStateChange(boolean on) { 2018 mCallback.onBluetoothStateChange(on); 2019 } 2020 } 2021 2022 private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) { 2023 Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices)); 2024 return Collections.unmodifiableSet(deviceSet); 2025 } 2026 2027 protected void finalize() throws Throwable { 2028 try { 2029 mManagerService.unregisterAdapter(mManagerCallback); 2030 } catch (RemoteException e) { 2031 Log.e(TAG, "", e); 2032 } finally { 2033 super.finalize(); 2034 } 2035 } 2036 2037 2038 /** 2039 * Validate a String Bluetooth address, such as "00:43:A8:23:10:F0" 2040 * <p>Alphabetic characters must be uppercase to be valid. 2041 * 2042 * @param address Bluetooth address as string 2043 * @return true if the address is valid, false otherwise 2044 */ 2045 public static boolean checkBluetoothAddress(String address) { 2046 if (address == null || address.length() != ADDRESS_LENGTH) { 2047 return false; 2048 } 2049 for (int i = 0; i < ADDRESS_LENGTH; i++) { 2050 char c = address.charAt(i); 2051 switch (i % 3) { 2052 case 0: 2053 case 1: 2054 if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { 2055 // hex character, OK 2056 break; 2057 } 2058 return false; 2059 case 2: 2060 if (c == ':') { 2061 break; // OK 2062 } 2063 return false; 2064 } 2065 } 2066 return true; 2067 } 2068 2069 /*package*/ IBluetoothManager getBluetoothManager() { 2070 return mManagerService; 2071 } 2072 2073 final private ArrayList<IBluetoothManagerCallback> mProxyServiceStateCallbacks = new ArrayList<IBluetoothManagerCallback>(); 2074 2075 /*package*/ IBluetooth getBluetoothService(IBluetoothManagerCallback cb) { 2076 synchronized (mProxyServiceStateCallbacks) { 2077 if (cb == null) { 2078 Log.w(TAG, "getBluetoothService() called with no BluetoothManagerCallback"); 2079 } else if (!mProxyServiceStateCallbacks.contains(cb)) { 2080 mProxyServiceStateCallbacks.add(cb); 2081 } 2082 } 2083 return mService; 2084 } 2085 2086 /*package*/ void removeServiceStateCallback(IBluetoothManagerCallback cb) { 2087 synchronized (mProxyServiceStateCallbacks) { 2088 mProxyServiceStateCallbacks.remove(cb); 2089 } 2090 } 2091 2092 /** 2093 * Callback interface used to deliver LE scan results. 2094 * 2095 * @see #startLeScan(LeScanCallback) 2096 * @see #startLeScan(UUID[], LeScanCallback) 2097 */ 2098 public interface LeScanCallback { 2099 /** 2100 * Callback reporting an LE device found during a device scan initiated 2101 * by the {@link BluetoothAdapter#startLeScan} function. 2102 * 2103 * @param device Identifies the remote device 2104 * @param rssi The RSSI value for the remote device as reported by the 2105 * Bluetooth hardware. 0 if no RSSI value is available. 2106 * @param scanRecord The content of the advertisement record offered by 2107 * the remote device. 2108 */ 2109 public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord); 2110 } 2111 2112 /** 2113 * Starts a scan for Bluetooth LE devices. 2114 * 2115 * <p>Results of the scan are reported using the 2116 * {@link LeScanCallback#onLeScan} callback. 2117 * 2118 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. 2119 * 2120 * @param callback the callback LE scan results are delivered 2121 * @return true, if the scan was started successfully 2122 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} 2123 * instead. 2124 */ 2125 @Deprecated 2126 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 2127 public boolean startLeScan(LeScanCallback callback) { 2128 return startLeScan(null, callback); 2129 } 2130 2131 /** 2132 * Starts a scan for Bluetooth LE devices, looking for devices that 2133 * advertise given services. 2134 * 2135 * <p>Devices which advertise all specified services are reported using the 2136 * {@link LeScanCallback#onLeScan} callback. 2137 * 2138 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. 2139 * 2140 * @param serviceUuids Array of services to look for 2141 * @param callback the callback LE scan results are delivered 2142 * @return true, if the scan was started successfully 2143 * @deprecated use {@link BluetoothLeScanner#startScan(List, ScanSettings, ScanCallback)} 2144 * instead. 2145 */ 2146 @Deprecated 2147 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 2148 public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) { 2149 if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids); 2150 if (callback == null) { 2151 if (DBG) Log.e(TAG, "startLeScan: null callback"); 2152 return false; 2153 } 2154 BluetoothLeScanner scanner = getBluetoothLeScanner(); 2155 if (scanner == null) { 2156 if (DBG) Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner"); 2157 return false; 2158 } 2159 2160 synchronized(mLeScanClients) { 2161 if (mLeScanClients.containsKey(callback)) { 2162 if (DBG) Log.e(TAG, "LE Scan has already started"); 2163 return false; 2164 } 2165 2166 try { 2167 IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); 2168 if (iGatt == null) { 2169 // BLE is not supported 2170 return false; 2171 } 2172 2173 ScanCallback scanCallback = new ScanCallback() { 2174 @Override 2175 public void onScanResult(int callbackType, ScanResult result) { 2176 if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) { 2177 // Should not happen. 2178 Log.e(TAG, "LE Scan has already started"); 2179 return; 2180 } 2181 ScanRecord scanRecord = result.getScanRecord(); 2182 if (scanRecord == null) { 2183 return; 2184 } 2185 if (serviceUuids != null) { 2186 List<ParcelUuid> uuids = new ArrayList<ParcelUuid>(); 2187 for (UUID uuid : serviceUuids) { 2188 uuids.add(new ParcelUuid(uuid)); 2189 } 2190 List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids(); 2191 if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) { 2192 if (DBG) Log.d(TAG, "uuids does not match"); 2193 return; 2194 } 2195 } 2196 callback.onLeScan(result.getDevice(), result.getRssi(), 2197 scanRecord.getBytes()); 2198 } 2199 }; 2200 ScanSettings settings = new ScanSettings.Builder() 2201 .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) 2202 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 2203 2204 List<ScanFilter> filters = new ArrayList<ScanFilter>(); 2205 if (serviceUuids != null && serviceUuids.length > 0) { 2206 // Note scan filter does not support matching an UUID array so we put one 2207 // UUID to hardware and match the whole array in callback. 2208 ScanFilter filter = new ScanFilter.Builder().setServiceUuid( 2209 new ParcelUuid(serviceUuids[0])).build(); 2210 filters.add(filter); 2211 } 2212 scanner.startScan(filters, settings, scanCallback); 2213 2214 mLeScanClients.put(callback, scanCallback); 2215 return true; 2216 2217 } catch (RemoteException e) { 2218 Log.e(TAG,"",e); 2219 } 2220 } 2221 return false; 2222 } 2223 2224 /** 2225 * Stops an ongoing Bluetooth LE device scan. 2226 * 2227 * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission. 2228 * 2229 * @param callback used to identify which scan to stop 2230 * must be the same handle used to start the scan 2231 * @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead. 2232 */ 2233 @Deprecated 2234 @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) 2235 public void stopLeScan(LeScanCallback callback) { 2236 if (DBG) Log.d(TAG, "stopLeScan()"); 2237 BluetoothLeScanner scanner = getBluetoothLeScanner(); 2238 if (scanner == null) { 2239 return; 2240 } 2241 synchronized (mLeScanClients) { 2242 ScanCallback scanCallback = mLeScanClients.remove(callback); 2243 if (scanCallback == null) { 2244 if (DBG) Log.d(TAG, "scan not started yet"); 2245 return; 2246 } 2247 scanner.stopScan(scanCallback); 2248 } 2249 } 2250} 2251