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

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

Handle reordering when recommendation clicked.

Flag: ACONFIG com.android.systemui.media_controls_refactor DISABLED
Bug: 328207006
Test: atest SystemUiRoboTests:MediaCarouselViewModelTest
Change-Id: Ic85447cdc112de33c237fe98ba06c4dd096f0856
parent 3f548c00
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -267,6 +267,35 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
                .inOrder()
        }

    @Test
    fun loadMediaFromRec() =
        testScope.runTest {
            val isMediaFromRec by collectLastValue(underTest.isMediaFromRec)
            val instanceId1 = InstanceId.fakeInstanceId(123)
            val instanceId2 = InstanceId.fakeInstanceId(456)
            val data =
                MediaData(
                    active = true,
                    instanceId = instanceId1,
                    packageName = PACKAGE_NAME,
                    isPlaying = true
                )
            val newData = MediaData(active = true, instanceId = instanceId2)

            assertThat(isMediaFromRec).isFalse()

            underTest.setMediaFromRecPackageName(PACKAGE_NAME)
            underTest.addSelectedUserMediaEntry(data)
            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId1))

            assertThat(isMediaFromRec).isTrue()

            underTest.addSelectedUserMediaEntry(newData)
            underTest.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId2))

            assertThat(isMediaFromRec).isFalse()
        }

    private fun createMediaData(
        app: String,
        playing: Boolean,
@@ -288,5 +317,6 @@ class MediaFilterRepositoryTest : SysuiTestCase() {
        private const val REMOTE = MediaData.PLAYBACK_CAST_LOCAL
        private const val KEY = "KEY"
        private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
        private const val PACKAGE_NAME = "com.android.example"
    }
}
+27 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ 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,7 +30,9 @@ 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.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaRecommendationsInteractor
import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
import com.android.systemui.media.controls.domain.pipeline.interactor.mediaRecommendationsInteractor
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
@@ -50,6 +53,8 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
    private val testScope = kosmos.testScope

    private val mediaFilterRepository: MediaFilterRepository = kosmos.mediaFilterRepository
    private val mediaRecommendationsInteractor: MediaRecommendationsInteractor =
        kosmos.mediaRecommendationsInteractor

    private val underTest: MediaCarouselInteractor = kosmos.mediaCarouselInteractor

@@ -226,7 +231,29 @@ class MediaCarouselInteractorTest : SysuiTestCase() {
    fun hasActiveMediaOrRecommendation_nothingSet_returnsFalse() =
        testScope.runTest { assertThat(underTest.hasActiveMediaOrRecommendation.value).isFalse() }

    @Test
    fun loadMediaFromRec() =
        testScope.runTest {
            val isMediaFromRec by collectLastValue(underTest.isMediaFromRec)
            val instanceId = InstanceId.fakeInstanceId(123)
            val data = MediaData(active = true, instanceId = instanceId, packageName = PACKAGE_NAME)

            assertThat(isMediaFromRec).isFalse()

            mediaRecommendationsInteractor.switchToMediaControl(PACKAGE_NAME)
            mediaFilterRepository.addSelectedUserMediaEntry(data)
            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))

            assertThat(isMediaFromRec).isFalse()

            mediaFilterRepository.addSelectedUserMediaEntry(data.copy(isPlaying = true))
            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))

            assertThat(isMediaFromRec).isTrue()
        }

    companion object {
        private const val KEY_MEDIA_SMARTSPACE = "MEDIA_SMARTSPACE_ID"
        private const val PACKAGE_NAME = "com.android.example"
    }
}
+33 −2
Original line number Diff line number Diff line
@@ -31,9 +31,11 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.MediaTestHelper
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.mediaRecommendationsInteractor
import com.android.systemui.media.controls.domain.pipeline.mediaDataFilter
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
import com.android.systemui.statusbar.notification.collection.provider.visualStabilityProvider
import com.android.systemui.statusbar.notificationLockscreenUserManager
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
@@ -119,7 +121,35 @@ class MediaCarouselViewModelTest : SysuiTestCase() {
            assertThat(recsCard.key).isEqualTo(KEY_MEDIA_SMARTSPACE)
        }

    private fun loadMediaControl(key: String, instanceId: InstanceId) {
    @Test
    fun recommendationClicked_switchToPlayer() =
        testScope.runTest {
            val sortedMedia by collectLastValue(underTest.mediaItems)
            kosmos.visualStabilityProvider.isReorderingAllowed = false
            kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false)
            val instanceId = InstanceId.fakeInstanceId(123)

            loadMediaRecommendations()
            kosmos.mediaRecommendationsInteractor.switchToMediaControl(PACKAGE_NAME)

            var recsCard = sortedMedia?.get(0) as MediaCommonViewModel.MediaRecommendations
            assertThat(sortedMedia).hasSize(1)
            assertThat(recsCard.key).isEqualTo(KEY_MEDIA_SMARTSPACE)

            loadMediaControl(KEY, instanceId, false)

            recsCard = sortedMedia?.get(0) as MediaCommonViewModel.MediaRecommendations
            assertThat(sortedMedia).hasSize(1)
            assertThat(recsCard.key).isEqualTo(KEY_MEDIA_SMARTSPACE)

            loadMediaControl(KEY, instanceId, true)

            val mediaControl = sortedMedia?.get(0) as MediaCommonViewModel.MediaControl
            assertThat(sortedMedia).hasSize(2)
            assertThat(mediaControl.instanceId).isEqualTo(instanceId)
        }

    private fun loadMediaControl(key: String, instanceId: InstanceId, isPlaying: Boolean = true) {
        whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
        whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
        val mediaData =
@@ -127,7 +157,8 @@ class MediaCarouselViewModelTest : SysuiTestCase() {
                userId = USER_ID,
                packageName = PACKAGE_NAME,
                notificationKey = key,
                instanceId = instanceId
                instanceId = instanceId,
                isPlaying = isPlaying,
            )

        mediaDataFilter.onMediaDataLoaded(key, key, mediaData)
+19 −0
Original line number Diff line number Diff line
@@ -72,6 +72,11 @@ class MediaFilterRepository @Inject constructor(private val systemClock: SystemC
    val sortedMedia: StateFlow<Map<MediaSortKeyModel, MediaCommonModel>> =
        _sortedMedia.asStateFlow()

    private val _isMediaFromRec: MutableStateFlow<Boolean> = MutableStateFlow(false)
    val isMediaFromRec: StateFlow<Boolean> = _isMediaFromRec.asStateFlow()

    private var mediaFromRecPackageName: String? = null

    fun addMediaEntry(key: String, data: MediaData) {
        val entries = LinkedHashMap<String, MediaData>(_allUserEntries.value)
        entries[key] = data
@@ -161,6 +166,12 @@ class MediaFilterRepository @Inject constructor(private val systemClock: SystemC
                )

            if (mediaDataLoadingModel is MediaDataLoadingModel.Loaded) {
                val isMediaFromRec = isMediaFromRec(it)

                _isMediaFromRec.value = isMediaFromRec
                if (isMediaFromRec) {
                    mediaFromRecPackageName = null
                }
                sortedMap[sortKey] =
                    MediaCommonModel.MediaControl(mediaDataLoadingModel, canBeRemoved(it))
            }
@@ -195,7 +206,15 @@ class MediaFilterRepository @Inject constructor(private val systemClock: SystemC
        _sortedMedia.value = sortedMap
    }

    fun setMediaFromRecPackageName(packageName: String) {
        mediaFromRecPackageName = packageName
    }

    private fun canBeRemoved(data: MediaData): Boolean {
        return data.isPlaying?.let { !it } ?: data.isClearable && !data.active
    }

    private fun isMediaFromRec(data: MediaData): Boolean {
        return data.isPlaying == true && mediaFromRecPackageName == data.packageName
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -133,6 +133,9 @@ constructor(
                initialValue = emptyList(),
            )

    /** Whether the current change in media was done by clicking on a recommendation */
    val isMediaFromRec: StateFlow<Boolean> = mediaFilterRepository.isMediaFromRec

    override fun start() {
        if (!mediaFlags.isMediaControlsRefactorEnabled()) {
            return
Loading