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

Commit 13de324b authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

Apply squishiness and expansion outside of composition

Separate the application of the state (which mostly involves what is
visible) from the expansion and the squishiness (how it's visible).

That way we can make sure that animation calls are only performed
outside of composition.

Test: atest QSSceneAdapterImpl
Test: manual
Bug: 341938306
Flag: com.android.systemui.scene_container
Change-Id: I2e071ba9bb4950408db611b3de0f5e24bc330c39
parent 6deed656
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.layout.layout
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
@@ -179,7 +180,13 @@ private fun QuickSettingsContent(
        qsView?.let { view ->
            Box(
                modifier =
                    modifier.fillMaxWidth().thenIf(isCustomizing) { Modifier.fillMaxHeight() }
                    modifier
                        .fillMaxWidth()
                        .thenIf(isCustomizing) { Modifier.fillMaxHeight() }
                        .drawWithContent {
                            qsSceneAdapter.applyLatestExpansionAndSquishiness()
                            drawContent()
                        }
            ) {
                AndroidView(
                    modifier = Modifier.fillMaxWidth(),
+72 −25
Original line number Diff line number Diff line
@@ -54,9 +54,11 @@ import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.Mockito.anyInt
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.inOrder
import org.mockito.Mockito.never
import org.mockito.Mockito.verify

@SmallTest
@@ -162,16 +164,25 @@ class QSSceneAdapterImplTest : SysuiTestCase() {

            with(qsImpl!!) {
                verify(this).setQsVisible(false)
                verify(this)
                verify(this, never())
                    .setQsExpansion(
                        /* expansion= */ anyFloat(),
                        /* panelExpansionFraction= */ anyFloat(),
                        /* proposedTranslation= */ anyFloat(),
                        /* squishinessFraction= */ anyFloat(),
                    )
                verify(this).setListening(false)
                verify(this).setExpanded(false)
            }

            underTest.applyLatestExpansionAndSquishiness()
            verify(qsImpl!!)
                .setQsExpansion(
                    /* expansion= */ 0f,
                    /* panelExpansionFraction= */ 1f,
                    /* proposedTranslation= */ 0f,
                    /* squishinessFraction= */ 1f,
                )
                verify(this).setListening(false)
                verify(this).setExpanded(false)
            }
        }

    @Test
@@ -186,16 +197,25 @@ class QSSceneAdapterImplTest : SysuiTestCase() {
            underTest.setState(QSSceneAdapter.State.QQS)
            with(qsImpl!!) {
                verify(this).setQsVisible(true)
                verify(this)
                verify(this, never())
                    .setQsExpansion(
                        /* expansion= */ anyFloat(),
                        /* panelExpansionFraction= */ anyFloat(),
                        /* proposedTranslation= */ anyFloat(),
                        /* squishinessFraction= */ anyFloat(),
                    )
                verify(this).setListening(true)
                verify(this).setExpanded(false)
            }

            underTest.applyLatestExpansionAndSquishiness()
            verify(qsImpl!!)
                .setQsExpansion(
                    /* expansion= */ 0f,
                    /* panelExpansionFraction= */ 1f,
                    /* proposedTranslation= */ 0f,
                    /* squishinessFraction= */ 1f,
                )
                verify(this).setListening(true)
                verify(this).setExpanded(false)
            }
        }

    @Test
@@ -210,16 +230,25 @@ class QSSceneAdapterImplTest : SysuiTestCase() {
            underTest.setState(QSSceneAdapter.State.QS)
            with(qsImpl!!) {
                verify(this).setQsVisible(true)
                verify(this)
                verify(this, never())
                    .setQsExpansion(
                        /* expansion= */ anyFloat(),
                        /* panelExpansionFraction= */ anyFloat(),
                        /* proposedTranslation= */ anyFloat(),
                        /* squishinessFraction= */ anyFloat(),
                    )
                verify(this).setListening(true)
                verify(this).setExpanded(true)
            }

            underTest.applyLatestExpansionAndSquishiness()
            verify(qsImpl!!)
                .setQsExpansion(
                    /* expansion= */ 1f,
                    /* panelExpansionFraction= */ 1f,
                    /* proposedTranslation= */ 0f,
                    /* squishinessFraction= */ 1f,
                )
                verify(this).setListening(true)
                verify(this).setExpanded(true)
            }
        }

    @Test
@@ -235,16 +264,25 @@ class QSSceneAdapterImplTest : SysuiTestCase() {
            underTest.setState(QSSceneAdapter.State.Expanding(progress))
            with(qsImpl!!) {
                verify(this).setQsVisible(true)
                verify(this)
                verify(this, never())
                    .setQsExpansion(
                        /* expansion= */ anyFloat(),
                        /* panelExpansionFraction= */ anyFloat(),
                        /* proposedTranslation= */ anyFloat(),
                        /* squishinessFraction= */ anyFloat(),
                    )
                verify(this).setListening(true)
                verify(this).setExpanded(true)
            }

            underTest.applyLatestExpansionAndSquishiness()
            verify(qsImpl!!)
                .setQsExpansion(
                    /* expansion= */ progress,
                    /* panelExpansionFraction= */ 1f,
                    /* proposedTranslation= */ 0f,
                    /* squishinessFraction= */ 1f,
                )
                verify(this).setListening(true)
                verify(this).setExpanded(true)
            }
        }

    @Test
@@ -260,16 +298,25 @@ class QSSceneAdapterImplTest : SysuiTestCase() {
            underTest.setState(QSSceneAdapter.State.UnsquishingQQS { squishiness })
            with(qsImpl!!) {
                verify(this).setQsVisible(true)
                verify(this)
                verify(this, never())
                    .setQsExpansion(
                        /* expansion= */ anyFloat(),
                        /* panelExpansionFraction= */ anyFloat(),
                        /* proposedTranslation= */ anyFloat(),
                        /* squishinessFraction= */ anyFloat(),
                    )
                verify(this).setListening(true)
                verify(this).setExpanded(false)
            }

            underTest.applyLatestExpansionAndSquishiness()
            verify(qsImpl!!)
                .setQsExpansion(
                    /* expansion= */ 0f,
                    /* panelExpansionFraction= */ 1f,
                    /* proposedTranslation= */ 0f,
                    /* squishinessFraction= */ squishiness,
                )
                verify(this).setListening(true)
                verify(this).setExpanded(false)
            }
        }

    @Test
+20 −2
Original line number Diff line number Diff line
@@ -102,9 +102,22 @@ interface QSSceneAdapter {
     */
    suspend fun inflate(context: Context)

    /** Set the current state for QS. [state]. */
    /**
     * Set the current state for QS. [state].
     *
     * This will not trigger expansion (animation between QQS or QS) or squishiness to be applied.
     * For that, use [applyLatestExpansionAndSquishiness] outside of the composition phase.
     */
    fun setState(state: State)

    /**
     * Explicitly applies the expansion and squishiness value from the latest state set. Call this
     * only outside of the composition phase as this will call [QSImpl.setQsExpansion] that is
     * normally called during animations. In particular, this will read the value of
     * [State.squishiness], that is not safe to read in the composition phase.
     */
    fun applyLatestExpansionAndSquishiness()

    /** Propagates the bottom nav bar size to [QSImpl] to be used as necessary. */
    suspend fun applyBottomNavBarPadding(padding: Int)

@@ -384,7 +397,12 @@ constructor(
        setQsVisible(state.isVisible)
        setExpanded(state.isVisible && state.expansion > 0f)
        setListening(state.isVisible)
        setQsExpansion(state.expansion, 1f, 0f, state.squishiness())
    }

    override fun applyLatestExpansionAndSquishiness() {
        val qsImpl = _qsImpl.value
        val state = state.value
        qsImpl?.setQsExpansion(state.expansion, 1f, 0f, state.squishiness())
    }

    override fun dump(pw: PrintWriter, args: Array<out String>) {
+2 −0
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ class FakeQSSceneAdapter(
        }
    }

    override fun applyLatestExpansionAndSquishiness() {}

    fun setCustomizing(value: Boolean) {
        updateCustomizerFlows(if (value) CustomizerState.Showing else CustomizerState.Hidden)
    }