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