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

Commit 5fe5f998 authored by Rahul Sabnis's avatar Rahul Sabnis
Browse files

API rename and requires a dual mode audio device for preferred audio

profile API calls.

This CL renames BluetoothAdapter#notifyPreferredAudioProfileChangeApplied
to BluetoothAdapter#notifyActiveDeviceChangeApplied.

Tag: #feature
Bug: 265031867
Test: atest BluetoothAdapterTest
Change-Id: Iedd78401144bd8bbffc92316b653011c4f4ec4dc
parent 73f82a17
Loading
Loading
Loading
Loading
+27 −11
Original line number Diff line number Diff line
@@ -1055,6 +1055,19 @@ public class AdapterService extends Service {
        }
    }

    /**
     * Checks whether the remote device is a dual mode audio sink device (supports both classic and
     * LE Audio sink roles.
     *
     * @param device the remote device
     * @return {@code true} if it's a dual mode audio device, {@code false} otherwise
     */
    private boolean isDualModeAudioSinkDevice(BluetoothDevice device) {
        return isProfileSupported(device, BluetoothProfile.LE_AUDIO)
                && mLeAudioService != null && (isProfileSupported(device, BluetoothProfile.HEADSET)
                || isProfileSupported(device, BluetoothProfile.A2DP));
    }

    /**
     * Checks whether the local and remote device support a connection for duplex audio (input and
     * output) over HFP or LE Audio.
@@ -4246,16 +4259,16 @@ public class AdapterService extends Service {
        }

        @Override
        public void notifyPreferredAudioProfileChangeApplied(BluetoothDevice device,
        public void notifyActiveDeviceChangeApplied(BluetoothDevice device,
                AttributionSource source, SynchronousResultReceiver receiver) {
            try {
                receiver.send(notifyPreferredAudioProfileChangeApplied(device, source));
                receiver.send(notifyActiveDeviceChangeApplied(device, source));
            } catch (RuntimeException e) {
                receiver.propagateException(e);
            }
        }

        private int notifyPreferredAudioProfileChangeApplied(BluetoothDevice device,
        private int notifyActiveDeviceChangeApplied(BluetoothDevice device,
                AttributionSource source) {
            AdapterService service = getService();
            if (service == null) {
@@ -4276,7 +4289,7 @@ public class AdapterService extends Service {
            }
            enforceBluetoothPrivilegedPermission(service);

            return service.notifyPreferredAudioProfileChangeApplied(device);
            return service.notifyActiveDeviceChangeApplied(device);
        }

        @Override
@@ -4362,7 +4375,7 @@ public class AdapterService extends Service {
     * @return a Bundle containing the preferred audio profiles for the device
     */
    private Bundle getPreferredAudioProfiles(BluetoothDevice device) {
        if (mLeAudioService == null) {
        if (mLeAudioService == null || !isDualModeAudioSinkDevice(device)) {
            return Bundle.EMPTY;
        }
        // Gets the lead device in the CSIP group to set the preference
@@ -4412,6 +4425,9 @@ public class AdapterService extends Service {
        if (mLeAudioService == null) {
            return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED;
        }
        if (!isDualModeAudioSinkDevice(device)) {
            return BluetoothStatusCodes.ERROR_NOT_DUAL_MODE_AUDIO_DEVICE;
        }
        // Gets the lead device in the CSIP group to set the preference
        BluetoothDevice groupLead = mLeAudioService.getLeadDevice(device);
        if (groupLead == null) {
@@ -4443,14 +4459,14 @@ public class AdapterService extends Service {
    }

    /**
     * Notification from the audio framework that a preferred audio profile change has taken effect.
     * See {@link BluetoothAdapter#notifyPreferredAudioProfileChangeApplied(BluetoothDevice)} for
     * Notification from the audio framework that an active device change has taken effect.
     * See {@link BluetoothAdapter#notifyActiveDeviceChangeApplied(BluetoothDevice)} for
     * more details.
     *
     * @param device the remote device whose preferred audio profiles have been changed
     * @return whether the Bluetooth stack acknowledged the change successfully
     */
    private int notifyPreferredAudioProfileChangeApplied(BluetoothDevice device) {
    private int notifyActiveDeviceChangeApplied(BluetoothDevice device) {
        // Gets the lead device in the CSIP group to set the preference
        BluetoothDevice groupLead = mLeAudioService.getLeadDevice(device);
        if (groupLead == null) {
@@ -4459,14 +4475,14 @@ public class AdapterService extends Service {

        synchronized (mDevicesPendingAudioProfileChanges) {
            if (!mDevicesPendingAudioProfileChanges.contains(groupLead)) {
                Log.e(TAG, "notifyPreferredAudioProfileChangeApplied, but no pending request for "
                Log.e(TAG, "notifyActiveDeviceChangeApplied, but no pending request for "
                        + "device: " + groupLead);
                return BluetoothStatusCodes.ERROR_UNKNOWN;
            }

            if (mPreferredAudioProfilesCallbacks != null) {
                int n = mPreferredAudioProfilesCallbacks.beginBroadcast();
                debugLog("notifyPreferredAudioProfileChangeApplied() - Broadcasting audio profile "
                debugLog("notifyActiveDeviceChangeApplied() - Broadcasting audio profile "
                        + "change applied to device: " + groupLead + " to " + n + " receivers.");
                for (int i = 0; i < n; i++) {
                    try {
@@ -4475,7 +4491,7 @@ public class AdapterService extends Service {
                                        getPreferredAudioProfiles(device),
                                        BluetoothStatusCodes.SUCCESS);
                    } catch (RemoteException e) {
                        debugLog("notifyPreferredAudioProfileChangeApplied() - Callback #" + i
                        debugLog("notifyActiveDeviceChangeApplied() - Callback #" + i
                                + " failed (" + e + ")");
                    }
                }
+2 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ package android.bluetooth {
    method public boolean isBleScanAlwaysAvailable();
    method public boolean isLeEnabled();
    method @NonNull public static String nameForState(int);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int notifyPreferredAudioProfileChangeApplied(@NonNull android.bluetooth.BluetoothDevice);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int notifyActiveDeviceChangeApplied(@NonNull android.bluetooth.BluetoothDevice);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean registerBluetoothConnectionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.BluetoothConnectionCallback);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int registerPreferredAudioProfilesChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.PreferredAudioProfilesChangedCallback);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int);
@@ -734,6 +734,7 @@ package android.bluetooth {
    field public static final int ERROR_LE_CONTENT_METADATA_INVALID_PROGRAM_INFO = 1204; // 0x4b4
    field public static final int ERROR_LOCAL_NOT_ENOUGH_RESOURCES = 22; // 0x16
    field public static final int ERROR_NOT_ACTIVE_DEVICE = 12; // 0xc
    field public static final int ERROR_NOT_DUAL_MODE_AUDIO_DEVICE = 3000; // 0xbb8
    field public static final int ERROR_NO_ACTIVE_DEVICES = 13; // 0xd
    field public static final int ERROR_PROFILE_NOT_CONNECTED = 14; // 0xe
    field public static final int ERROR_REMOTE_LINK_ERROR = 25; // 0x19
+14 −10
Original line number Diff line number Diff line
@@ -4984,6 +4984,7 @@ public final class BluetoothAdapter {
            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
            BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED,
            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
            BluetoothStatusCodes.ERROR_NOT_DUAL_MODE_AUDIO_DEVICE,
            BluetoothStatusCodes.ERROR_UNKNOWN
    })
    public @interface SetPreferredAudioProfilesReturnValues {}
@@ -4996,7 +4997,9 @@ public final class BluetoothAdapter {
     * <p>
     * Note: apps that invoke profile-specific audio APIs are not subject to the preference noted
     * here. These preferences will also be ignored if the remote device is not simultaneously
     * connected to a classic audio profile (A2DP and/or HFP) and LE Audio at the same time.
     * connected to a classic audio profile (A2DP and/or HFP) and LE Audio at the same time. If the
     * remote device does not support both BR/EDR audio and LE Audio, this API returns
     * {@link BluetoothStatusCodes#ERROR_NOT_DUAL_MODE_AUDIO_DEVICE}.
     * <p>
     * The Bundle is expected to contain the following mappings:
     * 1. For key {@link #AUDIO_MODE_OUTPUT_ONLY}, it expects an integer value of either
@@ -5086,8 +5089,9 @@ public final class BluetoothAdapter {
     * <p>
     * An audio capable device must support at least one audio mode with a preferred audio profile.
     * If a device does not support an audio mode, the audio mode will be omitted from the keys of
     * the Bundle. If the device is not recognized as an audio capable device (e.g. because it is
     * not bonded or does not support any audio profiles), this API returns an empty Bundle.
     * the Bundle. If the device is not recognized as a dual mode audio capable device (e.g. because
     * it is not bonded, does not support any audio profiles, or does not support both BR/EDR audio
     * and LE Audio), this API returns an empty Bundle.
     * <p>
     * The Bundle can contain the following mappings:
     * <ul>
@@ -5140,11 +5144,11 @@ public final class BluetoothAdapter {
    }

    /**
     * Called by audio framework to inform the Bluetooth stack that a request from
     * {@link #setPreferredAudioProfiles(BluetoothDevice, Bundle)} has taken effect in the audio
     * framework. After this is called, the Bluetooth stack will invoke
     * Called by audio framework to inform the Bluetooth stack that an active device change has
     * taken effect. If this active device change is triggered by an app calling
     * {@link #setPreferredAudioProfiles(BluetoothDevice, Bundle)}, the Bluetooth stack will invoke
     * {@link PreferredAudioProfilesChangedCallback#onPreferredAudioProfilesChanged(
     * BluetoothDevice, Bundle, int)}.
     * BluetoothDevice, Bundle, int)} if all requested changes for the device have been applied.
     * <p>
     * This method will return
     * {@link BluetoothStatusCodes#ERROR_BLUETOOTH_NOT_ALLOWED} if called outside system server.
@@ -5161,8 +5165,8 @@ public final class BluetoothAdapter {
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    public int notifyPreferredAudioProfileChangeApplied(@NonNull BluetoothDevice device) {
        if (DBG) Log.d(TAG, "notifyPreferredProfileChangeApplied(" + device + ")");
    public int notifyActiveDeviceChangeApplied(@NonNull BluetoothDevice device) {
        if (DBG) Log.d(TAG, "notifyActiveDeviceChangeApplied(" + device + ")");
        Objects.requireNonNull(device, "device cannot be null");
        if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
            throw new IllegalArgumentException("device cannot have an invalid address");
@@ -5173,7 +5177,7 @@ public final class BluetoothAdapter {
        try {
            if (mService != null) {
                final SynchronousResultReceiver<Integer> recv = SynchronousResultReceiver.get();
                mService.notifyPreferredAudioProfileChangeApplied(device,
                mService.notifyActiveDeviceChangeApplied(device,
                        mAttributionSource, recv);
                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
            }
+9 −0
Original line number Diff line number Diff line
@@ -556,6 +556,15 @@ public final class BluetoothStatusCodes {
    @SystemApi
    public static final int RFCOMM_LISTENER_NO_SOCKET_AVAILABLE = 2005;

    /**
     * Error code indicating that this operation is not allowed because the remote device does not
     * support both BR/EDR audio and BLE Audio.
     *
     * @hide
     */
    @SystemApi
    public static final int ERROR_NOT_DUAL_MODE_AUDIO_DEVICE = 3000;

    /**
     * Indicates that an unknown error has occurred.
     */
+1 −1
Original line number Diff line number Diff line
@@ -287,5 +287,5 @@ interface IBluetooth
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    oneway void unregisterPreferredAudioProfilesChangedCallback(in IBluetoothPreferredAudioProfilesCallback callback, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})")
    oneway void notifyPreferredAudioProfileChangeApplied(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    oneway void notifyActiveDeviceChangeApplied(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
}