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

Commit e8a3f0fe authored by Hawkwood Glazier's avatar Hawkwood Glazier
Browse files

Prevent default blueprint changes from triggering refreshes

Bug: 336400157
Bug: 339127387
Test: abtd run to verify perf improvement
Flag: ACONFIG com.android.systemui.migrate_clocks_to_blueprint STAGING
Change-Id: I4053f415ac7fd30cba81b67242a8046fab19416a
parent 11871ce2
Loading
Loading
Loading
Loading
+7 −26
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.data.repository

import android.os.Handler
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.shared.model.KeyguardBlueprint
@@ -57,21 +58,7 @@ constructor(
        TreeMap<String, KeyguardBlueprint>().apply { putAll(blueprints.associateBy { it.id }) }
    val blueprint: MutableStateFlow<KeyguardBlueprint> = MutableStateFlow(blueprintIdMap[DEFAULT]!!)
    val refreshTransition = MutableSharedFlow<Config>(extraBufferCapacity = 1)
    private var targetTransitionConfig: Config? = null

    /**
     * Emits the blueprint value to the collectors.
     *
     * @param blueprintId
     * @return whether the transition has succeeded.
     */
    fun applyBlueprint(index: Int): Boolean {
        ArrayList(blueprintIdMap.values)[index]?.let {
            applyBlueprint(it)
            return true
        }
        return false
    }
    @VisibleForTesting var targetTransitionConfig: Config? = null

    /**
     * Emits the blueprint value to the collectors.
@@ -81,27 +68,21 @@ constructor(
     */
    fun applyBlueprint(blueprintId: String?): Boolean {
        val blueprint = blueprintIdMap[blueprintId]
        return if (blueprint != null) {
            applyBlueprint(blueprint)
            true
        } else {
        if (blueprint == null) {
            Log.e(
                TAG,
                "Could not find blueprint with id: $blueprintId. " +
                    "Perhaps it was not added to KeyguardBlueprintModule?"
            )
            false
        }
            return false
        }

    /** Emits the blueprint value to the collectors. */
    fun applyBlueprint(blueprint: KeyguardBlueprint?) {
        if (blueprint == this.blueprint.value) {
            refreshBlueprint()
            return
            return true
        }

        blueprint?.let { this.blueprint.value = it }
        this.blueprint.value = blueprint
        return true
    }

    /**
+20 −10
Original line number Diff line number Diff line
@@ -36,9 +36,12 @@ import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch

@SysUISingleton
@@ -64,12 +67,7 @@ constructor(

    /** Current BlueprintId */
    val blueprintId =
        combine(
            configurationInteractor.onAnyConfigurationChange,
            fingerprintPropertyInteractor.propertiesInitialized.filter { it },
            clockInteractor.currentClock,
            shadeInteractor.shadeMode,
        ) { _, _, _, shadeMode ->
        shadeInteractor.shadeMode.map { shadeMode ->
            val useSplitShade = shadeMode == ShadeMode.Split && !ComposeLockscreen.isEnabled
            when {
                useSplitShade -> SplitShadeKeyguardBlueprint.ID
@@ -77,17 +75,29 @@ constructor(
            }
        }

    private val refreshEvents: Flow<Unit> =
        merge(
            configurationInteractor.onAnyConfigurationChange,
            fingerprintPropertyInteractor.propertiesInitialized.filter { it }.map { Unit },
        )

    init {
        applicationScope.launch { blueprintId.collect { transitionToBlueprint(it) } }
        applicationScope.launch { refreshEvents.collect { refreshBlueprint() } }
    }

    /**
     * Transitions to a blueprint.
     * Transitions to a blueprint, or refreshes it if already applied.
     *
     * @param blueprintId
     * @return whether the transition has succeeded.
     */
    fun transitionToBlueprint(blueprintId: String): Boolean {
    fun transitionOrRefreshBlueprint(blueprintId: String): Boolean {
        if (blueprintId == blueprint.value.id) {
            refreshBlueprint()
            return true
        }

        return keyguardBlueprintRepository.applyBlueprint(blueprintId)
    }

@@ -97,7 +107,7 @@ constructor(
     * @param blueprintId
     * @return whether the transition has succeeded.
     */
    fun transitionToBlueprint(blueprintId: Int): Boolean {
    fun transitionToBlueprint(blueprintId: String): Boolean {
        return keyguardBlueprintRepository.applyBlueprint(blueprintId)
    }

+0 −1
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.animation.Interpolators
import com.android.app.tracing.coroutines.launch
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
import com.android.systemui.Flags.newAodTransition
+8 −9
Original line number Diff line number Diff line
@@ -46,17 +46,16 @@ constructor(
                return
            }

            if (
                arg.isDigitsOnly() && keyguardBlueprintInteractor.transitionToBlueprint(arg.toInt())
            ) {
                pw.println("Transition succeeded!")
            } else if (keyguardBlueprintInteractor.transitionToBlueprint(arg)) {
            when {
                arg.isDigitsOnly() -> pw.println("Invalid argument! Use string ids.")
                keyguardBlueprintInteractor.transitionOrRefreshBlueprint(arg) ->
                    pw.println("Transition succeeded!")
            } else {
                else -> {
                    pw.println("Invalid argument! To see available blueprint ids, run:")
                    pw.println("$ adb shell cmd statusbar blueprint help")
                }
            }
        }

        override fun help(pw: PrintWriter) {
            pw.println("Usage: $ adb shell cmd statusbar blueprint <blueprintId>")
+22 −36
Original line number Diff line number Diff line
@@ -19,24 +19,20 @@

package com.android.systemui.keyguard.data.repository

import android.os.fakeExecutorHandler
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint
import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT
import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.android.systemui.util.ThreadAssert
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -50,31 +46,32 @@ import org.mockito.MockitoAnnotations
class KeyguardBlueprintRepositoryTest : SysuiTestCase() {
    private lateinit var underTest: KeyguardBlueprintRepository
    @Mock lateinit var configurationRepository: ConfigurationRepository
    @Mock lateinit var defaultLockscreenBlueprint: DefaultKeyguardBlueprint
    @Mock lateinit var threadAssert: ThreadAssert

    private val testScope = TestScope(StandardTestDispatcher())
    private val kosmos: Kosmos = testKosmos()

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)
        with(kosmos) {
            whenever(defaultLockscreenBlueprint.id).thenReturn(DEFAULT)
            underTest =
                KeyguardBlueprintRepository(
                    setOf(defaultLockscreenBlueprint),
                    fakeExecutorHandler,
                    threadAssert,
                )
        }
        underTest = kosmos.keyguardBlueprintRepository
    }

    @Test
    fun testApplyBlueprint_DefaultLayout() {
        testScope.runTest {
            val blueprint by collectLastValue(underTest.blueprint)
            underTest.applyBlueprint(defaultLockscreenBlueprint)
            assertThat(blueprint).isEqualTo(defaultLockscreenBlueprint)
            underTest.applyBlueprint(DefaultKeyguardBlueprint.DEFAULT)
            assertThat(blueprint).isEqualTo(kosmos.defaultKeyguardBlueprint)
        }
    }

    @Test
    fun testApplyBlueprint_SplitShadeLayout() {
        testScope.runTest {
            val blueprint by collectLastValue(underTest.blueprint)
            underTest.applyBlueprint(SplitShadeKeyguardBlueprint.ID)
            assertThat(blueprint).isEqualTo(kosmos.splitShadeBlueprint)
        }
    }

@@ -83,33 +80,22 @@ class KeyguardBlueprintRepositoryTest : SysuiTestCase() {
        testScope.runTest {
            val blueprint by collectLastValue(underTest.blueprint)
            underTest.refreshBlueprint()
            assertThat(blueprint).isEqualTo(defaultLockscreenBlueprint)
            assertThat(blueprint).isEqualTo(kosmos.defaultKeyguardBlueprint)
        }
    }

    @Test
    fun testTransitionToLayout_validId() {
        assertThat(underTest.applyBlueprint(DEFAULT)).isTrue()
    fun testTransitionToDefaultLayout_validId() {
        assertThat(underTest.applyBlueprint(DefaultKeyguardBlueprint.DEFAULT)).isTrue()
    }

    @Test
    fun testTransitionToLayout_invalidId() {
        assertThat(underTest.applyBlueprint("abc")).isFalse()
    fun testTransitionToSplitShadeLayout_validId() {
        assertThat(underTest.applyBlueprint(SplitShadeKeyguardBlueprint.ID)).isTrue()
    }

    @Test
    fun testTransitionToSameBlueprint_refreshesBlueprint() =
        with(kosmos) {
            testScope.runTest {
                val transition by collectLastValue(underTest.refreshTransition)
                fakeExecutor.runAllReady()
                runCurrent()

                underTest.applyBlueprint(defaultLockscreenBlueprint)
                fakeExecutor.runAllReady()
                runCurrent()

                assertThat(transition).isNotNull()
            }
    fun testTransitionToLayout_invalidId() {
        assertThat(underTest.applyBlueprint("abc")).isFalse()
    }
}
Loading