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

Commit a7ef1059 authored by Michael Mikhail's avatar Michael Mikhail
Browse files

Setting up environment for media carousel view model

Since we only need to show the sorted list of media, there is no need to
use loading states. Instead, we can have them in a common model that
should be exposed by interactor. View-model should expose the list of
MediaCommonViewModel that contains view-models of either media controls
or recommendations and non-UI change actions. The common view-model will
be used by DiffUtil to figure out the events occured on the new list and
call actions.

Flag: ACONFIG media_controls_refactor DISABLED
Bug: 326281896
Test: atest SystemUITests:MediaDataFilterImplTest
Test: atest SystemUiRoboTests:MediaCarouselInteractor
Test: Build.
Change-Id: I8b9a8fce266f322d94ad12ad38bcc393ad84ad5e
parent 81f6b5c6
Loading
Loading
Loading
Loading
+15 −43
Original line number Diff line number Diff line
@@ -147,37 +147,6 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
            assertThat(smartspaceMediaData?.isActive).isFalse()
        }

    @Test
    fun addMediaDataLoadingState() =
        testScope.runTest {
            val mediaDataLoadedStates by collectLastValue(underTest.mediaDataLoadedStates)
            val instanceId = InstanceId.fakeInstanceId(123)
            val mediaLoadedStates = mutableListOf(MediaDataLoadingModel.Loaded(instanceId))

            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))

            assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates)

            mediaLoadedStates.remove(MediaDataLoadingModel.Loaded(instanceId))

            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Removed(instanceId))

            assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates)
        }

    @Test
    fun setRecommendationsLoadingState() =
        testScope.runTest {
            val recommendationsLoadingState by
                collectLastValue(underTest.recommendationsLoadingState)
            val recommendationsLoadingModel =
                SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE)

            underTest.setRecommendationsLoadingState(recommendationsLoadingModel)

            assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel)
        }

    @Test
    fun addMediaControlPlayingThenRemote() =
        testScope.runTest {
@@ -195,9 +164,10 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
            assertThat(sortedMedia?.size).isEqualTo(2)
            assertThat(sortedMedia?.values)
                .containsExactly(
                    MediaCommonModel.MediaControl(playingInstanceId),
                    MediaCommonModel.MediaControl(remoteInstanceId)
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId)),
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(remoteInstanceId))
                )
                .inOrder()
        }

    @Test
@@ -217,8 +187,8 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
            assertThat(sortedMedia?.size).isEqualTo(2)
            assertThat(sortedMedia?.values)
                .containsExactly(
                    MediaCommonModel.MediaControl(playingInstanceId1),
                    MediaCommonModel.MediaControl(playingInstanceId2)
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId1)),
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId2))
                )
                .inOrder()

@@ -233,8 +203,8 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
            assertThat(sortedMedia?.size).isEqualTo(2)
            assertThat(sortedMedia?.values)
                .containsExactly(
                    MediaCommonModel.MediaControl(playingInstanceId2),
                    MediaCommonModel.MediaControl(playingInstanceId1)
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId2)),
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(playingInstanceId1))
                )
                .inOrder()
        }
@@ -285,12 +255,14 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
            assertThat(sortedMedia?.size).isEqualTo(6)
            assertThat(sortedMedia?.values)
                .containsExactly(
                    MediaCommonModel.MediaControl(instanceId1),
                    MediaCommonModel.MediaControl(instanceId2),
                    MediaCommonModel.MediaRecommendations(KEY_MEDIA_SMARTSPACE),
                    MediaCommonModel.MediaControl(instanceId4),
                    MediaCommonModel.MediaControl(instanceId3),
                    MediaCommonModel.MediaControl(instanceId5),
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId1)),
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId2)),
                    MediaCommonModel.MediaRecommendations(
                        SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true)
                    ),
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId4)),
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId3)),
                    MediaCommonModel.MediaControl(MediaDataLoadingModel.Loaded(instanceId5)),
                )
                .inOrder()
        }
+7 −92
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import android.R
import android.graphics.drawable.Icon
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.logging.InstanceId
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.Flags
@@ -29,18 +28,14 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.MediaTestHelper
import com.android.systemui.media.controls.data.repository.MediaFilterRepository
import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.domain.pipeline.MediaDataFilterImpl
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter
import com.android.systemui.media.controls.shared.model.MediaCommonModel
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
import com.android.systemui.statusbar.notificationLockscreenUserManager
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -54,8 +49,6 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope

    private val mediaDataFilter: MediaDataFilterImpl = kosmos.mediaDataFilter
    private val notificationLockscreenUserManager = kosmos.notificationLockscreenUserManager
    private val mediaFilterRepository: MediaFilterRepository = kosmos.mediaFilterRepository

    private val underTest: MediaCarouselInteractor = kosmos.mediaCarouselInteractor
@@ -95,7 +88,6 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
                collectLastValue(underTest.hasActiveMediaOrRecommendation)
            val hasActiveMedia by collectLastValue(underTest.hasActiveMedia)
            val hasAnyMedia by collectLastValue(underTest.hasAnyMedia)
            val sortedMedia by collectLastValue(underTest.sortedMedia)

            val userMedia = MediaData(active = false)
            val instanceId = userMedia.instanceId
@@ -106,7 +98,6 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
            assertThat(hasActiveMediaOrRecommendation).isFalse()
            assertThat(hasActiveMedia).isFalse()
            assertThat(hasAnyMedia).isTrue()
            assertThat(sortedMedia).containsExactly(MediaCommonModel.MediaControl(instanceId))

            assertThat(mediaFilterRepository.removeSelectedUserMediaEntry(instanceId, userMedia))
                .isTrue()
@@ -117,7 +108,6 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
            assertThat(hasActiveMediaOrRecommendation).isFalse()
            assertThat(hasActiveMedia).isFalse()
            assertThat(hasAnyMedia).isFalse()
            assertThat(sortedMedia).isEmpty()
        }

    @Test
@@ -138,28 +128,26 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
                    recommendations = MediaTestHelper.getValidRecommendationList(icon),
                )
            val userMedia = MediaData(active = false)
            val recsLoadingModel = SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true)
            val mediaLoadingModel = MediaDataLoadingModel.Loaded(userMedia.instanceId)

            mediaFilterRepository.setRecommendation(userMediaRecommendation)
            mediaFilterRepository.setRecommendationsLoadingState(
                SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, true)
            )
            mediaFilterRepository.setRecommendationsLoadingState(recsLoadingModel)

            assertThat(hasActiveMediaOrRecommendation).isTrue()
            assertThat(hasAnyMediaOrRecommendation).isTrue()
            assertThat(sortedMedia)
                .containsExactly(MediaCommonModel.MediaRecommendations(KEY_MEDIA_SMARTSPACE))
                .containsExactly(MediaCommonModel.MediaRecommendations(recsLoadingModel))

            mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
            mediaFilterRepository.addMediaDataLoadingState(
                MediaDataLoadingModel.Loaded(userMedia.instanceId)
            )
            mediaFilterRepository.addMediaDataLoadingState(mediaLoadingModel)

            assertThat(hasActiveMediaOrRecommendation).isTrue()
            assertThat(hasAnyMediaOrRecommendation).isTrue()
            assertThat(sortedMedia)
                .containsExactly(
                    MediaCommonModel.MediaRecommendations(KEY_MEDIA_SMARTSPACE),
                    MediaCommonModel.MediaControl(userMedia.instanceId)
                    MediaCommonModel.MediaRecommendations(recsLoadingModel),
                    MediaCommonModel.MediaControl(mediaLoadingModel, true)
                )
                .inOrder()
        }
@@ -238,80 +226,7 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
    fun hasActiveMediaOrRecommendation_nothingSet_returnsFalse() =
        testScope.runTest { assertThat(underTest.hasActiveMediaOrRecommendation.value).isFalse() }

    @Test
    fun onMediaDataUpdated_updatesLoadingState() =
        testScope.runTest {
            whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
            whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
            val mediaDataLoadedStates by collectLastValue(underTest.mediaDataLoadedStates)
            val instanceId = InstanceId.fakeInstanceId(123)
            val mediaLoadedStates: MutableList<MediaDataLoadingModel> = mutableListOf()

            mediaLoadedStates.add(MediaDataLoadingModel.Loaded(instanceId))
            mediaDataFilter.onMediaDataLoaded(
                KEY,
                KEY,
                MediaData(userId = USER_ID, instanceId = instanceId)
            )

            assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates)

            val newInstanceId = InstanceId.fakeInstanceId(321)

            mediaLoadedStates.add(MediaDataLoadingModel.Loaded(newInstanceId))
            mediaDataFilter.onMediaDataLoaded(
                KEY_2,
                KEY_2,
                MediaData(userId = USER_ID, instanceId = newInstanceId)
            )

            assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates)

            mediaLoadedStates.remove(MediaDataLoadingModel.Loaded(instanceId))

            mediaDataFilter.onMediaDataRemoved(KEY)

            assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates)

            mediaLoadedStates.remove(MediaDataLoadingModel.Loaded(newInstanceId))

            mediaDataFilter.onMediaDataRemoved(KEY_2)

            assertThat(mediaDataLoadedStates).isEqualTo(mediaLoadedStates)
        }

    @Test
    fun onMediaRecommendationsUpdated_updatesLoadingState() =
        testScope.runTest {
            whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
            whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
            val recommendationsLoadingState by
                collectLastValue(underTest.recommendationsLoadingState)
            val icon = Icon.createWithResource(context, R.drawable.ic_media_play)
            val mediaRecommendations =
                SmartspaceMediaData(
                    targetId = KEY_MEDIA_SMARTSPACE,
                    isActive = true,
                    recommendations = MediaTestHelper.getValidRecommendationList(icon),
                )
            var recommendationsLoadingModel: SmartspaceMediaLoadingModel =
                SmartspaceMediaLoadingModel.Loaded(KEY_MEDIA_SMARTSPACE, isPrioritized = true)

            mediaDataFilter.onSmartspaceMediaDataLoaded(KEY_MEDIA_SMARTSPACE, mediaRecommendations)

            assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel)

            recommendationsLoadingModel = SmartspaceMediaLoadingModel.Removed(KEY_MEDIA_SMARTSPACE)

            mediaDataFilter.onSmartspaceMediaDataRemoved(KEY_MEDIA_SMARTSPACE)

            assertThat(recommendationsLoadingState).isEqualTo(recommendationsLoadingModel)
        }

    companion object {
        private const val KEY = "key"
        private const val KEY_2 = "key2"
        private const val USER_ID = 0
        private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
    }
}
+22 −73
Original line number Diff line number Diff line
@@ -52,16 +52,6 @@ class MediaFilterRepository @Inject constructor(private val systemClock: SystemC
        MutableStateFlow(LinkedHashMap())
    val allUserEntries: StateFlow<Map<String, MediaData>> = _allUserEntries.asStateFlow()

    private val _mediaDataLoadedStates: MutableStateFlow<List<MediaDataLoadingModel>> =
        MutableStateFlow(mutableListOf())
    val mediaDataLoadedStates: StateFlow<List<MediaDataLoadingModel>> =
        _mediaDataLoadedStates.asStateFlow()

    private val _recommendationsLoadingState: MutableStateFlow<SmartspaceMediaLoadingModel> =
        MutableStateFlow(SmartspaceMediaLoadingModel.Unknown)
    val recommendationsLoadingState: StateFlow<SmartspaceMediaLoadingModel> =
        _recommendationsLoadingState.asStateFlow()

    private val comparator =
        compareByDescending<MediaSortKeyModel> {
                it.isPlaying == true && it.playbackLocation == MediaData.PLAYBACK_LOCAL
@@ -148,46 +138,15 @@ class MediaFilterRepository @Inject constructor(private val systemClock: SystemC
    }

    fun addMediaDataLoadingState(mediaDataLoadingModel: MediaDataLoadingModel) {
        // Filter out previous loading state that has same [InstanceId].
        val loadedStates =
            _mediaDataLoadedStates.value.filter { loadedModel ->
                loadedModel !is MediaDataLoadingModel.Loaded ||
                    !loadedModel.equalInstanceIds(mediaDataLoadingModel)
            }

        _mediaDataLoadedStates.value =
            loadedStates +
                if (mediaDataLoadingModel is MediaDataLoadingModel.Loaded) {
                    listOf(mediaDataLoadingModel)
                } else {
                    emptyList()
                }

        addMediaLoadingToSortedMap(mediaDataLoadingModel)
    }

    fun setRecommendationsLoadingState(smartspaceMediaLoadingModel: SmartspaceMediaLoadingModel) {
        _recommendationsLoadingState.value = smartspaceMediaLoadingModel

        addRecsLoadingToSortedMap(smartspaceMediaLoadingModel)
    }

    private fun addMediaLoadingToSortedMap(mediaDataLoadingModel: MediaDataLoadingModel) {
        val instanceId =
            when (mediaDataLoadingModel) {
                is MediaDataLoadingModel.Loaded -> mediaDataLoadingModel.instanceId
                is MediaDataLoadingModel.Removed -> mediaDataLoadingModel.instanceId
                MediaDataLoadingModel.Unknown -> null
            }
        val sortedMap = TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator)
        sortedMap.putAll(
            _sortedMedia.value.filter { (_, commonModel) ->
                commonModel !is MediaCommonModel.MediaControl ||
                    commonModel.instanceId != instanceId
                    commonModel.mediaLoadedModel.instanceId != mediaDataLoadingModel.instanceId
            }
        )

        _selectedUserEntries.value[instanceId]?.let {
        _selectedUserEntries.value[mediaDataLoadingModel.instanceId]?.let {
            val sortKey =
                MediaSortKeyModel(
                    isPrioritizedRec = false,
@@ -202,40 +161,27 @@ class MediaFilterRepository @Inject constructor(private val systemClock: SystemC
                )

            if (mediaDataLoadingModel is MediaDataLoadingModel.Loaded) {
                sortedMap[sortKey] = MediaCommonModel.MediaControl(it.instanceId)
                sortedMap[sortKey] =
                    MediaCommonModel.MediaControl(mediaDataLoadingModel, canBeRemoved(it))
            }
        }

        _sortedMedia.value = sortedMap
    }

    private fun addRecsLoadingToSortedMap(
        smartspaceMediaLoadingModel: SmartspaceMediaLoadingModel
    ) {
        val isPrioritized: Boolean
        val key: String?
    fun setRecommendationsLoadingState(smartspaceMediaLoadingModel: SmartspaceMediaLoadingModel) {
        val isPrioritized =
            when (smartspaceMediaLoadingModel) {
            is SmartspaceMediaLoadingModel.Loaded -> {
                isPrioritized = smartspaceMediaLoadingModel.isPrioritized
                key = smartspaceMediaLoadingModel.key
            }
            is SmartspaceMediaLoadingModel.Removed -> {
                isPrioritized = false
                key = smartspaceMediaLoadingModel.key
            }
            SmartspaceMediaLoadingModel.Unknown -> {
                isPrioritized = false
                key = null
            }
                is SmartspaceMediaLoadingModel.Loaded -> smartspaceMediaLoadingModel.isPrioritized
                else -> false
            }
        val sortedMap = TreeMap<MediaSortKeyModel, MediaCommonModel>(comparator)
        sortedMap.putAll(
            _sortedMedia.value.filter { (_, commonModel) ->
                commonModel !is MediaCommonModel.MediaRecommendations || commonModel.key != key
                commonModel !is MediaCommonModel.MediaRecommendations
            }
        )

        key?.let {
        val sortKey =
            MediaSortKeyModel(
                isPrioritizedRec = isPrioritized,
@@ -243,10 +189,13 @@ class MediaFilterRepository @Inject constructor(private val systemClock: SystemC
                active = _smartspaceMediaData.value.isActive,
            )
        if (smartspaceMediaLoadingModel is SmartspaceMediaLoadingModel.Loaded) {
                sortedMap[sortKey] = MediaCommonModel.MediaRecommendations(key)
            }
            sortedMap[sortKey] = MediaCommonModel.MediaRecommendations(smartspaceMediaLoadingModel)
        }

        _sortedMedia.value = sortedMap
    }

    private fun canBeRemoved(data: MediaData): Boolean {
        return data.isPlaying?.let { !it } ?: data.isClearable && !data.active
    }
}
+28 −23
Original line number Diff line number Diff line
@@ -35,20 +35,15 @@ import com.android.systemui.media.controls.domain.pipeline.MediaSessionBasedFilt
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.controls.shared.model.MediaDataLoadingModel
import com.android.systemui.media.controls.shared.model.SmartspaceMediaLoadingModel
import com.android.systemui.media.controls.util.MediaControlsRefactorFlag
import com.android.systemui.media.controls.util.MediaFlags
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn

@@ -82,8 +77,11 @@ constructor(
                    (smartspaceMediaData.isActive &&
                        (smartspaceMediaData.isValid() || reactivatedKey != null))
            }
            .distinctUntilChanged()
            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = false,
            )

    /** Are there any media entries we should display, including the recommendations? */
    val hasAnyMediaOrRecommendation: StateFlow<Boolean> =
@@ -98,34 +96,41 @@ constructor(
                        smartspaceMediaData.isActive && smartspaceMediaData.isValid()
                    })
            }
            .distinctUntilChanged()
            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = false,
            )

    /** Are there any media notifications active, excluding the recommendations? */
    val hasActiveMedia: StateFlow<Boolean> =
        mediaFilterRepository.selectedUserEntries
            .mapLatest { entries -> entries.any { it.value.active } }
            .distinctUntilChanged()
            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = false,
            )

    /** Are there any media notifications, excluding the recommendations? */
    val hasAnyMedia: StateFlow<Boolean> =
        mediaFilterRepository.selectedUserEntries
            .mapLatest { entries -> entries.isNotEmpty() }
            .distinctUntilChanged()
            .stateIn(applicationScope, SharingStarted.WhileSubscribed(), false)

    /** The most recent list of loaded media controls. */
    val mediaDataLoadedStates: Flow<List<MediaDataLoadingModel>> =
        mediaFilterRepository.mediaDataLoadedStates

    /** The most recent change to loaded media recommendations. */
    val recommendationsLoadingState: Flow<SmartspaceMediaLoadingModel> =
        mediaFilterRepository.recommendationsLoadingState
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = false,
            )

    /** The most recent sorted set for user media instances */
    val sortedMedia: Flow<List<MediaCommonModel>> =
        mediaFilterRepository.sortedMedia.map { it.values.toList() }
    val sortedMedia: StateFlow<List<MediaCommonModel>> =
        mediaFilterRepository.sortedMedia
            .mapLatest { it.values.toList() }
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = emptyList(),
            )

    override fun start() {
        if (!mediaFlags.isMediaControlsRefactorEnabled()) {
+6 −4
Original line number Diff line number Diff line
@@ -16,11 +16,13 @@

package com.android.systemui.media.controls.shared.model

import com.android.internal.logging.InstanceId

/** Models any type of media. */
sealed class MediaCommonModel {
    data class MediaControl(val instanceId: InstanceId) : MediaCommonModel()
    data class MediaControl(
        val mediaLoadedModel: MediaDataLoadingModel.Loaded,
        val canBeRemoved: Boolean = false
    ) : MediaCommonModel()

    data class MediaRecommendations(val key: String) : MediaCommonModel()
    data class MediaRecommendations(val recsLoadingModel: SmartspaceMediaLoadingModel) :
        MediaCommonModel()
}
Loading