Loading Android.bp +7 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ android_app { srcs: [ "src/**/*.java", ":statslog-bluetooth-java-gen", ":libbluetooth-binder-aidl", ], platform_apis: true, certificate: "platform", Loading @@ -83,6 +84,7 @@ android_app { libs: [ "javax.obex", "services.net", "unsupportedappusage", ], static_libs: [ "com.android.vcard", Loading Loading @@ -113,6 +115,11 @@ android_app { "//apex_available:platform", "com.android.bluetooth.updatable", ], errorprone: { javacflags: [ "-Xep:AndroidFrameworkRequiresPermission:ERROR", ], }, } genrule { Loading src/com/android/bluetooth/Utils.java +78 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading @@ -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); Loading @@ -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( Loading @@ -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); Loading @@ -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( Loading @@ -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) { Loading Loading @@ -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)) { Loading @@ -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)) { Loading Loading @@ -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)) { Loading @@ -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; Loading @@ -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) Loading @@ -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 Loading src/com/android/bluetooth/a2dp/A2dpNativeInterface.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading src/com/android/bluetooth/a2dp/A2dpService.java +29 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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"); Loading Loading @@ -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. Loading @@ -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; Loading @@ -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; Loading Loading @@ -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)) { Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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)) { Loading @@ -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"); Loading @@ -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"); Loading @@ -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"); Loading Loading @@ -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; Loading Loading @@ -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; Loading src/com/android/bluetooth/a2dp/A2dpStateMachine.java +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading
Android.bp +7 −0 Original line number Diff line number Diff line Loading @@ -75,6 +75,7 @@ android_app { srcs: [ "src/**/*.java", ":statslog-bluetooth-java-gen", ":libbluetooth-binder-aidl", ], platform_apis: true, certificate: "platform", Loading @@ -83,6 +84,7 @@ android_app { libs: [ "javax.obex", "services.net", "unsupportedappusage", ], static_libs: [ "com.android.vcard", Loading Loading @@ -113,6 +115,11 @@ android_app { "//apex_available:platform", "com.android.bluetooth.updatable", ], errorprone: { javacflags: [ "-Xep:AndroidFrameworkRequiresPermission:ERROR", ], }, } genrule { Loading
src/com/android/bluetooth/Utils.java +78 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading @@ -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); Loading @@ -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( Loading @@ -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); Loading @@ -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( Loading @@ -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) { Loading Loading @@ -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)) { Loading @@ -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)) { Loading Loading @@ -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)) { Loading @@ -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; Loading @@ -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) Loading @@ -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 Loading
src/com/android/bluetooth/a2dp/A2dpNativeInterface.java +2 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading
src/com/android/bluetooth/a2dp/A2dpService.java +29 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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"); Loading Loading @@ -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. Loading @@ -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; Loading @@ -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; Loading Loading @@ -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)) { Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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)) { Loading @@ -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"); Loading @@ -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"); Loading @@ -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"); Loading Loading @@ -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; Loading Loading @@ -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; Loading
src/com/android/bluetooth/a2dp/A2dpStateMachine.java +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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