diff --git a/Android.bp b/Android.bp
index ca014bc7b11c1..da52c2320048e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -408,6 +408,7 @@ filegroup {
"core/java/android/annotation/MainThread.java",
"core/java/android/annotation/NonNull.java",
"core/java/android/annotation/Nullable.java",
+ "core/java/android/annotation/RequiresNoPermission.java",
"core/java/android/annotation/RequiresPermission.java",
"core/java/android/annotation/SdkConstant.java",
"core/java/android/annotation/StringDef.java",
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 1d290def0bf24..c8a8d36a1b202 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -70,6 +70,7 @@ filegroup {
"android/annotation/Nullable.java",
"android/annotation/PluralsRes.java",
"android/annotation/RawRes.java",
+ "android/annotation/RequiresNoPermission.java",
"android/annotation/RequiresPermission.java",
"android/annotation/SdkConstant.java",
"android/annotation/Size.java",
diff --git a/core/java/android/annotation/RequiresNoPermission.java b/core/java/android/annotation/RequiresNoPermission.java
new file mode 100644
index 0000000000000..6ff4d6e34957e
--- /dev/null
+++ b/core/java/android/annotation/RequiresNoPermission.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that the annotated element requires no permissions.
+ *
+ * @hide
+ */
+@Retention(CLASS)
+@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER})
+public @interface RequiresNoPermission {
+}
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index a268e168ae744..0d21e09293b3c 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -20,8 +20,10 @@ import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SdkConstant.SdkConstantType;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
@@ -512,6 +514,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -534,6 +537,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -624,6 +628,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @return true if device supports absolute volume
* @hide
*/
+ @RequiresNoPermission
public boolean isAvrcpAbsoluteVolumeSupported() {
if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
try {
@@ -690,6 +695,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean shouldSendVolumeKeys(BluetoothDevice device) {
if (isEnabled() && isValidDevice(device)) {
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index d81316e357d32..6aba483b15158 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -282,6 +282,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -304,6 +305,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index df2c512ebf6e6..052a7733c220c 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -21,6 +21,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -716,6 +717,7 @@ public final class BluetoothAdapter {
* Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
* implementation.
*/
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private static final IBluetoothMetadataListener sBluetoothMetadataListener =
new IBluetoothMetadataListener.Stub() {
@Override
@@ -747,6 +749,7 @@ public final class BluetoothAdapter {
* @return the default local adapter, or null if Bluetooth is not supported on this hardware
* platform
*/
+ @RequiresNoPermission
public static synchronized BluetoothAdapter getDefaultAdapter() {
if (sAdapter == null) {
IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
@@ -792,6 +795,7 @@ public final class BluetoothAdapter {
* @param address valid Bluetooth MAC address
* @throws IllegalArgumentException if address is invalid
*/
+ @RequiresNoPermission
public BluetoothDevice getRemoteDevice(String address) {
return new BluetoothDevice(address);
}
@@ -807,6 +811,7 @@ public final class BluetoothAdapter {
* @param address Bluetooth MAC address (6 bytes)
* @throws IllegalArgumentException if address is invalid
*/
+ @RequiresNoPermission
public BluetoothDevice getRemoteDevice(byte[] address) {
if (address == null || address.length != 6) {
throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
@@ -824,6 +829,7 @@ public final class BluetoothAdapter {
* Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
* on this device before calling this method.
*/
+ @RequiresNoPermission
public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
if (!getLeAccess()) {
return null;
@@ -846,6 +852,7 @@ public final class BluetoothAdapter {
*
* @hide
*/
+ @RequiresNoPermission
public PeriodicAdvertisingManager getPeriodicAdvertisingManager() {
if (!getLeAccess()) {
return null;
@@ -866,6 +873,7 @@ public final class BluetoothAdapter {
/**
* Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
*/
+ @RequiresNoPermission
public BluetoothLeScanner getBluetoothLeScanner() {
if (!getLeAccess()) {
return null;
@@ -887,6 +895,7 @@ public final class BluetoothAdapter {
* @return true if the local adapter is turned on
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public boolean isEnabled() {
return getState() == BluetoothAdapter.STATE_ON;
}
@@ -900,6 +909,7 @@ public final class BluetoothAdapter {
* @hide
*/
@SystemApi
+ @RequiresNoPermission
public boolean isLeEnabled() {
final int state = getLeState();
if (DBG) {
@@ -937,6 +947,7 @@ public final class BluetoothAdapter {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disableBLE() {
if (!isBleScanAlwaysAvailable()) {
@@ -983,6 +994,7 @@ public final class BluetoothAdapter {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean enableBLE() {
if (!isBleScanAlwaysAvailable()) {
@@ -1015,6 +1027,7 @@ public final class BluetoothAdapter {
};
/** @hide */
+ @RequiresNoPermission
public void disableBluetoothGetStateCache() {
mBluetoothGetStateCache.disableLocal();
}
@@ -1059,6 +1072,7 @@ public final class BluetoothAdapter {
* @return current state of Bluetooth adapter
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
@AdapterState
public int getState() {
int state = getStateInternal();
@@ -1095,6 +1109,7 @@ public final class BluetoothAdapter {
* @hide
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
@AdapterState
@UnsupportedAppUsage(publicAlternatives = "Use {@link #getState()} instead to determine "
+ "whether you can use BLE & BT classic.")
@@ -1649,6 +1664,7 @@ public final class BluetoothAdapter {
/** @hide */
@UnsupportedAppUsage
+ @RequiresBluetoothScanPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
public int getDiscoverableTimeout() {
if (getState() != STATE_ON) {
@@ -1669,6 +1685,7 @@ public final class BluetoothAdapter {
/** @hide */
@UnsupportedAppUsage
+ @RequiresBluetoothScanPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
public void setDiscoverableTimeout(int timeout) {
if (getState() != STATE_ON) {
@@ -1714,6 +1731,7 @@ public final class BluetoothAdapter {
* Set the context for this BluetoothAdapter (only called from BluetoothManager)
* @hide
*/
+ @RequiresNoPermission
public void setContext(Context context) {
mContext = context;
}
@@ -1872,6 +1890,7 @@ public final class BluetoothAdapter {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -1916,6 +1935,7 @@ public final class BluetoothAdapter {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -1964,6 +1984,7 @@ public final class BluetoothAdapter {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -1996,6 +2017,7 @@ public final class BluetoothAdapter {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -2021,6 +2043,7 @@ public final class BluetoothAdapter {
* @return true if Multiple Advertisement feature is supported
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public boolean isMultipleAdvertisementSupported() {
if (getState() != STATE_ON) {
return false;
@@ -2049,6 +2072,7 @@ public final class BluetoothAdapter {
* @hide
*/
@SystemApi
+ @RequiresNoPermission
public boolean isBleScanAlwaysAvailable() {
try {
return mManagerService.isBleScanAlwaysAvailable();
@@ -2082,6 +2106,7 @@ public final class BluetoothAdapter {
};
/** @hide */
+ @RequiresNoPermission
public void disableIsOffloadedFilteringSupportedCache() {
mBluetoothFilteringCache.disableLocal();
}
@@ -2097,6 +2122,7 @@ public final class BluetoothAdapter {
* @return true if chipset supports on-chip filtering
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public boolean isOffloadedFilteringSupported() {
if (!getLeAccess()) {
return false;
@@ -2110,6 +2136,7 @@ public final class BluetoothAdapter {
* @return true if chipset supports on-chip scan batching
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public boolean isOffloadedScanBatchingSupported() {
if (!getLeAccess()) {
return false;
@@ -2133,6 +2160,7 @@ public final class BluetoothAdapter {
* @return true if chipset supports LE 2M PHY feature
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public boolean isLe2MPhySupported() {
if (!getLeAccess()) {
return false;
@@ -2156,6 +2184,7 @@ public final class BluetoothAdapter {
* @return true if chipset supports LE Coded PHY feature
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public boolean isLeCodedPhySupported() {
if (!getLeAccess()) {
return false;
@@ -2179,6 +2208,7 @@ public final class BluetoothAdapter {
* @return true if chipset supports LE Extended Advertising feature
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public boolean isLeExtendedAdvertisingSupported() {
if (!getLeAccess()) {
return false;
@@ -2202,6 +2232,7 @@ public final class BluetoothAdapter {
* @return true if chipset supports LE Periodic Advertising feature
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public boolean isLePeriodicAdvertisingSupported() {
if (!getLeAccess()) {
return false;
@@ -2226,6 +2257,7 @@ public final class BluetoothAdapter {
* @return the maximum LE advertising data length.
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public int getLeMaximumAdvertisingDataLength() {
if (!getLeAccess()) {
return 0;
@@ -2248,6 +2280,7 @@ public final class BluetoothAdapter {
*
* @return true if phone supports Hearing Aid Profile
*/
+ @RequiresNoPermission
private boolean isHearingAidProfileSupported() {
try {
return mManagerService.isHearingAidProfileSupported();
@@ -2286,6 +2319,7 @@ public final class BluetoothAdapter {
* @return true if there are hw entries available for matching beacons
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isHardwareTrackingFiltersAvailable() {
if (!getLeAccess()) {
@@ -2432,6 +2466,7 @@ public final class BluetoothAdapter {
* BluetoothProfile}.
* @hide
*/
+ @RequiresNoPermission
public @NonNull List getSupportedProfiles() {
final ArrayList supportedProfiles = new ArrayList();
@@ -2479,6 +2514,7 @@ public final class BluetoothAdapter {
};
/** @hide */
+ @RequiresNoPermission
public void disableGetAdapterConnectionStateCache() {
mBluetoothGetAdapterConnectionStateCache.disableLocal();
}
@@ -2503,6 +2539,7 @@ public final class BluetoothAdapter {
*/
@UnsupportedAppUsage
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public int getConnectionState() {
if (getState() != STATE_ON) {
return BluetoothAdapter.STATE_DISCONNECTED;
@@ -2553,6 +2590,7 @@ public final class BluetoothAdapter {
};
/** @hide */
+ @RequiresNoPermission
public void disableGetProfileConnectionStateCache() {
mGetProfileConnectionStateCache.disableLocal();
}
@@ -2753,6 +2791,7 @@ public final class BluetoothAdapter {
return createNewRfcommSocketAndRecord(name, uuid, false, true);
}
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
private BluetoothServerSocket createNewRfcommSocketAndRecord(String name, UUID uuid,
boolean auth, boolean encrypt) throws IOException {
@@ -2779,6 +2818,7 @@ public final class BluetoothAdapter {
* permissions.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
BluetoothServerSocket socket =
@@ -2811,6 +2851,7 @@ public final class BluetoothAdapter {
* permissions.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothServerSocket listenUsingL2capOn(int port, boolean mitm, boolean min16DigitPin)
throws IOException {
@@ -2844,6 +2885,7 @@ public final class BluetoothAdapter {
* permissions.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothServerSocket listenUsingL2capOn(int port) throws IOException {
return listenUsingL2capOn(port, false, false);
@@ -2861,6 +2903,7 @@ public final class BluetoothAdapter {
* permissions.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothServerSocket listenUsingInsecureL2capOn(int port) throws IOException {
Log.d(TAG, "listenUsingInsecureL2capOn: port=" + port);
@@ -2916,6 +2959,10 @@ public final class BluetoothAdapter {
* BluetoothProfile#HEARING_AID} or {@link BluetoothProfile#GATT_SERVER}.
* @return true on success, false on error
*/
+ @SuppressLint({
+ "AndroidFrameworkRequiresPermission",
+ "AndroidFrameworkBluetoothPermission"
+ })
public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
int profile) {
if (context == null || listener == null) {
@@ -2985,7 +3032,10 @@ public final class BluetoothAdapter {
* @param profile
* @param proxy Profile proxy object
*/
- @SuppressLint("AndroidFrameworkRequiresPermission")
+ @SuppressLint({
+ "AndroidFrameworkRequiresPermission",
+ "AndroidFrameworkBluetoothPermission"
+ })
public void closeProfileProxy(int profile, BluetoothProfile proxy) {
if (proxy == null) {
return;
@@ -3058,6 +3108,7 @@ public final class BluetoothAdapter {
}
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final IBluetoothManagerCallback mManagerCallback =
new IBluetoothManagerCallback.Stub() {
@SuppressLint("AndroidFrameworkRequiresPermission")
@@ -3380,7 +3431,6 @@ public final class BluetoothAdapter {
/**
* @hide
*/
- @SuppressLint("AndroidFrameworkRequiresPermission")
public class StateChangeCallbackWrapper extends IBluetoothStateChangeCallback.Stub {
private BluetoothStateChangeCallback mCallback;
@@ -3631,6 +3681,7 @@ public final class BluetoothAdapter {
return false;
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
@@ -3961,6 +4012,7 @@ public final class BluetoothAdapter {
@Nullable byte[] value);
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final IBluetoothConnectionCallback mConnectionCallback =
new IBluetoothConnectionCallback.Stub() {
@Override
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 942f8432639cc..9d3eed8f6fa19 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,15 +16,12 @@
package android.bluetooth;
-import android.compat.annotation.UnsupportedAppUsage;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
-import android.annotation.RequiresPermission;
-import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
-import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
-import android.bluetooth.annotations.RequiresBluetoothScanPermission;
+import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Handler;
import android.os.ParcelUuid;
@@ -158,6 +155,7 @@ public final class BluetoothGatt implements BluetoothProfile {
/**
* Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation.
*/
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final IBluetoothGattCallback mBluetoothGattCallback =
new IBluetoothGattCallback.Stub() {
/**
@@ -747,6 +745,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* Application should call this method as early as possible after it is done with
* this GATT client.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void close() {
if (DBG) Log.d(TAG, "close()");
@@ -881,6 +880,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* Unregister the current application and callbacks.
*/
@UnsupportedAppUsage
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
private void unregisterApp() {
if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
@@ -973,6 +973,7 @@ public final class BluetoothGatt implements BluetoothProfile {
*
* @return true, if the connection attempt was initiated successfully
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean connect() {
try {
@@ -1003,6 +1004,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or
* {@link BluetoothDevice#PHY_OPTION_S8}
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void setPreferredPhy(int txPhy, int rxPhy, int phyOptions) {
try {
@@ -1017,6 +1019,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* Read the current transmitter PHY and receiver PHY of the connection. The values are returned
* in {@link BluetoothGattCallback#onPhyRead}
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void readPhy() {
try {
@@ -1031,6 +1034,7 @@ public final class BluetoothGatt implements BluetoothProfile {
*
* @return remote bluetooth device
*/
+ @RequiresNoPermission
public BluetoothDevice getDevice() {
return mDevice;
}
@@ -1101,6 +1105,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* not yet been performed.
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public List getServices() {
List result =
new ArrayList();
@@ -1129,6 +1134,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* the remote device.
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public BluetoothGattService getService(UUID uuid) {
for (BluetoothGattService service : mServices) {
if (service.getDevice().equals(mDevice) && service.getUuid().equals(uuid)) {
@@ -1444,6 +1450,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* @deprecated Use {@link #abortReliableWrite()}
*/
@Deprecated
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void abortReliableWrite(BluetoothDevice mDevice) {
abortReliableWrite();
@@ -1496,6 +1503,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean refresh() {
if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
@@ -1579,6 +1587,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* or {@link BluetoothGatt#CONNECTION_PRIORITY_LOW_POWER}.
* @throws IllegalArgumentException If the parameters are outside of their specified range.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean requestConnectionPriority(int connectionPriority) {
if (connectionPriority < CONNECTION_PRIORITY_BALANCED
@@ -1607,6 +1616,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* @return true, if the request is send to the Bluetooth stack.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean requestLeConnectionUpdate(int minConnectionInterval, int maxConnectionInterval,
int slaveLatency, int supervisionTimeout,
@@ -1641,6 +1651,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* @throws UnsupportedOperationException
*/
@Override
+ @RequiresNoPermission
public int getConnectionState(BluetoothDevice device) {
throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
}
@@ -1652,6 +1663,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* @throws UnsupportedOperationException
*/
@Override
+ @RequiresNoPermission
public List getConnectedDevices() {
throw new UnsupportedOperationException(
"Use BluetoothManager#getConnectedDevices instead.");
@@ -1665,6 +1677,7 @@ public final class BluetoothGatt implements BluetoothProfile {
* @throws UnsupportedOperationException
*/
@Override
+ @RequiresNoPermission
public List getDevicesMatchingConnectionStates(int[] states) {
throw new UnsupportedOperationException(
"Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index fdb801850e8e6..865f476e78695 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -16,7 +16,9 @@
package android.bluetooth;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.os.ParcelUuid;
@@ -58,6 +60,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
/**
* Bluetooth GATT interface callbacks
*/
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final IBluetoothGattServerCallback mBluetoothGattServerCallback =
new IBluetoothGattServerCallback.Stub() {
/**
@@ -428,6 +431,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
* Application should call this method as early as possible after it is done with
* this GATT server.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void close() {
if (DBG) Log.d(TAG, "close()");
@@ -510,6 +514,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
/**
* Unregister the current application and callbacks.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
private void unregisterCallback() {
if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf);
@@ -618,6 +623,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
* of {@link BluetoothDevice#PHY_OPTION_NO_PREFERRED}, {@link BluetoothDevice#PHY_OPTION_S2} or
* {@link BluetoothDevice#PHY_OPTION_S8}
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void setPreferredPhy(BluetoothDevice device, int txPhy, int rxPhy, int phyOptions) {
try {
@@ -634,6 +640,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
*
* @param device The remote device to send this response to
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void readPhy(BluetoothDevice device) {
try {
@@ -814,6 +821,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
* @return List of services. Returns an empty list if no services have been added yet.
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public List getServices() {
return mServices;
}
@@ -830,6 +838,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
* this device.
*/
@RequiresLegacyBluetoothPermission
+ @RequiresNoPermission
public BluetoothGattService getService(UUID uuid) {
for (BluetoothGattService service : mServices) {
if (service.getUuid().equals(uuid)) {
@@ -848,6 +857,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
* @throws UnsupportedOperationException
*/
@Override
+ @RequiresNoPermission
public int getConnectionState(BluetoothDevice device) {
throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
}
@@ -859,6 +869,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
* @throws UnsupportedOperationException
*/
@Override
+ @RequiresNoPermission
public List getConnectedDevices() {
throw new UnsupportedOperationException(
"Use BluetoothManager#getConnectedDevices instead.");
@@ -872,6 +883,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
* @throws UnsupportedOperationException
*/
@Override
+ @RequiresNoPermission
public List getDevicesMatchingConnectionStates(int[] states) {
throw new UnsupportedOperationException(
"Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 84e8c5134e7b0..a1ece7fc825d3 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SdkConstant.SdkConstantType;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
@@ -339,6 +340,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
private volatile IBluetoothHeadset mService;
private BluetoothAdapter mAdapter;
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
@@ -509,6 +511,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
@@ -529,6 +532,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
@@ -549,6 +553,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
@@ -620,6 +625,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -858,6 +864,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getAudioState(BluetoothDevice device) {
if (VDBG) log("getAudioState");
@@ -885,6 +892,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @param allowed {@code true} if the profile can reroute audio, {@code false} otherwise.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void setAudioRouteAllowed(boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
@@ -907,6 +915,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean getAudioRouteAllowed() {
if (VDBG) log("getAudioRouteAllowed");
@@ -931,6 +940,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* False to use SCO audio in normal manner
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void setForceScoAudio(boolean forced) {
if (VDBG) log("setForceScoAudio " + String.valueOf(forced));
@@ -991,6 +1001,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean connectAudio() {
final IBluetoothHeadset service = mService;
@@ -1019,6 +1030,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnectAudio() {
final IBluetoothHeadset service = mService;
@@ -1123,6 +1135,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.MODIFY_PHONE_STATE,
@@ -1147,6 +1160,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.MODIFY_PHONE_STATE,
@@ -1320,6 +1334,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
com.android.internal.R.bool.config_bluetooth_hfp_inband_ringing_support);
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final IBluetoothProfileServiceConnection mConnection =
new IBluetoothProfileServiceConnection.Stub() {
@Override
@@ -1356,6 +1371,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
Log.d(TAG, msg);
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 092130d0ce913..5816500d2c37d 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -16,7 +16,6 @@
package android.bluetooth;
-import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
@@ -449,6 +448,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
@@ -476,6 +476,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -499,6 +500,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return list of connected devices; empty list if nothing is connected.
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
@@ -524,6 +526,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* list if nothing matches the states
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
@@ -548,6 +551,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return the state of connection of the device
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
@@ -576,6 +580,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
@@ -594,6 +599,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return true if connectionPolicy is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
@ConnectionPolicy int connectionPolicy) {
@@ -675,6 +681,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. This method invocation will fail silently when feature
* is not supported.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean startVoiceRecognition(BluetoothDevice device) {
if (DBG) log("startVoiceRecognition()");
@@ -700,6 +707,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return true if command has been issued successfully; false
* otherwise.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean sendVendorAtCommand(BluetoothDevice device, int vendorId,
String atCommand) {
@@ -728,6 +736,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* #EXTRA_AG_FEATURE_VOICE_RECOGNITION}. This method invocation will fail silently when feature
* is not supported.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean stopVoiceRecognition(BluetoothDevice device) {
if (DBG) log("stopVoiceRecognition()");
@@ -750,6 +759,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @param device remote device
* @return list of calls; empty list if none call exists
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public List getCurrentCalls(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
@@ -772,6 +782,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @param device remote device
* @return bundle of AG indicators; null if device is not in CONNECTED state
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public Bundle getCurrentAgEvents(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
@@ -798,6 +809,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean acceptCall(BluetoothDevice device, int flag) {
if (DBG) log("acceptCall()");
@@ -821,6 +833,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return true if command has been issued successfully; false
* otherwise; upon completion HFP sends {@link #ACTION_CALL_CHANGED} intent.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean holdCall(BluetoothDevice device) {
if (DBG) log("holdCall()");
@@ -849,6 +862,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* supported.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean rejectCall(BluetoothDevice device) {
if (DBG) log("rejectCall()");
@@ -881,6 +895,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* #EXTRA_AG_FEATURE_ECC}. This method invocation will fail silently when feature is not
* supported.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
if (DBG) log("terminateCall()");
@@ -911,6 +926,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* #EXTRA_AG_FEATURE_ECC}. This method invocation will fail silently when feature is not
* supported.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean enterPrivateMode(BluetoothDevice device, int index) {
if (DBG) log("enterPrivateMode()");
@@ -940,6 +956,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* #EXTRA_AG_FEATURE_MERGE_AND_DETACH}. This method invocation will fail silently when feature
* is not supported.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean explicitCallTransfer(BluetoothDevice device) {
if (DBG) log("explicitCallTransfer()");
@@ -965,6 +982,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* successfully; {@link null} otherwise; upon completion HFP sends {@link
* #ACTION_CALL_CHANGED} intent in case of success; {@link #ACTION_RESULT} is sent otherwise;
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
if (DBG) log("dial()");
@@ -991,6 +1009,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return true if command has been issued successfully; false
* otherwise; upon completion HFP sends {@link #ACTION_RESULT} intent;
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean sendDTMF(BluetoothDevice device, byte code) {
if (DBG) log("sendDTMF()");
@@ -1113,6 +1132,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return true if command has been issued successfully; false
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean connectAudio(BluetoothDevice device) {
final IBluetoothHeadsetClient service =
@@ -1139,6 +1159,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return true if command has been issued successfully; false
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnectAudio(BluetoothDevice device) {
final IBluetoothHeadsetClient service =
@@ -1162,6 +1183,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @param device remote device
* @return bundle of AG features; null if no service or AG not connected
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public Bundle getCurrentAgFeatures(BluetoothDevice device) {
final IBluetoothHeadsetClient service =
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 8ceeff53b1300..1fd779a17dbd7 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SdkConstant.SdkConstantType;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
@@ -170,6 +171,7 @@ public final class BluetoothHearingAid implements BluetoothProfile {
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -231,6 +233,7 @@ public final class BluetoothHearingAid implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @NonNull List getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
@@ -251,6 +254,7 @@ public final class BluetoothHearingAid implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @NonNull List getDevicesMatchingConnectionStates(
@NonNull int[] states) {
@@ -272,6 +276,7 @@ public final class BluetoothHearingAid implements BluetoothProfile {
* {@inheritDoc}
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @BluetoothProfile.BtProfileState int getConnectionState(
@NonNull BluetoothDevice device) {
@@ -368,6 +373,7 @@ public final class BluetoothHearingAid implements BluetoothProfile {
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -390,6 +396,7 @@ public final class BluetoothHearingAid implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index c214d2b85ac5b..6565ec0566bf7 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -20,6 +20,7 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
import android.annotation.SdkConstant.SdkConstantType;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
@@ -439,6 +440,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
/** {@inheritDoc} */
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getConnectedDevices() {
final IBluetoothHidDevice service = getService();
@@ -457,6 +459,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
/** {@inheritDoc} */
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
final IBluetoothHidDevice service = getService();
@@ -475,6 +478,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
/** {@inheritDoc} */
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(BluetoothDevice device) {
final IBluetoothHidDevice service = getService();
@@ -514,6 +518,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
* object is required.
* @return true if the command is successfully sent; otherwise false.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean registerApp(
BluetoothHidDeviceAppSdpSettings sdp,
@@ -560,6 +565,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
*
* @return true if the command is successfully sent; otherwise false.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean unregisterApp() {
boolean result = false;
@@ -586,6 +592,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
* @param data Report data, not including Report Id.
* @return true if the command is successfully sent; otherwise false.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
@@ -613,6 +620,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
* @param data Report data, not including Report Id.
* @return true if the command is successfully sent; otherwise false.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
boolean result = false;
@@ -638,6 +646,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
* @param error Error to be sent for SET_REPORT via HANDSHAKE.
* @return true if the command is successfully sent; otherwise false.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean reportError(BluetoothDevice device, byte error) {
boolean result = false;
@@ -662,6 +671,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
* @return the current user name, or empty string if cannot get the name
* {@hide}
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public String getUserAppName() {
final IBluetoothHidDevice service = getService();
@@ -687,6 +697,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
*
* @return true if the command is successfully sent; otherwise false.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean connect(BluetoothDevice device) {
boolean result = false;
@@ -712,6 +723,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
*
* @return true if the command is successfully sent; otherwise false.
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(BluetoothDevice device) {
boolean result = false;
@@ -748,6 +760,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 70e3809cb5909..bef4472b4a28d 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -331,6 +331,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
@SystemApi
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public @NonNull List getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
@@ -353,6 +354,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
* @hide
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
@@ -376,6 +378,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
@SystemApi
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(@NonNull BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
diff --git a/core/java/android/bluetooth/BluetoothInputStream.java b/core/java/android/bluetooth/BluetoothInputStream.java
index 8eb79b248d645..95f9229f0446a 100644
--- a/core/java/android/bluetooth/BluetoothInputStream.java
+++ b/core/java/android/bluetooth/BluetoothInputStream.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.annotation.SuppressLint;
+
import java.io.IOException;
import java.io.InputStream;
@@ -26,6 +28,7 @@ import java.io.InputStream;
*
* @hide
*/
+@SuppressLint("AndroidFrameworkBluetoothPermission")
/*package*/ final class BluetoothInputStream extends InputStream {
private BluetoothSocket mSocket;
diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java
index 4f095f6c70014..c12b1f77fb9e6 100644
--- a/core/java/android/bluetooth/BluetoothLeAudio.java
+++ b/core/java/android/bluetooth/BluetoothLeAudio.java
@@ -155,6 +155,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean connect(@Nullable BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
@@ -194,6 +195,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(@Nullable BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -214,6 +216,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
* {@inheritDoc}
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @NonNull List getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
@@ -234,6 +237,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
* {@inheritDoc}
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @NonNull List getDevicesMatchingConnectionStates(
@NonNull int[] states) {
@@ -294,6 +298,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
* @return false on immediate error, true otherwise
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
@@ -370,6 +375,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
* @return true if connectionPolicy is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -406,6 +412,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
* @return connection policy of the device
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
if (VDBG) log("getConnectionPolicy(" + device + ")");
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index a1e1b63050832..2374f1cdc5287 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -18,7 +18,9 @@ package android.bluetooth;
import android.Manifest;
import android.annotation.RequiresFeature;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemService;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
@@ -93,6 +95,7 @@ public final class BluetoothManager {
*
* @return the BLUETOOTH Adapter
*/
+ @RequiresNoPermission
public BluetoothAdapter getAdapter() {
return mAdapter;
}
@@ -218,6 +221,7 @@ public final class BluetoothManager {
* @param callback GATT server callback handler that will receive asynchronous callbacks.
* @return BluetoothGattServer instance
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGattServer openGattServer(Context context,
BluetoothGattServerCallback callback) {
@@ -238,6 +242,7 @@ public final class BluetoothManager {
* @return BluetoothGattServer instance
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGattServer openGattServer(Context context,
BluetoothGattServerCallback callback, boolean eatt_support) {
@@ -259,6 +264,7 @@ public final class BluetoothManager {
* @return BluetoothGattServer instance
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGattServer openGattServer(Context context,
BluetoothGattServerCallback callback, int transport) {
@@ -281,6 +287,7 @@ public final class BluetoothManager {
* @return BluetoothGattServer instance
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothGattServer openGattServer(Context context,
BluetoothGattServerCallback callback, int transport, boolean eatt_support) {
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index 3e7b75aa1f628..998fde02832d9 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -18,9 +18,11 @@ package android.bluetooth;
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
+import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Binder;
@@ -126,6 +128,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getState() {
if (VDBG) log("getState()");
@@ -151,6 +154,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
@@ -175,6 +179,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
@@ -198,6 +203,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
*
* @hide
*/
+ @RequiresNoPermission
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")" + "not supported for MAPS");
return false;
@@ -212,6 +218,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -259,6 +266,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -285,6 +293,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
@@ -308,6 +317,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
@@ -335,6 +345,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -357,6 +368,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -391,6 +403,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
* @return priority of the device
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -412,6 +425,7 @@ public final class BluetoothMap implements BluetoothProfile, AutoCloseable {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index db74a90f603b5..f20b533af045f 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -20,8 +20,10 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.PendingIntent;
+import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.Uri;
@@ -192,6 +194,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* currently connected to the Map service.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isConnected(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
@@ -215,6 +218,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -243,6 +247,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -268,6 +273,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @hide
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getConnectedDevices() {
if (DBG) Log.d(TAG, "getConnectedDevices()");
@@ -291,6 +297,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @hide
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
@@ -314,6 +321,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @hide
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
@@ -341,6 +349,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -362,6 +371,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return true if connectionPolicy is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -396,6 +406,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return priority of the device
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -416,6 +427,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return connection policy of the device
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -449,6 +461,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.SEND_SMS,
@@ -484,6 +497,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.SEND_SMS,
@@ -510,6 +524,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return true if the message is enqueued, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.READ_SMS,
@@ -536,6 +551,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* MapSupportedFeatures field is set. False is returned otherwise.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isUploadingSupported(BluetoothDevice device) {
final IBluetoothMapClient service = getService();
@@ -564,6 +580,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
* @return true if request has been sent, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.READ_SMS,
diff --git a/core/java/android/bluetooth/BluetoothOutputStream.java b/core/java/android/bluetooth/BluetoothOutputStream.java
index a0aa2dee9d348..ac2b3edb0eb85 100644
--- a/core/java/android/bluetooth/BluetoothOutputStream.java
+++ b/core/java/android/bluetooth/BluetoothOutputStream.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.annotation.SuppressLint;
+
import java.io.IOException;
import java.io.OutputStream;
@@ -26,6 +28,7 @@ import java.io.OutputStream;
*
* @hide
*/
+@SuppressLint("AndroidFrameworkBluetoothPermission")
/*package*/ final class BluetoothOutputStream extends OutputStream {
private BluetoothSocket mSocket;
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index b3924b1fa9207..c41c9dee2547e 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -240,6 +240,7 @@ public final class BluetoothPan implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -282,6 +283,7 @@ public final class BluetoothPan implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -311,6 +313,7 @@ public final class BluetoothPan implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -342,6 +345,7 @@ public final class BluetoothPan implements BluetoothProfile {
*/
@SystemApi
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -416,6 +420,7 @@ public final class BluetoothPan implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -441,6 +446,7 @@ public final class BluetoothPan implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isTetheringOn() {
if (VDBG) log("isTetheringOn()");
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 6c2e5bf2d3913..e41eb4f258102 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -110,6 +110,7 @@ public class BluetoothPbap implements BluetoothProfile {
*/
public static final int RESULT_CANCELED = 2;
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
@@ -217,6 +218,7 @@ public class BluetoothPbap implements BluetoothProfile {
* @hide
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getConnectedDevices() {
log("getConnectedDevices()");
@@ -264,6 +266,7 @@ public class BluetoothPbap implements BluetoothProfile {
* @hide
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
log("getDevicesMatchingConnectionStates: states=" + Arrays.toString(states));
@@ -297,6 +300,7 @@ public class BluetoothPbap implements BluetoothProfile {
* @hide
*/
@SystemApi
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -330,6 +334,7 @@ public class BluetoothPbap implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(BluetoothDevice device) {
log("disconnect()");
@@ -347,6 +352,7 @@ public class BluetoothPbap implements BluetoothProfile {
return false;
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
log("Proxy object connected");
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index 2c8fbc2509ff2..85b8650765084 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -20,6 +20,7 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
+import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.content.Context;
import android.os.Binder;
import android.os.IBinder;
@@ -161,6 +162,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
* @return list of connected devices
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getConnectedDevices() {
if (DBG) {
@@ -187,6 +189,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
* @return list of matching devices
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
if (DBG) {
@@ -213,6 +216,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
* @return device connection state
*/
@Override
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(BluetoothDevice device) {
if (DBG) {
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 70053ee71491d..161c843f03982 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.annotation.IntDef;
+import android.annotation.RequiresNoPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
@@ -333,6 +334,7 @@ public interface BluetoothProfile {
* @param profile - One of {@link #HEADSET} or {@link #A2DP}
* @param proxy - One of {@link BluetoothHeadset} or {@link BluetoothA2dp}
*/
+ @RequiresNoPermission
public void onServiceConnected(int profile, BluetoothProfile proxy);
/**
@@ -341,6 +343,7 @@ public interface BluetoothProfile {
*
* @param profile - One of {@link #HEADSET} or {@link #A2DP}
*/
+ @RequiresNoPermission
public void onServiceDisconnected(int profile);
}
diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
index 12abcc4d11da5..b20ab754932c6 100644
--- a/core/java/android/bluetooth/BluetoothProfileConnector.java
+++ b/core/java/android/bluetooth/BluetoothProfileConnector.java
@@ -16,7 +16,6 @@
package android.bluetooth;
-import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
@@ -33,6 +32,7 @@ import android.util.Log;
* @param The Bluetooth profile interface for this connection.
* @hide
*/
+@SuppressLint("AndroidFrameworkBluetoothPermission")
public abstract class BluetoothProfileConnector {
private final int mProfileId;
private BluetoothProfile.ServiceListener mServiceListener;
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index c85494c01b25c..87da22cbb7f5e 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
@@ -143,6 +144,7 @@ public final class BluetoothSap implements BluetoothProfile {
* connected to the Sap service.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public int getState() {
if (VDBG) log("getState()");
@@ -167,6 +169,7 @@ public final class BluetoothSap implements BluetoothProfile {
* this proxy object is not connected to the Sap service.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
@@ -191,6 +194,7 @@ public final class BluetoothSap implements BluetoothProfile {
*
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
@@ -214,6 +218,7 @@ public final class BluetoothSap implements BluetoothProfile {
*
* @hide
*/
+ @RequiresNoPermission
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")" + "not supported for SAPS");
return false;
@@ -227,6 +232,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
@@ -249,6 +255,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @return list of connected devices
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
@@ -271,6 +278,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @return list of matching devices
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public List getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
@@ -293,6 +301,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @return device connection state
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
@@ -320,6 +329,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @return true if priority is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -341,6 +351,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @return true if connectionPolicy is set, false on error
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -375,6 +386,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @return priority of the device
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
@@ -395,6 +407,7 @@ public final class BluetoothSap implements BluetoothProfile {
* @return connection policy of the device
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(allOf = {
android.Manifest.permission.BLUETOOTH_CONNECT,
android.Manifest.permission.BLUETOOTH_PRIVILEGED,
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 50822354d69fc..bb4e35483fea8 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -16,6 +16,7 @@
package android.bluetooth;
+import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Handler;
import android.os.ParcelUuid;
@@ -70,6 +71,7 @@ import java.io.IOException;
*
* {@see BluetoothSocket}
*/
+@SuppressLint("AndroidFrameworkBluetoothPermission")
public final class BluetoothServerSocket implements Closeable {
private static final String TAG = "BluetoothServerSocket";
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index ef88147a40fb5..bb409d5360f91 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -16,8 +16,10 @@
package android.bluetooth;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
+import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.net.LocalSocket;
import android.os.Build;
@@ -198,7 +200,6 @@ public final class BluetoothSocket implements Closeable {
* @throws IOException On error, for example Bluetooth not available, or insufficient
* privileges
*/
- @SuppressLint("AndroidFrameworkRequiresPermission")
/*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
BluetoothDevice device, int port, ParcelUuid uuid, boolean mitm, boolean min16DigitPin)
throws IOException {
@@ -326,6 +327,7 @@ public final class BluetoothSocket implements Closeable {
*
* @return remote device
*/
+ @RequiresNoPermission
public BluetoothDevice getRemoteDevice() {
return mDevice;
}
@@ -338,6 +340,7 @@ public final class BluetoothSocket implements Closeable {
*
* @return InputStream
*/
+ @RequiresNoPermission
public InputStream getInputStream() throws IOException {
return mInputStream;
}
@@ -350,6 +353,7 @@ public final class BluetoothSocket implements Closeable {
*
* @return OutputStream
*/
+ @RequiresNoPermission
public OutputStream getOutputStream() throws IOException {
return mOutputStream;
}
@@ -360,6 +364,7 @@ public final class BluetoothSocket implements Closeable {
*
* @return true if connected false if not connected
*/
+ @RequiresNoPermission
public boolean isConnected() {
return mSocketState == SocketState.CONNECTED;
}
@@ -386,6 +391,7 @@ public final class BluetoothSocket implements Closeable {
*
* @throws IOException on error, for example connection failure
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void connect() throws IOException {
if (mDevice == null) throw new IOException("Connect is called on null device");
@@ -637,6 +643,7 @@ public final class BluetoothSocket implements Closeable {
*
* @return the maximum supported Transmit packet size for the underlying transport.
*/
+ @RequiresNoPermission
public int getMaxTransmitPacketSize() {
return mMaxTxPacketSize;
}
@@ -649,6 +656,7 @@ public final class BluetoothSocket implements Closeable {
*
* @return the maximum supported Receive packet size for the underlying transport.
*/
+ @RequiresNoPermission
public int getMaxReceivePacketSize() {
return mMaxRxPacketSize;
}
@@ -658,6 +666,7 @@ public final class BluetoothSocket implements Closeable {
*
* @return one of {@link #TYPE_RFCOMM}, {@link #TYPE_SCO} or {@link #TYPE_L2CAP}
*/
+ @RequiresNoPermission
public int getConnectionType() {
if (mType == TYPE_L2CAP_LE) {
// Treat the LE CoC to be the same type as L2CAP.
@@ -674,6 +683,7 @@ public final class BluetoothSocket implements Closeable {
* generate SPP SDP record.
* @hide
*/
+ @RequiresNoPermission
public void setExcludeSdp(boolean excludeSdp) {
mExcludeSdp = excludeSdp;
}
@@ -684,6 +694,7 @@ public final class BluetoothSocket implements Closeable {
* connection. This function is currently used for testing only.
* @hide
*/
+ @RequiresBluetoothConnectPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
public void requestMaximumTxDataLength() throws IOException {
if (mDevice == null) {
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index d82cf19e88223..bc3754a2fc564 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -18,6 +18,7 @@ package android.bluetooth;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelUuid;
@@ -34,6 +35,7 @@ import java.util.UUID;
* @hide
*/
@SystemApi
+@SuppressLint("AndroidFrameworkBluetoothPermission")
public final class BluetoothUuid {
/* See Bluetooth Assigned Numbers document - SDP section, to get the values of UUIDs
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
index 54a18e6f1d62e..d7e48ca543ca1 100644
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -16,7 +16,9 @@
package android.bluetooth.le;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManager;
@@ -216,6 +218,7 @@ public final class AdvertisingSet {
*
* @hide
*/
+ @RequiresNoPermission
public int getAdvertiserId() {
return mAdvertiserId;
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 710fa6827b0bf..ff279d859873c 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
@@ -163,11 +164,13 @@ public final class BluetoothLeAdvertiser {
}
}
- @SuppressLint("AndroidFrameworkRequiresPermission")
+ @SuppressLint({
+ "AndroidFrameworkBluetoothPermission",
+ "AndroidFrameworkRequiresPermission",
+ })
AdvertisingSetCallback wrapOldCallback(AdvertiseCallback callback, AdvertiseSettings settings) {
return new AdvertisingSetCallback() {
@Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower,
int status) {
if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
@@ -180,7 +183,6 @@ public final class BluetoothLeAdvertiser {
/* Legacy advertiser is disabled on timeout */
@Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enabled,
int status) {
if (enabled) {
@@ -491,6 +493,7 @@ public final class BluetoothLeAdvertiser {
*
* @hide
*/
+ @RequiresNoPermission
public void cleanup() {
mLegacyAdvertisers.clear();
mCallbackWrappers.clear();
@@ -498,6 +501,7 @@ public final class BluetoothLeAdvertiser {
}
// Compute the size of advertisement data or scan resp
+ @RequiresBluetoothAdvertisePermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
private int totalBytes(AdvertiseData data, boolean isFlagsIncluded) {
if (data == null) return 0;
@@ -582,6 +586,7 @@ public final class BluetoothLeAdvertiser {
return array == null ? 0 : array.length;
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) {
return new IAdvertisingSetCallback.Stub() {
@Override
@@ -706,6 +711,7 @@ public final class BluetoothLeAdvertiser {
};
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private void postStartSetFailure(Handler handler, final AdvertisingSetCallback callback,
final int error) {
handler.post(new Runnable() {
@@ -716,6 +722,7 @@ public final class BluetoothLeAdvertiser {
});
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private void postStartFailure(final AdvertiseCallback callback, final int error) {
mHandler.post(new Runnable() {
@Override
@@ -725,6 +732,7 @@ public final class BluetoothLeAdvertiser {
});
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private void postStartSuccess(final AdvertiseCallback callback,
final AdvertiseSettings settings) {
mHandler.post(new Runnable() {
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 4271a905c2204..09cd11d075906 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -16,9 +16,9 @@
package android.bluetooth.le;
-import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
@@ -357,6 +357,7 @@ public final class BluetoothLeScanner {
* @hide
*/
@SystemApi
+ @RequiresBluetoothScanPermission
@RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
public void startTruncatedScan(List truncatedFilters, ScanSettings settings,
final ScanCallback callback) {
@@ -376,6 +377,7 @@ public final class BluetoothLeScanner {
*
* @hide
*/
+ @RequiresNoPermission
public void cleanup() {
mLeScanClients.clear();
}
@@ -383,6 +385,7 @@ public final class BluetoothLeScanner {
/**
* Bluetooth GATT interface callbacks
*/
+ @SuppressLint("AndroidFrameworkRequiresPermission")
private class BleScanCallbackWrapper extends IScannerCallback.Stub {
private static final int REGISTRATION_CALLBACK_TIMEOUT_MILLIS = 2000;
@@ -412,8 +415,6 @@ public final class BluetoothLeScanner {
mResultStorages = resultStorages;
}
- @SuppressLint("AndroidFrameworkRequiresPermission")
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
public void startRegistration() {
synchronized (this) {
// Scan stopped.
@@ -441,8 +442,6 @@ public final class BluetoothLeScanner {
}
}
- @SuppressLint("AndroidFrameworkRequiresPermission")
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
public void stopLeScan() {
synchronized (this) {
if (mScannerId <= 0) {
@@ -459,8 +458,6 @@ public final class BluetoothLeScanner {
}
}
- @SuppressLint("AndroidFrameworkRequiresPermission")
- @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
void flushPendingBatchResults() {
synchronized (this) {
if (mScannerId <= 0) {
@@ -479,7 +476,6 @@ public final class BluetoothLeScanner {
* Application interface registered - app is ready to go
*/
@Override
- @SuppressLint("AndroidFrameworkRequiresPermission")
public void onScannerRegistered(int status, int scannerId) {
Log.d(TAG, "onScannerRegistered() - status=" + status
+ " scannerId=" + scannerId + " mScannerId=" + mScannerId);
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
index 9ea6c4866f6d6..26978e398072d 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
@@ -17,6 +17,7 @@
package android.bluetooth.le;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.IBluetoothGatt;
@@ -208,6 +209,7 @@ public final class PeriodicAdvertisingManager {
}
}
+ @SuppressLint("AndroidFrameworkBluetoothPermission")
private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback,
Handler handler) {
return new IPeriodicAdvertisingCallback.Stub() {
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 27c579b3cdfe7..c5c4277d9eb83 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -16,7 +16,6 @@
package android.bluetooth.le;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index 794b512772fe8..9b8c2eaf4d197 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -18,6 +18,7 @@ package android.bluetooth.le;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.bluetooth.BluetoothUuid;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.ParcelUuid;
@@ -34,6 +35,7 @@ import java.util.function.Predicate;
/**
* Represents a scan record from Bluetooth LE scan.
*/
+@SuppressLint("AndroidFrameworkBluetoothPermission")
public final class ScanRecord {
private static final String TAG = "ScanRecord";
diff --git a/core/java/android/bluetooth/le/TruncatedFilter.java b/core/java/android/bluetooth/le/TruncatedFilter.java
index a753aa6fef170..93f526bb9f093 100644
--- a/core/java/android/bluetooth/le/TruncatedFilter.java
+++ b/core/java/android/bluetooth/le/TruncatedFilter.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import java.util.List;
@@ -26,6 +27,7 @@ import java.util.List;
* @hide
*/
@SystemApi
+@SuppressLint("AndroidFrameworkBluetoothPermission")
public final class TruncatedFilter {
private final ScanFilter mFilter;
private final List mStorageDescriptors;
diff --git a/errorprone/java/android/annotation/RequiresNoPermission.java b/errorprone/java/android/annotation/RequiresNoPermission.java
new file mode 100644
index 0000000000000..6ff4d6e34957e
--- /dev/null
+++ b/errorprone/java/android/annotation/RequiresNoPermission.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that the annotated element requires no permissions.
+ *
+ * @hide
+ */
+@Retention(CLASS)
+@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER})
+public @interface RequiresNoPermission {
+}
diff --git a/errorprone/java/android/annotation/RequiresPermission.java b/errorprone/java/android/annotation/RequiresPermission.java
new file mode 100644
index 0000000000000..303ab41bec8ef
--- /dev/null
+++ b/errorprone/java/android/annotation/RequiresPermission.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.annotation;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that the annotated element requires (or may require) one or more permissions.
+ *
+ * Example of requiring a single permission:
+ * {@code
+ * {@literal @}RequiresPermission(Manifest.permission.SET_WALLPAPER)
+ * public abstract void setWallpaper(Bitmap bitmap) throws IOException;
+ *
+ * {@literal @}RequiresPermission(ACCESS_COARSE_LOCATION)
+ * public abstract Location getLastKnownLocation(String provider);
+ * }
+ * Example of requiring at least one permission from a set:
+ * {@code
+ * {@literal @}RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
+ * public abstract Location getLastKnownLocation(String provider);
+ * }
+ * Example of requiring multiple permissions:
+ * {@code
+ * {@literal @}RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
+ * public abstract Location getLastKnownLocation(String provider);
+ * }
+ * Example of requiring separate read and write permissions for a content provider:
+ * {@code
+ * {@literal @}RequiresPermission.Read(@RequiresPermission(READ_HISTORY_BOOKMARKS))
+ * {@literal @}RequiresPermission.Write(@RequiresPermission(WRITE_HISTORY_BOOKMARKS))
+ * public static final Uri BOOKMARKS_URI = Uri.parse("content://browser/bookmarks");
+ * }
+ *
+ * When specified on a parameter, the annotation indicates that the method requires
+ * a permission which depends on the value of the parameter. For example, consider
+ * {@link android.app.Activity#startActivity(android.content.Intent)
+ * Activity#startActivity(Intent)}:
+ *
{@code
+ * public void startActivity(@RequiresPermission Intent intent) { ... }
+ * }
+ * Notice how there are no actual permission names listed in the annotation. The actual
+ * permissions required will depend on the particular intent passed in. For example,
+ * the code may look like this:
+ * {@code
+ * Intent intent = new Intent(Intent.ACTION_CALL);
+ * startActivity(intent);
+ * }
+ * and the actual permission requirement for this particular intent is described on
+ * the Intent name itself:
+ * {@code
+ * {@literal @}RequiresPermission(Manifest.permission.CALL_PHONE)
+ * public static final String ACTION_CALL = "android.intent.action.CALL";
+ * }
+ *
+ * @hide
+ */
+@Retention(CLASS)
+@Target({ANNOTATION_TYPE,METHOD,CONSTRUCTOR,FIELD,PARAMETER})
+public @interface RequiresPermission {
+ /**
+ * The name of the permission that is required, if precisely one permission
+ * is required. If more than one permission is required, specify either
+ * {@link #allOf()} or {@link #anyOf()} instead.
+ *
+ * If specified, {@link #anyOf()} and {@link #allOf()} must both be null.
+ */
+ String value() default "";
+
+ /**
+ * Specifies a list of permission names that are all required.
+ *
+ * If specified, {@link #anyOf()} and {@link #value()} must both be null.
+ */
+ String[] allOf() default {};
+
+ /**
+ * Specifies a list of permission names where at least one is required
+ *
+ * If specified, {@link #allOf()} and {@link #value()} must both be null.
+ */
+ String[] anyOf() default {};
+
+ /**
+ * If true, the permission may not be required in all cases (e.g. it may only be
+ * enforced on certain platforms, or for certain call parameters, etc.
+ */
+ boolean conditional() default false;
+
+ /**
+ * Specifies that the given permission is required for read operations.
+ *
+ * When specified on a parameter, the annotation indicates that the method requires
+ * a permission which depends on the value of the parameter (and typically
+ * the corresponding field passed in will be one of a set of constants which have
+ * been annotated with a @RequiresPermission annotation.)
+ */
+ @Target({FIELD, METHOD, PARAMETER})
+ @interface Read {
+ RequiresPermission value() default @RequiresPermission;
+ }
+
+ /**
+ * Specifies that the given permission is required for write operations.
+ *
+ * When specified on a parameter, the annotation indicates that the method requires
+ * a permission which depends on the value of the parameter (and typically
+ * the corresponding field passed in will be one of a set of constants which have
+ * been annotated with a @RequiresPermission annotation.)
+ */
+ @Target({FIELD, METHOD, PARAMETER})
+ @interface Write {
+ RequiresPermission value() default @RequiresPermission;
+ }
+}
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/BluetoothPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/BluetoothPermissionChecker.java
new file mode 100644
index 0000000000000..9d1cf87a5f9dc
--- /dev/null
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/BluetoothPermissionChecker.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.errorprone.bugpatterns.android;
+
+import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
+import static com.google.errorprone.bugpatterns.android.RequiresPermissionChecker.simpleNameMatches;
+import static com.google.errorprone.matchers.Matchers.allOf;
+import static com.google.errorprone.matchers.Matchers.anyOf;
+import static com.google.errorprone.matchers.Matchers.enclosingClass;
+import static com.google.errorprone.matchers.Matchers.isStatic;
+import static com.google.errorprone.matchers.Matchers.isSubtypeOf;
+import static com.google.errorprone.matchers.Matchers.methodHasVisibility;
+import static com.google.errorprone.matchers.Matchers.methodIsConstructor;
+import static com.google.errorprone.matchers.Matchers.methodIsNamed;
+import static com.google.errorprone.matchers.Matchers.not;
+import static com.google.errorprone.matchers.Matchers.packageStartsWith;
+
+import android.annotation.RequiresNoPermission;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+
+import com.google.auto.service.AutoService;
+import com.google.errorprone.BugPattern;
+import com.google.errorprone.VisitorState;
+import com.google.errorprone.bugpatterns.BugChecker;
+import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
+import com.google.errorprone.matchers.Description;
+import com.google.errorprone.matchers.Matcher;
+import com.google.errorprone.matchers.MethodVisibility.Visibility;
+import com.google.errorprone.util.ASTHelpers;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.util.TreePath;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.regex.Pattern;
+
+/**
+ * Verifies that all Bluetooth APIs have consistent permissions.
+ */
+@AutoService(BugChecker.class)
+@BugPattern(
+ name = "AndroidFrameworkBluetoothPermission",
+ summary = "Verifies that all Bluetooth APIs have consistent permissions",
+ severity = WARNING)
+public final class BluetoothPermissionChecker extends BugChecker implements MethodTreeMatcher {
+ private static final Matcher BLUETOOTH_API = allOf(
+ packageStartsWith("android.bluetooth"),
+ methodHasVisibility(Visibility.PUBLIC),
+ not(isStatic()),
+ not(methodIsConstructor()),
+ not(enclosingClass(isInsideParcelable())),
+ not(enclosingClass(simpleNameMatches(Pattern.compile(".+Callback$")))),
+ not(enclosingClass(isSubtypeOf("android.bluetooth.BluetoothProfileConnector"))),
+ not(enclosingClass(isSubtypeOf("android.app.PropertyInvalidatedCache"))));
+
+ private static final Matcher PARCELABLE_CLASS =
+ isSubtypeOf("android.os.Parcelable");
+ private static final Matcher BINDER_METHOD = enclosingClass(
+ isSubtypeOf("android.os.IInterface"));
+
+ private static final Matcher BINDER_INTERNALS = allOf(
+ enclosingClass(isSubtypeOf("android.os.IInterface")),
+ anyOf(
+ methodIsNamed("onTransact"),
+ methodIsNamed("dump"),
+ enclosingClass(simpleNameMatches(Pattern.compile("^(Stub|Default|Proxy)$")))));
+
+ private static final Matcher GENERIC_INTERNALS = anyOf(
+ methodIsNamed("close"),
+ methodIsNamed("finalize"),
+ methodIsNamed("equals"),
+ methodIsNamed("hashCode"),
+ methodIsNamed("toString"));
+
+ private static final String PERMISSION_ADVERTISE = "android.permission.BLUETOOTH_ADVERTISE";
+ private static final String PERMISSION_CONNECT = "android.permission.BLUETOOTH_CONNECT";
+ private static final String PERMISSION_SCAN = "android.permission.BLUETOOTH_SCAN";
+
+ private static final String ANNOTATION_ADVERTISE =
+ "android.bluetooth.annotations.RequiresBluetoothAdvertisePermission";
+ private static final String ANNOTATION_CONNECT =
+ "android.bluetooth.annotations.RequiresBluetoothConnectPermission";
+ private static final String ANNOTATION_SCAN =
+ "android.bluetooth.annotations.RequiresBluetoothScanPermission";
+
+ @Override
+ public Description matchMethod(MethodTree tree, VisitorState state) {
+ // Ignore methods outside Bluetooth area
+ if (!BLUETOOTH_API.matches(tree, state)) return Description.NO_MATCH;
+
+ // Ignore certain types of generated or internal code
+ if (BINDER_INTERNALS.matches(tree, state)) return Description.NO_MATCH;
+ if (GENERIC_INTERNALS.matches(tree, state)) return Description.NO_MATCH;
+
+ // Skip abstract methods, except for binder interfaces
+ if (tree.getBody() == null && !BINDER_METHOD.matches(tree, state)) {
+ return Description.NO_MATCH;
+ }
+
+ // Ignore callbacks which don't need permission enforcement
+ final MethodSymbol symbol = ASTHelpers.getSymbol(tree);
+ if (isCallbackOrWrapper(symbol)) return Description.NO_MATCH;
+
+ // Ignore when suppressed
+ if (isSuppressed(symbol)) return Description.NO_MATCH;
+
+ final RequiresPermission requiresPerm = ASTHelpers.getAnnotation(tree,
+ RequiresPermission.class);
+ final RequiresNoPermission requiresNoPerm = ASTHelpers.getAnnotation(tree,
+ RequiresNoPermission.class);
+
+ final boolean requiresValid = requiresPerm != null
+ && (requiresPerm.value() != null || requiresPerm.allOf() != null);
+ final boolean requiresNoValid = requiresNoPerm != null;
+ if (!requiresValid && !requiresNoValid) {
+ return buildDescription(tree)
+ .setMessage("Method " + symbol.name.toString()
+ + "() must be protected by at least one permission")
+ .build();
+ }
+
+ // No additional checks needed for Binder generated code
+ if (BINDER_METHOD.matches(tree, state)) return Description.NO_MATCH;
+
+ if (ASTHelpers.hasAnnotation(tree, ANNOTATION_ADVERTISE,
+ state) != isPermissionReferenced(requiresPerm, PERMISSION_ADVERTISE)) {
+ return buildDescription(tree)
+ .setMessage("Method " + symbol.name.toString()
+ + "() has inconsistent annotations for " + PERMISSION_ADVERTISE)
+ .build();
+ }
+ if (ASTHelpers.hasAnnotation(tree, ANNOTATION_CONNECT,
+ state) != isPermissionReferenced(requiresPerm, PERMISSION_CONNECT)) {
+ return buildDescription(tree)
+ .setMessage("Method " + symbol.name.toString()
+ + "() has inconsistent annotations for " + PERMISSION_CONNECT)
+ .build();
+ }
+ if (ASTHelpers.hasAnnotation(tree, ANNOTATION_SCAN,
+ state) != isPermissionReferenced(requiresPerm, PERMISSION_SCAN)) {
+ return buildDescription(tree)
+ .setMessage("Method " + symbol.name.toString()
+ + "() has inconsistent annotations for " + PERMISSION_SCAN)
+ .build();
+ }
+
+ return Description.NO_MATCH;
+ }
+
+ private static boolean isPermissionReferenced(RequiresPermission anno, String perm) {
+ if (anno == null) return false;
+ if (perm.equals(anno.value())) return true;
+ return anno.allOf() != null && Arrays.asList(anno.allOf()).contains(perm);
+ }
+
+ private static boolean isCallbackOrWrapper(Symbol symbol) {
+ if (symbol == null) return false;
+ final String name = symbol.name.toString();
+ return isCallbackOrWrapper(ASTHelpers.enclosingClass(symbol))
+ || name.endsWith("Callback")
+ || name.endsWith("Wrapper");
+ }
+
+ public boolean isSuppressed(Symbol symbol) {
+ if (symbol == null) return false;
+ return isSuppressed(ASTHelpers.enclosingClass(symbol))
+ || isSuppressed(ASTHelpers.getAnnotation(symbol, SuppressWarnings.class))
+ || isSuppressed(ASTHelpers.getAnnotation(symbol, SuppressLint.class));
+ }
+
+ private boolean isSuppressed(SuppressWarnings anno) {
+ return (anno != null) && !Collections.disjoint(Arrays.asList(anno.value()), allNames());
+ }
+
+ private boolean isSuppressed(SuppressLint anno) {
+ return (anno != null) && !Collections.disjoint(Arrays.asList(anno.value()), allNames());
+ }
+
+ private static Matcher isInsideParcelable() {
+ return new Matcher() {
+ @Override
+ public boolean matches(ClassTree tree, VisitorState state) {
+ final TreePath path = state.getPath();
+ for (Tree node : path) {
+ if (node instanceof ClassTree
+ && PARCELABLE_CLASS.matches((ClassTree) node, state)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ }
+}
diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
index 3b5a58c46f713..f54782d4eb77d 100644
--- a/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
+++ b/errorprone/java/com/google/errorprone/bugpatterns/android/RequiresPermissionChecker.java
@@ -143,8 +143,11 @@ public final class RequiresPermissionChecker extends BugChecker implements Metho
final ParsedRequiresPermission nodePerm = parseRequiresPermissionRecursively(
node, state);
if (!expectedPerm.containsAll(nodePerm)) {
- return buildDescription(node).setMessage("Annotated " + expectedPerm
- + " but too narrow; invokes method requiring " + nodePerm).build();
+ return buildDescription(node)
+ .setMessage("Method " + method.name.toString() + "() annotated "
+ + expectedPerm
+ + " but too narrow; invokes method requiring " + nodePerm)
+ .build();
} else {
actualPerm.addAll(nodePerm);
}
@@ -162,8 +165,10 @@ public final class RequiresPermissionChecker extends BugChecker implements Metho
// Second, determine if we actually used all permissions that we claim
// to require; yell if we're too broad
if (!actualPerm.containsAll(expectedPerm)) {
- return buildDescription(tree).setMessage("Annotated " + expectedPerm
- + " but too wide; only invokes methods requiring " + actualPerm).build();
+ return buildDescription(tree)
+ .setMessage("Method " + method.name.toString() + "() annotated " + expectedPerm
+ + " but too wide; only invokes methods requiring " + actualPerm)
+ .build();
}
return Description.NO_MATCH;
@@ -316,7 +321,7 @@ public final class RequiresPermissionChecker extends BugChecker implements Metho
return (anno != null) && !Collections.disjoint(Arrays.asList(anno.value()), allNames());
}
- private static Matcher simpleNameMatches(Pattern pattern) {
+ static Matcher simpleNameMatches(Pattern pattern) {
return new Matcher() {
@Override
public boolean matches(ClassTree tree, VisitorState state) {