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