summaryrefslogtreecommitdiff
path: root/framework/java/android/bluetooth/BluetoothHeadset.java
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2021-04-02 08:06:09 -0600
committerJeff Sharkey <jsharkey@android.com>2021-04-14 21:13:24 -0600
commit8f80e4a05b3f1b227f40de5ec0e9a6297154ffc0 (patch)
tree03263d64510c4477b5cc75eeda52a0c9b547fe21 /framework/java/android/bluetooth/BluetoothHeadset.java
parenta95b9490ca30736c3b508e102f8d92bf9aea4ad3 (diff)
Update Bluetooth API annotations.
Recent work has introduced a new "Nearby devices" runtime permission which protects all existing Bluetooth APIs; we've done this by defining a <split-permission> to convert the old BLUETOOTH and BLUETOOTH_ADMIN permissions into one of three new permissions: * BLUETOOTH_ADVERTISE: Required to be able to advertise to nearby Bluetooth devices. * BLUETOOTH_CONNECT: Allows applications to connect to paired bluetooth devices. * BLUETOOTH_SCAN: Required to be able to discover and pair nearby Bluetooth devices. At its core, this change begins updating the Bluetooth APIs to have correct @RequiresPermission indicating which permission is actually enforced internally. To ensure alignment across Binder, the newly added "RequiresPermissionChecker" Error Prone checker was used to discover any inconsistencies, ensuring correctness from server-side enforcement up through to the public APIs. In addition, since developers will continue building apps for both modern and legacy platforms, this change introduces new auto-doc annotations which will emit helpful consistent documentation describing the behavior of older devices that are still using the old permission model. Bug: 183626724 Test: ./build/soong/soong_ui.bash --make-mode Bluetooth RUN_ERROR_PRONE=true Change-Id: I02aa127e8e07f239561f4f2a3bbdfc6fccb82f7f
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothHeadset.java')
-rw-r--r--framework/java/android/bluetooth/BluetoothHeadset.java149
1 files changed, 106 insertions, 43 deletions
diff --git a/framework/java/android/bluetooth/BluetoothHeadset.java b/framework/java/android/bluetooth/BluetoothHeadset.java
index 632572dea3..84e8c5134e 100644
--- a/framework/java/android/bluetooth/BluetoothHeadset.java
+++ b/framework/java/android/bluetooth/BluetoothHeadset.java
@@ -22,6 +22,9 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
+import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
+import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -70,10 +73,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
* <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
* {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
* {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
- * receive.
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.headset.profile.action.CONNECTION_STATE_CHANGED";
@@ -90,10 +93,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
* </ul>
* <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
* {@link #STATE_AUDIO_CONNECTED}, {@link #STATE_AUDIO_DISCONNECTED},
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission
- * to receive.
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_AUDIO_STATE_CHANGED =
"android.bluetooth.headset.profile.action.AUDIO_STATE_CHANGED";
@@ -107,11 +110,11 @@ public final class BluetoothHeadset implements BluetoothProfile {
* be null if no device is active. </li>
* </ul>
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
- * receive.
- *
* @hide
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@UnsupportedAppUsage(trackingBug = 171933273)
public static final String ACTION_ACTIVE_DEVICE_CHANGED =
@@ -147,9 +150,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
* <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE = AT_CMD_TYPE_SET </li>
* <li> EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS = foo, 3 </li>
* </ul>
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission
- * to receive.
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_VENDOR_SPECIFIC_HEADSET_EVENT =
"android.bluetooth.headset.action.VENDOR_SPECIFIC_HEADSET_EVENT";
@@ -299,10 +303,12 @@ public final class BluetoothHeadset implements BluetoothProfile {
* are given an assigned number. Below shows the assigned number of Indicator added so far
* - Enhanced Safety - 1, Valid Values: 0 - Disabled, 1 - Enabled
* - Battery Level - 2, Valid Values: 0~100 - Remaining level of Battery
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to receive.
*
* @hide
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public static final String ACTION_HF_INDICATORS_VALUE_CHANGED =
"android.bluetooth.headset.action.HF_INDICATORS_VALUE_CHANGED";
@@ -432,15 +438,17 @@ public final class BluetoothHeadset implements BluetoothProfile {
* the state. Users can get the connection state of the profile
* from this intent.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
- *
* @param device Remote Bluetooth Device
* @return false on immediate error, true otherwise
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothHeadset service = mService;
@@ -474,15 +482,14 @@ public final class BluetoothHeadset implements BluetoothProfile {
* {@link #STATE_DISCONNECTING} can be used to distinguish between the
* two scenarios.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
- *
* @param device Remote Bluetooth Device
* @return false on immediate error, true otherwise
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothHeadset service = mService;
@@ -502,6 +509,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHeadset service = mService;
@@ -521,6 +529,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothHeadset service = mService;
@@ -540,6 +549,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
final IBluetoothHeadset service = mService;
@@ -571,7 +581,12 @@ public final class BluetoothHeadset implements BluetoothProfile {
*/
@Deprecated
@SystemApi
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
final IBluetoothHeadset service = mService;
@@ -605,7 +620,11 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@SystemApi
- @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
@ConnectionPolicy int connectionPolicy) {
if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
@@ -638,7 +657,9 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
final IBluetoothHeadset service = mService;
@@ -688,7 +709,9 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @param device Bluetooth device
* @return true if echo cancellation and/or noise reduction is supported, false otherwise
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isNoiseReductionSupported(@NonNull BluetoothDevice device) {
if (DBG) log("isNoiseReductionSupported()");
final IBluetoothHeadset service = mService;
@@ -709,7 +732,9 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @param device Bluetooth device
* @return true if voice recognition is supported, false otherwise
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isVoiceRecognitionSupported(@NonNull BluetoothDevice device) {
if (DBG) log("isVoiceRecognitionSupported()");
final IBluetoothHeadset service = mService;
@@ -738,13 +763,17 @@ public final class BluetoothHeadset implements BluetoothProfile {
* audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
* in case of failure to establish the audio connection.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param device Bluetooth headset
* @return false if there is no headset connected, or the connected headset doesn't support
* voice recognition, or voice recognition is already started, or audio channel is occupied,
* or on error, true otherwise
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
public boolean startVoiceRecognition(BluetoothDevice device) {
if (DBG) log("startVoiceRecognition()");
final IBluetoothHeadset service = mService;
@@ -767,12 +796,13 @@ public final class BluetoothHeadset implements BluetoothProfile {
* If this function returns true, this intent will be broadcasted with
* {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_DISCONNECTED}.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param device Bluetooth headset
* @return false if there is no headset connected, or voice recognition has not started,
* or voice recognition has ended on this headset, or on error, true otherwise
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean stopVoiceRecognition(BluetoothDevice device) {
if (DBG) log("stopVoiceRecognition()");
final IBluetoothHeadset service = mService;
@@ -790,11 +820,12 @@ public final class BluetoothHeadset implements BluetoothProfile {
/**
* Check if Bluetooth SCO audio is connected.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param device Bluetooth headset
* @return true if SCO is connected, false otherwise or on error
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isAudioConnected(BluetoothDevice device) {
if (VDBG) log("isAudioConnected()");
final IBluetoothHeadset service = mService;
@@ -827,6 +858,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getAudioState(BluetoothDevice device) {
if (VDBG) log("getAudioState");
final IBluetoothHeadset service = mService;
@@ -853,6 +885,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise.
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void setAudioRouteAllowed(boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
final IBluetoothHeadset service = mService;
@@ -874,6 +907,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
*
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean getAudioRouteAllowed() {
if (VDBG) log("getAudioRouteAllowed");
final IBluetoothHeadset service = mService;
@@ -897,6 +931,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* False to use SCO audio in normal manner
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void setForceScoAudio(boolean forced) {
if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
final IBluetoothHeadset service = mService;
@@ -915,12 +950,13 @@ public final class BluetoothHeadset implements BluetoothProfile {
/**
* Check if at least one headset's SCO audio is connected or connecting
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return true if at least one device's SCO audio is connected or connecting, false otherwise
* or on error
* @hide
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isAudioOn() {
if (VDBG) log("isAudioOn()");
final IBluetoothHeadset service = mService;
@@ -955,6 +991,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean connectAudio() {
final IBluetoothHeadset service = mService;
if (service != null && isEnabled()) {
@@ -982,6 +1019,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnectAudio() {
final IBluetoothHeadset service = mService;
if (service != null && isEnabled()) {
@@ -1018,7 +1056,12 @@ public final class BluetoothHeadset implements BluetoothProfile {
* - binder is dead or Bluetooth is disabled or other error
* @hide
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
@UnsupportedAppUsage
public boolean startScoUsingVirtualVoiceCall() {
if (DBG) log("startScoUsingVirtualVoiceCall()");
@@ -1048,7 +1091,12 @@ public final class BluetoothHeadset implements BluetoothProfile {
* - binder is dead or Bluetooth is disabled or other error
* @hide
*/
- @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
@UnsupportedAppUsage
public boolean stopScoUsingVirtualVoiceCall() {
if (DBG) log("stopScoUsingVirtualVoiceCall()");
@@ -1075,6 +1123,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
public void phoneStateChanged(int numActive, int numHeld, int callState, String number,
int type, String name) {
final IBluetoothHeadset service = mService;
@@ -1095,6 +1147,10 @@ public final class BluetoothHeadset implements BluetoothProfile {
*
* @hide
*/
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
String number, int type) {
final IBluetoothHeadset service = mService;
@@ -1119,8 +1175,6 @@ public final class BluetoothHeadset implements BluetoothProfile {
*
* <p>Currently only {@link #VENDOR_RESULT_CODE_COMMAND_ANDROID} is allowed as {@code command}.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param device Bluetooth headset.
* @param command A vendor-specific command.
* @param arg The argument that will be attached to the command.
@@ -1128,6 +1182,9 @@ public final class BluetoothHeadset implements BluetoothProfile {
* vendor-specific unsolicited result code, or on error. {@code true} otherwise.
* @throws IllegalArgumentException if {@code command} is {@code null}.
*/
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean sendVendorSpecificResultCode(BluetoothDevice device, String command,
String arg) {
if (DBG) {
@@ -1164,15 +1221,17 @@ public final class BluetoothHeadset implements BluetoothProfile {
* {@link #ACTION_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
* with the active device.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
- * permission.
- *
* @param device Remote Bluetooth Device, could be null if phone call audio should not be
* streamed to a headset
* @return false on immediate error, true otherwise
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.BLUETOOTH_CONNECT,
+ android.Manifest.permission.MODIFY_PHONE_STATE,
+ })
@UnsupportedAppUsage(trackingBug = 171933273)
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) {
@@ -1201,7 +1260,9 @@ public final class BluetoothHeadset implements BluetoothProfile {
*/
@UnsupportedAppUsage(trackingBug = 171933273)
@Nullable
- @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothDevice getActiveDevice() {
if (VDBG) {
Log.d(TAG, "getActiveDevice");
@@ -1227,7 +1288,9 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @return true if in-band ringing is enabled, false if in-band ringing is disabled
* @hide
*/
- @RequiresPermission(android.Manifest.permission.BLUETOOTH)
+ @RequiresLegacyBluetoothPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isInbandRingingEnabled() {
if (DBG) {
log("isInbandRingingEnabled()");