/core/java/android/bluetooth/BluetoothDevice.java

http://github.com/android/platform_frameworks_base · Java · 2831 lines · 1297 code · 212 blank · 1322 comment · 124 complexity · 570bfa5bbe15ac9ce9465de88dbb882c MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * Copyright (C) 2009 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package android.bluetooth;
  17. import android.annotation.IntDef;
  18. import android.annotation.NonNull;
  19. import android.annotation.Nullable;
  20. import android.annotation.RequiresPermission;
  21. import android.annotation.SdkConstant;
  22. import android.annotation.SdkConstant.SdkConstantType;
  23. import android.annotation.SuppressLint;
  24. import android.annotation.SystemApi;
  25. import android.app.PropertyInvalidatedCache;
  26. import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
  27. import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
  28. import android.bluetooth.annotations.RequiresBluetoothScanPermission;
  29. import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
  30. import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
  31. import android.companion.AssociationRequest;
  32. import android.compat.annotation.UnsupportedAppUsage;
  33. import android.content.Attributable;
  34. import android.content.AttributionSource;
  35. import android.content.Context;
  36. import android.os.Build;
  37. import android.os.Handler;
  38. import android.os.Parcel;
  39. import android.os.ParcelUuid;
  40. import android.os.Parcelable;
  41. import android.os.Process;
  42. import android.os.RemoteException;
  43. import android.util.Log;
  44. import java.io.IOException;
  45. import java.io.UnsupportedEncodingException;
  46. import java.lang.annotation.Retention;
  47. import java.lang.annotation.RetentionPolicy;
  48. import java.util.UUID;
  49. /**
  50. * Represents a remote Bluetooth device. A {@link BluetoothDevice} lets you
  51. * create a connection with the respective device or query information about
  52. * it, such as the name, address, class, and bonding state.
  53. *
  54. * <p>This class is really just a thin wrapper for a Bluetooth hardware
  55. * address. Objects of this class are immutable. Operations on this class
  56. * are performed on the remote Bluetooth hardware address, using the
  57. * {@link BluetoothAdapter} that was used to create this {@link
  58. * BluetoothDevice}.
  59. *
  60. * <p>To get a {@link BluetoothDevice}, use
  61. * {@link BluetoothAdapter#getRemoteDevice(String)
  62. * BluetoothAdapter.getRemoteDevice(String)} to create one representing a device
  63. * of a known MAC address (which you can get through device discovery with
  64. * {@link BluetoothAdapter}) or get one from the set of bonded devices
  65. * returned by {@link BluetoothAdapter#getBondedDevices()
  66. * BluetoothAdapter.getBondedDevices()}. You can then open a
  67. * {@link BluetoothSocket} for communication with the remote device, using
  68. * {@link #createRfcommSocketToServiceRecord(UUID)} over Bluetooth BR/EDR or using
  69. * {@link #createL2capChannel(int)} over Bluetooth LE.
  70. *
  71. * <div class="special reference">
  72. * <h3>Developer Guides</h3>
  73. * <p>
  74. * For more information about using Bluetooth, read the <a href=
  75. * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer
  76. * guide.
  77. * </p>
  78. * </div>
  79. *
  80. * {@see BluetoothAdapter}
  81. * {@see BluetoothSocket}
  82. */
  83. public final class BluetoothDevice implements Parcelable, Attributable {
  84. private static final String TAG = "BluetoothDevice";
  85. private static final boolean DBG = false;
  86. /**
  87. * Connection state bitmask as returned by getConnectionState.
  88. */
  89. private static final int CONNECTION_STATE_DISCONNECTED = 0;
  90. private static final int CONNECTION_STATE_CONNECTED = 1;
  91. private static final int CONNECTION_STATE_ENCRYPTED_BREDR = 2;
  92. private static final int CONNECTION_STATE_ENCRYPTED_LE = 4;
  93. /**
  94. * Sentinel error value for this class. Guaranteed to not equal any other
  95. * integer constant in this class. Provided as a convenience for functions
  96. * that require a sentinel error value, for example:
  97. * <p><code>Intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
  98. * BluetoothDevice.ERROR)</code>
  99. */
  100. public static final int ERROR = Integer.MIN_VALUE;
  101. /**
  102. * Broadcast Action: Remote device discovered.
  103. * <p>Sent when a remote device is found during discovery.
  104. * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
  105. * #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or
  106. * {@link #EXTRA_RSSI} and/or {@link #EXTRA_IS_COORDINATED_SET_MEMBER} if they are available.
  107. */
  108. // TODO: Change API to not broadcast RSSI if not available (incoming connection)
  109. @RequiresLegacyBluetoothPermission
  110. @RequiresBluetoothScanPermission
  111. @RequiresBluetoothLocationPermission
  112. @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
  113. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  114. public static final String ACTION_FOUND =
  115. "android.bluetooth.device.action.FOUND";
  116. /**
  117. * Broadcast Action: Bluetooth class of a remote device has changed.
  118. * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
  119. * #EXTRA_CLASS}.
  120. * {@see BluetoothClass}
  121. */
  122. @RequiresLegacyBluetoothPermission
  123. @RequiresBluetoothConnectPermission
  124. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  125. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  126. public static final String ACTION_CLASS_CHANGED =
  127. "android.bluetooth.device.action.CLASS_CHANGED";
  128. /**
  129. * Broadcast Action: Indicates a low level (ACL) connection has been
  130. * established with a remote device.
  131. * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
  132. * <p>ACL connections are managed automatically by the Android Bluetooth
  133. * stack.
  134. */
  135. @RequiresLegacyBluetoothPermission
  136. @RequiresBluetoothConnectPermission
  137. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  138. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  139. public static final String ACTION_ACL_CONNECTED =
  140. "android.bluetooth.device.action.ACL_CONNECTED";
  141. /**
  142. * Broadcast Action: Indicates that a low level (ACL) disconnection has
  143. * been requested for a remote device, and it will soon be disconnected.
  144. * <p>This is useful for graceful disconnection. Applications should use
  145. * this intent as a hint to immediately terminate higher level connections
  146. * (RFCOMM, L2CAP, or profile connections) to the remote device.
  147. * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
  148. */
  149. @RequiresLegacyBluetoothPermission
  150. @RequiresBluetoothConnectPermission
  151. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  152. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  153. public static final String ACTION_ACL_DISCONNECT_REQUESTED =
  154. "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
  155. /**
  156. * Broadcast Action: Indicates a low level (ACL) disconnection from a
  157. * remote device.
  158. * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
  159. * <p>ACL connections are managed automatically by the Android Bluetooth
  160. * stack.
  161. */
  162. @RequiresLegacyBluetoothPermission
  163. @RequiresBluetoothConnectPermission
  164. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  165. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  166. public static final String ACTION_ACL_DISCONNECTED =
  167. "android.bluetooth.device.action.ACL_DISCONNECTED";
  168. /**
  169. * Broadcast Action: Indicates the friendly name of a remote device has
  170. * been retrieved for the first time, or changed since the last retrieval.
  171. * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
  172. * #EXTRA_NAME}.
  173. */
  174. @RequiresLegacyBluetoothPermission
  175. @RequiresBluetoothConnectPermission
  176. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  177. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  178. public static final String ACTION_NAME_CHANGED =
  179. "android.bluetooth.device.action.NAME_CHANGED";
  180. /**
  181. * Broadcast Action: Indicates the alias of a remote device has been
  182. * changed.
  183. * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
  184. */
  185. @SuppressLint("ActionValue")
  186. @RequiresLegacyBluetoothPermission
  187. @RequiresBluetoothConnectPermission
  188. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  189. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  190. public static final String ACTION_ALIAS_CHANGED =
  191. "android.bluetooth.device.action.ALIAS_CHANGED";
  192. /**
  193. * Broadcast Action: Indicates a change in the bond state of a remote
  194. * device. For example, if a device is bonded (paired).
  195. * <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link
  196. * #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}.
  197. */
  198. // Note: When EXTRA_BOND_STATE is BOND_NONE then this will also
  199. // contain a hidden extra field EXTRA_REASON with the result code.
  200. @RequiresLegacyBluetoothPermission
  201. @RequiresBluetoothConnectPermission
  202. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  203. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  204. public static final String ACTION_BOND_STATE_CHANGED =
  205. "android.bluetooth.device.action.BOND_STATE_CHANGED";
  206. /**
  207. * Broadcast Action: Indicates the battery level of a remote device has
  208. * been retrieved for the first time, or changed since the last retrieval
  209. * <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
  210. * #EXTRA_BATTERY_LEVEL}.
  211. *
  212. * @hide
  213. */
  214. @RequiresLegacyBluetoothPermission
  215. @RequiresBluetoothConnectPermission
  216. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  217. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  218. public static final String ACTION_BATTERY_LEVEL_CHANGED =
  219. "android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";
  220. /**
  221. * Used as an Integer extra field in {@link #ACTION_BATTERY_LEVEL_CHANGED}
  222. * intent. It contains the most recently retrieved battery level information
  223. * ranging from 0% to 100% for a remote device, {@link #BATTERY_LEVEL_UNKNOWN}
  224. * when the valid is unknown or there is an error
  225. *
  226. * @hide
  227. */
  228. public static final String EXTRA_BATTERY_LEVEL =
  229. "android.bluetooth.device.extra.BATTERY_LEVEL";
  230. /**
  231. * Used as the unknown value for {@link #EXTRA_BATTERY_LEVEL} and {@link #getBatteryLevel()}
  232. *
  233. * @hide
  234. */
  235. public static final int BATTERY_LEVEL_UNKNOWN = -1;
  236. /**
  237. * Used as an error value for {@link #getBatteryLevel()} to represent bluetooth is off
  238. *
  239. * @hide
  240. */
  241. public static final int BATTERY_LEVEL_BLUETOOTH_OFF = -100;
  242. /**
  243. * Used as a Parcelable {@link BluetoothDevice} extra field in every intent
  244. * broadcast by this class. It contains the {@link BluetoothDevice} that
  245. * the intent applies to.
  246. */
  247. public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";
  248. /**
  249. * Used as a String extra field in {@link #ACTION_NAME_CHANGED} and {@link
  250. * #ACTION_FOUND} intents. It contains the friendly Bluetooth name.
  251. */
  252. public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";
  253. /**
  254. * Used as an optional short extra field in {@link #ACTION_FOUND} intents.
  255. * Contains the RSSI value of the remote device as reported by the
  256. * Bluetooth hardware.
  257. */
  258. public static final String EXTRA_RSSI = "android.bluetooth.device.extra.RSSI";
  259. /**
  260. * Used as an bool extra field in {@link #ACTION_FOUND} intents.
  261. * It contains the information if device is discovered as member of a coordinated set or not.
  262. * Pairing with device that belongs to a set would trigger pairing with the rest of set members.
  263. * See Bluetooth CSIP specification for more details.
  264. */
  265. public static final String EXTRA_IS_COORDINATED_SET_MEMBER =
  266. "android.bluetooth.extra.IS_COORDINATED_SET_MEMBER";
  267. /**
  268. * Used as a Parcelable {@link BluetoothClass} extra field in {@link
  269. * #ACTION_FOUND} and {@link #ACTION_CLASS_CHANGED} intents.
  270. */
  271. public static final String EXTRA_CLASS = "android.bluetooth.device.extra.CLASS";
  272. /**
  273. * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
  274. * Contains the bond state of the remote device.
  275. * <p>Possible values are:
  276. * {@link #BOND_NONE},
  277. * {@link #BOND_BONDING},
  278. * {@link #BOND_BONDED}.
  279. */
  280. public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";
  281. /**
  282. * Used as an int extra field in {@link #ACTION_BOND_STATE_CHANGED} intents.
  283. * Contains the previous bond state of the remote device.
  284. * <p>Possible values are:
  285. * {@link #BOND_NONE},
  286. * {@link #BOND_BONDING},
  287. * {@link #BOND_BONDED}.
  288. */
  289. public static final String EXTRA_PREVIOUS_BOND_STATE =
  290. "android.bluetooth.device.extra.PREVIOUS_BOND_STATE";
  291. /**
  292. * Indicates the remote device is not bonded (paired).
  293. * <p>There is no shared link key with the remote device, so communication
  294. * (if it is allowed at all) will be unauthenticated and unencrypted.
  295. */
  296. public static final int BOND_NONE = 10;
  297. /**
  298. * Indicates bonding (pairing) is in progress with the remote device.
  299. */
  300. public static final int BOND_BONDING = 11;
  301. /**
  302. * Indicates the remote device is bonded (paired).
  303. * <p>A shared link keys exists locally for the remote device, so
  304. * communication can be authenticated and encrypted.
  305. * <p><i>Being bonded (paired) with a remote device does not necessarily
  306. * mean the device is currently connected. It just means that the pending
  307. * procedure was completed at some earlier time, and the link key is still
  308. * stored locally, ready to use on the next connection.
  309. * </i>
  310. */
  311. public static final int BOND_BONDED = 12;
  312. /**
  313. * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
  314. * intents for unbond reason.
  315. *
  316. * @hide
  317. */
  318. @UnsupportedAppUsage
  319. public static final String EXTRA_REASON = "android.bluetooth.device.extra.REASON";
  320. /**
  321. * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
  322. * intents to indicate pairing method used. Possible values are:
  323. * {@link #PAIRING_VARIANT_PIN},
  324. * {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION},
  325. */
  326. public static final String EXTRA_PAIRING_VARIANT =
  327. "android.bluetooth.device.extra.PAIRING_VARIANT";
  328. /**
  329. * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
  330. * intents as the value of passkey.
  331. */
  332. public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
  333. /**
  334. * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
  335. * intents as the value of passkey.
  336. * @hide
  337. */
  338. public static final String EXTRA_PAIRING_INITIATOR =
  339. "android.bluetooth.device.extra.PAIRING_INITIATOR";
  340. /**
  341. * Bluetooth pairing initiator, Foreground App
  342. * @hide
  343. */
  344. public static final int EXTRA_PAIRING_INITIATOR_FOREGROUND = 1;
  345. /**
  346. * Bluetooth pairing initiator, Background
  347. * @hide
  348. */
  349. public static final int EXTRA_PAIRING_INITIATOR_BACKGROUND = 2;
  350. /**
  351. * Bluetooth device type, Unknown
  352. */
  353. public static final int DEVICE_TYPE_UNKNOWN = 0;
  354. /**
  355. * Bluetooth device type, Classic - BR/EDR devices
  356. */
  357. public static final int DEVICE_TYPE_CLASSIC = 1;
  358. /**
  359. * Bluetooth device type, Low Energy - LE-only
  360. */
  361. public static final int DEVICE_TYPE_LE = 2;
  362. /**
  363. * Bluetooth device type, Dual Mode - BR/EDR/LE
  364. */
  365. public static final int DEVICE_TYPE_DUAL = 3;
  366. /** @hide */
  367. @RequiresBluetoothConnectPermission
  368. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  369. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  370. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  371. public static final String ACTION_SDP_RECORD =
  372. "android.bluetooth.device.action.SDP_RECORD";
  373. /** @hide */
  374. @IntDef(prefix = "METADATA_", value = {
  375. METADATA_MANUFACTURER_NAME,
  376. METADATA_MODEL_NAME,
  377. METADATA_SOFTWARE_VERSION,
  378. METADATA_HARDWARE_VERSION,
  379. METADATA_COMPANION_APP,
  380. METADATA_MAIN_ICON,
  381. METADATA_IS_UNTETHERED_HEADSET,
  382. METADATA_UNTETHERED_LEFT_ICON,
  383. METADATA_UNTETHERED_RIGHT_ICON,
  384. METADATA_UNTETHERED_CASE_ICON,
  385. METADATA_UNTETHERED_LEFT_BATTERY,
  386. METADATA_UNTETHERED_RIGHT_BATTERY,
  387. METADATA_UNTETHERED_CASE_BATTERY,
  388. METADATA_UNTETHERED_LEFT_CHARGING,
  389. METADATA_UNTETHERED_RIGHT_CHARGING,
  390. METADATA_UNTETHERED_CASE_CHARGING,
  391. METADATA_ENHANCED_SETTINGS_UI_URI,
  392. METADATA_DEVICE_TYPE,
  393. METADATA_MAIN_BATTERY,
  394. METADATA_MAIN_CHARGING,
  395. METADATA_MAIN_LOW_BATTERY_THRESHOLD,
  396. METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD,
  397. METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD,
  398. METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD})
  399. @Retention(RetentionPolicy.SOURCE)
  400. public @interface MetadataKey{}
  401. /**
  402. * Maximum length of a metadata entry, this is to avoid exploding Bluetooth
  403. * disk usage
  404. * @hide
  405. */
  406. @SystemApi
  407. public static final int METADATA_MAX_LENGTH = 2048;
  408. /**
  409. * Manufacturer name of this Bluetooth device
  410. * Data type should be {@String} as {@link Byte} array.
  411. * @hide
  412. */
  413. @SystemApi
  414. public static final int METADATA_MANUFACTURER_NAME = 0;
  415. /**
  416. * Model name of this Bluetooth device
  417. * Data type should be {@String} as {@link Byte} array.
  418. * @hide
  419. */
  420. @SystemApi
  421. public static final int METADATA_MODEL_NAME = 1;
  422. /**
  423. * Software version of this Bluetooth device
  424. * Data type should be {@String} as {@link Byte} array.
  425. * @hide
  426. */
  427. @SystemApi
  428. public static final int METADATA_SOFTWARE_VERSION = 2;
  429. /**
  430. * Hardware version of this Bluetooth device
  431. * Data type should be {@String} as {@link Byte} array.
  432. * @hide
  433. */
  434. @SystemApi
  435. public static final int METADATA_HARDWARE_VERSION = 3;
  436. /**
  437. * Package name of the companion app, if any
  438. * Data type should be {@String} as {@link Byte} array.
  439. * @hide
  440. */
  441. @SystemApi
  442. public static final int METADATA_COMPANION_APP = 4;
  443. /**
  444. * URI to the main icon shown on the settings UI
  445. * Data type should be {@link Byte} array.
  446. * @hide
  447. */
  448. @SystemApi
  449. public static final int METADATA_MAIN_ICON = 5;
  450. /**
  451. * Whether this device is an untethered headset with left, right and case
  452. * Data type should be {@String} as {@link Byte} array.
  453. * @hide
  454. */
  455. @SystemApi
  456. public static final int METADATA_IS_UNTETHERED_HEADSET = 6;
  457. /**
  458. * URI to icon of the left headset
  459. * Data type should be {@link Byte} array.
  460. * @hide
  461. */
  462. @SystemApi
  463. public static final int METADATA_UNTETHERED_LEFT_ICON = 7;
  464. /**
  465. * URI to icon of the right headset
  466. * Data type should be {@link Byte} array.
  467. * @hide
  468. */
  469. @SystemApi
  470. public static final int METADATA_UNTETHERED_RIGHT_ICON = 8;
  471. /**
  472. * URI to icon of the headset charging case
  473. * Data type should be {@link Byte} array.
  474. * @hide
  475. */
  476. @SystemApi
  477. public static final int METADATA_UNTETHERED_CASE_ICON = 9;
  478. /**
  479. * Battery level of left headset
  480. * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
  481. * as invalid.
  482. * @hide
  483. */
  484. @SystemApi
  485. public static final int METADATA_UNTETHERED_LEFT_BATTERY = 10;
  486. /**
  487. * Battery level of rigth headset
  488. * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
  489. * as invalid.
  490. * @hide
  491. */
  492. @SystemApi
  493. public static final int METADATA_UNTETHERED_RIGHT_BATTERY = 11;
  494. /**
  495. * Battery level of the headset charging case
  496. * Data type should be {@String} 0-100 as {@link Byte} array, otherwise
  497. * as invalid.
  498. * @hide
  499. */
  500. @SystemApi
  501. public static final int METADATA_UNTETHERED_CASE_BATTERY = 12;
  502. /**
  503. * Whether the left headset is charging
  504. * Data type should be {@String} as {@link Byte} array.
  505. * @hide
  506. */
  507. @SystemApi
  508. public static final int METADATA_UNTETHERED_LEFT_CHARGING = 13;
  509. /**
  510. * Whether the right headset is charging
  511. * Data type should be {@String} as {@link Byte} array.
  512. * @hide
  513. */
  514. @SystemApi
  515. public static final int METADATA_UNTETHERED_RIGHT_CHARGING = 14;
  516. /**
  517. * Whether the headset charging case is charging
  518. * Data type should be {@String} as {@link Byte} array.
  519. * @hide
  520. */
  521. @SystemApi
  522. public static final int METADATA_UNTETHERED_CASE_CHARGING = 15;
  523. /**
  524. * URI to the enhanced settings UI slice
  525. * Data type should be {@String} as {@link Byte} array, null means
  526. * the UI does not exist.
  527. * @hide
  528. */
  529. @SystemApi
  530. public static final int METADATA_ENHANCED_SETTINGS_UI_URI = 16;
  531. /**
  532. * Type of the Bluetooth device, must be within the list of
  533. * BluetoothDevice.DEVICE_TYPE_*
  534. * Data type should be {@String} as {@link Byte} array.
  535. * @hide
  536. */
  537. @SystemApi
  538. public static final int METADATA_DEVICE_TYPE = 17;
  539. /**
  540. * Battery level of the Bluetooth device, use when the Bluetooth device
  541. * does not support HFP battery indicator.
  542. * Data type should be {@String} as {@link Byte} array.
  543. * @hide
  544. */
  545. @SystemApi
  546. public static final int METADATA_MAIN_BATTERY = 18;
  547. /**
  548. * Whether the device is charging.
  549. * Data type should be {@String} as {@link Byte} array.
  550. * @hide
  551. */
  552. @SystemApi
  553. public static final int METADATA_MAIN_CHARGING = 19;
  554. /**
  555. * The battery threshold of the Bluetooth device to show low battery icon.
  556. * Data type should be {@String} as {@link Byte} array.
  557. * @hide
  558. */
  559. @SystemApi
  560. public static final int METADATA_MAIN_LOW_BATTERY_THRESHOLD = 20;
  561. /**
  562. * The battery threshold of the left headset to show low battery icon.
  563. * Data type should be {@String} as {@link Byte} array.
  564. * @hide
  565. */
  566. @SystemApi
  567. public static final int METADATA_UNTETHERED_LEFT_LOW_BATTERY_THRESHOLD = 21;
  568. /**
  569. * The battery threshold of the right headset to show low battery icon.
  570. * Data type should be {@String} as {@link Byte} array.
  571. * @hide
  572. */
  573. @SystemApi
  574. public static final int METADATA_UNTETHERED_RIGHT_LOW_BATTERY_THRESHOLD = 22;
  575. /**
  576. * The battery threshold of the case to show low battery icon.
  577. * Data type should be {@String} as {@link Byte} array.
  578. * @hide
  579. */
  580. @SystemApi
  581. public static final int METADATA_UNTETHERED_CASE_LOW_BATTERY_THRESHOLD = 23;
  582. /**
  583. * Device type which is used in METADATA_DEVICE_TYPE
  584. * Indicates this Bluetooth device is a standard Bluetooth accessory or
  585. * not listed in METADATA_DEVICE_TYPE_*.
  586. * @hide
  587. */
  588. @SystemApi
  589. public static final String DEVICE_TYPE_DEFAULT = "Default";
  590. /**
  591. * Device type which is used in METADATA_DEVICE_TYPE
  592. * Indicates this Bluetooth device is a watch.
  593. * @hide
  594. */
  595. @SystemApi
  596. public static final String DEVICE_TYPE_WATCH = "Watch";
  597. /**
  598. * Device type which is used in METADATA_DEVICE_TYPE
  599. * Indicates this Bluetooth device is an untethered headset.
  600. * @hide
  601. */
  602. @SystemApi
  603. public static final String DEVICE_TYPE_UNTETHERED_HEADSET = "Untethered Headset";
  604. /**
  605. * Broadcast Action: This intent is used to broadcast the {@link UUID}
  606. * wrapped as a {@link android.os.ParcelUuid} of the remote device after it
  607. * has been fetched. This intent is sent only when the UUIDs of the remote
  608. * device are requested to be fetched using Service Discovery Protocol
  609. * <p> Always contains the extra field {@link #EXTRA_DEVICE}
  610. * <p> Always contains the extra field {@link #EXTRA_UUID}
  611. */
  612. @RequiresLegacyBluetoothAdminPermission
  613. @RequiresBluetoothConnectPermission
  614. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  615. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  616. public static final String ACTION_UUID =
  617. "android.bluetooth.device.action.UUID";
  618. /** @hide */
  619. @RequiresBluetoothConnectPermission
  620. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  621. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  622. public static final String ACTION_MAS_INSTANCE =
  623. "android.bluetooth.device.action.MAS_INSTANCE";
  624. /**
  625. * Broadcast Action: Indicates a failure to retrieve the name of a remote
  626. * device.
  627. * <p>Always contains the extra field {@link #EXTRA_DEVICE}.
  628. *
  629. * @hide
  630. */
  631. //TODO: is this actually useful?
  632. @RequiresLegacyBluetoothPermission
  633. @RequiresBluetoothConnectPermission
  634. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  635. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  636. public static final String ACTION_NAME_FAILED =
  637. "android.bluetooth.device.action.NAME_FAILED";
  638. /**
  639. * Broadcast Action: This intent is used to broadcast PAIRING REQUEST
  640. */
  641. @RequiresLegacyBluetoothAdminPermission
  642. @RequiresBluetoothConnectPermission
  643. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  644. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  645. public static final String ACTION_PAIRING_REQUEST =
  646. "android.bluetooth.device.action.PAIRING_REQUEST";
  647. /** @hide */
  648. @RequiresBluetoothConnectPermission
  649. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  650. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  651. @UnsupportedAppUsage
  652. public static final String ACTION_PAIRING_CANCEL =
  653. "android.bluetooth.device.action.PAIRING_CANCEL";
  654. /** @hide */
  655. @RequiresBluetoothConnectPermission
  656. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  657. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  658. public static final String ACTION_CONNECTION_ACCESS_REQUEST =
  659. "android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST";
  660. /** @hide */
  661. @RequiresBluetoothConnectPermission
  662. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  663. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  664. public static final String ACTION_CONNECTION_ACCESS_REPLY =
  665. "android.bluetooth.device.action.CONNECTION_ACCESS_REPLY";
  666. /** @hide */
  667. @RequiresBluetoothConnectPermission
  668. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  669. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  670. public static final String ACTION_CONNECTION_ACCESS_CANCEL =
  671. "android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL";
  672. /**
  673. * Intent to broadcast silence mode changed.
  674. * Alway contains the extra field {@link #EXTRA_DEVICE}
  675. *
  676. * @hide
  677. */
  678. @RequiresBluetoothConnectPermission
  679. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  680. @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
  681. @SystemApi
  682. public static final String ACTION_SILENCE_MODE_CHANGED =
  683. "android.bluetooth.device.action.SILENCE_MODE_CHANGED";
  684. /**
  685. * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intent.
  686. *
  687. * @hide
  688. */
  689. public static final String EXTRA_ACCESS_REQUEST_TYPE =
  690. "android.bluetooth.device.extra.ACCESS_REQUEST_TYPE";
  691. /** @hide */
  692. public static final int REQUEST_TYPE_PROFILE_CONNECTION = 1;
  693. /** @hide */
  694. public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2;
  695. /** @hide */
  696. public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3;
  697. /** @hide */
  698. public static final int REQUEST_TYPE_SIM_ACCESS = 4;
  699. /**
  700. * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
  701. * Contains package name to return reply intent to.
  702. *
  703. * @hide
  704. */
  705. public static final String EXTRA_PACKAGE_NAME = "android.bluetooth.device.extra.PACKAGE_NAME";
  706. /**
  707. * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
  708. * Contains class name to return reply intent to.
  709. *
  710. * @hide
  711. */
  712. public static final String EXTRA_CLASS_NAME = "android.bluetooth.device.extra.CLASS_NAME";
  713. /**
  714. * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intent.
  715. *
  716. * @hide
  717. */
  718. public static final String EXTRA_CONNECTION_ACCESS_RESULT =
  719. "android.bluetooth.device.extra.CONNECTION_ACCESS_RESULT";
  720. /** @hide */
  721. public static final int CONNECTION_ACCESS_YES = 1;
  722. /** @hide */
  723. public static final int CONNECTION_ACCESS_NO = 2;
  724. /**
  725. * Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REPLY} intents,
  726. * Contains boolean to indicate if the allowed response is once-for-all so that
  727. * next request will be granted without asking user again.
  728. *
  729. * @hide
  730. */
  731. public static final String EXTRA_ALWAYS_ALLOWED =
  732. "android.bluetooth.device.extra.ALWAYS_ALLOWED";
  733. /**
  734. * A bond attempt succeeded
  735. *
  736. * @hide
  737. */
  738. public static final int BOND_SUCCESS = 0;
  739. /**
  740. * A bond attempt failed because pins did not match, or remote device did
  741. * not respond to pin request in time
  742. *
  743. * @hide
  744. */
  745. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  746. public static final int UNBOND_REASON_AUTH_FAILED = 1;
  747. /**
  748. * A bond attempt failed because the other side explicitly rejected
  749. * bonding
  750. *
  751. * @hide
  752. */
  753. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  754. public static final int UNBOND_REASON_AUTH_REJECTED = 2;
  755. /**
  756. * A bond attempt failed because we canceled the bonding process
  757. *
  758. * @hide
  759. */
  760. public static final int UNBOND_REASON_AUTH_CANCELED = 3;
  761. /**
  762. * A bond attempt failed because we could not contact the remote device
  763. *
  764. * @hide
  765. */
  766. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  767. public static final int UNBOND_REASON_REMOTE_DEVICE_DOWN = 4;
  768. /**
  769. * A bond attempt failed because a discovery is in progress
  770. *
  771. * @hide
  772. */
  773. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  774. public static final int UNBOND_REASON_DISCOVERY_IN_PROGRESS = 5;
  775. /**
  776. * A bond attempt failed because of authentication timeout
  777. *
  778. * @hide
  779. */
  780. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  781. public static final int UNBOND_REASON_AUTH_TIMEOUT = 6;
  782. /**
  783. * A bond attempt failed because of repeated attempts
  784. *
  785. * @hide
  786. */
  787. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  788. public static final int UNBOND_REASON_REPEATED_ATTEMPTS = 7;
  789. /**
  790. * A bond attempt failed because we received an Authentication Cancel
  791. * by remote end
  792. *
  793. * @hide
  794. */
  795. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  796. public static final int UNBOND_REASON_REMOTE_AUTH_CANCELED = 8;
  797. /**
  798. * An existing bond was explicitly revoked
  799. *
  800. * @hide
  801. */
  802. public static final int UNBOND_REASON_REMOVED = 9;
  803. /**
  804. * The user will be prompted to enter a pin or
  805. * an app will enter a pin for user.
  806. */
  807. public static final int PAIRING_VARIANT_PIN = 0;
  808. /**
  809. * The user will be prompted to enter a passkey
  810. *
  811. * @hide
  812. */
  813. public static final int PAIRING_VARIANT_PASSKEY = 1;
  814. /**
  815. * The user will be prompted to confirm the passkey displayed on the screen or
  816. * an app will confirm the passkey for the user.
  817. */
  818. public static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2;
  819. /**
  820. * The user will be prompted to accept or deny the incoming pairing request
  821. *
  822. * @hide
  823. */
  824. public static final int PAIRING_VARIANT_CONSENT = 3;
  825. /**
  826. * The user will be prompted to enter the passkey displayed on remote device
  827. * This is used for Bluetooth 2.1 pairing.
  828. *
  829. * @hide
  830. */
  831. public static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4;
  832. /**
  833. * The user will be prompted to enter the PIN displayed on remote device.
  834. * This is used for Bluetooth 2.0 pairing.
  835. *
  836. * @hide
  837. */
  838. public static final int PAIRING_VARIANT_DISPLAY_PIN = 5;
  839. /**
  840. * The user will be prompted to accept or deny the OOB pairing request
  841. *
  842. * @hide
  843. */
  844. public static final int PAIRING_VARIANT_OOB_CONSENT = 6;
  845. /**
  846. * The user will be prompted to enter a 16 digit pin or
  847. * an app will enter a 16 digit pin for user.
  848. *
  849. * @hide
  850. */
  851. public static final int PAIRING_VARIANT_PIN_16_DIGITS = 7;
  852. /**
  853. * Used as an extra field in {@link #ACTION_UUID} intents,
  854. * Contains the {@link android.os.ParcelUuid}s of the remote device which
  855. * is a parcelable version of {@link UUID}.
  856. */
  857. public static final String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
  858. /** @hide */
  859. public static final String EXTRA_SDP_RECORD =
  860. "android.bluetooth.device.extra.SDP_RECORD";
  861. /** @hide */
  862. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
  863. public static final String EXTRA_SDP_SEARCH_STATUS =
  864. "android.bluetooth.device.extra.SDP_SEARCH_STATUS";
  865. /** @hide */
  866. @IntDef(prefix = "ACCESS_", value = {ACCESS_UNKNOWN,
  867. ACCESS_ALLOWED, ACCESS_REJECTED})
  868. @Retention(RetentionPolicy.SOURCE)
  869. public @interface AccessPermission{}
  870. /**
  871. * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
  872. * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
  873. *
  874. * @hide
  875. */
  876. @SystemApi
  877. public static final int ACCESS_UNKNOWN = 0;
  878. /**
  879. * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
  880. * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
  881. *
  882. * @hide
  883. */
  884. @SystemApi
  885. public static final int ACCESS_ALLOWED = 1;
  886. /**
  887. * For {@link #getPhonebookAccessPermission}, {@link #setPhonebookAccessPermission},
  888. * {@link #getMessageAccessPermission} and {@link #setMessageAccessPermission}.
  889. *
  890. * @hide
  891. */
  892. @SystemApi
  893. public static final int ACCESS_REJECTED = 2;
  894. /** @hide */
  895. @Retention(RetentionPolicy.SOURCE)
  896. @IntDef(
  897. prefix = { "TRANSPORT_" },
  898. value = {
  899. /** Allow host to automatically select a transport (dual-mode only) */
  900. TRANSPORT_AUTO,
  901. /** Use Classic or BR/EDR transport.*/
  902. TRANSPORT_BREDR,
  903. /** Use Low Energy transport.*/
  904. TRANSPORT_LE,
  905. }
  906. )
  907. public @interface Transport {}
  908. /**
  909. * No preference of physical transport for GATT connections to remote dual-mode devices
  910. */
  911. public static final int TRANSPORT_AUTO = 0;
  912. /**
  913. * Prefer BR/EDR transport for GATT connections to remote dual-mode devices
  914. */
  915. public static final int TRANSPORT_BREDR = 1;
  916. /**
  917. * Prefer LE transport for GATT connections to remote dual-mode devices
  918. */
  919. public static final int TRANSPORT_LE = 2;
  920. /**
  921. * Bluetooth LE 1M PHY. Used to refer to LE 1M Physical Channel for advertising, scanning or
  922. * connection.
  923. */
  924. public static final int PHY_LE_1M = 1;
  925. /**
  926. * Bluetooth LE 2M PHY. Used to refer to LE 2M Physical Channel for advertising, scanning or
  927. * connection.
  928. */
  929. public static final int PHY_LE_2M = 2;
  930. /**
  931. * Bluetooth LE Coded PHY. Used to refer to LE Coded Physical Channel for advertising, scanning
  932. * or connection.
  933. */
  934. public static final int PHY_LE_CODED = 3;
  935. /**
  936. * Bluetooth LE 1M PHY mask. Used to specify LE 1M Physical Channel as one of many available
  937. * options in a bitmask.
  938. */
  939. public static final int PHY_LE_1M_MASK = 1;
  940. /**
  941. * Bluetooth LE 2M PHY mask. Used to specify LE 2M Physical Channel as one of many available
  942. * options in a bitmask.
  943. */
  944. public static final int PHY_LE_2M_MASK = 2;
  945. /**
  946. * Bluetooth LE Coded PHY mask. Used to specify LE Coded Physical Channel as one of many
  947. * available options in a bitmask.
  948. */
  949. public static final int PHY_LE_CODED_MASK = 4;
  950. /**
  951. * No preferred coding when transmitting on the LE Coded PHY.
  952. */
  953. public static final int PHY_OPTION_NO_PREFERRED = 0;
  954. /**
  955. * Prefer the S=2 coding to be used when transmitting on the LE Coded PHY.
  956. */
  957. public static final int PHY_OPTION_S2 = 1;
  958. /**
  959. * Prefer the S=8 coding to be used when transmitting on the LE Coded PHY.
  960. */
  961. public static final int PHY_OPTION_S8 = 2;
  962. /** @hide */
  963. public static final String EXTRA_MAS_INSTANCE =
  964. "android.bluetooth.device.extra.MAS_INSTANCE";
  965. /** @hide */
  966. @Retention(RetentionPolicy.SOURCE)
  967. @IntDef(
  968. prefix = { "ADDRESS_TYPE_" },
  969. value = {
  970. /** Hardware MAC Address */
  971. ADDRESS_TYPE_PUBLIC,
  972. /** Address is either resolvable, non-resolvable or static.*/
  973. ADDRESS_TYPE_RANDOM,
  974. }
  975. )
  976. public @interface AddressType {}
  977. /** Hardware MAC Address of the device */
  978. public static final int ADDRESS_TYPE_PUBLIC = 0;
  979. /** Address is either resolvable, non-resolvable or static. */
  980. public static final int ADDRESS_TYPE_RANDOM = 1;
  981. private static final String NULL_MAC_ADDRESS = "00:00:00:00:00:00";
  982. /**
  983. * Lazy initialization. Guaranteed final after first object constructed, or
  984. * getService() called.
  985. * TODO: Unify implementation of sService amongst BluetoothFoo API's
  986. */
  987. private static volatile IBluetooth sService;
  988. private final String mAddress;
  989. @AddressType private final int mAddressType;
  990. private AttributionSource mAttributionSource;
  991. /*package*/
  992. @UnsupportedAppUsage
  993. static IBluetooth getService() {
  994. synchronized (BluetoothDevice.class) {
  995. if (sService == null) {
  996. BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
  997. sService = adapter.getBluetoothService(sStateChangeCallback);
  998. }
  999. }
  1000. return sService;
  1001. }
  1002. static IBluetoothManagerCallback sStateChangeCallback = new IBluetoothManagerCallback.Stub() {
  1003. public void onBluetoothServiceUp(IBluetooth bluetoothService)
  1004. throws RemoteException {
  1005. synchronized (BluetoothDevice.class) {
  1006. if (sService == null) {
  1007. sService = bluetoothService;
  1008. }
  1009. }
  1010. }
  1011. public void onBluetoothServiceDown()
  1012. throws RemoteException {
  1013. synchronized (BluetoothDevice.class) {
  1014. sService = null;
  1015. }
  1016. }
  1017. public void onBrEdrDown() {
  1018. if (DBG) Log.d(TAG, "onBrEdrDown: reached BLE ON state");
  1019. }
  1020. public void onOobData(@Transport int transport, OobData oobData) {
  1021. if (DBG) Log.d(TAG, "onOobData: got data");
  1022. }
  1023. };
  1024. /**
  1025. * Create a new BluetoothDevice
  1026. * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB",
  1027. * and is validated in this constructor.
  1028. *
  1029. * @param address valid Bluetooth MAC address
  1030. * @param attributionSource attribution for permission-protected calls
  1031. * @throws RuntimeException Bluetooth is not available on this platform
  1032. * @throws IllegalArgumentException address is invalid
  1033. * @hide
  1034. */
  1035. @UnsupportedAppUsage
  1036. /*package*/ BluetoothDevice(String address) {
  1037. getService(); // ensures sService is initialized
  1038. if (!BluetoothAdapter.checkBluetoothAddress(address)) {
  1039. throw new IllegalArgumentException(address + " is not a valid Bluetooth address");
  1040. }
  1041. mAddress = address;
  1042. mAddressType = ADDRESS_TYPE_PUBLIC;
  1043. mAttributionSource = BluetoothManager.resolveAttributionSource(null);
  1044. }
  1045. /** {@hide} */
  1046. public void setAttributionSource(@NonNull AttributionSource attributionSource) {
  1047. mAttributionSource = attributionSource;
  1048. }
  1049. /** {@hide} */
  1050. public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
  1051. setAttributionSource(attributionSource);
  1052. }
  1053. @Override
  1054. public boolean equals(@Nullable Object o) {
  1055. if (o instanceof BluetoothDevice) {
  1056. return mAddress.equals(((BluetoothDevice) o).getAddress());
  1057. }
  1058. return false;
  1059. }
  1060. @Override
  1061. public int hashCode() {
  1062. return mAddress.hashCode();
  1063. }
  1064. /**
  1065. * Returns a string representation of this BluetoothDevice.
  1066. * <p>Currently this is the Bluetooth hardware address, for example
  1067. * "00:11:22:AA:BB:CC". However, you should always use {@link #getAddress}
  1068. * if you explicitly require the Bluetooth hardware address in case the
  1069. * {@link #toString} representation changes in the future.
  1070. *
  1071. * @return string representation of this BluetoothDevice
  1072. */
  1073. @Override
  1074. public String toString() {
  1075. return mAddress;
  1076. }
  1077. @Override
  1078. public int describeContents() {
  1079. return 0;
  1080. }
  1081. public static final @android.annotation.NonNull Parcelable.Creator<BluetoothDevice> CREATOR =
  1082. new Parcelable.Creator<BluetoothDevice>() {
  1083. public BluetoothDevice createFromParcel(Parcel in) {
  1084. return new BluetoothDevice(in.readString());
  1085. }
  1086. public BluetoothDevice[] newArray(int size) {
  1087. return new BluetoothDevice[size];
  1088. }
  1089. };
  1090. @Override
  1091. public void writeToParcel(Parcel out, int flags) {
  1092. out.writeString(mAddress);
  1093. }
  1094. /**
  1095. * Returns the hardware address of this BluetoothDevice.
  1096. * <p> For example, "00:11:22:AA:BB:CC".
  1097. *
  1098. * @return Bluetooth hardware address as string
  1099. */
  1100. public String getAddress() {
  1101. if (DBG) Log.d(TAG, "mAddress: " + mAddress);
  1102. return mAddress;
  1103. }
  1104. /**
  1105. * Returns the anonymized hardware address of this BluetoothDevice. The first three octets
  1106. * will be suppressed for anonymization.
  1107. * <p> For example, "XX:XX:XX:AA:BB:CC".
  1108. *
  1109. * @return Anonymized bluetooth hardware address as string
  1110. * @hide
  1111. */
  1112. public String getAnonymizedAddress() {
  1113. return "XX:XX:XX" + getAddress().substring(8);
  1114. }
  1115. /**
  1116. * Get the friendly Bluetooth name of the remote device.
  1117. *
  1118. * <p>The local adapter will automatically retrieve remote names when
  1119. * performing a device scan, and will cache them. This method just returns
  1120. * the name for this device from the cache.
  1121. *
  1122. * @return the Bluetooth name, or null if there was a problem.
  1123. */
  1124. @RequiresLegacyBluetoothPermission
  1125. @RequiresBluetoothConnectPermission
  1126. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  1127. public String getName() {
  1128. final IBluetooth service = sService;
  1129. if (service == null) {
  1130. Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
  1131. return null;
  1132. }
  1133. try {
  1134. String name = service.getRemoteName(this, mAttributionSource);
  1135. if (name != null) {
  1136. // remove whitespace characters from the name
  1137. return name
  1138. .replace('\t', ' ')
  1139. .replace('\n', ' ')
  1140. .replace('\r', ' ');
  1141. }
  1142. return null;
  1143. } catch (RemoteException e) {
  1144. Log.e(TAG, "", e);
  1145. }
  1146. return null;
  1147. }
  1148. /**
  1149. * Get the Bluetooth device type of the remote device.
  1150. *
  1151. * @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} {@link
  1152. * #DEVICE_TYPE_DUAL}. {@link #DEVICE_TYPE_UNKNOWN} if it's not available
  1153. */
  1154. @RequiresLegacyBluetoothPermission
  1155. @RequiresBluetoothConnectPermission
  1156. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  1157. public int getType() {
  1158. final IBluetooth service = sService;
  1159. if (service == null) {
  1160. Log.e(TAG, "BT not enabled. Cannot get Remote Device type");
  1161. return DEVICE_TYPE_UNKNOWN;
  1162. }
  1163. try {
  1164. return service.getRemoteType(this, mAttributionSource);
  1165. } catch (RemoteException e) {
  1166. Log.e(TAG, "", e);
  1167. }
  1168. return DEVICE_TYPE_UNKNOWN;
  1169. }
  1170. /**
  1171. * Get the locally modifiable name (alias) of the remote Bluetooth device.
  1172. *
  1173. * @return the Bluetooth alias, the friendly device name if no alias, or
  1174. * null if there was a problem
  1175. */
  1176. @Nullable
  1177. @RequiresLegacyBluetoothPermission
  1178. @RequiresBluetoothConnectPermission
  1179. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  1180. public String getAlias() {
  1181. final IBluetooth service = sService;
  1182. if (service == null) {
  1183. Log.e(TAG, "BT not enabled. Cannot get Remote Device Alias");
  1184. return null;
  1185. }
  1186. try {
  1187. String alias = service.getRemoteAliasWithAttribution(this, mAttributionSource);
  1188. if (alias == null) {
  1189. return getName();
  1190. }
  1191. return alias
  1192. .replace('\t', ' ')
  1193. .replace('\n', ' ')
  1194. .replace('\r', ' ');
  1195. } catch (RemoteException e) {
  1196. Log.e(TAG, "", e);
  1197. }
  1198. return null;
  1199. }
  1200. /** @hide */
  1201. @Retention(RetentionPolicy.SOURCE)
  1202. @IntDef(value = {
  1203. BluetoothStatusCodes.SUCCESS,
  1204. BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
  1205. BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
  1206. BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
  1207. BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
  1208. })
  1209. public @interface SetAliasReturnValues{}
  1210. /**
  1211. * Sets the locally modifiable name (alias) of the remote Bluetooth device. This method
  1212. * overwrites the previously stored alias. The new alias is saved in local
  1213. * storage so that the change is preserved over power cycles.
  1214. *
  1215. * <p>This method requires the calling app to be associated with Companion Device Manager (see
  1216. * {@link android.companion.CompanionDeviceManager#associate(AssociationRequest,
  1217. * android.companion.CompanionDeviceManager.Callback, Handler)}) and have the
  1218. * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. Alternatively, if the
  1219. * caller has the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission, they can
  1220. * bypass the Companion Device Manager association requirement as well as other permission
  1221. * requirements.
  1222. *
  1223. * @param alias is the new locally modifiable name for the remote Bluetooth device which must
  1224. * be the empty string. If null, we clear the alias.
  1225. * @return whether the alias was successfully changed
  1226. * @throws IllegalArgumentException if the alias is the empty string
  1227. */
  1228. @RequiresLegacyBluetoothPermission
  1229. @RequiresBluetoothConnectPermission
  1230. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  1231. public @SetAliasReturnValues int setAlias(@Nullable String alias) {
  1232. if (alias != null && alias.isEmpty()) {
  1233. throw new IllegalArgumentException("alias cannot be the empty string");
  1234. }
  1235. final IBluetooth service = sService;
  1236. if (service == null) {
  1237. Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
  1238. return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
  1239. }
  1240. try {
  1241. return service.setRemoteAlias(this, alias, mAttributionSource);
  1242. } catch (RemoteException e) {
  1243. Log.e(TAG, "", e);
  1244. throw e.rethrowFromSystemServer();
  1245. }
  1246. }
  1247. /**
  1248. * Get the most recent identified battery level of this Bluetooth device
  1249. *
  1250. * @return Battery level in percents from 0 to 100, {@link #BATTERY_LEVEL_BLUETOOTH_OFF} if
  1251. * Bluetooth is disabled or {@link #BATTERY_LEVEL_UNKNOWN} if device is disconnected, or does
  1252. * not have any battery reporting service, or return value is invalid
  1253. * @hide
  1254. */
  1255. @UnsupportedAppUsage
  1256. @RequiresLegacyBluetoothPermission
  1257. @RequiresBluetoothConnectPermission
  1258. @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
  1259. public int getBatteryLevel() {
  1260. final IBluetooth service = sService;
  1261. if (service == null) {
  1262. Log.e(TAG, "Bluetooth disabled. Cannot get remote device battery level");
  1263. return BATTERY_LEVEL_BLUETOOTH_OFF;
  1264. }
  1265. try {
  1266. return service.getBatter