Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d1485f3 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Update Bluetooth API annotations." into sc-dev

parents 3816c399 8bc7b2ee
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ android_app {
    srcs: [
        "src/**/*.java",
        ":statslog-bluetooth-java-gen",
        ":libbluetooth-binder-aidl",
    ],
    platform_apis: true,
    certificate: "platform",
@@ -83,6 +84,7 @@ android_app {
    libs: [
        "javax.obex",
        "services.net",
        "unsupportedappusage",
    ],
    static_libs: [
        "com.android.vcard",
@@ -113,6 +115,11 @@ android_app {
        "//apex_available:platform",
        "com.android.bluetooth.updatable",
    ],
    errorprone: {
        javacflags: [
            "-Xep:AndroidFrameworkRequiresPermission:ERROR",
        ],
    },
}

genrule {
+78 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.bluetooth;

import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.BLUETOOTH_ADVERTISE;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_SCAN;
import static android.Manifest.permission.RENOUNCE_PERMISSIONS;
@@ -28,6 +29,8 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -359,23 +362,28 @@ public final class Utils {
     * @return {@code true} if the caller has the BLUETOOTH_PRIVILEGED permission, {@code false}
     *         otherwise
     */
    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean hasBluetoothPrivilegedPermission(Context context) {
        return context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
                == PackageManager.PERMISSION_GRANTED;
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    public static void enforceBluetoothPrivilegedPermission(Context context) {
        context.enforceCallingOrSelfPermission(
                android.Manifest.permission.BLUETOOTH_PRIVILEGED,
                "Need BLUETOOTH PRIVILEGED permission");
    }

    @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS)
    public static void enforceLocalMacAddressPermission(Context context) {
        context.enforceCallingOrSelfPermission(
                android.Manifest.permission.LOCAL_MAC_ADDRESS,
                "Need LOCAL_MAC_ADDRESS permission");
    }

    @RequiresPermission(android.Manifest.permission.DUMP)
    public static void enforceDumpPermission(Context context) {
        context.enforceCallingOrSelfPermission(
                android.Manifest.permission.DUMP,
@@ -389,6 +397,7 @@ public final class Utils {
     *
     * <p>Should be used in situations where the app op should not be noted.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public static boolean checkConnectPermissionForPreflight(Context context) {
        int permissionCheckResult = PermissionChecker.checkCallingOrSelfPermissionForPreflight(
                context, BLUETOOTH_CONNECT);
@@ -406,6 +415,7 @@ public final class Utils {
     * <p>Should be used in situations where data will be delivered and hence the app op should
     * be noted.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public static boolean checkConnectPermissionForDataDelivery(
            Context context, String callingPackage, String callingAttributionTag, String message) {
        int permissionCheckResult = PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(
@@ -422,6 +432,7 @@ public final class Utils {
     *
     * <p>Should be used in situations where the app op should not be noted.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
    public static boolean checkScanPermissionForPreflight(Context context) {
        int permissionCheckResult = PermissionChecker.checkCallingOrSelfPermissionForPreflight(
                context, BLUETOOTH_SCAN);
@@ -438,6 +449,7 @@ public final class Utils {
     * <p>Should be used in situations where data will be delivered and hence the app op should
     * be noted.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
    public static boolean checkScanPermissionForDataDelivery(
            Context context, AttributionSource attributionSource, String message) {
        int permissionCheckResult = PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
@@ -449,11 +461,50 @@ public final class Utils {
        return permissionCheckResult == PERMISSION_GRANTED;
    }

    /**
     * Returns true if the BLUETOOTH_ADVERTISE permission is granted for the
     * calling app. Returns false if the result is a soft denial. Throws
     * SecurityException if the result is a hard denial.
     * <p>
     * Should be used in situations where the app op should not be noted.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
    public static boolean checkAdvertisePermissionForPreflight(Context context) {
        int permissionCheckResult = PermissionChecker.checkCallingOrSelfPermissionForPreflight(
                context, BLUETOOTH_ADVERTISE);
        if (permissionCheckResult == PERMISSION_HARD_DENIED) {
            throw new SecurityException("Need BLUETOOTH_ADVERTISE permission");
        }
        return permissionCheckResult == PERMISSION_GRANTED;
    }

    /**
     * Returns true if the BLUETOOTH_ADVERTISE permission is granted for the
     * calling app. Returns false if the result is a soft denial. Throws
     * SecurityException if the result is a hard denial.
     * <p>
     * Should be used in situations where data will be delivered and hence the
     * app op should be noted.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE)
    public static boolean checkAdvertisePermissionForDataDelivery(
            Context context, AttributionSource attributionSource, String message) {
        int permissionCheckResult = PermissionChecker.checkPermissionForDataDeliveryFromDataSource(
                context, BLUETOOTH_ADVERTISE, PID_UNKNOWN,
                new AttributionSource(context.getAttributionSource(), attributionSource), message);
        if (permissionCheckResult == PERMISSION_HARD_DENIED) {
            throw new SecurityException("Need BLUETOOTH_ADVERTISE permission");
        }
        return permissionCheckResult == PERMISSION_GRANTED;
    }

    /**
     * Returns true if the specified package has disavowed the use of bluetooth scans for location,
     * that is, if they have specified the {@code neverForLocation} flag on the BLUETOOTH_SCAN
     * permission.
     */
    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean hasDisavowedLocationForScan(
            Context context, String packageName, AttributionSource attributionSource) {

@@ -542,6 +593,8 @@ public final class Utils {
     * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION and
     * OP_COARSE_LOCATION is allowed
     */
    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean checkCallerHasCoarseLocation(
            Context context, AttributionSource attributionSource, UserHandle userHandle) {
        if (blockedByLocationOff(context, userHandle)) {
@@ -566,6 +619,8 @@ public final class Utils {
     * OP_COARSE_LOCATION is allowed or android.Manifest.permission.ACCESS_FINE_LOCATION and
     * OP_FINE_LOCATION is allowed
     */
    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean checkCallerHasCoarseOrFineLocation(
            Context context, AttributionSource attributionSource, UserHandle userHandle) {
        if (blockedByLocationOff(context, userHandle)) {
@@ -596,6 +651,8 @@ public final class Utils {
     * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION and
     * OP_FINE_LOCATION is allowed
     */
    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean checkCallerHasFineLocation(
            Context context, AttributionSource attributionSource, UserHandle userHandle) {
        if (blockedByLocationOff(context, userHandle)) {
@@ -618,6 +675,8 @@ public final class Utils {
    /**
     * Returns true if the caller holds NETWORK_SETTINGS
     */
    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean checkCallerHasNetworkSettingsPermission(Context context) {
        return context.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS)
                == PackageManager.PERMISSION_GRANTED;
@@ -626,6 +685,8 @@ public final class Utils {
    /**
     * Returns true if the caller holds NETWORK_SETUP_WIZARD
     */
    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean checkCallerHasNetworkSetupWizardPermission(Context context) {
        return context.checkCallingOrSelfPermission(
                android.Manifest.permission.NETWORK_SETUP_WIZARD)
@@ -635,12 +696,29 @@ public final class Utils {
    /**
     * Returns true if the caller holds RADIO_SCAN_WITHOUT_LOCATION
     */
    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean checkCallerHasScanWithoutLocationPermission(Context context) {
        return context.checkCallingOrSelfPermission(
                android.Manifest.permission.RADIO_SCAN_WITHOUT_LOCATION)
                == PackageManager.PERMISSION_GRANTED;
    }

    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean checkCallerHasPrivilegedPermission(Context context) {
        return context.checkCallingOrSelfPermission(
                android.Manifest.permission.BLUETOOTH_PRIVILEGED)
                == PackageManager.PERMISSION_GRANTED;
    }

    // Suppressed since we're not actually enforcing here
    @SuppressLint("AndroidFrameworkRequiresPermission")
    public static boolean checkCallerHasWriteSmsPermission(Context context) {
        return context.checkCallingOrSelfPermission(
                android.Manifest.permission.WRITE_SMS) == PackageManager.PERMISSION_GRANTED;
    }

    public static boolean isQApp(Context context, String pkgName) {
        try {
            return context.getPackageManager().getApplicationInfo(pkgName, 0).targetSdkVersion
+2 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
 */
package com.android.bluetooth.a2dp;

import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothCodecConfig;
@@ -204,6 +205,7 @@ public class A2dpNativeInterface {
        sendMessageToService(event);
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    private boolean isMandatoryCodecPreferred(byte[] address) {
        A2dpService service = A2dpService.getA2dpService();
        if (service != null) {
+29 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.Manifest.permission.BLUETOOTH_CONNECT;

import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;

import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothA2dp.OptionalCodecsPreferenceStatus;
import android.bluetooth.BluetoothA2dp.OptionalCodecsSupportStatus;
@@ -239,6 +240,7 @@ public class A2dpService extends ProfileService {
        sA2dpService = instance;
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean connect(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return false;
@@ -293,6 +295,7 @@ public class A2dpService extends ProfileService {
     * @param device is the device with which we would like to disconnect a2dp
     * @return true if profile disconnected, false if device not connected over a2dp
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean disconnect(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return false;
@@ -312,6 +315,7 @@ public class A2dpService extends ProfileService {
        }
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public List<BluetoothDevice> getConnectedDevices() {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return new ArrayList<>(0);
@@ -395,6 +399,7 @@ public class A2dpService extends ProfileService {
        return true;
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return new ArrayList<>(0);
@@ -445,6 +450,7 @@ public class A2dpService extends ProfileService {
        }
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public int getConnectionState(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return BluetoothProfile.STATE_DISCONNECTED;
@@ -458,6 +464,7 @@ public class A2dpService extends ProfileService {
        }
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    private void removeActiveDevice(boolean forceStopPlayingAudio) {
        synchronized (mActiveSwitchingGuard) {
            BluetoothDevice previousActiveDevice = null;
@@ -500,6 +507,7 @@ public class A2dpService extends ProfileService {
     * @return true on success, false on error
     */
    @VisibleForTesting
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean setSilenceMode(BluetoothDevice device, boolean silence) {
        if (DBG) {
            Log.d(TAG, "setSilenceMode(" + device + "): " + silence);
@@ -523,6 +531,7 @@ public class A2dpService extends ProfileService {
     * @param device the active device
     * @return true on success, otherwise false
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public boolean setActiveDevice(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return false;
@@ -614,6 +623,7 @@ public class A2dpService extends ProfileService {
     *
     * @return the active device or null if no device is active
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public BluetoothDevice getActiveDevice() {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return null;
@@ -644,6 +654,10 @@ public class A2dpService extends ProfileService {
     * @param connectionPolicy is the connection policy to set to for this profile
     * @return true if connectionPolicy is set, false on error
     */
    @RequiresPermission(allOf = {
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
                "Need BLUETOOTH_PRIVILEGED permission");
@@ -686,6 +700,7 @@ public class A2dpService extends ProfileService {
    }


    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void setAvrcpAbsoluteVolume(int volume) {
        // TODO (apanicke): Instead of using A2DP as a middleman for volume changes, add a binder
        // service to the new AVRCP Profile and have the audio manager use that instead.
@@ -695,6 +710,7 @@ public class A2dpService extends ProfileService {
        }
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    boolean isA2dpPlaying(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return false;
@@ -719,6 +735,7 @@ public class A2dpService extends ProfileService {
     * @return the current codec status
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return null;
@@ -749,6 +766,7 @@ public class A2dpService extends ProfileService {
     * @param codecConfig the codec configuration preference
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void setCodecConfigPreference(BluetoothDevice device,
                                         BluetoothCodecConfig codecConfig) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
@@ -784,6 +802,7 @@ public class A2dpService extends ProfileService {
     * active A2DP Bluetooth device.
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void enableOptionalCodecs(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return;
@@ -817,6 +836,7 @@ public class A2dpService extends ProfileService {
     * active A2DP Bluetooth device.
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void disableOptionalCodecs(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return;
@@ -852,6 +872,7 @@ public class A2dpService extends ProfileService {
     * {@link OptionalCodecsSupportStatus#OPTIONAL_CODECS_NOT_SUPPORTED},
     * {@link OptionalCodecsSupportStatus#OPTIONAL_CODECS_SUPPORT_UNKNOWN}.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public @OptionalCodecsSupportStatus int getSupportsOptionalCodecs(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return BluetoothA2dp.OPTIONAL_CODECS_SUPPORT_UNKNOWN;
@@ -859,6 +880,7 @@ public class A2dpService extends ProfileService {
        return mDatabaseManager.getA2dpSupportsOptionalCodecs(device);
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void setSupportsOptionalCodecs(BluetoothDevice device, boolean doesSupport) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return;
@@ -877,6 +899,7 @@ public class A2dpService extends ProfileService {
     * {@link OptionalCodecsPreferenceStatus#OPTIONAL_CODECS_PREF_DISABLED},
     * {@link OptionalCodecsPreferenceStatus#OPTIONAL_CODECS_PREF_UNKNOWN}.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public @OptionalCodecsPreferenceStatus int getOptionalCodecsEnabled(BluetoothDevice device) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
            return BluetoothA2dp.OPTIONAL_CODECS_PREF_UNKNOWN;
@@ -893,6 +916,7 @@ public class A2dpService extends ProfileService {
     * {@link OptionalCodecsPreferenceStatus#OPTIONAL_CODECS_PREF_DISABLED},
     * {@link OptionalCodecsPreferenceStatus#OPTIONAL_CODECS_PREF_UNKNOWN}.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void setOptionalCodecsEnabled(BluetoothDevice device,
            @OptionalCodecsPreferenceStatus int value) {
        if (!Utils.checkConnectPermissionForPreflight(this)) {
@@ -915,6 +939,7 @@ public class A2dpService extends ProfileService {
     * {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_OFFLOAD},
     * {@link BluetoothA2dp#DYNAMIC_BUFFER_SUPPORT_A2DP_SOFTWARE_ENCODING}.
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    public int getDynamicBufferSupport() {
        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
                "Need BLUETOOTH_PRIVILEGED permission");
@@ -926,6 +951,7 @@ public class A2dpService extends ProfileService {
     *
     * @return BufferConstraints
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    public BufferConstraints getBufferConstraints() {
        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
                "Need BLUETOOTH_PRIVILEGED permission");
@@ -939,6 +965,7 @@ public class A2dpService extends ProfileService {
     * @param value buffer millis
     * @return true if the settings is successful, false otherwise
     */
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED)
    public boolean setBufferLengthMillis(int codec, int value) {
        enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED,
                "Need BLUETOOTH_PRIVILEGED permission");
@@ -1151,6 +1178,7 @@ public class A2dpService extends ProfileService {
     * @param device the device to change optional codec status
     */
    @VisibleForTesting
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void updateOptionalCodecsSupport(BluetoothDevice device) {
        int previousSupport = getSupportsOptionalCodecs(device);
        boolean supportsOptional = false;
@@ -1202,6 +1230,7 @@ public class A2dpService extends ProfileService {
        }
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    private void connectionStateChanged(BluetoothDevice device, int fromState, int toState) {
        if ((device == null) || (fromState == toState)) {
            return;
+3 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ package com.android.bluetooth.a2dp;

import static android.Manifest.permission.BLUETOOTH_CONNECT;

import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothCodecConfig;
import android.bluetooth.BluetoothCodecStatus;
@@ -616,6 +617,7 @@ final class A2dpStateMachine extends StateMachine {

    // NOTE: This event is processed in any state
    @VisibleForTesting
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    void processCodecConfigEvent(BluetoothCodecStatus newCodecStatus) {
        BluetoothCodecConfig prevCodecConfig = null;
        BluetoothCodecStatus prevCodecStatus = mCodecStatus;
@@ -765,6 +767,7 @@ final class A2dpStateMachine extends StateMachine {
        return Integer.toString(state);
    }

    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public void dump(StringBuilder sb) {
        boolean isActive = Objects.equals(mDevice, mA2dpService.getActiveDevice());
        ProfileService.println(sb,
Loading