Loading src/com/android/bluetooth/a2dp/A2dpService.java +25 −23 Original line number Diff line number Diff line Loading @@ -34,10 +34,10 @@ import android.util.StatsLog; import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.avrcp.AvrcpTargetService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.ServiceFactory; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading @@ -62,6 +62,8 @@ public class A2dpService extends ProfileService { @VisibleForTesting A2dpNativeInterface mA2dpNativeInterface; @VisibleForTesting ServiceFactory mFactory = new ServiceFactory(); private AudioManager mAudioManager; private A2dpCodecConfig mA2dpCodecConfig; Loading Loading @@ -156,11 +158,6 @@ public class A2dpService extends ProfileService { return true; } // Step 10: Store volume if there is an active device if (mActiveDevice != null && AvrcpTargetService.get() != null) { AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice); } // Step 9: Clear active device and stop playing audio removeActiveDevice(true); Loading Loading @@ -430,9 +427,19 @@ public class A2dpService extends ProfileService { } } private void storeActiveDeviceVolume() { // Make sure volume has been stored before been removed from active. if (mFactory.getAvrcpTargetService() != null && mActiveDevice != null) { mFactory.getAvrcpTargetService().storeVolumeForDevice(mActiveDevice); } } private void removeActiveDevice(boolean forceStopPlayingAudio) { BluetoothDevice previousActiveDevice = mActiveDevice; synchronized (mStateMachines) { // Make sure volume has been store before device been remove from active. storeActiveDeviceVolume(); // This needs to happen before we inform the audio manager that the device // disconnected. Please see comment in updateAndBroadcastActiveDevice() for why. updateAndBroadcastActiveDevice(null); Loading Loading @@ -474,9 +481,6 @@ public class A2dpService extends ProfileService { Log.d(TAG, "setSilenceMode(" + device + "): " + silence); } if (silence && Objects.equals(mActiveDevice, device)) { if (mActiveDevice != null && AvrcpTargetService.get() != null) { AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice); } removeActiveDevice(true); } else if (!silence && mActiveDevice == null) { // Set the device as the active device if currently no active device. Loading @@ -497,13 +501,11 @@ public class A2dpService extends ProfileService { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); synchronized (mStateMachines) { if ((mActiveDevice != null) && (AvrcpTargetService.get() != null)) { // Switch active device from A2DP to Hearing Aids. if (DBG) { Log.d(TAG, "earlyNotifyHearingAidActive: Save volume for " + mActiveDevice); } AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice); } storeActiveDeviceVolume(); } } Loading Loading @@ -546,12 +548,12 @@ public class A2dpService extends ProfileService { codecStatus = sm.getCodecStatus(); boolean deviceChanged = !Objects.equals(device, mActiveDevice); if ((AvrcpTargetService.get() != null) && (mActiveDevice != null) && deviceChanged) { if (deviceChanged) { // Switch from one A2DP to another A2DP device if (DBG) { Log.d(TAG, "Switch A2DP devices to " + device + " from " + mActiveDevice); } AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice); storeActiveDeviceVolume(); } // This needs to happen before we inform the audio manager that the device Loading @@ -578,8 +580,8 @@ public class A2dpService extends ProfileService { } int rememberedVolume = -1; if (AvrcpTargetService.get() != null) { rememberedVolume = AvrcpTargetService.get() if (mFactory.getAvrcpTargetService() != null) { rememberedVolume = mFactory.getAvrcpTargetService() .getRememberedVolumeForDevice(mActiveDevice); } Loading Loading @@ -643,8 +645,8 @@ public class A2dpService extends ProfileService { public void setAvrcpAbsoluteVolume(int volume) { // TODO (apanicke): Instead of using A2DP as a middleman for volume changes, add a binder // service to the new AVRCP Profile and have the audio manager use that instead. if (AvrcpTargetService.get() != null) { AvrcpTargetService.get().sendVolumeChanged(volume); if (mFactory.getAvrcpTargetService() != null) { mFactory.getAvrcpTargetService().sendVolumeChanged(volume); return; } } Loading Loading @@ -923,8 +925,8 @@ public class A2dpService extends ProfileService { } synchronized (mStateMachines) { if (AvrcpTargetService.get() != null) { AvrcpTargetService.get().volumeDeviceSwitched(device); if (mFactory.getAvrcpTargetService() != null) { mFactory.getAvrcpTargetService().volumeDeviceSwitched(device); } mActiveDevice = device; Loading src/com/android/bluetooth/btservice/ServiceFactory.java +5 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.bluetooth.btservice; import com.android.bluetooth.a2dp.A2dpService; import com.android.bluetooth.avrcp.AvrcpTargetService; import com.android.bluetooth.hearingaid.HearingAidService; import com.android.bluetooth.hfp.HeadsetService; import com.android.bluetooth.hid.HidDeviceService; Loading Loading @@ -48,4 +49,8 @@ public class ServiceFactory { public HearingAidService getHearingAidService() { return HearingAidService.getHearingAidService(); } public AvrcpTargetService getAvrcpTargetService() { return AvrcpTargetService.get(); } } tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -38,7 +38,9 @@ import android.support.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.avrcp.AvrcpTargetService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ServiceFactory; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; Loading Loading @@ -75,6 +77,8 @@ public class A2dpServiceTest { @Mock private AdapterService mAdapterService; @Mock private A2dpNativeInterface mA2dpNativeInterface; @Mock private DatabaseManager mDatabaseManager; @Mock private AvrcpTargetService mAvrcpTargetService; @Mock private ServiceFactory mFactory; @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); Loading @@ -93,11 +97,13 @@ public class A2dpServiceTest { TestUtils.setAdapterService(mAdapterService); doReturn(MAX_CONNECTED_AUDIO_DEVICES).when(mAdapterService).getMaxConnectedAudioDevices(); doReturn(false).when(mAdapterService).isQuietModeEnabled(); doReturn(mAvrcpTargetService).when(mFactory).getAvrcpTargetService(); mAdapter = BluetoothAdapter.getDefaultAdapter(); startService(); mA2dpService.mA2dpNativeInterface = mA2dpNativeInterface; mA2dpService.mFactory = mFactory; // Override the timeout value to speed up the test A2dpStateMachine.sConnectTimeoutMs = TIMEOUT_MS; // 1s Loading Loading @@ -245,6 +251,8 @@ public class A2dpServiceTest { }); // Verify that setActiveDevice(null) was called during shutdown verify(mA2dpNativeInterface).setActiveDevice(null); // Verify that storeVolumeForDevice(mTestDevice) was called during shutdown verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); // Try to restart the service. Note: must be done on the main thread. InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { public void run() { Loading Loading @@ -787,11 +795,13 @@ public class A2dpServiceTest { Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); Assert.assertTrue(mA2dpService.setSilenceMode(mTestDevice, true)); verify(mA2dpNativeInterface).setSilenceDevice(mTestDevice, true); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); Assert.assertNull(mA2dpService.getActiveDevice()); // Test whether active device been resumeed after disable silence mode. Assert.assertTrue(mA2dpService.setSilenceMode(mTestDevice, false)); verify(mA2dpNativeInterface).setSilenceDevice(mTestDevice, false); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); // Test that active device should not be changed when silence a non-active device Loading @@ -799,11 +809,13 @@ public class A2dpServiceTest { Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); Assert.assertTrue(mA2dpService.setSilenceMode(otherDevice, true)); verify(mA2dpNativeInterface).setSilenceDevice(otherDevice, true); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); // Test that active device should not be changed when another device exits silence mode Assert.assertTrue(mA2dpService.setSilenceMode(otherDevice, false)); verify(mA2dpNativeInterface).setSilenceDevice(otherDevice, false); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); } Loading Loading @@ -893,6 +905,28 @@ public class A2dpServiceTest { verifySupportTime, verifyNotSupportTime, verifyEnabledTime); } /** * Test that volume level of previous active device will be stored after set active device. */ @Test public void testStoreVolumeAfterSetActiveDevice() { BluetoothDevice otherDevice = mAdapter.getRemoteDevice("05:04:03:02:01:00"); connectDevice(otherDevice); connectDevice(mTestDevice); doReturn(true).when(mA2dpNativeInterface).setActiveDevice(any(BluetoothDevice.class)); doReturn(true).when(mA2dpNativeInterface).setActiveDevice(null); Assert.assertTrue(mA2dpService.setActiveDevice(mTestDevice)); // Test volume stored for previous active device an adjust for current active device Assert.assertTrue(mA2dpService.setActiveDevice(otherDevice)); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); verify(mAvrcpTargetService).getRememberedVolumeForDevice(otherDevice); // Test volume store for previous active device when set active device to null Assert.assertTrue(mA2dpService.setActiveDevice(null)); verify(mAvrcpTargetService).storeVolumeForDevice(otherDevice); } private void connectDevice(BluetoothDevice device) { connectDeviceWithCodecStatus(device, null); } Loading Loading
src/com/android/bluetooth/a2dp/A2dpService.java +25 −23 Original line number Diff line number Diff line Loading @@ -34,10 +34,10 @@ import android.util.StatsLog; import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.avrcp.AvrcpTargetService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.ServiceFactory; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; Loading @@ -62,6 +62,8 @@ public class A2dpService extends ProfileService { @VisibleForTesting A2dpNativeInterface mA2dpNativeInterface; @VisibleForTesting ServiceFactory mFactory = new ServiceFactory(); private AudioManager mAudioManager; private A2dpCodecConfig mA2dpCodecConfig; Loading Loading @@ -156,11 +158,6 @@ public class A2dpService extends ProfileService { return true; } // Step 10: Store volume if there is an active device if (mActiveDevice != null && AvrcpTargetService.get() != null) { AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice); } // Step 9: Clear active device and stop playing audio removeActiveDevice(true); Loading Loading @@ -430,9 +427,19 @@ public class A2dpService extends ProfileService { } } private void storeActiveDeviceVolume() { // Make sure volume has been stored before been removed from active. if (mFactory.getAvrcpTargetService() != null && mActiveDevice != null) { mFactory.getAvrcpTargetService().storeVolumeForDevice(mActiveDevice); } } private void removeActiveDevice(boolean forceStopPlayingAudio) { BluetoothDevice previousActiveDevice = mActiveDevice; synchronized (mStateMachines) { // Make sure volume has been store before device been remove from active. storeActiveDeviceVolume(); // This needs to happen before we inform the audio manager that the device // disconnected. Please see comment in updateAndBroadcastActiveDevice() for why. updateAndBroadcastActiveDevice(null); Loading Loading @@ -474,9 +481,6 @@ public class A2dpService extends ProfileService { Log.d(TAG, "setSilenceMode(" + device + "): " + silence); } if (silence && Objects.equals(mActiveDevice, device)) { if (mActiveDevice != null && AvrcpTargetService.get() != null) { AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice); } removeActiveDevice(true); } else if (!silence && mActiveDevice == null) { // Set the device as the active device if currently no active device. Loading @@ -497,13 +501,11 @@ public class A2dpService extends ProfileService { enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); synchronized (mStateMachines) { if ((mActiveDevice != null) && (AvrcpTargetService.get() != null)) { // Switch active device from A2DP to Hearing Aids. if (DBG) { Log.d(TAG, "earlyNotifyHearingAidActive: Save volume for " + mActiveDevice); } AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice); } storeActiveDeviceVolume(); } } Loading Loading @@ -546,12 +548,12 @@ public class A2dpService extends ProfileService { codecStatus = sm.getCodecStatus(); boolean deviceChanged = !Objects.equals(device, mActiveDevice); if ((AvrcpTargetService.get() != null) && (mActiveDevice != null) && deviceChanged) { if (deviceChanged) { // Switch from one A2DP to another A2DP device if (DBG) { Log.d(TAG, "Switch A2DP devices to " + device + " from " + mActiveDevice); } AvrcpTargetService.get().storeVolumeForDevice(mActiveDevice); storeActiveDeviceVolume(); } // This needs to happen before we inform the audio manager that the device Loading @@ -578,8 +580,8 @@ public class A2dpService extends ProfileService { } int rememberedVolume = -1; if (AvrcpTargetService.get() != null) { rememberedVolume = AvrcpTargetService.get() if (mFactory.getAvrcpTargetService() != null) { rememberedVolume = mFactory.getAvrcpTargetService() .getRememberedVolumeForDevice(mActiveDevice); } Loading Loading @@ -643,8 +645,8 @@ public class A2dpService extends ProfileService { public void setAvrcpAbsoluteVolume(int volume) { // TODO (apanicke): Instead of using A2DP as a middleman for volume changes, add a binder // service to the new AVRCP Profile and have the audio manager use that instead. if (AvrcpTargetService.get() != null) { AvrcpTargetService.get().sendVolumeChanged(volume); if (mFactory.getAvrcpTargetService() != null) { mFactory.getAvrcpTargetService().sendVolumeChanged(volume); return; } } Loading Loading @@ -923,8 +925,8 @@ public class A2dpService extends ProfileService { } synchronized (mStateMachines) { if (AvrcpTargetService.get() != null) { AvrcpTargetService.get().volumeDeviceSwitched(device); if (mFactory.getAvrcpTargetService() != null) { mFactory.getAvrcpTargetService().volumeDeviceSwitched(device); } mActiveDevice = device; Loading
src/com/android/bluetooth/btservice/ServiceFactory.java +5 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.bluetooth.btservice; import com.android.bluetooth.a2dp.A2dpService; import com.android.bluetooth.avrcp.AvrcpTargetService; import com.android.bluetooth.hearingaid.HearingAidService; import com.android.bluetooth.hfp.HeadsetService; import com.android.bluetooth.hid.HidDeviceService; Loading Loading @@ -48,4 +49,8 @@ public class ServiceFactory { public HearingAidService getHearingAidService() { return HearingAidService.getHearingAidService(); } public AvrcpTargetService getAvrcpTargetService() { return AvrcpTargetService.get(); } }
tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java +34 −0 Original line number Diff line number Diff line Loading @@ -38,7 +38,9 @@ import android.support.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.avrcp.AvrcpTargetService; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.ServiceFactory; import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; Loading Loading @@ -75,6 +77,8 @@ public class A2dpServiceTest { @Mock private AdapterService mAdapterService; @Mock private A2dpNativeInterface mA2dpNativeInterface; @Mock private DatabaseManager mDatabaseManager; @Mock private AvrcpTargetService mAvrcpTargetService; @Mock private ServiceFactory mFactory; @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); Loading @@ -93,11 +97,13 @@ public class A2dpServiceTest { TestUtils.setAdapterService(mAdapterService); doReturn(MAX_CONNECTED_AUDIO_DEVICES).when(mAdapterService).getMaxConnectedAudioDevices(); doReturn(false).when(mAdapterService).isQuietModeEnabled(); doReturn(mAvrcpTargetService).when(mFactory).getAvrcpTargetService(); mAdapter = BluetoothAdapter.getDefaultAdapter(); startService(); mA2dpService.mA2dpNativeInterface = mA2dpNativeInterface; mA2dpService.mFactory = mFactory; // Override the timeout value to speed up the test A2dpStateMachine.sConnectTimeoutMs = TIMEOUT_MS; // 1s Loading Loading @@ -245,6 +251,8 @@ public class A2dpServiceTest { }); // Verify that setActiveDevice(null) was called during shutdown verify(mA2dpNativeInterface).setActiveDevice(null); // Verify that storeVolumeForDevice(mTestDevice) was called during shutdown verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); // Try to restart the service. Note: must be done on the main thread. InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { public void run() { Loading Loading @@ -787,11 +795,13 @@ public class A2dpServiceTest { Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); Assert.assertTrue(mA2dpService.setSilenceMode(mTestDevice, true)); verify(mA2dpNativeInterface).setSilenceDevice(mTestDevice, true); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); Assert.assertNull(mA2dpService.getActiveDevice()); // Test whether active device been resumeed after disable silence mode. Assert.assertTrue(mA2dpService.setSilenceMode(mTestDevice, false)); verify(mA2dpNativeInterface).setSilenceDevice(mTestDevice, false); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); // Test that active device should not be changed when silence a non-active device Loading @@ -799,11 +809,13 @@ public class A2dpServiceTest { Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); Assert.assertTrue(mA2dpService.setSilenceMode(otherDevice, true)); verify(mA2dpNativeInterface).setSilenceDevice(otherDevice, true); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); // Test that active device should not be changed when another device exits silence mode Assert.assertTrue(mA2dpService.setSilenceMode(otherDevice, false)); verify(mA2dpNativeInterface).setSilenceDevice(otherDevice, false); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); Assert.assertEquals(mTestDevice, mA2dpService.getActiveDevice()); } Loading Loading @@ -893,6 +905,28 @@ public class A2dpServiceTest { verifySupportTime, verifyNotSupportTime, verifyEnabledTime); } /** * Test that volume level of previous active device will be stored after set active device. */ @Test public void testStoreVolumeAfterSetActiveDevice() { BluetoothDevice otherDevice = mAdapter.getRemoteDevice("05:04:03:02:01:00"); connectDevice(otherDevice); connectDevice(mTestDevice); doReturn(true).when(mA2dpNativeInterface).setActiveDevice(any(BluetoothDevice.class)); doReturn(true).when(mA2dpNativeInterface).setActiveDevice(null); Assert.assertTrue(mA2dpService.setActiveDevice(mTestDevice)); // Test volume stored for previous active device an adjust for current active device Assert.assertTrue(mA2dpService.setActiveDevice(otherDevice)); verify(mAvrcpTargetService).storeVolumeForDevice(mTestDevice); verify(mAvrcpTargetService).getRememberedVolumeForDevice(otherDevice); // Test volume store for previous active device when set active device to null Assert.assertTrue(mA2dpService.setActiveDevice(null)); verify(mAvrcpTargetService).storeVolumeForDevice(otherDevice); } private void connectDevice(BluetoothDevice device) { connectDeviceWithCodecStatus(device, null); } Loading