diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt index a7bd68b5450d3..f972da560ed87 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt @@ -28,6 +28,7 @@ import com.android.systemui.Dumpable import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager +import com.android.systemui.media.muteawait.MediaMuteAwaitConnectionManager import com.android.systemui.media.muteawait.MediaMuteAwaitConnectionManagerFactory import java.io.FileDescriptor import java.io.PrintWriter @@ -84,14 +85,14 @@ class MediaDeviceManager @Inject constructor( controllerFactory.create(it) } val localMediaManager = localMediaManagerFactory.create(data.packageName) - // We don't need to set this muteAwaitConnectionManager anywhere; it will just notify - // [localMediaManager] on the appropriate events. - muteAwaitConnectionManagerFactory.create(localMediaManager) + val muteAwaitConnectionManager = + muteAwaitConnectionManagerFactory.create(localMediaManager) entry = Entry( key, oldKey, controller, - localMediaManager + localMediaManager, + muteAwaitConnectionManager ) entries[key] = entry entry.start() @@ -137,7 +138,8 @@ class MediaDeviceManager @Inject constructor( val key: String, val oldKey: String?, val controller: MediaController?, - val localMediaManager: LocalMediaManager + val localMediaManager: LocalMediaManager, + val muteAwaitConnectionManager: MediaMuteAwaitConnectionManager? ) : LocalMediaManager.DeviceCallback, MediaController.Callback() { val token @@ -161,6 +163,7 @@ class MediaDeviceManager @Inject constructor( fun start() = bgExecutor.execute { localMediaManager.registerCallback(this) localMediaManager.startScan() + muteAwaitConnectionManager?.startListening() playbackType = controller?.playbackInfo?.playbackType ?: PLAYBACK_TYPE_UNKNOWN controller?.registerCallback(this) updateCurrent() @@ -173,6 +176,7 @@ class MediaDeviceManager @Inject constructor( controller?.unregisterCallback(this) localMediaManager.stopScan() localMediaManager.unregisterCallback(this) + muteAwaitConnectionManager?.stopListening() } fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array) { diff --git a/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt b/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt index 1b53776e045bb..22bc5572f5a5b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt @@ -37,8 +37,8 @@ import java.util.concurrent.Executor * TODO(b/206614671): Add logging. */ class MediaMuteAwaitConnectionManager constructor( - @Main mainExecutor: Executor, - localMediaManager: LocalMediaManager, + @Main private val mainExecutor: Executor, + private val localMediaManager: LocalMediaManager, private val context: Context, private val deviceIconUtil: DeviceIconUtil ) { @@ -68,8 +68,8 @@ class MediaMuteAwaitConnectionManager constructor( } } - init { - // TODO(b/206614671): Unregister this callback (likely on [MediaDeviceManager.Entry.Stop]). + /** Start listening for mute await events. */ + fun startListening() { audioManager.registerMuteAwaitConnectionCallback( mainExecutor, muteAwaitConnectionChangeListener ) @@ -82,6 +82,11 @@ class MediaMuteAwaitConnectionManager constructor( } } + /** Stop listening for mute await events. */ + fun stopListening() { + audioManager.unregisterMuteAwaitConnectionCallback(muteAwaitConnectionChangeListener) + } + private fun AudioDeviceAttributes.getIcon(): Drawable { return deviceIconUtil.getIconFromAudioDeviceType(this.type, context) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt index e28927e3aac23..64b5b86f47f66 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt @@ -30,6 +30,7 @@ import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager +import com.android.systemui.media.muteawait.MediaMuteAwaitConnectionManager import com.android.systemui.media.muteawait.MediaMuteAwaitConnectionManagerFactory import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock @@ -74,6 +75,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Mock private lateinit var lmm: LocalMediaManager @Mock private lateinit var mr2: MediaRouter2Manager @Mock private lateinit var muteAwaitFactory: MediaMuteAwaitConnectionManagerFactory + @Mock private lateinit var muteAwaitManager: MediaMuteAwaitConnectionManager private lateinit var fakeFgExecutor: FakeExecutor private lateinit var fakeBgExecutor: FakeExecutor @Mock private lateinit var dumpster: DumpManager @@ -106,6 +108,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() { whenever(device.name).thenReturn(DEVICE_NAME) whenever(device.iconWithoutBackground).thenReturn(icon) whenever(lmmFactory.create(PACKAGE)).thenReturn(lmm) + whenever(muteAwaitFactory.create(lmm)).thenReturn(muteAwaitManager) whenever(lmm.getCurrentConnectedDevice()).thenReturn(device) whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(route) @@ -156,6 +159,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() { manager.onMediaDataRemoved(KEY) fakeBgExecutor.runAllReady() verify(lmm).unregisterCallback(any()) + verify(muteAwaitManager).stopListening() } @Test @@ -179,6 +183,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fakeFgExecutor.runAllReady() // THEN the listener for the old key should removed. verify(lmm).unregisterCallback(any()) + verify(muteAwaitManager).stopListening() // AND a new device event emitted val data = captureDeviceData(KEY, KEY_OLD) assertThat(data.enabled).isTrue() @@ -250,6 +255,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() { manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() val deviceCallback = captureCallback() + verify(muteAwaitManager).startListening() // WHEN the device list changes deviceCallback.onDeviceListUpdate(mutableListOf(device)) assertThat(fakeBgExecutor.runAllReady()).isEqualTo(1) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt index 98d5cbacb253a..88c451499d21b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt @@ -16,7 +16,6 @@ package com.android.systemui.media.muteawait -import android.annotation.DrawableRes import android.content.Context import android.graphics.drawable.Drawable import android.media.AudioAttributes.USAGE_MEDIA @@ -54,7 +53,6 @@ class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { private lateinit var deviceIconUtil: DeviceIconUtil @Mock private lateinit var localMediaManager: LocalMediaManager - private lateinit var muteAwaitListener: AudioManager.MuteAwaitConnectionCallback private lateinit var icon: Drawable @Before @@ -63,29 +61,56 @@ class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { context.addMockSystemService(Context.AUDIO_SERVICE, audioManager) icon = context.getDrawable(R.drawable.ic_cake)!! whenever(deviceIconUtil.getIconFromAudioDeviceType(any(), any())).thenReturn(icon) + + muteAwaitConnectionManager = MediaMuteAwaitConnectionManager( + FakeExecutor(FakeSystemClock()), + localMediaManager, + context, + deviceIconUtil + ) } @Test - fun constructor_audioManagerHasNoMuteAwaitDevice_localMediaMangerNotNotified() { + fun constructor_audioManagerCallbackNotRegistered() { + verify(audioManager, never()).registerMuteAwaitConnectionCallback(any(), any()) + } + + @Test + fun startListening_audioManagerCallbackRegistered() { + muteAwaitConnectionManager.startListening() + + verify(audioManager).registerMuteAwaitConnectionCallback(any(), any()) + } + + @Test + fun stopListening_audioManagerCallbackUnregistered() { + muteAwaitConnectionManager.stopListening() + + verify(audioManager).unregisterMuteAwaitConnectionCallback(any()) + } + + @Test + fun startListening_audioManagerHasNoMuteAwaitDevice_localMediaMangerNotNotified() { whenever(audioManager.mutingExpectedDevice).thenReturn(null) - instantiateManager() + muteAwaitConnectionManager.startListening() verify(localMediaManager, never()).dispatchAboutToConnectDeviceChanged(any(), any()) } @Test - fun constructor_audioManagerHasMuteAwaitDevice_localMediaMangerNotified() { + fun startListening_audioManagerHasMuteAwaitDevice_localMediaMangerNotified() { whenever(audioManager.mutingExpectedDevice).thenReturn(DEVICE) - instantiateManager() + muteAwaitConnectionManager.startListening() verify(localMediaManager).dispatchAboutToConnectDeviceChanged(eq(DEVICE_NAME), eq(icon)) } @Test fun onMutedUntilConnection_notUsageMedia_localMediaManagerNotNotified() { - instantiateManager() + muteAwaitConnectionManager.startListening() + val muteAwaitListener = getMuteAwaitListener() muteAwaitListener.onMutedUntilConnection(DEVICE, intArrayOf(USAGE_UNKNOWN)) @@ -94,7 +119,9 @@ class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { @Test fun onMutedUntilConnection_isUsageMedia_localMediaManagerNotified() { - instantiateManager() + muteAwaitConnectionManager.startListening() + val muteAwaitListener = getMuteAwaitListener() + muteAwaitListener.onMutedUntilConnection(DEVICE, intArrayOf(USAGE_MEDIA)) @@ -103,7 +130,9 @@ class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { @Test fun onUnmutedEvent_noDeviceMutedBefore_localMediaManagerNotNotified() { - instantiateManager() + muteAwaitConnectionManager.startListening() + val muteAwaitListener = getMuteAwaitListener() + muteAwaitListener.onUnmutedEvent(EVENT_CONNECTION, DEVICE, intArrayOf(USAGE_MEDIA)) verify(localMediaManager, never()).dispatchAboutToConnectDeviceChanged(any(), any()) @@ -111,7 +140,8 @@ class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { @Test fun onUnmutedEvent_notSameDevice_localMediaManagerNotNotified() { - instantiateManager() + muteAwaitConnectionManager.startListening() + val muteAwaitListener = getMuteAwaitListener() muteAwaitListener.onMutedUntilConnection(DEVICE, intArrayOf(USAGE_MEDIA)) reset(localMediaManager) @@ -130,7 +160,8 @@ class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { @Test fun onUnmutedEvent_notUsageMedia_localMediaManagerNotNotified() { - instantiateManager() + muteAwaitConnectionManager.startListening() + val muteAwaitListener = getMuteAwaitListener() muteAwaitListener.onMutedUntilConnection(DEVICE, intArrayOf(USAGE_MEDIA)) reset(localMediaManager) @@ -141,7 +172,8 @@ class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { @Test fun onUnmutedEvent_sameDeviceAndUsageMedia_localMediaManagerNotified() { - instantiateManager() + muteAwaitConnectionManager.startListening() + val muteAwaitListener = getMuteAwaitListener() muteAwaitListener.onMutedUntilConnection(DEVICE, intArrayOf(USAGE_MEDIA)) reset(localMediaManager) @@ -150,20 +182,12 @@ class MediaMuteAwaitConnectionManagerTest : SysuiTestCase() { verify(localMediaManager).dispatchAboutToConnectDeviceChanged(eq(null), eq(null)) } - // Some classes test the constructor, so don't instantiate the manager in @SetUp. - private fun instantiateManager() { - muteAwaitConnectionManager = MediaMuteAwaitConnectionManager( - FakeExecutor(FakeSystemClock()), - localMediaManager, - context, - deviceIconUtil - ) - + private fun getMuteAwaitListener(): AudioManager.MuteAwaitConnectionCallback { val listenerCaptor = ArgumentCaptor.forClass( AudioManager.MuteAwaitConnectionCallback::class.java ) verify(audioManager).registerMuteAwaitConnectionCallback(any(), listenerCaptor.capture()) - muteAwaitListener = listenerCaptor.value!! + return listenerCaptor.value!! } }