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

Commit 6cc61409 authored by Rahul Sabnis's avatar Rahul Sabnis Committed by Gerrit Code Review
Browse files

Merge "API rename and requires a dual mode audio device for preferred audio profile API calls."

parents 7eccca95 5fe5f998
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.
@@ -4270,16 +4283,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) {
@@ -4300,7 +4313,7 @@ public class AdapterService extends Service {
            }
            enforceBluetoothPrivilegedPermission(service);

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

        @Override
@@ -4386,7 +4399,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
@@ -4436,6 +4449,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) {
@@ -4467,14 +4483,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) {
@@ -4483,14 +4499,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 {
@@ -4499,7 +4515,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
@@ -70,7 +70,7 @@ package android.bluetooth {
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int isDistanceMeasurementSupported();
    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);
@@ -781,6 +781,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_NO_LE_CONNECTION = 1300; // 0x514
    field public static final int ERROR_PROFILE_NOT_CONNECTED = 14; // 0xe
+14 −10
Original line number Diff line number Diff line
@@ -5058,6 +5058,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 {}
@@ -5070,7 +5071,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
@@ -5160,8 +5163,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>
@@ -5214,11 +5218,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.
@@ -5235,8 +5239,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");
@@ -5247,7 +5251,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
@@ -575,6 +575,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
@@ -289,5 +289,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);
}