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

Commit 606334b1 authored by Beth Thibodeau's avatar Beth Thibodeau
Browse files

Add support in new pipeline for compose flag

- Use MediaPipelineRepository instead of specific implementation to
  allow switching based on flag
- Use relevant parts of new pipeline when flag is enabled

Flag: com.android.systemui.media_controls_in_compose
Bug: 397989775
Test: manual - play media with flag off and on
Test: MediaFilterRepositoryTest MediaCarouselInteractorTest
Change-Id: Ifdf0c0d2552f25fc30c0cd7abc99b78e70b17a14
parent ea54a75f
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -137,14 +137,6 @@ class MediaFilterRepository @Inject constructor(private val systemClock: SystemC
        _currentMedia.value = sortedMedia.values.toList()
    }

    fun hasActiveMedia(): Boolean {
        return mutableUserEntries.value.any { it.value.active }
    }

    fun hasAnyMedia(): Boolean {
        return mutableUserEntries.value.entries.isNotEmpty()
    }

    private fun canBeRemoved(data: MediaData): Boolean {
        return data.isPlaying?.let { !it } ?: data.isClearable && !data.active
    }
+2 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.media.controls.domain

import com.android.systemui.CoreStartable
import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.media.controls.domain.pipeline.LegacyMediaDataManagerImpl
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
@@ -54,7 +55,7 @@ interface MediaDomainModule {
            legacyProvider: Provider<LegacyMediaDataManagerImpl>,
            newProvider: Provider<MediaCarouselInteractor>,
        ): MediaDataManager {
            return if (SceneContainerFlag.isEnabled) {
            return if (SceneContainerFlag.isEnabled || Flags.mediaControlsInCompose()) {
                newProvider.get()
            } else {
                legacyProvider.get()
+15 −15
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ constructor(
    userTracker: UserTracker,
    private val lockscreenUserManager: NotificationLockscreenUserManager,
    @Main private val executor: Executor,
    private val mediaFilterRepository: MediaPipelineRepository,
    private val mediaPipelineRepository: MediaPipelineRepository,
    private val mediaLogger: MediaLogger,
) : MediaDataManager.Listener {
    /** Non-UI listeners to media changes. */
@@ -83,9 +83,9 @@ constructor(
        immediately: Boolean,
    ) {
        if (oldKey != null && oldKey != key) {
            mediaFilterRepository.removeMediaEntry(oldKey)
            mediaPipelineRepository.removeMediaEntry(oldKey)
        }
        mediaFilterRepository.addMediaEntry(key, data)
        mediaPipelineRepository.addMediaEntry(key, data)

        if (
            !lockscreenUserManager.isCurrentProfile(data.userId) ||
@@ -94,7 +94,7 @@ constructor(
            return
        }

        mediaFilterRepository.addCurrentUserMediaEntry(data)
        mediaPipelineRepository.addCurrentUserMediaEntry(data)

        mediaLogger.logMediaLoaded(data.instanceId, data.active, "loading media")

@@ -103,9 +103,9 @@ constructor(
    }

    override fun onMediaDataRemoved(key: String, userInitiated: Boolean) {
        mediaFilterRepository.removeMediaEntry(key)?.let { mediaData ->
        mediaPipelineRepository.removeMediaEntry(key)?.let { mediaData ->
            val instanceId = mediaData.instanceId
            mediaFilterRepository.removeCurrentUserMediaEntry(instanceId)?.let {
            mediaPipelineRepository.removeCurrentUserMediaEntry(instanceId)?.let {
                mediaLogger.logMediaRemoved(instanceId, "removing media card")
                // Only notify listeners if something actually changed
                listeners.forEach { it.onMediaDataRemoved(key, userInitiated) }
@@ -116,10 +116,10 @@ constructor(
    @VisibleForTesting
    internal fun handleProfileChanged() {
        // TODO(b/317221348) re-add media removed when profile is available.
        mediaFilterRepository.allMediaEntries.value.forEach { (key, data) ->
        mediaPipelineRepository.allMediaEntries.value.forEach { (key, data) ->
            if (!lockscreenUserManager.isProfileAvailable(data.userId)) {
                // Only remove media when the profile is unavailable.
                mediaFilterRepository.removeCurrentUserMediaEntry(data.instanceId, data)
                mediaPipelineRepository.removeCurrentUserMediaEntry(data.instanceId, data)
                mediaLogger.logMediaRemoved(data.instanceId, "Removing $key after profile change")
                listeners.forEach { listener -> listener.onMediaDataRemoved(key, false) }
            }
@@ -130,9 +130,9 @@ constructor(
    internal fun handleUserSwitched() {
        // If the user changes, remove all current MediaData objects.
        val listenersCopy = listeners
        val keyCopy = mediaFilterRepository.currentUserEntries.value.keys.toMutableList()
        val keyCopy = mediaPipelineRepository.currentUserEntries.value.keys.toMutableList()
        // Clear the list first and update loading state to remove media from UI.
        mediaFilterRepository.clearCurrentUserMedia()
        mediaPipelineRepository.clearCurrentUserMedia()
        keyCopy.forEach { instanceId ->
            mediaLogger.logMediaRemoved(instanceId, "Removing media after user change")
            getKey(instanceId)?.let {
@@ -140,9 +140,9 @@ constructor(
            }
        }

        mediaFilterRepository.allMediaEntries.value.forEach { (key, data) ->
        mediaPipelineRepository.allMediaEntries.value.forEach { (key, data) ->
            if (lockscreenUserManager.isCurrentProfile(data.userId)) {
                mediaFilterRepository.addCurrentUserMediaEntry(data)
                mediaPipelineRepository.addCurrentUserMediaEntry(data)
                mediaLogger.logMediaLoaded(
                    data.instanceId,
                    data.active,
@@ -156,9 +156,9 @@ constructor(
    /** Invoked when the user has dismissed the media carousel */
    fun onSwipeToDismiss() {
        if (DEBUG) Log.d(TAG, "Media carousel swiped away")
        val mediaEntries = mediaFilterRepository.allMediaEntries.value.entries
        val mediaEntries = mediaPipelineRepository.allMediaEntries.value.entries
        mediaEntries.forEach { (key, data) ->
            if (mediaFilterRepository.currentUserEntries.value.containsKey(data.instanceId)) {
            if (mediaPipelineRepository.currentUserEntries.value.containsKey(data.instanceId)) {
                // Force updates to listeners, needed for re-activated card
                mediaDataProcessor.setInactive(key, timedOut = true, forceUpdate = true)
            }
@@ -172,7 +172,7 @@ constructor(
    fun removeListener(listener: MediaDataProcessor.Listener) = _listeners.remove(listener)

    private fun getKey(instanceId: InstanceId): String? {
        val allEntries = mediaFilterRepository.allMediaEntries.value
        val allEntries = mediaPipelineRepository.allMediaEntries.value
        val filteredEntries = allEntries.filter { (_, data) -> data.instanceId == instanceId }
        return if (filteredEntries.isNotEmpty()) {
            filteredEntries.keys.first()
+1 −1
Original line number Diff line number Diff line
@@ -184,7 +184,7 @@ class MediaDataProcessor(
        }

    override fun start() {
        if (!SceneContainerFlag.isEnabled) {
        if (!SceneContainerFlag.isEnabled && !Flags.mediaControlsInCompose()) {
            return
        }

+23 −10
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.media.session.PlaybackState
import android.service.notification.StatusBarNotification
import com.android.internal.logging.InstanceId
import com.android.systemui.CoreStartable
import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.media.controls.data.repository.MediaFilterRepository
@@ -34,11 +35,12 @@ import com.android.systemui.media.controls.domain.pipeline.MediaDeviceManager
import com.android.systemui.media.controls.domain.pipeline.MediaSessionBasedFilter
import com.android.systemui.media.controls.domain.pipeline.MediaTimeoutListener
import com.android.systemui.media.controls.domain.resume.MediaResumeListener
import com.android.systemui.media.controls.shared.model.MediaCommonModel
import com.android.systemui.media.remedia.data.repository.MediaPipelineRepository
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
@@ -57,12 +59,12 @@ constructor(
    private val mediaDeviceManager: MediaDeviceManager,
    private val mediaDataCombineLatest: MediaDataCombineLatest,
    private val mediaDataFilter: MediaDataFilterImpl,
    private val mediaFilterRepository: MediaFilterRepository,
    private val mediaPipelineRepository: MediaPipelineRepository,
) : MediaDataManager, CoreStartable {

    /** Are there any media notifications active? */
    val hasActiveMedia: StateFlow<Boolean> =
        mediaFilterRepository.currentUserEntries
        mediaPipelineRepository.currentUserEntries
            .map { entries -> entries.any { it.value.active } }
            .stateIn(
                scope = applicationScope,
@@ -72,7 +74,7 @@ constructor(

    /** Are there any media entries, including inactive ones? */
    val hasAnyMedia: StateFlow<Boolean> =
        mediaFilterRepository.currentUserEntries
        mediaPipelineRepository.currentUserEntries
            .map { entries -> entries.isNotEmpty() }
            .stateIn(
                scope = applicationScope,
@@ -81,10 +83,16 @@ constructor(
            )

    /** The current list for user media instances */
    val currentMedia: StateFlow<List<MediaCommonModel>> = mediaFilterRepository.currentMedia
    val currentMedia =
        if (!Flags.mediaControlsInCompose()) {
            (mediaPipelineRepository as MediaFilterRepository).currentMedia
        } else {
            // TODO(b/397989775) remove, not used with media_controls_in_compose
            MutableStateFlow(mutableListOf())
        }

    override fun start() {
        if (!SceneContainerFlag.isEnabled) {
        if (!SceneContainerFlag.isEnabled && !Flags.mediaControlsInCompose()) {
            return
        }

@@ -182,12 +190,14 @@ constructor(
        mediaDataFilter.onSwipeToDismiss()
    }

    override fun hasActiveMedia() = mediaFilterRepository.hasActiveMedia()
    override fun hasActiveMedia() = mediaPipelineRepository.hasActiveMedia()

    override fun hasAnyMedia() = mediaFilterRepository.hasAnyMedia()
    override fun hasAnyMedia() = mediaPipelineRepository.hasAnyMedia()

    fun reorderMedia() {
        mediaFilterRepository.setOrderedMedia()
        if (!Flags.mediaControlsInCompose()) {
            (mediaPipelineRepository as MediaFilterRepository).setOrderedMedia()
        }
    }

    /** Add a listener for internal events. */
@@ -201,6 +211,9 @@ constructor(
    companion object {
        val unsupported: Nothing
            get() =
                error("Code path not supported when ${SceneContainerFlag.DESCRIPTION} is enabled")
                error(
                    "Code path not supported when ${SceneContainerFlag.DESCRIPTION} or " +
                        "media_controls_in_compose is enabled"
                )
    }
}
Loading