aboutsummaryrefslogtreecommitdiff
path: root/framework/java/android/bluetooth/BluetoothDevice.java
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2021-10-06 22:53:28 +0000
committerXin Li <delphij@google.com>2021-10-06 22:53:28 +0000
commit68e41e54ff587aa4d6976b57f91c2c71dda03227 (patch)
tree81737c0faf16ad7c721df5c0e039e641041bec9c /framework/java/android/bluetooth/BluetoothDevice.java
parent7151fef225d7b92b21c938dab2d5c5aac0ae6864 (diff)
parentfaffc6e464445c0378296c2106f9f6b7075d23ec (diff)
Merge Android 12
Bug: 202323961 Merged-In: Iba1443da42161f4a41830081f2e1985b30444cc0 Change-Id: I2bebe60bb7114706a3ba6af35522268cdf031f41
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothDevice.java')
-rw-r--r--framework/java/android/bluetooth/BluetoothDevice.java554
1 files changed, 441 insertions, 113 deletions
diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java
index 1054b4cd49..c71fcc637c 100644
--- a/framework/java/android/bluetooth/BluetoothDevice.java
+++ b/framework/java/android/bluetooth/BluetoothDevice.java
@@ -16,7 +16,6 @@
package android.bluetooth;
-import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -26,7 +25,15 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.PropertyInvalidatedCache;
+import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
+import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
+import android.bluetooth.annotations.RequiresBluetoothScanPermission;
+import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
+import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
+import android.companion.AssociationRequest;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.Attributable;
+import android.content.AttributionSource;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
@@ -65,9 +72,6 @@ import java.util.UUID;
* {@link #createRfcommSocketToServiceRecord(UUID)} over Bluetooth BR/EDR or using
* {@link #createL2capChannel(int)} over Bluetooth LE.
*
- * <p class="note"><strong>Note:</strong>
- * Requires the {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* <div class="special reference">
* <h3>Developer Guides</h3>
* <p>
@@ -80,7 +84,7 @@ import java.util.UUID;
* {@see BluetoothAdapter}
* {@see BluetoothSocket}
*/
-public final class BluetoothDevice implements Parcelable {
+public final class BluetoothDevice implements Parcelable, Attributable {
private static final String TAG = "BluetoothDevice";
private static final boolean DBG = false;
@@ -107,10 +111,12 @@ public final class BluetoothDevice implements Parcelable {
* <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
* #EXTRA_CLASS}. Can contain the extra fields {@link #EXTRA_NAME} and/or
* {@link #EXTRA_RSSI} and/or {@link #EXTRA_IS_COORDINATED_SET_MEMBER} if they are available.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} and
- * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} to receive.
*/
// TODO: Change API to not broadcast RSSI if not available (incoming connection)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothScanPermission
+ @RequiresBluetoothLocationPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_FOUND =
"android.bluetooth.device.action.FOUND";
@@ -119,9 +125,11 @@ public final class BluetoothDevice implements Parcelable {
* Broadcast Action: Bluetooth class of a remote device has changed.
* <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
* #EXTRA_CLASS}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
* {@see BluetoothClass}
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CLASS_CHANGED =
"android.bluetooth.device.action.CLASS_CHANGED";
@@ -132,8 +140,10 @@ public final class BluetoothDevice implements Parcelable {
* <p>Always contains the extra field {@link #EXTRA_DEVICE}.
* <p>ACL connections are managed automatically by the Android Bluetooth
* stack.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACL_CONNECTED =
"android.bluetooth.device.action.ACL_CONNECTED";
@@ -145,8 +155,10 @@ public final class BluetoothDevice implements Parcelable {
* this intent as a hint to immediately terminate higher level connections
* (RFCOMM, L2CAP, or profile connections) to the remote device.
* <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACL_DISCONNECT_REQUESTED =
"android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";
@@ -157,8 +169,10 @@ public final class BluetoothDevice implements Parcelable {
* <p>Always contains the extra field {@link #EXTRA_DEVICE}.
* <p>ACL connections are managed automatically by the Android Bluetooth
* stack.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ACL_DISCONNECTED =
"android.bluetooth.device.action.ACL_DISCONNECTED";
@@ -168,8 +182,10 @@ public final class BluetoothDevice implements Parcelable {
* been retrieved for the first time, or changed since the last retrieval.
* <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
* #EXTRA_NAME}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_NAME_CHANGED =
"android.bluetooth.device.action.NAME_CHANGED";
@@ -178,9 +194,11 @@ public final class BluetoothDevice implements Parcelable {
* Broadcast Action: Indicates the alias of a remote device has been
* changed.
* <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
*/
@SuppressLint("ActionValue")
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_ALIAS_CHANGED =
"android.bluetooth.device.action.ALIAS_CHANGED";
@@ -190,10 +208,12 @@ public final class BluetoothDevice implements Parcelable {
* device. For example, if a device is bonded (paired).
* <p>Always contains the extra fields {@link #EXTRA_DEVICE}, {@link
* #EXTRA_BOND_STATE} and {@link #EXTRA_PREVIOUS_BOND_STATE}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
*/
// Note: When EXTRA_BOND_STATE is BOND_NONE then this will also
// contain a hidden extra field EXTRA_REASON with the result code.
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_BOND_STATE_CHANGED =
"android.bluetooth.device.action.BOND_STATE_CHANGED";
@@ -203,10 +223,12 @@ public final class BluetoothDevice implements Parcelable {
* been retrieved for the first time, or changed since the last retrieval
* <p>Always contains the extra fields {@link #EXTRA_DEVICE} and {@link
* #EXTRA_BATTERY_LEVEL}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
*
* @hide
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_BATTERY_LEVEL_CHANGED =
"android.bluetooth.device.action.BATTERY_LEVEL_CHANGED";
@@ -337,6 +359,26 @@ public final class BluetoothDevice implements Parcelable {
public static final String EXTRA_PAIRING_KEY = "android.bluetooth.device.extra.PAIRING_KEY";
/**
+ * Used as an int extra field in {@link #ACTION_PAIRING_REQUEST}
+ * intents as the value of passkey.
+ * @hide
+ */
+ public static final String EXTRA_PAIRING_INITIATOR =
+ "android.bluetooth.device.extra.PAIRING_INITIATOR";
+
+ /**
+ * Bluetooth pairing initiator, Foreground App
+ * @hide
+ */
+ public static final int EXTRA_PAIRING_INITIATOR_FOREGROUND = 1;
+
+ /**
+ * Bluetooth pairing initiator, Background
+ * @hide
+ */
+ public static final int EXTRA_PAIRING_INITIATOR_BACKGROUND = 2;
+
+ /**
* Bluetooth device type, Unknown
*/
public static final int DEVICE_TYPE_UNKNOWN = 0;
@@ -358,6 +400,8 @@ public final class BluetoothDevice implements Parcelable {
/** @hide */
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final String ACTION_SDP_RECORD =
@@ -630,13 +674,17 @@ public final class BluetoothDevice implements Parcelable {
* device are requested to be fetched using Service Discovery Protocol
* <p> Always contains the extra field {@link #EXTRA_DEVICE}
* <p> Always contains the extra field {@link #EXTRA_UUID}
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} to receive.
*/
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_UUID =
"android.bluetooth.device.action.UUID";
/** @hide */
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_MAS_INSTANCE =
"android.bluetooth.device.action.MAS_INSTANCE";
@@ -645,40 +693,51 @@ public final class BluetoothDevice implements Parcelable {
* Broadcast Action: Indicates a failure to retrieve the name of a remote
* device.
* <p>Always contains the extra field {@link #EXTRA_DEVICE}.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} to receive.
*
* @hide
*/
//TODO: is this actually useful?
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_NAME_FAILED =
"android.bluetooth.device.action.NAME_FAILED";
/**
* Broadcast Action: This intent is used to broadcast PAIRING REQUEST
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} to
- * receive.
*/
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_PAIRING_REQUEST =
"android.bluetooth.device.action.PAIRING_REQUEST";
/** @hide */
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@UnsupportedAppUsage
public static final String ACTION_PAIRING_CANCEL =
"android.bluetooth.device.action.PAIRING_CANCEL";
/** @hide */
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CONNECTION_ACCESS_REQUEST =
"android.bluetooth.device.action.CONNECTION_ACCESS_REQUEST";
/** @hide */
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CONNECTION_ACCESS_REPLY =
"android.bluetooth.device.action.CONNECTION_ACCESS_REPLY";
/** @hide */
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CONNECTION_ACCESS_CANCEL =
"android.bluetooth.device.action.CONNECTION_ACCESS_CANCEL";
@@ -689,6 +748,8 @@ public final class BluetoothDevice implements Parcelable {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@SystemApi
public static final String ACTION_SILENCE_MODE_CHANGED =
@@ -1056,6 +1117,8 @@ public final class BluetoothDevice implements Parcelable {
private final String mAddress;
@AddressType private final int mAddressType;
+ private AttributionSource mAttributionSource;
+
/*package*/
@UnsupportedAppUsage
static IBluetooth getService() {
@@ -1101,6 +1164,7 @@ public final class BluetoothDevice implements Parcelable {
* and is validated in this constructor.
*
* @param address valid Bluetooth MAC address
+ * @param attributionSource attribution for permission-protected calls
* @throws RuntimeException Bluetooth is not available on this platform
* @throws IllegalArgumentException address is invalid
* @hide
@@ -1114,10 +1178,21 @@ public final class BluetoothDevice implements Parcelable {
mAddress = address;
mAddressType = ADDRESS_TYPE_PUBLIC;
+ mAttributionSource = BluetoothManager.resolveAttributionSource(null);
+ }
+
+ /** {@hide} */
+ public void setAttributionSource(@NonNull AttributionSource attributionSource) {
+ mAttributionSource = attributionSource;
+ }
+
+ /** {@hide} */
+ public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
+ setAttributionSource(attributionSource);
}
@Override
- public boolean equals(Object o) {
+ public boolean equals(@Nullable Object o) {
if (o instanceof BluetoothDevice) {
return mAddress.equals(((BluetoothDevice) o).getAddress());
}
@@ -1176,6 +1251,18 @@ public final class BluetoothDevice implements Parcelable {
}
/**
+ * Returns the anonymized hardware address of this BluetoothDevice. The first three octets
+ * will be suppressed for anonymization.
+ * <p> For example, "XX:XX:XX:AA:BB:CC".
+ *
+ * @return Anonymized bluetooth hardware address as string
+ * @hide
+ */
+ public String getAnonymizedAddress() {
+ return "XX:XX:XX" + getAddress().substring(8);
+ }
+
+ /**
* Get the friendly Bluetooth name of the remote device.
*
* <p>The local adapter will automatically retrieve remote names when
@@ -1184,7 +1271,9 @@ public final class BluetoothDevice implements Parcelable {
*
* @return the Bluetooth name, or null if there was a problem.
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public String getName() {
final IBluetooth service = sService;
if (service == null) {
@@ -1192,7 +1281,7 @@ public final class BluetoothDevice implements Parcelable {
return null;
}
try {
- String name = service.getRemoteName(this);
+ String name = service.getRemoteName(this, mAttributionSource);
if (name != null) {
// remove whitespace characters from the name
return name
@@ -1213,7 +1302,9 @@ public final class BluetoothDevice implements Parcelable {
* @return the device type {@link #DEVICE_TYPE_CLASSIC}, {@link #DEVICE_TYPE_LE} {@link
* #DEVICE_TYPE_DUAL}. {@link #DEVICE_TYPE_UNKNOWN} if it's not available
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getType() {
final IBluetooth service = sService;
if (service == null) {
@@ -1221,7 +1312,7 @@ public final class BluetoothDevice implements Parcelable {
return DEVICE_TYPE_UNKNOWN;
}
try {
- return service.getRemoteType(this);
+ return service.getRemoteType(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1229,14 +1320,15 @@ public final class BluetoothDevice implements Parcelable {
}
/**
- * Get the Bluetooth alias of the remote device.
- * <p>Alias is the locally modified name of a remote device.
+ * Get the locally modifiable name (alias) of the remote Bluetooth device.
*
* @return the Bluetooth alias, the friendly device name if no alias, or
* null if there was a problem
*/
@Nullable
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public String getAlias() {
final IBluetooth service = sService;
if (service == null) {
@@ -1244,7 +1336,7 @@ public final class BluetoothDevice implements Parcelable {
return null;
}
try {
- String alias = service.getRemoteAlias(this);
+ String alias = service.getRemoteAliasWithAttribution(this, mAttributionSource);
if (alias == null) {
return getName();
}
@@ -1255,30 +1347,53 @@ public final class BluetoothDevice implements Parcelable {
return null;
}
- /**
- * Set the Bluetooth alias of the remote device.
- * <p>Alias is the locally modified name of a remote device.
- * <p>This methoid overwrites the alias. The changed
- * alias is saved in the local storage so that the change
- * is preserved over power cycle.
- *
- * @return true on success, false on error
- * @hide
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresPermission(Manifest.permission.BLUETOOTH)
- public boolean setAlias(@NonNull String alias) {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
+ BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
+ BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
+ })
+ public @interface SetAliasReturnValues{}
+
+ /**
+ * Sets the locally modifiable name (alias) of the remote Bluetooth device. This method
+ * overwrites the previously stored alias. The new alias is saved in local
+ * storage so that the change is preserved over power cycles.
+ *
+ * <p>This method requires the calling app to be associated with Companion Device Manager (see
+ * {@link android.companion.CompanionDeviceManager#associate(AssociationRequest,
+ * android.companion.CompanionDeviceManager.Callback, Handler)}) and have the
+ * {@link android.Manifest.permission#BLUETOOTH_CONNECT} permission. Alternatively, if the
+ * caller has the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED} permission, they can
+ * bypass the Companion Device Manager association requirement as well as other permission
+ * requirements.
+ *
+ * @param alias is the new locally modifiable name for the remote Bluetooth device which must
+ * be the empty string. If null, we clear the alias.
+ * @return whether the alias was successfully changed
+ * @throws IllegalArgumentException if the alias is the empty string
+ */
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ public @SetAliasReturnValues int setAlias(@Nullable String alias) {
+ if (alias != null && alias.isEmpty()) {
+ throw new IllegalArgumentException("alias cannot be the empty string");
+ }
final IBluetooth service = sService;
if (service == null) {
Log.e(TAG, "BT not enabled. Cannot set Remote Device name");
- return false;
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
}
try {
- return service.setRemoteAlias(this, alias);
+ return service.setRemoteAlias(this, alias, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
+ throw e.rethrowFromSystemServer();
}
- return false;
}
/**
@@ -1290,7 +1405,9 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getBatteryLevel() {
final IBluetooth service = sService;
if (service == null) {
@@ -1298,7 +1415,7 @@ public final class BluetoothDevice implements Parcelable {
return BATTERY_LEVEL_BLUETOOTH_OFF;
}
try {
- return service.getBatteryLevel(this);
+ return service.getBatteryLevel(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1315,7 +1432,9 @@ public final class BluetoothDevice implements Parcelable {
*
* @return false on immediate error, true if bonding will begin
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean createBond() {
return createBond(TRANSPORT_AUTO);
}
@@ -1336,7 +1455,9 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean createBond(int transport) {
return createBondInternal(transport, null, null);
}
@@ -1364,7 +1485,7 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean createBondOutOfBand(int transport, @Nullable OobData remoteP192Data,
@Nullable OobData remoteP256Data) {
if (remoteP192Data == null && remoteP256Data == null) {
@@ -1375,6 +1496,7 @@ public final class BluetoothDevice implements Parcelable {
return createBondInternal(transport, remoteP192Data, remoteP256Data);
}
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
private boolean createBondInternal(int transport, @Nullable OobData remoteP192Data,
@Nullable OobData remoteP256Data) {
final IBluetooth service = sService;
@@ -1387,7 +1509,8 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.createBond(this, transport, remoteP192Data, remoteP256Data);
+ return service.createBond(
+ this, transport, remoteP192Data, remoteP256Data, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1402,7 +1525,9 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isBondingInitiatedLocally() {
final IBluetooth service = sService;
if (service == null) {
@@ -1410,7 +1535,7 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.isBondingInitiatedLocally(this);
+ return service.isBondingInitiatedLocally(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1424,7 +1549,7 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean cancelBondProcess() {
final IBluetooth service = sService;
if (service == null) {
@@ -1435,7 +1560,7 @@ public final class BluetoothDevice implements Parcelable {
Log.i(TAG, "cancelBondProcess() for device " + getAddress()
+ " called by pid: " + Process.myPid()
+ " tid: " + Process.myTid());
- return service.cancelBondProcess(this);
+ return service.cancelBondProcess(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1452,7 +1577,7 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean removeBond() {
final IBluetooth service = sService;
if (service == null) {
@@ -1463,7 +1588,7 @@ public final class BluetoothDevice implements Parcelable {
Log.i(TAG, "removeBond() for device " + getAddress()
+ " called by pid: " + Process.myPid()
+ " tid: " + Process.myTid());
- return service.removeBond(this);
+ return service.removeBond(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1476,9 +1601,10 @@ public final class BluetoothDevice implements Parcelable {
new PropertyInvalidatedCache<BluetoothDevice, Integer>(
8, BLUETOOTH_BONDING_CACHE_PROPERTY) {
@Override
+ @SuppressLint("AndroidFrameworkRequiresPermission")
protected Integer recompute(BluetoothDevice query) {
try {
- return sService.getBondState(query);
+ return sService.getBondState(query, mAttributionSource);
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
@@ -1504,7 +1630,10 @@ public final class BluetoothDevice implements Parcelable {
*
* @return the bond state
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public int getBondState() {
final IBluetooth service = sService;
if (service == null) {
@@ -1524,13 +1653,127 @@ public final class BluetoothDevice implements Parcelable {
}
/**
+ * Checks whether this bluetooth device is associated with CDM and meets the criteria to skip
+ * the bluetooth pairing dialog because it has been already consented by the CDM prompt.
+ *
+ * @return true if we can bond without the dialog, false otherwise
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public boolean canBondWithoutDialog() {
+ final IBluetooth service = sService;
+ if (service == null) {
+ Log.e(TAG, "BT not enabled. Cannot check if we can skip pairing dialog");
+ return false;
+ }
+ try {
+ if (DBG) Log.d(TAG, "canBondWithoutDialog, device: " + this);
+ return service.canBondWithoutDialog(this, mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ return false;
+ }
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ BluetoothStatusCodes.SUCCESS,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+ BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
+ BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
+ BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED
+ })
+ public @interface ConnectionReturnValues{}
+
+ /**
+ * Connects all user enabled and supported bluetooth profiles between the local and remote
+ * device. If no profiles are user enabled (e.g. first connection), we connect all supported
+ * profiles. If the device is not already connected, this will page the device before initiating
+ * profile connections. Connection is asynchronous and you should listen to each profile's
+ * broadcast intent ACTION_CONNECTION_STATE_CHANGED to verify whether connection was successful.
+ * For example, to verify a2dp is connected, you would listen for
+ * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
+ *
+ * @return whether the messages were successfully sent to try to connect all profiles
+ * @throws IllegalArgumentException if the device address is invalid
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
+ public @ConnectionReturnValues int connect() {
+ if (!BluetoothAdapter.checkBluetoothAddress(getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+
+ try {
+ if (sService == null) {
+ Log.e(TAG, "BT not enabled. Cannot connect to remote device.");
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ return sService.connectAllEnabledProfiles(this, mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Disconnects all connected bluetooth profiles between the local and remote device.
+ * Disconnection is asynchronous and you should listen to each profile's broadcast intent
+ * ACTION_CONNECTION_STATE_CHANGED to verify whether disconnection was successful. For example,
+ * to verify a2dp is disconnected, you would listen for
+ * {@link BluetoothA2dp#ACTION_CONNECTION_STATE_CHANGED}
+ *
+ * @return whether the messages were successfully sent to try to disconnect all profiles
+ * @throws IllegalArgumentException if the device address is invalid
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
+ public @ConnectionReturnValues int disconnect() {
+ if (!BluetoothAdapter.checkBluetoothAddress(getAddress())) {
+ throw new IllegalArgumentException("device cannot have an invalid address");
+ }
+
+ try {
+ if (sService == null) {
+ Log.e(TAG, "BT not enabled. Cannot disconnect from remote device.");
+ return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+ }
+ return sService.disconnectAllEnabledProfiles(this, mAttributionSource);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Returns whether there is an open connection to this device.
*
* @return True if there is at least one open connection to this device.
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isConnected() {
final IBluetooth service = sService;
if (service == null) {
@@ -1538,7 +1781,8 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.getConnectionState(this) != CONNECTION_STATE_DISCONNECTED;
+ return service.getConnectionStateWithAttribution(this, mAttributionSource)
+ != CONNECTION_STATE_DISCONNECTED;
} catch (RemoteException e) {
Log.e(TAG, "", e);
return false;
@@ -1553,7 +1797,9 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isEncrypted() {
final IBluetooth service = sService;
if (service == null) {
@@ -1561,7 +1807,8 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.getConnectionState(this) > CONNECTION_STATE_CONNECTED;
+ return service.getConnectionStateWithAttribution(this, mAttributionSource)
+ > CONNECTION_STATE_CONNECTED;
} catch (RemoteException e) {
Log.e(TAG, "", e);
return false;
@@ -1573,7 +1820,9 @@ public final class BluetoothDevice implements Parcelable {
*
* @return Bluetooth class object, or null on error
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothClass getBluetoothClass() {
final IBluetooth service = sService;
if (service == null) {
@@ -1581,7 +1830,7 @@ public final class BluetoothDevice implements Parcelable {
return null;
}
try {
- int classInt = service.getRemoteClass(this);
+ int classInt = service.getRemoteClass(this, mAttributionSource);
if (classInt == BluetoothClass.ERROR) return null;
return new BluetoothClass(classInt);
} catch (RemoteException e) {
@@ -1600,7 +1849,9 @@ public final class BluetoothDevice implements Parcelable {
*
* @return the supported features (UUIDs) of the remote device, or null on error
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public ParcelUuid[] getUuids() {
final IBluetooth service = sService;
if (service == null || !isBluetoothEnabled()) {
@@ -1608,7 +1859,7 @@ public final class BluetoothDevice implements Parcelable {
return null;
}
try {
- return service.getRemoteUuids(this);
+ return service.getRemoteUuids(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1629,7 +1880,9 @@ public final class BluetoothDevice implements Parcelable {
* @return False if the check fails, True if the process of initiating an ACL connection
* to the remote device was started or cached UUIDs will be broadcast.
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean fetchUuidsWithSdp() {
return fetchUuidsWithSdp(TRANSPORT_AUTO);
}
@@ -1654,7 +1907,10 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean fetchUuidsWithSdp(@Transport int transport) {
final IBluetooth service = sService;
if (service == null || !isBluetoothEnabled()) {
@@ -1662,7 +1918,7 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.fetchRemoteUuids(this, transport);
+ return service.fetchRemoteUuidsWithAttribution(this, transport, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1680,8 +1936,7 @@ public final class BluetoothDevice implements Parcelable {
* {@link #EXTRA_SDP_SEARCH_STATUS} different from 0.
* Detailed status error codes can be found by members of the Bluetooth package in
* the AbstractionLayer class.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
- * The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}.
+ * <p>The SDP record data will be stored in the intent as {@link #EXTRA_SDP_RECORD}.
* The object type will match one of the SdpXxxRecord types, depending on the UUID searched
* for.
*
@@ -1690,6 +1945,9 @@ public final class BluetoothDevice implements Parcelable {
* was started.
*/
/** @hide */
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean sdpSearch(ParcelUuid uuid) {
final IBluetooth service = sService;
if (service == null) {
@@ -1697,7 +1955,7 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.sdpSearch(this, uuid);
+ return service.sdpSearch(this, uuid, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1706,10 +1964,12 @@ public final class BluetoothDevice implements Parcelable {
/**
* Set the pin during pairing when the pairing method is {@link #PAIRING_VARIANT_PIN}
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}.
*
* @return true pin has been set false for error
*/
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean setPin(byte[] pin) {
final IBluetooth service = sService;
if (service == null) {
@@ -1717,7 +1977,7 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.setPin(this, true, pin.length, pin);
+ return service.setPin(this, true, pin.length, pin, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1731,7 +1991,9 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean setPin(@NonNull String pin) {
byte[] pinBytes = convertPinToBytes(pin);
if (pinBytes == null) {
@@ -1745,7 +2007,10 @@ public final class BluetoothDevice implements Parcelable {
*
* @return true confirmation has been sent out false for error
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setPairingConfirmation(boolean confirm) {
final IBluetooth service = sService;
if (service == null) {
@@ -1753,7 +2018,7 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.setPairingConfirmation(this, confirm);
+ return service.setPairingConfirmation(this, confirm, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1768,7 +2033,9 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
- @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean cancelPairing() {
final IBluetooth service = sService;
if (service == null) {
@@ -1776,7 +2043,7 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.cancelBondProcess(this);
+ return service.cancelBondProcess(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1800,14 +2067,16 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @AccessPermission int getPhonebookAccessPermission() {
final IBluetooth service = sService;
if (service == null) {
return ACCESS_UNKNOWN;
}
try {
- return service.getPhonebookAccessPermission(this);
+ return service.getPhonebookAccessPermission(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1832,22 +2101,23 @@ public final class BluetoothDevice implements Parcelable {
* If the {@link BluetoothDevice} is not connected with A2DP or HFP, it cannot
* enter silence mode.
*
- * <p> Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
- *
* @param silence true to enter silence mode, false to exit
* @return true on success, false on error.
* @throws IllegalStateException if Bluetooth is not turned ON.
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setSilenceMode(boolean silence) {
final IBluetooth service = sService;
if (service == null) {
throw new IllegalStateException("Bluetooth is not turned ON");
}
try {
- return service.setSilenceMode(this, silence);
+ return service.setSilenceMode(this, silence, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "setSilenceMode fail", e);
return false;
@@ -1857,21 +2127,22 @@ public final class BluetoothDevice implements Parcelable {
/**
* Check whether the {@link BluetoothDevice} is in silence mode
*
- * <p> Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
- *
* @return true on device in silence mode, otherwise false.
* @throws IllegalStateException if Bluetooth is not turned ON.
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean isInSilenceMode() {
final IBluetooth service = sService;
if (service == null) {
throw new IllegalStateException("Bluetooth is not turned ON");
}
try {
- return service.getSilenceMode(this);
+ return service.getSilenceMode(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "isInSilenceMode fail", e);
return false;
@@ -1887,14 +2158,17 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setPhonebookAccessPermission(@AccessPermission int value) {
final IBluetooth service = sService;
if (service == null) {
return false;
}
try {
- return service.setPhonebookAccessPermission(this, value);
+ return service.setPhonebookAccessPermission(this, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1908,14 +2182,16 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @AccessPermission int getMessageAccessPermission() {
final IBluetooth service = sService;
if (service == null) {
return ACCESS_UNKNOWN;
}
try {
- return service.getMessageAccessPermission(this);
+ return service.getMessageAccessPermission(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1932,7 +2208,10 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setMessageAccessPermission(@AccessPermission int value) {
// Validates param value is one of the accepted constants
if (value != ACCESS_ALLOWED && value != ACCESS_REJECTED && value != ACCESS_UNKNOWN) {
@@ -1943,7 +2222,7 @@ public final class BluetoothDevice implements Parcelable {
return false;
}
try {
- return service.setMessageAccessPermission(this, value);
+ return service.setMessageAccessPermission(this, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1957,14 +2236,16 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @AccessPermission int getSimAccessPermission() {
final IBluetooth service = sService;
if (service == null) {
return ACCESS_UNKNOWN;
}
try {
- return service.getSimAccessPermission(this);
+ return service.getSimAccessPermission(this, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -1981,14 +2262,17 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setSimAccessPermission(int value) {
final IBluetooth service = sService;
if (service == null) {
return false;
}
try {
- return service.setSimAccessPermission(this, value);
+ return service.setSimAccessPermission(this, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
@@ -2012,7 +2296,6 @@ public final class BluetoothDevice implements Parcelable {
* <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
* connection.
* <p>Valid RFCOMM channels are in range 1 to 30.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
* @param channel RFCOMM channel to connect to
* @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
@@ -2021,6 +2304,10 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public BluetoothSocket createRfcommSocket(int channel) throws IOException {
if (!isBluetoothEnabled()) {
Log.e(TAG, "Bluetooth is not enabled");
@@ -2047,7 +2334,6 @@ public final class BluetoothDevice implements Parcelable {
* <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
* connection.
* <p>Valid L2CAP PSM channels are in range 1 to 2^16.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
* @param channel L2cap PSM/channel to connect to
* @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
@@ -2055,6 +2341,10 @@ public final class BluetoothDevice implements Parcelable {
* permissions
* @hide
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public BluetoothSocket createL2capSocket(int channel) throws IOException {
return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, true, true, this, channel,
null);
@@ -2068,7 +2358,6 @@ public final class BluetoothDevice implements Parcelable {
* <p>Use {@link BluetoothSocket#connect} to initiate the outgoing
* connection.
* <p>Valid L2CAP PSM channels are in range 1 to 2^16.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
* @param channel L2cap PSM/channel to connect to
* @return a RFCOMM BluetoothServerSocket ready for an outgoing connection
@@ -2076,6 +2365,10 @@ public final class BluetoothDevice implements Parcelable {
* permissions
* @hide
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public BluetoothSocket createInsecureL2capSocket(int channel) throws IOException {
return new BluetoothSocket(BluetoothSocket.TYPE_L2CAP, -1, false, false, this, channel,
null);
@@ -2111,7 +2404,10 @@ public final class BluetoothDevice implements Parcelable {
* @throws IOException on error, for example Bluetooth not available, or insufficient
* permissions
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
if (!isBluetoothEnabled()) {
Log.e(TAG, "Bluetooth is not enabled");
@@ -2149,7 +2445,10 @@ public final class BluetoothDevice implements Parcelable {
* @throws IOException on error, for example Bluetooth not available, or insufficient
* permissions
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
if (!isBluetoothEnabled()) {
Log.e(TAG, "Bluetooth is not enabled");
@@ -2165,7 +2464,6 @@ public final class BluetoothDevice implements Parcelable {
* Call #connect on the returned #BluetoothSocket to begin the connection.
* The remote device will not be authenticated and communication on this
* socket will not be encrypted.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
*
* @param port remote port
* @return An RFCOMM BluetoothSocket
@@ -2175,6 +2473,10 @@ public final class BluetoothDevice implements Parcelable {
*/
@UnsupportedAppUsage(publicAlternatives = "Use "
+ "{@link #createInsecureRfcommSocketToServiceRecord} instead.")
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
if (!isBluetoothEnabled()) {
Log.e(TAG, "Bluetooth is not enabled");
@@ -2187,7 +2489,6 @@ public final class BluetoothDevice implements Parcelable {
/**
* Construct a SCO socket ready to start an outgoing connection.
* Call #connect on the returned #BluetoothSocket to begin the connection.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
*
* @return a SCO BluetoothSocket
* @throws IOException on error, for example Bluetooth not available, or insufficient
@@ -2195,6 +2496,10 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public BluetoothSocket createScoSocket() throws IOException {
if (!isBluetoothEnabled()) {
Log.e(TAG, "Bluetooth is not enabled");
@@ -2242,6 +2547,8 @@ public final class BluetoothDevice implements Parcelable {
* automatically connect as soon as the remote device becomes available (true).
* @throws IllegalArgumentException if callback is null
*/
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback) {
return (connectGatt(context, autoConnect, callback, TRANSPORT_AUTO));
@@ -2262,6 +2569,8 @@ public final class BluetoothDevice implements Parcelable {
* BluetoothDevice#TRANSPORT_LE}
* @throws IllegalArgumentException if callback is null
*/
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport) {
return (connectGatt(context, autoConnect, callback, transport, PHY_LE_1M_MASK));
@@ -2286,6 +2595,8 @@ public final class BluetoothDevice implements Parcelable {
* is set to true.
* @throws NullPointerException if callback is null
*/
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport, int phy) {
return connectGatt(context, autoConnect, callback, transport, phy, null);
@@ -2312,6 +2623,8 @@ public final class BluetoothDevice implements Parcelable {
* an un-specified background thread.
* @throws NullPointerException if callback is null
*/
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport, int phy,
Handler handler) {
@@ -2345,6 +2658,8 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport,
boolean opportunistic, int phy, Handler handler) {
@@ -2362,7 +2677,8 @@ public final class BluetoothDevice implements Parcelable {
// BLE is not supported
return null;
}
- BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy);
+ BluetoothGatt gatt = new BluetoothGatt(
+ iGatt, this, transport, opportunistic, phy, mAttributionSource);
gatt.connect(autoConnect, callback, handler);
return gatt;
} catch (RemoteException e) {
@@ -2389,7 +2705,10 @@ public final class BluetoothDevice implements Parcelable {
* @throws IOException on error, for example Bluetooth not available, or insufficient
* permissions
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public @NonNull BluetoothSocket createL2capChannel(int psm) throws IOException {
if (!isBluetoothEnabled()) {
Log.e(TAG, "createL2capChannel: Bluetooth is not enabled");
@@ -2417,7 +2736,10 @@ public final class BluetoothDevice implements Parcelable {
* @throws IOException on error, for example Bluetooth not available, or insufficient
* permissions
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ @SuppressLint("AndroidFrameworkRequiresPermission")
public @NonNull BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
if (!isBluetoothEnabled()) {
Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled");
@@ -2445,7 +2767,10 @@ public final class BluetoothDevice implements Parcelable {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public boolean setMetadata(@MetadataKey int key, @NonNull byte[] value) {
final IBluetooth service = sService;
if (service == null) {
@@ -2457,7 +2782,7 @@ public final class BluetoothDevice implements Parcelable {
+ ", should not over " + METADATA_MAX_LENGTH);
}
try {
- return service.setMetadata(this, key, value);
+ return service.setMetadata(this, key, value, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "setMetadata fail", e);
return false;
@@ -2473,7 +2798,10 @@ public final class BluetoothDevice implements Parcelable {
*/
@SystemApi
@Nullable
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ })
public byte[] getMetadata(@MetadataKey int key) {
final IBluetooth service = sService;
if (service == null) {
@@ -2481,7 +2809,7 @@ public final class BluetoothDevice implements Parcelable {
return null;
}
try {
- return service.getMetadata(this, key);
+ return service.getMetadata(this, key, mAttributionSource);
} catch (RemoteException e) {
Log.e(TAG, "getMetadata fail", e);
return null;