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

Commit c0b94efa authored by Jakub Tyszkowski's avatar Jakub Tyszkowski Committed by Automerger Merge Worker
Browse files

Merge changes Ia60c7255,I5d111686 am: 6c8ad601 am: 41f8372c am: d9bb2722 am: 005770aa

parents 9741e943 005770aa
Loading
Loading
Loading
Loading
+98 −23
Original line number Original line Diff line number Diff line
@@ -191,6 +191,7 @@ public class VolumeControlService extends ProfileService {
    private final Map<BluetoothDevice, VolumeControlOffsetDescriptor> mAudioOffsets =
    private final Map<BluetoothDevice, VolumeControlOffsetDescriptor> mAudioOffsets =
                                                                            new HashMap<>();
                                                                            new HashMap<>();
    private final Map<Integer, Integer> mGroupVolumeCache = new HashMap<>();
    private final Map<Integer, Integer> mGroupVolumeCache = new HashMap<>();
    private final Map<Integer, Boolean> mGroupMuteCache = new HashMap<>();


    private BroadcastReceiver mBondStateChangedReceiver;
    private BroadcastReceiver mBondStateChangedReceiver;
    private BroadcastReceiver mConnectionStateChangedReceiver;
    private BroadcastReceiver mConnectionStateChangedReceiver;
@@ -253,6 +254,7 @@ public class VolumeControlService extends ProfileService {


        mAudioOffsets.clear();
        mAudioOffsets.clear();
        mGroupVolumeCache.clear();
        mGroupVolumeCache.clear();
        mGroupMuteCache.clear();
        mCallbacks = new RemoteCallbackList<IBluetoothVolumeControlCallback>();
        mCallbacks = new RemoteCallbackList<IBluetoothVolumeControlCallback>();


        // Mark service as started
        // Mark service as started
@@ -308,6 +310,7 @@ public class VolumeControlService extends ProfileService {


        mAudioOffsets.clear();
        mAudioOffsets.clear();
        mGroupVolumeCache.clear();
        mGroupVolumeCache.clear();
        mGroupMuteCache.clear();


        // Clear AdapterService, VolumeControlNativeInterface
        // Clear AdapterService, VolumeControlNativeInterface
        mAudioManager = null;
        mAudioManager = null;
@@ -597,6 +600,32 @@ public class VolumeControlService extends ProfileService {


        mGroupVolumeCache.put(groupId, volume);
        mGroupVolumeCache.put(groupId, volume);
        mVolumeControlNativeInterface.setGroupVolume(groupId, volume);
        mVolumeControlNativeInterface.setGroupVolume(groupId, volume);

        // We only receive the volume change and mute state needs to be acquired manually
        Boolean isGroupMute = mGroupMuteCache.getOrDefault(groupId, false);
        Boolean isStreamMute = mAudioManager.isStreamMute(getBluetoothContextualVolumeStream());

        /* Note: AudioService keeps volume levels for each stream and for each device type,
         * however it stores the mute state only for the stream type but not for each individual
         * device type. When active device changes, it's volume level gets aplied, but mute state
         * is not, but can be either derived from the volume level or just unmuted like for A2DP.
         * Also setting volume level > 0 to audio system will implicitly unmute the stream.
         * However LeAudio devices can keep their volume level high, while keeping it mute so we
         * have to explicitly unmute the remote device.
         */
        if (!isGroupMute.equals(isStreamMute)) {
            Log.w(TAG, "Mute state mismatch, stream mute: " + isStreamMute
                    + ", device group mute: " + isGroupMute
                    + ", new volume: " + volume);
            if (isStreamMute) {
                Log.i(TAG, "Mute the group " + groupId);
                muteGroup(groupId);
            }
            if (!isStreamMute && (volume > 0)) {
                Log.i(TAG, "Unmute the group " + groupId);
                unmuteGroup(groupId);
            }
        }
    }
    }


    /**
    /**
@@ -608,6 +637,13 @@ public class VolumeControlService extends ProfileService {
                        IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME);
                        IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME);
    }
    }


    /**
     * @param groupId the group identifier
     */
    public Boolean getGroupMute(int groupId) {
        return mGroupMuteCache.getOrDefault(groupId, false);
    }

    /**
    /**
     * {@hide}
     * {@hide}
     */
     */
@@ -619,6 +655,7 @@ public class VolumeControlService extends ProfileService {
     * {@hide}
     * {@hide}
     */
     */
    public void muteGroup(int groupId) {
    public void muteGroup(int groupId) {
        mGroupMuteCache.put(groupId, true);
        mVolumeControlNativeInterface.muteGroup(groupId);
        mVolumeControlNativeInterface.muteGroup(groupId);
    }
    }


@@ -633,6 +670,7 @@ public class VolumeControlService extends ProfileService {
     * {@hide}
     * {@hide}
     */
     */
    public void unmuteGroup(int groupId) {
    public void unmuteGroup(int groupId) {
        mGroupMuteCache.put(groupId, false);
        mVolumeControlNativeInterface.unmuteGroup(groupId);
        mVolumeControlNativeInterface.unmuteGroup(groupId);
    }
    }


@@ -651,10 +689,6 @@ public class VolumeControlService extends ProfileService {
            }
            }
        }
        }


        // If group volume has already changed, the new group member should set it
        Integer groupVolume = mGroupVolumeCache.getOrDefault(groupId,
                IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME);
        if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) {
        // Correct the volume level only if device was already reported as connected.
        // Correct the volume level only if device was already reported as connected.
        boolean can_change_volume = false;
        boolean can_change_volume = false;
        synchronized (mStateMachines) {
        synchronized (mStateMachines) {
@@ -664,10 +698,23 @@ public class VolumeControlService extends ProfileService {
                        (sm.getConnectionState() == BluetoothProfile.STATE_CONNECTED);
                        (sm.getConnectionState() == BluetoothProfile.STATE_CONNECTED);
            }
            }
        }
        }

        // If group volume has already changed, the new group member should set it
        if (can_change_volume) {
        if (can_change_volume) {
            Integer groupVolume = mGroupVolumeCache.getOrDefault(groupId,
                    IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME);
            if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) {
                Log.i(TAG, "Setting value:" + groupVolume + " to " + device);
                Log.i(TAG, "Setting value:" + groupVolume + " to " + device);
                mVolumeControlNativeInterface.setVolume(device, groupVolume);
                mVolumeControlNativeInterface.setVolume(device, groupVolume);
            }
            }

            Boolean isGroupMuted = mGroupMuteCache.getOrDefault(groupId, false);
            Log.i(TAG, "Setting mute:" + isGroupMuted + " to " + device);
            if (isGroupMuted) {
                mVolumeControlNativeInterface.mute(device);
            } else {
                mVolumeControlNativeInterface.unmute(device);
            }
        }
        }
    }
    }


@@ -694,6 +741,7 @@ public class VolumeControlService extends ProfileService {
        }
        }


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


        if (!isAutonomous) {
        if (!isAutonomous) {
            /* If the change is triggered by Android device, the stream is already changed.
            /* If the change is triggered by Android device, the stream is already changed.
@@ -702,13 +750,12 @@ public class VolumeControlService extends ProfileService {
             * remote side send us wrong value - lets check it.
             * remote side send us wrong value - lets check it.
             */
             */


            if (groupVolume == volume) {
            if ((groupVolume == volume) && (groupMute == mute)) {
                Log.i(TAG, " Volume:" + volume + " confirmed by remote side.");
                Log.i(TAG, " Volume:" + volume + ", mute:" + mute + " confirmed by remote side.");
                return;
                return;
            }
            }


            if (device != null && groupVolume
            if (device != null) {
                            != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) {
                // Correct the volume level only if device was already reported as connected.
                // Correct the volume level only if device was already reported as connected.
                boolean can_change_volume = false;
                boolean can_change_volume = false;
                synchronized (mStateMachines) {
                synchronized (mStateMachines) {
@@ -718,23 +765,37 @@ public class VolumeControlService extends ProfileService {
                                (sm.getConnectionState() == BluetoothProfile.STATE_CONNECTED);
                                (sm.getConnectionState() == BluetoothProfile.STATE_CONNECTED);
                    }
                    }
                }
                }
                if (can_change_volume) {

                if (can_change_volume && (groupVolume != volume) && (groupVolume
                            != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME)) {
                    Log.i(TAG, "Setting value:" + groupVolume + " to " + device);
                    Log.i(TAG, "Setting value:" + groupVolume + " to " + device);
                    mVolumeControlNativeInterface.setVolume(device, groupVolume);
                    mVolumeControlNativeInterface.setVolume(device, groupVolume);
                }
                }
                if (can_change_volume && (groupMute != mute)) {
                    Log.i(TAG, "Setting mute:" + groupMute + " to " + device);
                    if (groupMute) {
                        mVolumeControlNativeInterface.mute(device);
                    } else {
                        mVolumeControlNativeInterface.unmute(device);
                    }
                }
            } else {
            } else {
                Log.e(TAG, "Volume changed did not succeed. Volume: " + volume
                Log.e(TAG, "Volume changed did not succeed. Volume: " + volume
                                + " expected volume: " + groupVolume);
                                + " expected volume: " + groupVolume);
            }
            }
        } else {
        } else {
            // TODO: Handle the other arguments: mute.

            /* Received group notification for autonomous change. Update cache and audio system. */
            /* Received group notification for autonomous change. Update cache and audio system. */
            mGroupVolumeCache.put(groupId, volume);
            mGroupVolumeCache.put(groupId, volume);
            mGroupMuteCache.put(groupId, mute);


            int streamType = getBluetoothContextualVolumeStream();
            int streamType = getBluetoothContextualVolumeStream();
            mAudioManager.setStreamVolume(streamType, getDeviceVolume(streamType, volume),
            int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME;
                    AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME);
            mAudioManager.setStreamVolume(streamType, getDeviceVolume(streamType, volume), flags);

            if (mAudioManager.isStreamMute(streamType) != mute) {
                int adjustment = mute ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE;
                mAudioManager.adjustStreamVolume(streamType, adjustment, flags);
            }
        }
        }
    }
    }


@@ -743,6 +804,12 @@ public class VolumeControlService extends ProfileService {
     */
     */
    public int getAudioDeviceGroupVolume(int groupId) {
    public int getAudioDeviceGroupVolume(int groupId) {
        int volume = getGroupVolume(groupId);
        int volume = getGroupVolume(groupId);
        if (getGroupMute(groupId)) {
            Log.w(TAG, "Volume level is " + volume
                    + ", but muted. Will report 0 for the audio device.");
            volume = 0;
        }

        if (volume == IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) return -1;
        if (volume == IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) return -1;
        return getDeviceVolume(getBluetoothContextualVolumeStream(), volume);
        return getDeviceVolume(getBluetoothContextualVolumeStream(), volume);
    }
    }
@@ -1036,6 +1103,13 @@ public class VolumeControlService extends ProfileService {
                if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) {
                if (groupVolume != IBluetoothVolumeControl.VOLUME_CONTROL_UNKNOWN_VOLUME) {
                    mVolumeControlNativeInterface.setVolume(device, groupVolume);
                    mVolumeControlNativeInterface.setVolume(device, groupVolume);
                }
                }

                Boolean groupMute = mGroupMuteCache.getOrDefault(groupId, false);
                if (groupMute) {
                    mVolumeControlNativeInterface.mute(device);
                } else {
                    mVolumeControlNativeInterface.unmute(device);
                }
            }
            }
        }
        }
    }
    }
@@ -1421,8 +1495,9 @@ public class VolumeControlService extends ProfileService {
            descriptor.dump(sb);
            descriptor.dump(sb);
        }
        }
        for (Map.Entry<Integer, Integer> entry : mGroupVolumeCache.entrySet()) {
        for (Map.Entry<Integer, Integer> entry : mGroupVolumeCache.entrySet()) {
            Boolean isMute = mGroupMuteCache.getOrDefault(entry.getKey(), false);
            ProfileService.println(sb, "    GroupId: " + entry.getKey() + " volume: "
            ProfileService.println(sb, "    GroupId: " + entry.getKey() + " volume: "
                            + entry.getValue());
                            + entry.getValue() + ", mute: " + isMute);
        }
        }
    }
    }
}
}
+232 −0
Original line number Original line Diff line number Diff line
@@ -607,6 +607,42 @@ public class VolumeControlServiceTest {
        testVolumeCalculations(AudioManager.STREAM_MUSIC, MEDIA_MIN_VOL, MEDIA_MAX_VOL);
        testVolumeCalculations(AudioManager.STREAM_MUSIC, MEDIA_MIN_VOL, MEDIA_MAX_VOL);
    }
    }


    /**
     * Test if autonomous Mute/Unmute propagates the event to audio manager.
     */
    @Test
    public void testAutonomousMuteUnmute() {
        int streamType = AudioManager.STREAM_MUSIC;
        int streamVol = getLeAudioVolume(19, MEDIA_MIN_VOL, MEDIA_MAX_VOL, streamType);

        // Send a message to trigger volume state changed broadcast
        final VolumeControlStackEvent stackEvent = new VolumeControlStackEvent(
                VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
        stackEvent.device = null;
        stackEvent.valueInt1 = 1;       // groupId
        stackEvent.valueInt2 = streamVol;
        stackEvent.valueBool1 = false;  // isMuted
        stackEvent.valueBool2 = true;   // isAutonomous

        doReturn(false).when(mAudioManager)
                .isStreamMute(eq(AudioManager.STREAM_MUSIC));

        // Verify that muting LeAudio device, sets the mute state on the audio device
        stackEvent.valueBool1 = true;
        mService.messageFromNative(stackEvent);
        verify(mAudioManager, times(1)).adjustStreamVolume(eq(streamType),
                eq(AudioManager.ADJUST_MUTE), anyInt());

        doReturn(true).when(mAudioManager)
                .isStreamMute(eq(AudioManager.STREAM_MUSIC));

        // Verify that unmuting LeAudio device, unsets the mute state on the audio device
        stackEvent.valueBool1 = false;
        mService.messageFromNative(stackEvent);
        verify(mAudioManager, times(1)).adjustStreamVolume(eq(streamType),
                eq(AudioManager.ADJUST_UNMUTE), anyInt());
    }

    /**
    /**
     * Test Volume Control cache.
     * Test Volume Control cache.
     */
     */
@@ -641,6 +677,99 @@ public class VolumeControlServiceTest {
        Assert.assertEquals(volume, mService.getGroupVolume(groupId));
        Assert.assertEquals(volume, mService.getGroupVolume(groupId));
    }
    }


    /**
     * Test Volume Control Mute cache.
     */
    @Test
    public void testMuteCache() throws Exception {
        int groupId = 1;
        int volume = 6;

        Assert.assertEquals(false, mService.getGroupMute(groupId));

        // Send autonomous volume change
        VolumeControlStackEvent stackEvent = new VolumeControlStackEvent(
                VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
        stackEvent.device = null;
        stackEvent.valueInt1 = groupId;
        stackEvent.valueInt2 = volume;
        stackEvent.valueBool1 = false; /* unmuted */
        stackEvent.valueBool2 = true; /* autonomous */
        mService.messageFromNative(stackEvent);

        // Mute
        final SynchronousResultReceiver<Void> voidRecv = SynchronousResultReceiver.get();
        mServiceBinder.muteGroup(groupId, mAttributionSource, voidRecv);
        voidRecv.awaitResultNoInterrupt(Duration.ofMillis(TIMEOUT_MS));
        Assert.assertEquals(true, mService.getGroupMute(groupId));

        // Make sure the volume is kept even when muted
        Assert.assertEquals(volume, mService.getGroupVolume(groupId));

        // Send autonomous unmute
        stackEvent.valueBool1 = false; /* unmuted */
        mService.messageFromNative(stackEvent);

        Assert.assertEquals(false, mService.getGroupMute(groupId));
    }

    /**
     * Test Volume Control with muted stream.
     */
    @Test
    public void testVolumeChangeWhileMuted() throws Exception {
        int groupId = 1;
        int volume = 6;

        Assert.assertEquals(false, mService.getGroupMute(groupId));

        // Set the initial volume state
        VolumeControlStackEvent stackEvent = new VolumeControlStackEvent(
                VolumeControlStackEvent.EVENT_TYPE_VOLUME_STATE_CHANGED);
        stackEvent.device = null;
        stackEvent.valueInt1 = groupId;
        stackEvent.valueInt2 = volume;
        stackEvent.valueBool1 = false; /* unmuted */
        stackEvent.valueBool2 = true; /* autonomous */
        mService.messageFromNative(stackEvent);

        // Mute
        mService.muteGroup(groupId);
        Assert.assertEquals(true, mService.getGroupMute(groupId));
        verify(mNativeInterface, times(1)).muteGroup(eq(groupId));

        // Make sure the volume is kept even when muted
        doReturn(true).when(mAudioManager)
                .isStreamMute(eq(AudioManager.STREAM_MUSIC));
        Assert.assertEquals(volume, mService.getGroupVolume(groupId));

        // Lower the volume and keep it mute
        mService.setGroupVolume(groupId, --volume);
        Assert.assertEquals(true, mService.getGroupMute(groupId));
        verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume));
        verify(mNativeInterface, times(0)).unmuteGroup(eq(groupId));

        // Don't unmute on consecutive calls either
        mService.setGroupVolume(groupId, --volume);
        Assert.assertEquals(true, mService.getGroupMute(groupId));
        verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume));
        verify(mNativeInterface, times(0)).unmuteGroup(eq(groupId));

        // Raise the volume and unmute
        volume += 10; // avoid previous volume levels and simplify mock verification
        doReturn(false).when(mAudioManager)
                .isStreamMute(eq(AudioManager.STREAM_MUSIC));
        mService.setGroupVolume(groupId, ++volume);
        Assert.assertEquals(false, mService.getGroupMute(groupId));
        verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume));
        // Verify the number of unmute calls after the second volume change
        mService.setGroupVolume(groupId, ++volume);
        Assert.assertEquals(false, mService.getGroupMute(groupId));
        verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume));
        // Make sure we unmuted only once
        verify(mNativeInterface, times(1)).unmuteGroup(eq(groupId));
    }

    /**
    /**
     * Test setting volume for a group member who connects after the volume level
     * Test setting volume for a group member who connects after the volume level
     * for a group was already changed and cached.
     * for a group was already changed and cached.
@@ -727,6 +856,109 @@ public class VolumeControlServiceTest {
        verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(groupVolume));
        verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(groupVolume));
    }
    }


    /**
     * Test setting volume to 0 for a group member who connects after the volume level
     * for a group was already changed and cached. LeAudio has no knowledge of mute
     * for anything else than telephony, thus setting volume level to 0 is considered
     * as muting.
     */
    @Test
    public void testMuteLateConnectingDevice() throws Exception {
        int groupId = 1;
        int volume = 100;

        // Both devices are in the same group
        when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId);
        when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId);

        // Update the device policy so okToConnect() returns true
        when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager);
        when(mDatabaseManager
                .getProfileConnectionPolicy(any(BluetoothDevice.class),
                        eq(BluetoothProfile.VOLUME_CONTROL)))
                .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
        doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class));
        doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class));

        generateConnectionMessageFromNative(mDevice, BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mDevice));
        Assert.assertTrue(mService.getDevices().contains(mDevice));

        // Set the initial volume and mute conditions
        doReturn(true).when(mAudioManager).isStreamMute(anyInt());
        mService.setGroupVolume(groupId, volume);

        verify(mNativeInterface, times(1)).setGroupVolume(eq(groupId), eq(volume));
        verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(volume));
        // Check if it was muted
        verify(mNativeInterface, times(1)).muteGroup(eq(groupId));

        Assert.assertEquals(true, mService.getGroupMute(groupId));

        // Verify that second device gets the proper group volume level when connected
        generateConnectionMessageFromNative(mDeviceTwo, BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mDeviceTwo));
        Assert.assertTrue(mService.getDevices().contains(mDeviceTwo));
        verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(volume));
        // Check if new device was muted
        verify(mNativeInterface, times(1)).mute(eq(mDeviceTwo));
    }

    /**
     * Test setting volume to 0 for a new group member who is discovered after the volume level
     * for a group was already changed and cached. LeAudio has no knowledge of mute
     * for anything else than telephony, thus setting volume level to 0 is considered
     * as muting.
     */
    @Test
    public void testMuteLateDiscoveredGroupMember() throws Exception {
        int groupId = 1;
        int volume = 100;

        // For now only one device is in the group
        when(mCsipService.getGroupId(mDevice, BluetoothUuid.CAP)).thenReturn(groupId);
        when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(-1);

        // Update the device policy so okToConnect() returns true
        when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager);
        when(mDatabaseManager
                .getProfileConnectionPolicy(any(BluetoothDevice.class),
                        eq(BluetoothProfile.VOLUME_CONTROL)))
                .thenReturn(BluetoothProfile.CONNECTION_POLICY_ALLOWED);
        doReturn(true).when(mNativeInterface).connectVolumeControl(any(BluetoothDevice.class));
        doReturn(true).when(mNativeInterface).disconnectVolumeControl(any(BluetoothDevice.class));

        generateConnectionMessageFromNative(mDevice, BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mDevice));
        Assert.assertTrue(mService.getDevices().contains(mDevice));

        // Set the initial volume and mute conditions
        doReturn(true).when(mAudioManager).isStreamMute(anyInt());
        mService.setGroupVolume(groupId, volume);

        // Verify that second device will not get the group volume level if it is not a group member
        generateConnectionMessageFromNative(mDeviceTwo, BluetoothProfile.STATE_CONNECTED,
                BluetoothProfile.STATE_DISCONNECTED);
        Assert.assertEquals(BluetoothProfile.STATE_CONNECTED,
                mService.getConnectionState(mDeviceTwo));
        Assert.assertTrue(mService.getDevices().contains(mDeviceTwo));
        verify(mNativeInterface, times(0)).setVolume(eq(mDeviceTwo), eq(volume));
        // Check if it was not muted
        verify(mNativeInterface, times(0)).mute(eq(mDeviceTwo));

        // But gets the volume when it becomes the group member
        when(mCsipService.getGroupId(mDeviceTwo, BluetoothUuid.CAP)).thenReturn(groupId);
        mService.handleGroupNodeAdded(groupId, mDeviceTwo);
        verify(mNativeInterface, times(1)).setVolume(eq(mDeviceTwo), eq(volume));
        verify(mNativeInterface, times(1)).mute(eq(mDeviceTwo));
    }

    @Test
    @Test
    public void testServiceBinderGetDevicesMatchingConnectionStates() throws Exception {
    public void testServiceBinderGetDevicesMatchingConnectionStates() throws Exception {
        final SynchronousResultReceiver<List<BluetoothDevice>> recv =
        final SynchronousResultReceiver<List<BluetoothDevice>> recv =
+3 −3
Original line number Original line Diff line number Diff line
@@ -863,7 +863,7 @@ class VolumeControlImpl : public VolumeControl {
        LOG_DEBUG("Address: %s: isReady: %s",
        LOG_DEBUG("Address: %s: isReady: %s",
                  ADDRESS_TO_LOGGABLE_CSTR(dev->address),
                  ADDRESS_TO_LOGGABLE_CSTR(dev->address),
                  dev->IsReady() ? "true" : "false");
                  dev->IsReady() ? "true" : "false");
        if (dev->IsReady()) {
        if (dev->IsReady() && (dev->mute != mute)) {
          std::vector<RawAddress> devices = {dev->address};
          std::vector<RawAddress> devices = {dev->address};
          PrepareVolumeControlOperation(
          PrepareVolumeControlOperation(
              devices, bluetooth::groups::kGroupUnknown, false, opcode, arg);
              devices, bluetooth::groups::kGroupUnknown, false, opcode, arg);
@@ -882,7 +882,7 @@ class VolumeControlImpl : public VolumeControl {
      auto devices = csis_api->GetDeviceList(group_id);
      auto devices = csis_api->GetDeviceList(group_id);
      for (auto it = devices.begin(); it != devices.end();) {
      for (auto it = devices.begin(); it != devices.end();) {
        auto dev = volume_control_devices_.FindByAddress(*it);
        auto dev = volume_control_devices_.FindByAddress(*it);
        if (!dev || !dev->IsReady()) {
        if (!dev || !dev->IsReady() || (dev->mute == mute)) {
          it = devices.erase(it);
          it = devices.erase(it);
        } else {
        } else {
          it++;
          it++;
@@ -948,7 +948,7 @@ class VolumeControlImpl : public VolumeControl {
      auto devices = csis_api->GetDeviceList(group_id);
      auto devices = csis_api->GetDeviceList(group_id);
      for (auto it = devices.begin(); it != devices.end();) {
      for (auto it = devices.begin(); it != devices.end();) {
        auto dev = volume_control_devices_.FindByAddress(*it);
        auto dev = volume_control_devices_.FindByAddress(*it);
        if (!dev || !dev->IsReady()) {
        if (!dev || !dev->IsReady() || (dev->volume == volume)) {
          it = devices.erase(it);
          it = devices.erase(it);
        } else {
        } else {
          it++;
          it++;
+52 −20

File changed.

Preview size limit exceeded, changes collapsed.