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

Commit 9406a7ed authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Automerger Merge Worker
Browse files

leaudio: Improve Volume Control API am: b99f7ece

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/1954637

Change-Id: I4bb037fe351df7e15b8c46c8e11ada5702dcfab3
parents 2265b5b2 b99f7ece
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -410,8 +410,8 @@ public class VolumeControlService extends ProfileService {
                .getProfileConnectionPolicy(device, BluetoothProfile.VOLUME_CONTROL);
    }

    void setVolume(BluetoothDevice device, int volume) {
        mVolumeControlNativeInterface.setVolume(device, volume);
    void setVolumeOffset(BluetoothDevice device, int volumeOffset) {
        // TODO Implement
    }

    /**
@@ -728,12 +728,12 @@ public class VolumeControlService extends ProfileService {
        }

        @Override
        public void setVolume(BluetoothDevice device, int volume, AttributionSource source,
                SynchronousResultReceiver receiver) {
        public void setVolumeOffset(BluetoothDevice device, int volumeOffset,
                AttributionSource source, SynchronousResultReceiver receiver) {
            try {
                VolumeControlService service = getService(source);
                if (service != null) {
                    service.setVolume(device, volume);
                    service.setVolumeOffset(device, volumeOffset);
                }
                receiver.send(null);
            } catch (RuntimeException e) {
+8 −1
Original line number Diff line number Diff line
@@ -316,11 +316,18 @@ package android.bluetooth {
    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) protected void finalize();
    method @NonNull @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean isVolumeOffsetAvailable(@NonNull android.bluetooth.BluetoothDevice);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothVolumeControl.Callback);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolume(@Nullable android.bluetooth.BluetoothDevice, @IntRange(from=0, to=255) int);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void setVolumeOffset(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0xffffff01, to=255) int);
    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public void unregisterCallback(@NonNull android.bluetooth.BluetoothVolumeControl.Callback);
    field @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.volume-control.profile.action.CONNECTION_STATE_CHANGED";
  }

  public static interface BluetoothVolumeControl.Callback {
    method public void onVolumeOffsetChanged(@NonNull android.bluetooth.BluetoothDevice, @IntRange(from=0xffffff01, to=255) int);
  }

  public final class BufferConstraint implements android.os.Parcelable {
    ctor public BufferConstraint(int, int, int);
    method public int describeContents();
+116 −7
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package android.bluetooth;
import static android.bluetooth.BluetoothUtils.getSyncTimeout;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -40,6 +41,7 @@ import com.android.modules.utils.SynchronousResultReceiver;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeoutException;

/**
@@ -58,6 +60,33 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose

    private CloseGuard mCloseGuard;

    /**
     * This class provides a callback that is invoked when volume offset value changes on
     * the remote device.
     *
     * <p> In order to balance volume on the group of Le Audio devices,
     * Volume Offset Control Service (VOCS) shall be used. User can verify
     * if the remote device supports VOCS by calling {@link #isVolumeOffsetAvailable(device)}.
     *
     * @hide
     */
    @SystemApi
    public interface Callback {
        /**
         * Callback invoked when callback is registered and when volume offset
         * changes on the remote device. Change can be triggered autonomously by the remote device
         * or after volume offset change on the user request done by calling
         * {@link #setVolumeOffset(device, volumeOffset)}
         *
         * @param device remote device whose volume offset changed
         * @param volumeOffset latest volume offset for this device
         * @hide
         */
        @SystemApi
        void onVolumeOffsetChanged(@NonNull BluetoothDevice device,
                                   @IntRange(from = -255, to = 255) int volumeOffset);
    }

    /**
     * Intent used to broadcast the change in connection state of the Volume Control
     * profile.
@@ -217,10 +246,17 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
    }

    /**
     * Tells remote device to set an absolute volume.
     * Register a {@link Callback} that will be invoked during the
     * operation of this profile.
     *
     * Repeated registration of the same <var>callback</var> object will have no effect after
     * the first call to this method, even when the <var>executor</var> is different. API caller
     * would have to call {@link #unregisterCallback(Callback)} with
     * the same callback object before registering it again.
     *
     * @param volume Absolute volume to be set on remote device.
     *               Minimum value is 0 and maximum value is 255
     * @param executor an {@link Executor} to execute given callback
     * @param callback user implementation of the {@link Callback}
     * @throws IllegalArgumentException if a null executor, sink, or callback is given
     * @hide
     */
    @SystemApi
@@ -229,9 +265,60 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    public void setVolume(@Nullable BluetoothDevice device,
            @IntRange(from = 0, to = 255) int volume) {
        if (DBG) log("setVolume(" + volume + ")");
    public void registerCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull Callback callback) {
        if (executor == null) {
            throw new IllegalArgumentException("executor cannot be null");
        }
        if (callback == null) {
            throw new IllegalArgumentException("callback cannot be null");
        }
        if (DBG) log("registerCallback");
        throw new UnsupportedOperationException("Not Implemented");
    }

    /**
     * Unregister the specified {@link Callback}.
     * <p>The same {@link Callback} object used when calling
     * {@link #registerCallback(Executor, Callback)} must be used.
     *
     * <p>Callbacks are automatically unregistered when application process goes away
     *
     * @param callback user implementation of the {@link Callback}
     * @throws IllegalArgumentException when callback is null or when no callback is registered
     * @hide
     */
    @SystemApi
    @RequiresBluetoothConnectPermission
    @RequiresPermission(allOf = {
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    public void unregisterCallback(@NonNull Callback callback) {
        if (callback == null) {
            throw new IllegalArgumentException("callback cannot be null");
        }
        if (DBG) log("unregisterCallback");
        throw new UnsupportedOperationException("Not Implemented");
    }

    /**
     * Tells the remote device to set a volume offset to the absolute volume.
     *
     * @param device {@link BluetoothDevice} representing the remote device
     * @param volumeOffset volume offset to be set on the remote device
     *
     * @hide
     */
    @SystemApi
    @RequiresBluetoothConnectPermission
    @RequiresPermission(allOf = {
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    public void setVolumeOffset(@NonNull BluetoothDevice device,
            @IntRange(from = -255, to = 255) int volumeOffset) {
        if (DBG) log("setVolumeOffset(" + device  + " volumeOffset: " + volumeOffset + ")");
        final IBluetoothVolumeControl service = getService();
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
@@ -239,7 +326,7 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
        } else if (isEnabled()) {
            try {
                final SynchronousResultReceiver recv = new SynchronousResultReceiver();
                service.setVolume(device, volume, mAttributionSource, recv);
                service.setVolumeOffset(device, volumeOffset, mAttributionSource, recv);
                recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(null);
            } catch (RemoteException | TimeoutException e) {
                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
@@ -247,6 +334,28 @@ public final class BluetoothVolumeControl implements BluetoothProfile, AutoClose
        }
    }

    /**
     * Provides information about the possibility to set volume offset on the remote device.
     * If the remote device supports Volume Offset Control Service, it is automatically
     * connected.
     *
     * @param device {@link BluetoothDevice} representing the remote device
     * @return {@code true} if volume offset function is supported and available to use on the
     *         remote device. When Bluetooth is off, the return value should always be
     *         {@code false}.
     * @hide
     */
    @SystemApi
    @RequiresBluetoothConnectPermission
    @RequiresPermission(allOf = {
            android.Manifest.permission.BLUETOOTH_CONNECT,
            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
    })
    public boolean isVolumeOffsetAvailable(@NonNull BluetoothDevice device) {
        if (DBG) log("isVolumeOffsetAvailable(" + device + ")");
        return false;
    }

    /**
     * Set connection policy of the profile
     *
+1 −1
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ oneway interface IBluetoothVolumeControl {
    void getConnectionPolicy(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);

    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    void setVolume(in BluetoothDevice device, int volume, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    void setVolumeOffset(in BluetoothDevice device, int volumeOffset, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    void setVolumeGroup(int group_id, int volume, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
}