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

Commit 031513b4 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

VolumeControlService: Fix setting volume on active group

Volume control service was missing information about group being active
and was no able to change the volume for the active group.

Issue could be observed after phone restart or when switching between
two LE HS

Bug: 302142886
Test: atest VolumeControlServiceTest
Tag: #feature
Change-Id: Idc11e503d2c0cea67ce0738fabde0adb0797a358
parent 698e6238
Loading
Loading
Loading
Loading
+34 −19
Original line number Diff line number Diff line
@@ -495,17 +495,23 @@ public class LeAudioService extends ProfileService {
        sLeAudioService = instance;
    }

    @VisibleForTesting
    int getAudioDeviceGroupVolume(int groupId) {
    VolumeControlService getVolumeControlService() {
        if (mVolumeControlService == null) {
            mVolumeControlService = mServiceFactory.getVolumeControlService();
            if (mVolumeControlService == null) {
                Log.e(TAG, "Volume control service is not available");
                return IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME;
            }
        }
        return mVolumeControlService;
    }

        return mVolumeControlService.getAudioDeviceGroupVolume(groupId);
    @VisibleForTesting
    int getAudioDeviceGroupVolume(int groupId) {
        VolumeControlService volumeControlService = getVolumeControlService();
        if (volumeControlService == null) {
            return IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME;
        }
        return volumeControlService.getAudioDeviceGroupVolume(groupId);
    }

    LeAudioDeviceDescriptor createDeviceDescriptor(BluetoothDevice device,
@@ -1224,6 +1230,20 @@ public class LeAudioService extends ProfileService {
                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
        sendBroadcast(intent, BLUETOOTH_CONNECT);
    }

    void notifyVolumeControlServiceAboutActiveGroup(BluetoothDevice device) {
        VolumeControlService volumeControlService = getVolumeControlService();
        if (volumeControlService == null) {
            return;
        }

        if (mExposedActiveDevice != null) {
            volumeControlService.setGroupActive(getGroupId(mExposedActiveDevice), false);
        }

        volumeControlService.setGroupActive(getGroupId(device), true);
    }

    /**
     * Send broadcast intent about LeAudio active device.
     * This is called when AudioManager confirms, LeAudio device
@@ -1238,6 +1258,7 @@ public class LeAudioService extends ProfileService {

        mAdapterService.handleActiveDeviceChange(BluetoothProfile.LE_AUDIO, device);
        sentActiveDeviceChangeIntent(device);
        notifyVolumeControlServiceAboutActiveGroup(device);
        mExposedActiveDevice = device;
    }

@@ -2711,11 +2732,9 @@ public class LeAudioService extends ProfileService {
            Log.d(TAG, "setLeAudioGattClientProfilesPolicy for device " + device + " to policy="
                    + connectionPolicy);
        }
        if (mVolumeControlService == null) {
            mVolumeControlService = mServiceFactory.getVolumeControlService();
        }
        if (mVolumeControlService != null) {
            mVolumeControlService.setConnectionPolicy(device, connectionPolicy);
        VolumeControlService volumeControlService = getVolumeControlService();
        if (volumeControlService != null) {
            volumeControlService.setConnectionPolicy(device, connectionPolicy);
        }

        if (mHapClientService == null) {
@@ -2812,11 +2831,9 @@ public class LeAudioService extends ProfileService {
            return;
        }

        if (mVolumeControlService == null) {
            mVolumeControlService = mServiceFactory.getVolumeControlService();
        }
        if (mVolumeControlService != null) {
            mVolumeControlService.setGroupVolume(currentlyActiveGroupId, volume);
        VolumeControlService volumeControlService = getVolumeControlService();
        if (volumeControlService != null) {
            volumeControlService.setGroupVolume(currentlyActiveGroupId, volume);
        }
    }

@@ -2938,11 +2955,9 @@ public class LeAudioService extends ProfileService {
    }

    private void notifyGroupNodeAdded(BluetoothDevice device, int groupId) {
        if (mVolumeControlService == null) {
            mVolumeControlService = mServiceFactory.getVolumeControlService();
        }
        if (mVolumeControlService != null) {
            mVolumeControlService.handleGroupNodeAdded(groupId, device);
        VolumeControlService volumeControlService = getVolumeControlService();
        if (volumeControlService != null) {
            volumeControlService.handleGroupNodeAdded(groupId, device);
        }

        if (mLeAudioCallbacks != null) {
+43 −1
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@
package com.android.bluetooth.vc;

import static android.Manifest.permission.BLUETOOTH_CONNECT;

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

import android.annotation.RequiresPermission;
@@ -639,6 +638,30 @@ public class VolumeControlService extends ProfileService {
                        IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME);
    }

    /**
     * This should be called by LeAudioService when LE Audio group change it
     * active state.
     *
     * @param groupId   the group identifier
     * @param active    indicator if group is active or not
     */
    public void setGroupActive(int groupId, boolean active) {
        if (DBG) {
            Log.d(TAG, "setGroupActive: " + groupId + ", active: " + active);
        }
        if (!active) {
            /* For now we don't need to handle group inactivation */
            return;
        }

        int groupVolume = getGroupVolume(groupId);
        Boolean groupMute = getGroupMute(groupId);

        if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) {
            updateGroupCacheAndAudioSystem(groupId, groupVolume, groupMute);
        }
    }

    /**
     * @param groupId the group identifier
     */
@@ -1384,6 +1407,25 @@ public class VolumeControlService extends ProfileService {
            }
        }

        @Override
        public void setGroupActive(
                int groupId,
                boolean active,
                AttributionSource source,
                SynchronousResultReceiver receiver) {
            try {
                Objects.requireNonNull(source, "source cannot be null");
                Objects.requireNonNull(receiver, "receiver cannot be null");

                VolumeControlService service = getService(source);
                receiver.send(null);
                if (service != null) {
                    service.setGroupActive(groupId, active);
                }
            } catch (RuntimeException e) {
                receiver.propagateException(e);
            }
        }

        @Override
        public void mute(BluetoothDevice device,  AttributionSource source,
+37 −0
Original line number Diff line number Diff line
@@ -677,6 +677,43 @@ public class VolumeControlServiceTest {
        Assert.assertEquals(volume, mService.getGroupVolume(groupId));
    }

    /** Test Active Group change */
    @Test
    public void testActiveGroupChange() throws Exception {
        int groupId_1 = 1;
        int volume_groupId_1 = 6;

        int groupId_2 = 2;
        int volume_groupId_2 = 20;

        Assert.assertEquals(-1, mService.getGroupVolume(groupId_1));
        Assert.assertEquals(-1, mService.getGroupVolume(groupId_2));
        SynchronousResultReceiver<Void> voidRecv = SynchronousResultReceiver.get();
        mServiceBinder.setGroupVolume(groupId_1, volume_groupId_1, mAttributionSource, voidRecv);
        voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS));

        voidRecv = SynchronousResultReceiver.get();
        mServiceBinder.setGroupVolume(groupId_2, volume_groupId_2, mAttributionSource, voidRecv);
        voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS));

        voidRecv = SynchronousResultReceiver.get();
        mServiceBinder.setGroupActive(groupId_1, true, mAttributionSource, voidRecv);
        voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS));

        // Expected index for STREAM_MUSIC
        int expectedVol =
                (int) Math.round((double) (volume_groupId_1 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL);
        verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedVol), anyInt());

        voidRecv = SynchronousResultReceiver.get();
        mServiceBinder.setGroupActive(groupId_2, true, mAttributionSource, voidRecv);

        expectedVol =
                (int) Math.round((double) (volume_groupId_2 * MEDIA_MAX_VOL) / BT_LE_AUDIO_MAX_VOL);
        verify(mAudioManager, times(1)).setStreamVolume(anyInt(), eq(expectedVol), anyInt());
        voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS));
    }

    /**
     * Test Volume Control Mute cache.
     */
+3 −0
Original line number Diff line number Diff line
@@ -56,6 +56,9 @@ oneway interface IBluetoothVolumeControl {
    void setGroupVolume(int group_id, int volume, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    void getGroupVolume(int group_id, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    void setGroupActive(int group_id, boolean active, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);


    @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
    void mute(in BluetoothDevice device, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);