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

Commit 8b8f766e authored by Andrew Xu's avatar Andrew Xu
Browse files

[Flexiglass] Use BC25 brightness bar in the QS scene

This CL uses the BC25 brightness bar in the QuickSettingsScene.

This CL also adds a compose test to verify the view hierarchy of
the QuickSettingsScene.

Bug: 420960164
Flag: com.android.systemui.scene_container
Test: added a compose test
Change-Id: Id24f267b7a91756e3146e3e27b744c7adbdfc133
parent 83e70fac
Loading
Loading
Loading
Loading
+53 −48
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.Layout
@@ -77,6 +78,8 @@ import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.modifiers.thenIf
import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer
import com.android.systemui.brightness.ui.compose.ContainerColors
import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation
import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout
import com.android.systemui.compose.modifiers.sysuiResTag
@@ -94,6 +97,7 @@ import com.android.systemui.notifications.ui.composable.HeadsUpNotificationSpace
import com.android.systemui.notifications.ui.composable.NotificationScrollingStack
import com.android.systemui.notifications.ui.composable.NotificationStackCutoffGuideline
import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility
import com.android.systemui.qs.shared.ui.ElementKeys
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.InQS
import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneContentViewModel
@@ -146,10 +150,6 @@ constructor(
    override fun ContentScope.Content(modifier: Modifier) {
        val viewModel =
            rememberViewModel("QuickSettingsScene-viewModel") { contentViewModelFactory.create() }
        val headerViewModel =
            rememberViewModel("QuickSettingsScene-headerViewModel") {
                viewModel.shadeHeaderViewModelFactory.create()
            }
        val brightnessMirrorViewModel =
            rememberViewModel("QuickSettingsScene-brightnessMirrorViewModel") {
                viewModel.brightnessMirrorViewModelFactory.create()
@@ -161,7 +161,7 @@ constructor(
        QuickSettingsScene(
            notificationStackScrollView = notificationStackScrollView.get(),
            viewModel = viewModel,
            headerViewModel = headerViewModel,
            headerViewModel = viewModel.qsContainerViewModel.shadeHeaderViewModel,
            brightnessMirrorViewModel = brightnessMirrorViewModel,
            notificationsPlaceholderViewModel = notificationsPlaceholderViewModel,
            mediaCarouselController = mediaCarouselController,
@@ -208,18 +208,6 @@ private fun ContentScope.QuickSettingsScene(
    val shadeHorizontalPadding =
        dimensionResource(id = R.dimen.notification_panel_margin_horizontal)

    Box(modifier = Modifier.fillMaxSize()) {
        BrightnessMirror(
            viewModel = brightnessMirrorViewModel,
            qsSceneAdapter = viewModel.qsSceneAdapter,
            modifier =
                Modifier.thenIf(cutoutLocation != CutoutLocation.CENTER) {
                        Modifier.displayCutoutPadding()
                    }
                    .align(Alignment.TopCenter),
        )
    }

    val shouldPunchHoleBehindScrim =
        layoutState.isTransitioningBetween(Scenes.Gone, Scenes.QuickSettings) ||
            layoutState.isTransitioningBetween(Scenes.Lockscreen, Scenes.QuickSettings)
@@ -366,6 +354,19 @@ private fun ContentScope.QuickSettingsScene(
                            CollapsedShadeHeader(viewModel = headerViewModel, isSplitShade = false)
                    }
                    Spacer(modifier = Modifier.height(16.dp))
                    Column(modifier = Modifier.element(ElementKeys.QuickSettingsContent)) {
                        BrightnessSliderContainer(
                            viewModel.qsContainerViewModel.brightnessSliderViewModel,
                            containerColors =
                                ContainerColors(
                                    Color.Transparent,
                                    ContainerColors.defaultContainerColor,
                                ),
                            modifier = Modifier.padding(
                                horizontal =
                                    dimensionResource(id = R.dimen.qs_horizontal_margin)
                            )
                        )
                        // This view has its own horizontal padding
                        val content: @Composable () -> Unit = {
                            QuickSettings(
@@ -396,13 +397,17 @@ private fun ContentScope.QuickSettingsScene(
                        }
                        Column(modifier = Modifier.padding(horizontal = shadeHorizontalPadding)) {
                            if (mediaInRow) {
                            Layout(content = content, measurePolicy = landscapeQsMediaMeasurePolicy)
                                Layout(
                                    content = content,
                                    measurePolicy = landscapeQsMediaMeasurePolicy
                                )
                            } else {
                                content()
                            }
                        }
                    }
                }
            }

            FooterActionsWithAnimatedVisibility(
                viewModel = footerActionsViewModel,
+1 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
                    brightnessMirrorViewModelFactory = brightnessMirrorViewModelFactory,
                    shadeHeaderViewModelFactory = shadeHeaderViewModelFactory,
                    qsSceneAdapter = fakeQsSceneAdapter,
                    qsContainerViewModelFactory = kosmos.quickSettingsContainerViewModelFactory,
                    footerActionsViewModelFactory = footerActionsViewModelFactory,
                    footerActionsController = footerActionsController,
                    mediaCarouselInteractor = mediaCarouselInteractor,
+4 −0
Original line number Diff line number Diff line
@@ -49,12 +49,14 @@ constructor(
    val brightnessMirrorViewModelFactory: BrightnessMirrorViewModel.Factory,
    val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
    val qsSceneAdapter: QSSceneAdapter,
    qsContainerViewModelFactory: QuickSettingsContainerViewModel.Factory,
    private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
    private val footerActionsController: FooterActionsController,
    val mediaCarouselInteractor: MediaCarouselInteractor,
    private val shadeModeInteractor: ShadeModeInteractor,
    private val sceneInteractor: SceneInteractor,
) : ExclusiveActivatable() {
    val qsContainerViewModel = qsContainerViewModelFactory.create(supportsBrightnessMirroring = true)

    private val hydrator = Hydrator("QuickSettingsSceneContentViewModel.hydrator")

@@ -77,6 +79,8 @@ constructor(
        coroutineScope {
            launch { hydrator.activate() }

            launch { qsContainerViewModel.activate() }

            launch {
                shadeModeInteractor.shadeMode.collect { shadeMode ->
                    if (shadeMode is ShadeMode.Split) {
+97 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.ui.composable

import android.testing.TestableLooper
import androidx.compose.runtime.Composable
import androidx.compose.runtime.saveable.Saver
import androidx.compose.ui.Modifier
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.TestContentScope
import com.android.compose.theme.PlatformTheme
import com.android.systemui.SysuiTestCase
import com.android.systemui.compose.modifiers.resIdToTestTag
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.jank.interactionJankMonitor
import com.android.systemui.media.controls.ui.controller.mediaCarouselController
import com.android.systemui.media.controls.ui.view.qsMediaHost
import com.android.systemui.qs.ui.viewmodel.quickSettingsSceneContentViewModelFactory
import com.android.systemui.qs.ui.viewmodel.quickSettingsUserActionsViewModelFactory
import com.android.systemui.scene.session.shared.SessionStorage
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.session.ui.composable.Session
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModelFactory
import com.android.systemui.testKosmos
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.mock

@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
class QuickSettingsSceneTest : SysuiTestCase() {
    @get:Rule
    val composeTestRule = createComposeRule()

    private val kosmos = testKosmos()

    @Test
    fun testViewHierarchy() = {
        val shadeSession = object : SaveableSession, Session by Session(SessionStorage()) {
            @Composable
            override fun <T : Any> rememberSaveableSession(
                vararg inputs: Any?,
                saver: Saver<T, out Any>,
                key: String?,
                init: () -> T
            ): T = rememberSession(key, inputs = inputs, init = init)
        }

        val scene = QuickSettingsScene(
            shadeSession = shadeSession,
            notificationStackScrollView = {
                mock(NotificationScrollView::class.java)
            },
            notificationsPlaceholderViewModelFactory = kosmos.notificationsPlaceholderViewModelFactory,
            actionsViewModelFactory = kosmos.quickSettingsUserActionsViewModelFactory,
            contentViewModelFactory = kosmos.quickSettingsSceneContentViewModelFactory,
            mediaCarouselController = kosmos.mediaCarouselController,
            mediaHost = kosmos.qsMediaHost,
            jankMonitor = kosmos.interactionJankMonitor,
        )

        composeTestRule.setContent {
            PlatformTheme {
                with(scene) {
                    TestContentScope(currentScene = Scenes.QuickSettings) { Content(Modifier) }
                }
            }
        }

        composeTestRule.waitForIdle()

        // Verify that the brightness slider exists.
        composeTestRule.onNodeWithTag(resIdToTestTag("brightness_slider")).assertExists()
    }
}
 No newline at end of file
+3 −1
Original line number Diff line number Diff line
@@ -17,5 +17,7 @@
package com.android.systemui.media.controls.domain.pipeline

import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import org.mockito.kotlin.mock

var Kosmos.mediaDataManager: MediaDataManager by Kosmos.Fixture()
var Kosmos.mediaDataManager by Fixture { mock<MediaDataManager>() }
Loading