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

Commit 2c4238a3 authored by Beth Thibodeau's avatar Beth Thibodeau Committed by Android (Google) Code Review
Browse files

Merge "Add media composable to quick settings" into main

parents 5bf8b71f d9a62712
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.systemui.media.controls.ui.controller.MediaLocation
import com.android.systemui.media.controls.ui.controller.mediaHostStatesManager
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.qs.composefragment.dagger.usingMediaInComposeFragment
import com.android.systemui.qs.ui.viewmodel.QuickSettingsContainerViewModel
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
@@ -54,7 +55,10 @@ class MediaInRowInLandscapeViewModelTest(private val testData: TestData) : Sysui
    private val kosmos = testKosmos().apply { usingMediaInComposeFragment = testData.usingMedia }

    private val underTest by lazy {
        kosmos.mediaInRowInLandscapeViewModelFactory.create(TESTED_MEDIA_LOCATION)
        kosmos.mediaInRowInLandscapeViewModelFactory.create(
            TESTED_MEDIA_LOCATION,
            TESTED_MEDIA_BEHAVIOR,
        )
    }

    @Before
@@ -110,6 +114,7 @@ class MediaInRowInLandscapeViewModelTest(private val testData: TestData) : Sysui

    companion object {
        private const val TESTED_MEDIA_LOCATION = LOCATION_QS
        private val TESTED_MEDIA_BEHAVIOR = QuickSettingsContainerViewModel.mediaUiBehavior

        @JvmStatic
        @Parameters(name = "{0}")
+43 −10
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.qs.composefragment.dagger.usingMediaInComposeFragment
import com.android.systemui.qs.panels.data.repository.QSColumnsRepository
import com.android.systemui.qs.panels.data.repository.qsColumnsRepository
import com.android.systemui.qs.ui.viewmodel.QuickSettingsContainerViewModel
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.disableDualShade
import com.android.systemui.shade.domain.interactor.enableDualShade
@@ -76,7 +77,7 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @Test
    fun mediaLocationNull_singleOrSplit_alwaysSingleShadeColumns() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(null)
            val underTest = qsColumnsViewModelFactory.create(null, null)
            underTest.activateIn(testScope)
            disableDualShade()

@@ -96,7 +97,7 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @EnableSceneContainer
    fun mediaLocationNull_dualShade_alwaysDualShadeColumns() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(null)
            val underTest = qsColumnsViewModelFactory.create(null, null)
            underTest.activateIn(testScope)
            enableDualShade()

@@ -116,7 +117,11 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @EnableSceneContainer
    fun mediaLocationQS_dualShade_alwaysDualShadeColumns() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(LOCATION_QS)
            val underTest =
                qsColumnsViewModelFactory.create(
                    LOCATION_QS,
                    QuickSettingsContainerViewModel.mediaUiBehavior,
                )
            underTest.activateIn(testScope)
            enableDualShade()

@@ -135,7 +140,11 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @EnableSceneContainer
    fun mediaLocationQQS_dualShade_alwaysDualShadeColumns() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(LOCATION_QQS)
            val underTest =
                qsColumnsViewModelFactory.create(
                    LOCATION_QQS,
                    QuickQuickSettingsViewModel.mediaUiBehavior,
                )
            underTest.activateIn(testScope)
            enableDualShade()

@@ -153,7 +162,11 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @Test
    fun mediaLocationQS_singleOrSplit_halfColumnsOnCorrectConfigurationAndVisible() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(LOCATION_QS)
            val underTest =
                qsColumnsViewModelFactory.create(
                    LOCATION_QS,
                    QuickSettingsContainerViewModel.mediaUiBehavior,
                )
            underTest.activateIn(testScope)
            disableDualShade()

@@ -173,7 +186,11 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @Test
    fun mediaLocationQQS_singleOrSplit_halfColumnsOnCorrectConfigurationAndVisible() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(LOCATION_QQS)
            val underTest =
                qsColumnsViewModelFactory.create(
                    LOCATION_QQS,
                    QuickQuickSettingsViewModel.mediaUiBehavior,
                )
            underTest.activateIn(testScope)
            disableDualShade()

@@ -193,7 +210,11 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @Test
    fun largeSpan_normalTiles_ignoreColumns() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(LOCATION_QQS)
            val underTest =
                qsColumnsViewModelFactory.create(
                    LOCATION_QQS,
                    QuickQuickSettingsViewModel.mediaUiBehavior,
                )
            underTest.activateIn(testScope)

            // Set extra large tiles to false
@@ -212,7 +233,11 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @Test
    fun largeSpan_extraLargeTiles_tracksColumns() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(LOCATION_QQS)
            val underTest =
                qsColumnsViewModelFactory.create(
                    LOCATION_QQS,
                    QuickQuickSettingsViewModel.mediaUiBehavior,
                )
            underTest.activateIn(testScope)

            // Set extra large tiles to true
@@ -237,7 +262,11 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @Test
    fun largeSpan_extraLargeTiles_tracksMaxWidth() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(LOCATION_QQS)
            val underTest =
                qsColumnsViewModelFactory.create(
                    LOCATION_QQS,
                    QuickQuickSettingsViewModel.mediaUiBehavior,
                )
            underTest.activateIn(testScope)

            // Set extra large tiles to true
@@ -262,7 +291,11 @@ class QSColumnsViewModelTest : SysuiTestCase() {
    @Test
    fun largeSpan_tracksExtraLargeTiles() =
        kosmos.runTest {
            val underTest = qsColumnsViewModelFactory.create(LOCATION_QQS)
            val underTest =
                qsColumnsViewModelFactory.create(
                    LOCATION_QQS,
                    QuickQuickSettingsViewModel.mediaUiBehavior,
                )
            underTest.activateIn(testScope)

            // Set extra large tiles to false
+56 −28
Original line number Diff line number Diff line
@@ -125,8 +125,13 @@ import com.android.systemui.keyboard.shortcut.ui.composable.ProvideShortcutHelpe
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.lifecycle.setSnapshotBinding
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.ui.controller.MediaViewLogger
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.remedia.ui.compose.Media
import com.android.systemui.media.remedia.ui.compose.MediaPresentationStyle
import com.android.systemui.media.remedia.ui.compose.MediaUiBehavior
import com.android.systemui.media.remedia.ui.viewmodel.MediaViewModel
import com.android.systemui.plugins.qs.QS
import com.android.systemui.plugins.qs.QSContainerController
import com.android.systemui.qs.composefragment.SceneKeys.QuickQuickSettings
@@ -748,6 +753,9 @@ constructor(
                                modifier = Modifier.requiredHeightIn(max = Dp.Infinity),
                                mediaHost = viewModel.qqsMediaHost,
                                mediaLogger = mediaLogger,
                                mediaCarouselInteractor = viewModel.mediaCarouselInteractor,
                                mediaViewModelFactory = viewModel.mediaViewModelFactory,
                                behavior = viewModel.qqsMediaUiBehavior,
                            )
                        }
                    }
@@ -904,6 +912,9 @@ constructor(
                                    MediaObject(
                                        mediaHost = viewModel.qsMediaHost,
                                        mediaLogger = mediaLogger,
                                        mediaViewModelFactory = viewModel.mediaViewModelFactory,
                                        mediaCarouselInteractor = viewModel.mediaCarouselInteractor,
                                        behavior = viewModel.qsMediaUiBehavior,
                                        update = { translationY = viewModel.qsMediaTranslationY },
                                    )
                                }
@@ -1384,8 +1395,20 @@ private fun MediaObject(
    mediaHost: MediaHost,
    modifier: Modifier = Modifier,
    mediaLogger: MediaViewLogger,
    mediaViewModelFactory: MediaViewModel.Factory,
    mediaCarouselInteractor: MediaCarouselInteractor,
    behavior: MediaUiBehavior,
    update: UniqueObjectHostView.() -> Unit = {},
) {
    if (Flags.mediaControlsInCompose()) {
        Media(
            viewModelFactory = mediaViewModelFactory,
            presentationStyle = MediaPresentationStyle.Default,
            behavior = behavior,
            onDismissed = { mediaCarouselInteractor.onSwipeToDismiss() },
            modifier = modifier,
        )
    } else {
        Box {
            AndroidView(
                modifier = modifier,
@@ -1405,13 +1428,17 @@ private fun MediaObject(
                    val width = mediaHost.hostView.width
                    var measure = false
                    mediaHost.hostView.children.forEach { child ->
                    if (child is FrameLayout && (height > child.height || width > child.width)) {
                        if (
                            child is FrameLayout && (height > child.height || width > child.width)
                        ) {
                            measure = true
                            child.layoutParams = FrameLayout.LayoutParams(width, height)
                        }
                    }
                    if (measure) {
                    mediaHost.hostView.measurementManager.onMeasure(MeasurementInput(width, height))
                        mediaHost.hostView.measurementManager.onMeasure(
                            MeasurementInput(width, height)
                        )
                        mediaLogger.logMediaSize("update size in compose", width, height)
                    }
                },
@@ -1419,6 +1446,7 @@ private fun MediaObject(
            )
        }
    }
}

@Composable
@VisibleForTesting
+29 −6
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@ import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.media.dagger.MediaModule.QS_PANEL
import com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL
import com.android.systemui.media.remedia.ui.compose.MediaUiBehavior
import com.android.systemui.media.remedia.ui.viewmodel.MediaCarouselVisibility
import com.android.systemui.media.remedia.ui.viewmodel.MediaViewModel
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.QSEvent
@@ -116,14 +119,17 @@ constructor(
    @Named(QSFragmentComposeModule.QS_USING_MEDIA_PLAYER) private val usingMedia: Boolean,
    private val uiEventLogger: UiEventLogger,
    @Assisted private val lifecycleScope: LifecycleCoroutineScope,
    private val mediaCarouselInteractor: MediaCarouselInteractor,
    val mediaCarouselInteractor: MediaCarouselInteractor,
    val mediaViewModelFactory: MediaViewModel.Factory,
) : Dumpable, ExclusiveActivatable() {

    val containerViewModel = containerViewModelFactory.create(supportsBrightnessMirroring = true)
    val quickQuickSettingsViewModel = quickQuickSettingsViewModelFactory.create()

    private val qqsMediaInRowViewModel = mediaInRowInLandscapeViewModelFactory.create(LOCATION_QQS)
    private val qsMediaInRowViewModel = mediaInRowInLandscapeViewModelFactory.create(LOCATION_QS)
    private val qqsMediaInRowViewModel =
        mediaInRowInLandscapeViewModelFactory.create(LOCATION_QQS, qqsMediaUiBehavior)
    private val qsMediaInRowViewModel =
        mediaInRowInLandscapeViewModelFactory.create(LOCATION_QS, qsMediaUiBehavior)

    private val hydrator = Hydrator("QSFragmentComposeViewModel.hydrator", tableLogBuffer)

@@ -275,12 +281,26 @@ constructor(
            initialValue = usingMedia,
            source =
                if (usingMedia) {
                    mediaHostVisible(qqsMediaHost, mediaCarouselInteractor)
                    mediaHostVisible(qqsMediaHost, qqsMediaUiBehavior, mediaCarouselInteractor)
                } else {
                    flowOf(false)
                },
        )

    val qsMediaUiBehavior: MediaUiBehavior
        get() =
            MediaUiBehavior(
                isCarouselDismissible = false,
                carouselVisibility = MediaCarouselVisibility.WhenNotEmpty,
            )

    val qqsMediaUiBehavior: MediaUiBehavior
        get() =
            MediaUiBehavior(
                isCarouselDismissible = true,
                carouselVisibility = MediaCarouselVisibility.WhenAnyCardIsActive,
            )

    val qqsMediaInRow: Boolean
        get() = qqsMediaInRowViewModel.shouldMediaShowInRow

@@ -290,7 +310,7 @@ constructor(
            initialValue = usingMedia,
            source =
                if (usingMedia) {
                    mediaHostVisible(qsMediaHost, mediaCarouselInteractor)
                    mediaHostVisible(qsMediaHost, qsMediaUiBehavior, mediaCarouselInteractor)
                } else {
                    flowOf(false)
                },
@@ -622,10 +642,13 @@ private val SHORT_PARALLAX_AMOUNT = 0.1f
 */
private fun mediaHostVisible(
    mediaHost: MediaHost,
    mediaUiBehavior: MediaUiBehavior,
    mediaCarouselInteractor: MediaCarouselInteractor,
): Flow<Boolean> {
    if (Flags.mediaControlsInCompose()) {
        return if (mediaHost.showsOnlyActiveMedia) {
        return if (
            mediaUiBehavior.carouselVisibility == MediaCarouselVisibility.WhenAnyCardIsActive
        ) {
            mediaCarouselInteractor.hasActiveMedia
        } else {
            mediaCarouselInteractor.hasAnyMedia
+6 −2
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.systemui.qs.panels.ui.viewmodel

import androidx.compose.runtime.getValue
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.Hydrator
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager.Companion.LOCATION_QS
@@ -24,6 +23,7 @@ import com.android.systemui.qs.panels.shared.model.SizedTileImpl
import com.android.systemui.qs.panels.ui.dialog.QSResetDialogDelegate
import com.android.systemui.qs.panels.ui.viewmodel.PaginatableViewModel.Companion.splitInRows
import com.android.systemui.qs.pipeline.shared.TileSpec
import com.android.systemui.qs.ui.viewmodel.QuickSettingsContainerViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.awaitCancellation
@@ -42,7 +42,11 @@ constructor(
    private val hydrator = Hydrator("InfiniteGridViewModel.hydrator")

    val iconTilesViewModel = dynamicIconTilesViewModelFactory.create()
    val columnsWithMediaViewModel = columnsWithMediaViewModelFactory.create(LOCATION_QS)
    val columnsWithMediaViewModel =
        columnsWithMediaViewModelFactory.create(
            LOCATION_QS,
            QuickSettingsContainerViewModel.mediaUiBehavior,
        )

    override val pageKeys: Array<Any>
        get() =
Loading