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