Loading android/app/jni/com_android_bluetooth_vc.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -348,7 +348,7 @@ static void setVolumeNative(JNIEnv* env, jobject object, jbyteArray address, env->ReleaseByteArrayElements(address, addr, 0); } static void setVolumeGroupNative(JNIEnv* env, jobject object, jint group_id, static void setGroupVolumeNative(JNIEnv* env, jobject object, jint group_id, jint volume) { if (!sVolumeControlInterface) { LOG(ERROR) << __func__ Loading Loading @@ -549,7 +549,7 @@ static JNINativeMethod sMethods[] = { {"disconnectVolumeControlNative", "([B)Z", (void*)disconnectVolumeControlNative}, {"setVolumeNative", "([BI)V", (void*)setVolumeNative}, {"setVolumeGroupNative", "(II)V", (void*)setVolumeGroupNative}, {"setGroupVolumeNative", "(II)V", (void*)setGroupVolumeNative}, {"muteNative", "([B)V", (void*)muteNative}, {"muteGroupNative", "(I)V", (void*)muteGroupNative}, {"unmuteNative", "([B)V", (void*)unmuteNative}, Loading android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +44 −4 Original line number Diff line number Diff line Loading @@ -121,6 +121,9 @@ public class LeAudioService extends ProfileService { AudioManager mAudioManager; LeAudioTmapGattServer mTmapGattServer; @VisibleForTesting VolumeControlService mVolumeControlService; @VisibleForTesting RemoteCallbackList<IBluetoothLeBroadcastCallback> mBroadcastCallbacks; Loading Loading @@ -379,6 +382,7 @@ public class LeAudioService extends ProfileService { mAdapterService = null; mAudioManager = null; mVolumeControlService = null; return true; } Loading Loading @@ -407,6 +411,18 @@ public class LeAudioService extends ProfileService { sLeAudioService = instance; } private int getGroupVolume(int groupId) { if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService == null) { Log.e(TAG, "Volume control service is not available"); return -1; } return mVolumeControlService.getGroupVolume(groupId); } public boolean connect(BluetoothDevice device) { if (DBG) { Log.d(TAG, "connect(): " + device); Loading Loading @@ -822,6 +838,7 @@ public class LeAudioService extends ProfileService { + previousInDevice + ", mActiveAudioInDevice" + mActiveAudioInDevice + " isLeOutput: false"); } mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioInDevice,previousInDevice, BluetoothProfileConnectionInfo.createLeAudioInfo(false, false)); Loading Loading @@ -890,9 +907,14 @@ public class LeAudioService extends ProfileService { + previousOutDevice + ", mActiveOutDevice: " + mActiveAudioOutDevice + " isLeOutput: true"); } int volume = -1; if (mActiveAudioOutDevice != null) { volume = getGroupVolume(groupId); } mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice, previousOutDevice, BluetoothProfileConnectionInfo.createLeAudioInfo(suppressNoisyIntent, true)); getLeAudioOutputProfile(suppressNoisyIntent, volume)); return true; } Log.d(TAG, "updateActiveOutDevice: Nothing to do."); Loading Loading @@ -1059,6 +1081,22 @@ public class LeAudioService extends ProfileService { return profileInfo; } BluetoothProfileConnectionInfo getLeAudioOutputProfile(boolean suppressNoisyIntent, int volume) { /* TODO - b/236618595 */ Parcel parcel = Parcel.obtain(); parcel.writeInt(BluetoothProfile.LE_AUDIO); parcel.writeBoolean(suppressNoisyIntent); parcel.writeInt(volume); parcel.writeBoolean(true /* isLeOutput */); parcel.setDataPosition(0); BluetoothProfileConnectionInfo profileInfo = BluetoothProfileConnectionInfo.CREATOR.createFromParcel(parcel); parcel.recycle(); return profileInfo; } private void clearLostDevicesWhileStreaming(LeAudioGroupDescriptor descriptor) { if (DBG) { Log.d(TAG, " lost dev: " + descriptor.mLostLeadDeviceWhileStreaming); Loading Loading @@ -1757,9 +1795,11 @@ public class LeAudioService extends ProfileService { return; } VolumeControlService service = mServiceFactory.getVolumeControlService(); if (service != null) { service.setVolumeGroup(currentlyActiveGroupId, volume); if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService != null) { mVolumeControlService.setGroupVolume(currentlyActiveGroupId, volume); } } Loading android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java +3 −3 Original line number Diff line number Diff line Loading @@ -113,8 +113,8 @@ public class VolumeControlNativeInterface { * @param volume */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void setVolumeGroup(int groupId, int volume) { setVolumeGroupNative(groupId, volume); public void setGroupVolume(int groupId, int volume) { setGroupVolumeNative(groupId, volume); } /** Loading Loading @@ -374,7 +374,7 @@ public class VolumeControlNativeInterface { private native boolean connectVolumeControlNative(byte[] address); private native boolean disconnectVolumeControlNative(byte[] address); private native void setVolumeNative(byte[] address, int volume); private native void setVolumeGroupNative(int groupId, int volume); private native void setGroupVolumeNative(int groupId, int volume); private native void muteNative(byte[] address); private native void muteGroupNative(int groupId); private native void unmuteNative(byte[] address); Loading android/app/src/com/android/bluetooth/vc/VolumeControlService.java +43 −4 Original line number Diff line number Diff line Loading @@ -181,6 +181,7 @@ public class VolumeControlService extends ProfileService { private final Map<BluetoothDevice, VolumeControlStateMachine> mStateMachines = new HashMap<>(); private final Map<BluetoothDevice, VolumeControlOffsetDescriptor> mAudioOffsets = new HashMap<>(); private final Map<Integer, Integer> mGroupVolumeCache = new HashMap<>(); private BroadcastReceiver mBondStateChangedReceiver; private BroadcastReceiver mConnectionStateChangedReceiver; Loading Loading @@ -246,6 +247,7 @@ public class VolumeControlService extends ProfileService { registerReceiver(mConnectionStateChangedReceiver, filter); mAudioOffsets.clear(); mGroupVolumeCache.clear(); mCallbacks = new RemoteCallbackList<IBluetoothVolumeControlCallback>(); // Mark service as started Loading Loading @@ -300,6 +302,7 @@ public class VolumeControlService extends ProfileService { mVolumeControlNativeInterface = null; mAudioOffsets.clear(); mGroupVolumeCache.clear(); // Clear AdapterService, VolumeControlNativeInterface mAudioManager = null; Loading Loading @@ -580,8 +583,17 @@ public class VolumeControlService extends ProfileService { /** * {@hide} */ public void setVolumeGroup(int groupId, int volume) { mVolumeControlNativeInterface.setVolumeGroup(groupId, volume); public void setGroupVolume(int groupId, int volume) { mGroupVolumeCache.put(groupId, volume); mVolumeControlNativeInterface.setGroupVolume(groupId, volume); } /** * {@hide} * @param groupId */ public int getGroupVolume(int groupId) { return mGroupVolumeCache.getOrDefault(groupId, -1); } /** Loading Loading @@ -620,6 +632,11 @@ public class VolumeControlService extends ProfileService { } // TODO: Handle the other arguments: device, groupId, mute. /* We are interested only in the group volume as any LeAudio device is a part of group */ if (device == null) { mGroupVolumeCache.put(groupId, volume); } int streamType = getBluetoothContextualVolumeStream(); mAudioManager.setStreamVolume(streamType, getDeviceVolume(streamType, volume), AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); Loading Loading @@ -1127,7 +1144,7 @@ public class VolumeControlService extends ProfileService { } @Override public void setVolumeGroup(int groupId, int volume, AttributionSource source, public void setGroupVolume(int groupId, int volume, AttributionSource source, SynchronousResultReceiver receiver) { try { Objects.requireNonNull(source, "source cannot be null"); Loading @@ -1135,7 +1152,7 @@ public class VolumeControlService extends ProfileService { VolumeControlService service = getService(source); if (service != null) { service.setVolumeGroup(groupId, volume); service.setGroupVolume(groupId, volume); } receiver.send(null); } catch (RuntimeException e) { Loading @@ -1143,6 +1160,24 @@ public class VolumeControlService extends ProfileService { } } @Override public void getGroupVolume(int groupId, AttributionSource source, SynchronousResultReceiver receiver) { try { Objects.requireNonNull(source, "source cannot be null"); Objects.requireNonNull(receiver, "receiver cannot be null"); VolumeControlService service = getService(source); if (service != null) { service.getGroupVolume(groupId); } receiver.send(null); } catch (RuntimeException e) { receiver.propagateException(e); } } @Override public void mute(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { Loading Loading @@ -1273,5 +1308,9 @@ public class VolumeControlService extends ProfileService { ProfileService.println(sb, " Volume offset cnt: " + descriptor.size()); descriptor.dump(sb); } for (Map.Entry<Integer, Integer> entry : mGroupVolumeCache.entrySet()) { ProfileService.println(sb, " GroupId: " + entry.getKey() + " volume: " + entry.getValue()); } } } android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +54 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; import android.os.Parcel; import android.os.ParcelUuid; import androidx.test.InstrumentationRegistry; Loading @@ -58,6 +59,7 @@ import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.vc.VolumeControlService; import org.junit.After; import org.junit.Assume; Loading @@ -65,6 +67,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; Loading Loading @@ -104,6 +107,7 @@ public class LeAudioServiceTest { @Mock private DatabaseManager mDatabaseManager; @Mock private LeAudioNativeInterface mNativeInterface; @Mock private AudioManager mAudioManager; @Mock private VolumeControlService mVolumeControlService; @Mock private LeAudioTmapGattServer mTmapGattServer; @Spy private LeAudioObjectsFactory mObjectsFactory = LeAudioObjectsFactory.getInstance(); Loading Loading @@ -178,6 +182,7 @@ public class LeAudioServiceTest { startService(); mService.mLeAudioNativeInterface = mNativeInterface; mService.mAudioManager = mAudioManager; mService.mVolumeControlService = mVolumeControlService; LeAudioStackEvent stackEvent = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_NATIVE_INITIALIZED); Loading Loading @@ -1407,4 +1412,53 @@ public class LeAudioServiceTest { verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(eq(null), eq(leadDevice), any(BluetoothProfileConnectionInfo.class)); } /** * Test volume caching for the group */ @Test public void testVolumeCache() { int groupId = 1; int volume = 100; int availableContexts = 4; doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class)); connectTestDevice(mLeftDevice, groupId); connectTestDevice(mRightDevice, groupId); assertThat(mService.setActiveDevice(mLeftDevice)).isTrue(); ArgumentCaptor<BluetoothProfileConnectionInfo> profileInfo = ArgumentCaptor.forClass(BluetoothProfileConnectionInfo.class); //Add location support. injectAudioConfChanged(groupId, availableContexts); doReturn(-1).when(mVolumeControlService).getGroupVolume(groupId); //Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(any(), eq(null), profileInfo.capture()); assertThat(profileInfo.getValue().getVolume()).isEqualTo(-1); mService.setVolume(volume); verify(mVolumeControlService, times(1)).setGroupVolume(groupId, volume); // Set group to inactive. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(eq(null), any(), any(BluetoothProfileConnectionInfo.class)); doReturn(100).when(mVolumeControlService).getGroupVolume(groupId); //Set back to active and check if last volume is restored. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); verify(mAudioManager, times(2)).handleBluetoothActiveDeviceChanged(any(), eq(null), profileInfo.capture()); assertThat(profileInfo.getValue().getVolume()).isEqualTo(volume); } } Loading
android/app/jni/com_android_bluetooth_vc.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -348,7 +348,7 @@ static void setVolumeNative(JNIEnv* env, jobject object, jbyteArray address, env->ReleaseByteArrayElements(address, addr, 0); } static void setVolumeGroupNative(JNIEnv* env, jobject object, jint group_id, static void setGroupVolumeNative(JNIEnv* env, jobject object, jint group_id, jint volume) { if (!sVolumeControlInterface) { LOG(ERROR) << __func__ Loading Loading @@ -549,7 +549,7 @@ static JNINativeMethod sMethods[] = { {"disconnectVolumeControlNative", "([B)Z", (void*)disconnectVolumeControlNative}, {"setVolumeNative", "([BI)V", (void*)setVolumeNative}, {"setVolumeGroupNative", "(II)V", (void*)setVolumeGroupNative}, {"setGroupVolumeNative", "(II)V", (void*)setGroupVolumeNative}, {"muteNative", "([B)V", (void*)muteNative}, {"muteGroupNative", "(I)V", (void*)muteGroupNative}, {"unmuteNative", "([B)V", (void*)unmuteNative}, Loading
android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +44 −4 Original line number Diff line number Diff line Loading @@ -121,6 +121,9 @@ public class LeAudioService extends ProfileService { AudioManager mAudioManager; LeAudioTmapGattServer mTmapGattServer; @VisibleForTesting VolumeControlService mVolumeControlService; @VisibleForTesting RemoteCallbackList<IBluetoothLeBroadcastCallback> mBroadcastCallbacks; Loading Loading @@ -379,6 +382,7 @@ public class LeAudioService extends ProfileService { mAdapterService = null; mAudioManager = null; mVolumeControlService = null; return true; } Loading Loading @@ -407,6 +411,18 @@ public class LeAudioService extends ProfileService { sLeAudioService = instance; } private int getGroupVolume(int groupId) { if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService == null) { Log.e(TAG, "Volume control service is not available"); return -1; } return mVolumeControlService.getGroupVolume(groupId); } public boolean connect(BluetoothDevice device) { if (DBG) { Log.d(TAG, "connect(): " + device); Loading Loading @@ -822,6 +838,7 @@ public class LeAudioService extends ProfileService { + previousInDevice + ", mActiveAudioInDevice" + mActiveAudioInDevice + " isLeOutput: false"); } mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioInDevice,previousInDevice, BluetoothProfileConnectionInfo.createLeAudioInfo(false, false)); Loading Loading @@ -890,9 +907,14 @@ public class LeAudioService extends ProfileService { + previousOutDevice + ", mActiveOutDevice: " + mActiveAudioOutDevice + " isLeOutput: true"); } int volume = -1; if (mActiveAudioOutDevice != null) { volume = getGroupVolume(groupId); } mAudioManager.handleBluetoothActiveDeviceChanged(mActiveAudioOutDevice, previousOutDevice, BluetoothProfileConnectionInfo.createLeAudioInfo(suppressNoisyIntent, true)); getLeAudioOutputProfile(suppressNoisyIntent, volume)); return true; } Log.d(TAG, "updateActiveOutDevice: Nothing to do."); Loading Loading @@ -1059,6 +1081,22 @@ public class LeAudioService extends ProfileService { return profileInfo; } BluetoothProfileConnectionInfo getLeAudioOutputProfile(boolean suppressNoisyIntent, int volume) { /* TODO - b/236618595 */ Parcel parcel = Parcel.obtain(); parcel.writeInt(BluetoothProfile.LE_AUDIO); parcel.writeBoolean(suppressNoisyIntent); parcel.writeInt(volume); parcel.writeBoolean(true /* isLeOutput */); parcel.setDataPosition(0); BluetoothProfileConnectionInfo profileInfo = BluetoothProfileConnectionInfo.CREATOR.createFromParcel(parcel); parcel.recycle(); return profileInfo; } private void clearLostDevicesWhileStreaming(LeAudioGroupDescriptor descriptor) { if (DBG) { Log.d(TAG, " lost dev: " + descriptor.mLostLeadDeviceWhileStreaming); Loading Loading @@ -1757,9 +1795,11 @@ public class LeAudioService extends ProfileService { return; } VolumeControlService service = mServiceFactory.getVolumeControlService(); if (service != null) { service.setVolumeGroup(currentlyActiveGroupId, volume); if (mVolumeControlService == null) { mVolumeControlService = mServiceFactory.getVolumeControlService(); } if (mVolumeControlService != null) { mVolumeControlService.setGroupVolume(currentlyActiveGroupId, volume); } } Loading
android/app/src/com/android/bluetooth/vc/VolumeControlNativeInterface.java +3 −3 Original line number Diff line number Diff line Loading @@ -113,8 +113,8 @@ public class VolumeControlNativeInterface { * @param volume */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public void setVolumeGroup(int groupId, int volume) { setVolumeGroupNative(groupId, volume); public void setGroupVolume(int groupId, int volume) { setGroupVolumeNative(groupId, volume); } /** Loading Loading @@ -374,7 +374,7 @@ public class VolumeControlNativeInterface { private native boolean connectVolumeControlNative(byte[] address); private native boolean disconnectVolumeControlNative(byte[] address); private native void setVolumeNative(byte[] address, int volume); private native void setVolumeGroupNative(int groupId, int volume); private native void setGroupVolumeNative(int groupId, int volume); private native void muteNative(byte[] address); private native void muteGroupNative(int groupId); private native void unmuteNative(byte[] address); Loading
android/app/src/com/android/bluetooth/vc/VolumeControlService.java +43 −4 Original line number Diff line number Diff line Loading @@ -181,6 +181,7 @@ public class VolumeControlService extends ProfileService { private final Map<BluetoothDevice, VolumeControlStateMachine> mStateMachines = new HashMap<>(); private final Map<BluetoothDevice, VolumeControlOffsetDescriptor> mAudioOffsets = new HashMap<>(); private final Map<Integer, Integer> mGroupVolumeCache = new HashMap<>(); private BroadcastReceiver mBondStateChangedReceiver; private BroadcastReceiver mConnectionStateChangedReceiver; Loading Loading @@ -246,6 +247,7 @@ public class VolumeControlService extends ProfileService { registerReceiver(mConnectionStateChangedReceiver, filter); mAudioOffsets.clear(); mGroupVolumeCache.clear(); mCallbacks = new RemoteCallbackList<IBluetoothVolumeControlCallback>(); // Mark service as started Loading Loading @@ -300,6 +302,7 @@ public class VolumeControlService extends ProfileService { mVolumeControlNativeInterface = null; mAudioOffsets.clear(); mGroupVolumeCache.clear(); // Clear AdapterService, VolumeControlNativeInterface mAudioManager = null; Loading Loading @@ -580,8 +583,17 @@ public class VolumeControlService extends ProfileService { /** * {@hide} */ public void setVolumeGroup(int groupId, int volume) { mVolumeControlNativeInterface.setVolumeGroup(groupId, volume); public void setGroupVolume(int groupId, int volume) { mGroupVolumeCache.put(groupId, volume); mVolumeControlNativeInterface.setGroupVolume(groupId, volume); } /** * {@hide} * @param groupId */ public int getGroupVolume(int groupId) { return mGroupVolumeCache.getOrDefault(groupId, -1); } /** Loading Loading @@ -620,6 +632,11 @@ public class VolumeControlService extends ProfileService { } // TODO: Handle the other arguments: device, groupId, mute. /* We are interested only in the group volume as any LeAudio device is a part of group */ if (device == null) { mGroupVolumeCache.put(groupId, volume); } int streamType = getBluetoothContextualVolumeStream(); mAudioManager.setStreamVolume(streamType, getDeviceVolume(streamType, volume), AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_BLUETOOTH_ABS_VOLUME); Loading Loading @@ -1127,7 +1144,7 @@ public class VolumeControlService extends ProfileService { } @Override public void setVolumeGroup(int groupId, int volume, AttributionSource source, public void setGroupVolume(int groupId, int volume, AttributionSource source, SynchronousResultReceiver receiver) { try { Objects.requireNonNull(source, "source cannot be null"); Loading @@ -1135,7 +1152,7 @@ public class VolumeControlService extends ProfileService { VolumeControlService service = getService(source); if (service != null) { service.setVolumeGroup(groupId, volume); service.setGroupVolume(groupId, volume); } receiver.send(null); } catch (RuntimeException e) { Loading @@ -1143,6 +1160,24 @@ public class VolumeControlService extends ProfileService { } } @Override public void getGroupVolume(int groupId, AttributionSource source, SynchronousResultReceiver receiver) { try { Objects.requireNonNull(source, "source cannot be null"); Objects.requireNonNull(receiver, "receiver cannot be null"); VolumeControlService service = getService(source); if (service != null) { service.getGroupVolume(groupId); } receiver.send(null); } catch (RuntimeException e) { receiver.propagateException(e); } } @Override public void mute(BluetoothDevice device, AttributionSource source, SynchronousResultReceiver receiver) { Loading Loading @@ -1273,5 +1308,9 @@ public class VolumeControlService extends ProfileService { ProfileService.println(sb, " Volume offset cnt: " + descriptor.size()); descriptor.dump(sb); } for (Map.Entry<Integer, Integer> entry : mGroupVolumeCache.entrySet()) { ProfileService.println(sb, " GroupId: " + entry.getKey() + " volume: " + entry.getValue()); } } }
android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +54 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; import android.os.Parcel; import android.os.ParcelUuid; import androidx.test.InstrumentationRegistry; Loading @@ -58,6 +59,7 @@ import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.vc.VolumeControlService; import org.junit.After; import org.junit.Assume; Loading @@ -65,6 +67,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.Spy; Loading Loading @@ -104,6 +107,7 @@ public class LeAudioServiceTest { @Mock private DatabaseManager mDatabaseManager; @Mock private LeAudioNativeInterface mNativeInterface; @Mock private AudioManager mAudioManager; @Mock private VolumeControlService mVolumeControlService; @Mock private LeAudioTmapGattServer mTmapGattServer; @Spy private LeAudioObjectsFactory mObjectsFactory = LeAudioObjectsFactory.getInstance(); Loading Loading @@ -178,6 +182,7 @@ public class LeAudioServiceTest { startService(); mService.mLeAudioNativeInterface = mNativeInterface; mService.mAudioManager = mAudioManager; mService.mVolumeControlService = mVolumeControlService; LeAudioStackEvent stackEvent = new LeAudioStackEvent(LeAudioStackEvent.EVENT_TYPE_NATIVE_INITIALIZED); Loading Loading @@ -1407,4 +1412,53 @@ public class LeAudioServiceTest { verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(eq(null), eq(leadDevice), any(BluetoothProfileConnectionInfo.class)); } /** * Test volume caching for the group */ @Test public void testVolumeCache() { int groupId = 1; int volume = 100; int availableContexts = 4; doReturn(true).when(mNativeInterface).connectLeAudio(any(BluetoothDevice.class)); connectTestDevice(mLeftDevice, groupId); connectTestDevice(mRightDevice, groupId); assertThat(mService.setActiveDevice(mLeftDevice)).isTrue(); ArgumentCaptor<BluetoothProfileConnectionInfo> profileInfo = ArgumentCaptor.forClass(BluetoothProfileConnectionInfo.class); //Add location support. injectAudioConfChanged(groupId, availableContexts); doReturn(-1).when(mVolumeControlService).getGroupVolume(groupId); //Set group and device as active. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(any(), eq(null), profileInfo.capture()); assertThat(profileInfo.getValue().getVolume()).isEqualTo(-1); mService.setVolume(volume); verify(mVolumeControlService, times(1)).setGroupVolume(groupId, volume); // Set group to inactive. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_INACTIVE); verify(mAudioManager, times(1)).handleBluetoothActiveDeviceChanged(eq(null), any(), any(BluetoothProfileConnectionInfo.class)); doReturn(100).when(mVolumeControlService).getGroupVolume(groupId); //Set back to active and check if last volume is restored. injectGroupStatusChange(groupId, LeAudioStackEvent.GROUP_STATUS_ACTIVE); verify(mAudioManager, times(2)).handleBluetoothActiveDeviceChanged(any(), eq(null), profileInfo.capture()); assertThat(profileInfo.getValue().getVolume()).isEqualTo(volume); } }