Loading packages/SystemUI/multivalentTests/src/com/android/systemui/topwindoweffects/TopLevelWindowEffectsTest.kt +50 −62 Original line number Diff line number Diff line Loading @@ -24,9 +24,6 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.haptics.fakeVibratorHelper import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor import com.android.systemui.keyevent.domain.interactor.keyEventInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.advanceTimeBy import com.android.systemui.kosmos.runCurrent Loading Loading @@ -89,13 +86,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { TopLevelWindowEffects( applicationScope = testScope.backgroundScope, squeezeEffectInteractor = SqueezeEffectInteractor( squeezeEffectRepository = fakeSqueezeEffectRepository, keyEventInteractor = KeyEventInteractor(fakeKeyEventRepository), coroutineContext = testScope.testScheduler, ), SqueezeEffectInteractor(squeezeEffectRepository = fakeSqueezeEffectRepository), appZoomOutOptional = appZoomOutOptional, keyEventInteractor = keyEventInteractor, squeezeEffectHapticPlayerFactory = squeezeEffectHapticPlayerFactory, notificationShadeWindowController = notificationShadeWindowController, topUiController = mockTopUiController, Loading @@ -116,7 +108,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { @Test fun testNoProgressWhenSqueezeEffectDisabled() = kosmos.runTest { fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = false fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false underTest.start() Loading @@ -127,11 +120,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun testSqueezeEffectStarts_afterInitialDelay() = kosmos.runTest { val expectedDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -147,11 +139,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun testSqueezeEffectNotStarted_beforeInitialDelay() = kosmos.runTest { val expectedDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -167,18 +158,18 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun testSqueezeEffectNotStarted_whenUpEventReceivedBefore100Millis() = kosmos.runTest { val expectedDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() // subtract 1ms time to simulate initial delay duration is yet not finished advanceTime((expectedDelay - 1).milliseconds) fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() animatorTestRule.advanceTimeBy(1) Loading @@ -191,11 +182,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun testSqueezeEffectStarted_whenUpEventReceivedAfter100Millis() = kosmos.runTest { val expectedDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -204,7 +194,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { animatorTestRule.advanceTimeBy(1) val timesCancelledBefore = vibratorHelper.timesCancelled fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() animatorTestRule.advanceTimeBy(1) Loading @@ -217,11 +208,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { val expectedDelay = DEFAULT_INITIAL_DELAY_MILLIS + 750 - DEFAULT_LONG_PRESS_POWER_DURATION_MILLIS fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -230,7 +220,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { animatorTestRule.advanceTimeBy(1) val timesCancelledBefore = vibratorHelper.timesCancelled fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() animatorTestRule.advanceTimeBy(1) Loading @@ -244,11 +235,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { val expectedDelay = DEFAULT_INITIAL_DELAY_MILLIS + 750 - DEFAULT_LONG_PRESS_POWER_DURATION_MILLIS fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -256,7 +246,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { advanceTime((expectedDelay - 1).milliseconds) animatorTestRule.advanceTimeBy(1) fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() Loading @@ -269,11 +260,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { val expectedDelay = DEFAULT_INITIAL_DELAY_MILLIS + 750 - DEFAULT_LONG_PRESS_POWER_DURATION_MILLIS fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false underTest.start() Loading @@ -289,13 +279,12 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun animationContinuesAndCompletes_whenPowerButtonReleased_afterLongPressDetected() = kosmos.runTest { val initialDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true runCurrent() // Advance time past initial delay to start the animation Loading @@ -307,11 +296,12 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { assertThat(vibratorHelper.hasVibratedWithEffects(invocationHaptics.vibration)).isTrue() // Simulate power button long press fakeKeyEventRepository.setPowerButtonLongPressed(true) fakeSqueezeEffectRepository.isPowerButtonLongPressed.value = true runCurrent() // Process collection of isPowerButtonLongPressed // Release power button fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() // Triggers cancelSqueeze, but it should not interrupt // Animation should be non-interruptible, so haptics are not cancelled at this point Loading @@ -335,14 +325,13 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun hapticsNotPlayed_whenHapticsDisabledInRepository_butAnimationRuns() = kosmos.runTest { val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = false // Haptics explicitly disabled fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true runCurrent() advanceTime((initialDelay + 1).milliseconds) Loading @@ -367,7 +356,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { assertThat(vibratorHelper.timesCancelled).isEqualTo(timesCancelledBefore) // Release power button (should not change anything as animation is finished) fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() } Loading @@ -375,13 +365,12 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun fullAnimationCycle_completesSuccessfully_withoutInterruption() = kosmos.runTest { val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true runCurrent() // Advance past initial delay advanceTime((initialDelay + 1).milliseconds) Loading @@ -402,7 +391,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { assertThat(vibratorHelper.timesCancelled).isEqualTo(timesCancelledBefore) // Release power button (does not affect completed animation) fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() } Loading @@ -410,13 +400,12 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun animationInterruptsMidway_andHapticsAreCorrectlyCancelled() = kosmos.runTest { val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true runCurrent() // Advance time past initial delay to start the animation Loading @@ -432,7 +421,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { assertThat(vibratorHelper.hasVibratedWithEffects(invocationHaptics.vibration)).isTrue() // Release power button before long press is detected fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() // Process button release, triggers cancelSqueeze // cancelSqueeze calls hapticPlayer.cancel() Loading @@ -450,10 +440,9 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { // Setup: Enable effect and trigger power button down val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false // Action: Start the effect and advance time past initial delay to start animation underTest.start() Loading @@ -469,10 +458,9 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { // Setup: Enable effect and trigger power button down val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false // Action: Start the effect underTest.start() Loading @@ -499,10 +487,9 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { // Setup: Enable effect and trigger power button down val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false // Action: Start the effect underTest.start() Loading @@ -517,7 +504,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { reset(kosmos.mockTopUiController, kosmos.notificationShadeWindowController) // Action: Release power button to cancel the animation fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() // Allow cancellation animation to complete animatorTestRule.advanceTimeBy(DEFAULT_OUTWARD_EFFECT_DURATION.toLong()) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/topwindoweffects/data/repository/SqueezeEffectRepositoryTest.kt +73 −32 File changed.Preview size limit exceeded, changes collapsed. Show changes packages/SystemUI/multivalentTests/src/com/android/systemui/topwindoweffects/domain/interactor/SqueezeEffectInteractorTest.kt +22 −25 Original line number Diff line number Diff line Loading @@ -19,12 +19,9 @@ package com.android.systemui.topwindoweffects.domain.interactor import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos import com.android.systemui.topwindoweffects.data.repository.fakeSqueezeEffectRepository Loading @@ -40,54 +37,54 @@ class SqueezeEffectInteractorTest : SysuiTestCase() { private val Kosmos.underTest by Kosmos.Fixture { SqueezeEffectInteractor( squeezeEffectRepository = fakeSqueezeEffectRepository, keyEventInteractor = KeyEventInteractor(fakeKeyEventRepository), coroutineContext = testScope.testScheduler, ) SqueezeEffectInteractor(squeezeEffectRepository = fakeSqueezeEffectRepository) } @Test fun testIsSqueezeEffectDisabled_whenDisabledInRepository() = kosmos.runTest { fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = false fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false val isSqueezeEffectEnabled by collectLastValue(underTest.isSqueezeEffectEnabled) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(isSqueezeEffectEnabled).isFalse() assertThat(isEffectEnabledAndPowerButtonPressed).isFalse() } @Test fun testIsSqueezeEffectEnabled_whenEnabledInRepository() = fun testShowInvocationEffect_whenEnabledInRepository() = kosmos.runTest { fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true val isSqueezeEffectEnabled by collectLastValue(underTest.isSqueezeEffectEnabled) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(isSqueezeEffectEnabled).isTrue() assertThat(isEffectEnabledAndPowerButtonPressed).isTrue() } @Test fun testPowerKeyInKeyCombination_powerKeyNotDownAsSingleGesture() = kosmos.runTest { fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = true fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false val isPowerButtonDownAsSingleKeyGesture by collectLastValue(underTest.isPowerButtonDownAsSingleKeyGesture) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(isPowerButtonDownAsSingleKeyGesture).isFalse() assertThat(isEffectEnabledAndPowerButtonPressed).isFalse() } @Test fun testPowerKeyNotInKeyCombination_powerKeyDownAsSingleGesture() = kosmos.runTest { fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true val isPowerButtonDownAsSingleKeyGesture by collectLastValue(underTest.isPowerButtonDownAsSingleKeyGesture) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(isPowerButtonDownAsSingleKeyGesture).isTrue() assertThat(isEffectEnabledAndPowerButtonPressed).isTrue() } } packages/SystemUI/src/com/android/systemui/topwindoweffects/TopLevelWindowEffects.kt +7 −13 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.topui.TopUiController import com.android.systemui.topui.TopUiControllerRefactor Loading @@ -49,7 +48,6 @@ class TopLevelWindowEffects constructor( @Application private val applicationScope: CoroutineScope, private val squeezeEffectInteractor: SqueezeEffectInteractor, private val keyEventInteractor: KeyEventInteractor, // TODO(b/409930584): make AppZoomOut non-optional private val appZoomOutOptional: Optional<AppZoomOut>, squeezeEffectHapticPlayerFactory: SqueezeEffectHapticPlayer.Factory, Loading Loading @@ -79,11 +77,9 @@ constructor( override fun start() { applicationScope.launch { squeezeEffectInteractor.isSqueezeEffectEnabled.collectLatest { enabled -> if (enabled) { squeezeEffectInteractor.isPowerButtonDownAsSingleKeyGesture.collectLatest { down -> if (down) { squeezeEffectInteractor.isEffectEnabledAndPowerButtonPressedAsSingleGesture .collectLatest { enabledAndPressed -> if (enabledAndPressed) { startSqueeze() } else { cancelSqueeze() Loading @@ -91,8 +87,6 @@ constructor( } } } } } private suspend fun startSqueeze() { delay(squeezeEffectInteractor.getInvocationEffectInitialDelayMs()) Loading @@ -113,7 +107,7 @@ constructor( } } hapticPlayer?.start(inwardsAnimationDuration.toInt() + DEFAULT_OUTWARD_EFFECT_DURATION) keyEventInteractor.isPowerButtonLongPressed.collectLatest { isLongPressed -> squeezeEffectInteractor.isPowerButtonLongPressed.collectLatest { isLongPressed -> if (isLongPressed) { isAnimationInterruptible = false } Loading packages/SystemUI/src/com/android/systemui/topwindoweffects/data/repository/SqueezeEffectRepository.kt +3 −2 Original line number Diff line number Diff line Loading @@ -19,11 +19,12 @@ package com.android.systemui.topwindoweffects.data.repository import kotlinx.coroutines.flow.Flow interface SqueezeEffectRepository { val isSqueezeEffectEnabled: Flow<Boolean> val isSqueezeEffectHapticEnabled: Boolean val isPowerButtonDownInKeyCombination: Flow<Boolean> val isEffectEnabledAndPowerButtonPressedAsSingleGesture: Flow<Boolean> val isPowerButtonLongPressed: Flow<Boolean> suspend fun getInvocationEffectInitialDelayMs(): Long Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/topwindoweffects/TopLevelWindowEffectsTest.kt +50 −62 Original line number Diff line number Diff line Loading @@ -24,9 +24,6 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.haptics.fakeVibratorHelper import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor import com.android.systemui.keyevent.domain.interactor.keyEventInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.advanceTimeBy import com.android.systemui.kosmos.runCurrent Loading Loading @@ -89,13 +86,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { TopLevelWindowEffects( applicationScope = testScope.backgroundScope, squeezeEffectInteractor = SqueezeEffectInteractor( squeezeEffectRepository = fakeSqueezeEffectRepository, keyEventInteractor = KeyEventInteractor(fakeKeyEventRepository), coroutineContext = testScope.testScheduler, ), SqueezeEffectInteractor(squeezeEffectRepository = fakeSqueezeEffectRepository), appZoomOutOptional = appZoomOutOptional, keyEventInteractor = keyEventInteractor, squeezeEffectHapticPlayerFactory = squeezeEffectHapticPlayerFactory, notificationShadeWindowController = notificationShadeWindowController, topUiController = mockTopUiController, Loading @@ -116,7 +108,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { @Test fun testNoProgressWhenSqueezeEffectDisabled() = kosmos.runTest { fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = false fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false underTest.start() Loading @@ -127,11 +120,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun testSqueezeEffectStarts_afterInitialDelay() = kosmos.runTest { val expectedDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -147,11 +139,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun testSqueezeEffectNotStarted_beforeInitialDelay() = kosmos.runTest { val expectedDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -167,18 +158,18 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun testSqueezeEffectNotStarted_whenUpEventReceivedBefore100Millis() = kosmos.runTest { val expectedDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() // subtract 1ms time to simulate initial delay duration is yet not finished advanceTime((expectedDelay - 1).milliseconds) fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() animatorTestRule.advanceTimeBy(1) Loading @@ -191,11 +182,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun testSqueezeEffectStarted_whenUpEventReceivedAfter100Millis() = kosmos.runTest { val expectedDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -204,7 +194,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { animatorTestRule.advanceTimeBy(1) val timesCancelledBefore = vibratorHelper.timesCancelled fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() animatorTestRule.advanceTimeBy(1) Loading @@ -217,11 +208,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { val expectedDelay = DEFAULT_INITIAL_DELAY_MILLIS + 750 - DEFAULT_LONG_PRESS_POWER_DURATION_MILLIS fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -230,7 +220,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { animatorTestRule.advanceTimeBy(1) val timesCancelledBefore = vibratorHelper.timesCancelled fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() animatorTestRule.advanceTimeBy(1) Loading @@ -244,11 +235,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { val expectedDelay = DEFAULT_INITIAL_DELAY_MILLIS + 750 - DEFAULT_LONG_PRESS_POWER_DURATION_MILLIS fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() Loading @@ -256,7 +246,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { advanceTime((expectedDelay - 1).milliseconds) animatorTestRule.advanceTimeBy(1) fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() Loading @@ -269,11 +260,10 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { val expectedDelay = DEFAULT_INITIAL_DELAY_MILLIS + 750 - DEFAULT_LONG_PRESS_POWER_DURATION_MILLIS fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = expectedDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false underTest.start() Loading @@ -289,13 +279,12 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun animationContinuesAndCompletes_whenPowerButtonReleased_afterLongPressDetected() = kosmos.runTest { val initialDelay = 100L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true runCurrent() // Advance time past initial delay to start the animation Loading @@ -307,11 +296,12 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { assertThat(vibratorHelper.hasVibratedWithEffects(invocationHaptics.vibration)).isTrue() // Simulate power button long press fakeKeyEventRepository.setPowerButtonLongPressed(true) fakeSqueezeEffectRepository.isPowerButtonLongPressed.value = true runCurrent() // Process collection of isPowerButtonLongPressed // Release power button fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() // Triggers cancelSqueeze, but it should not interrupt // Animation should be non-interruptible, so haptics are not cancelled at this point Loading @@ -335,14 +325,13 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun hapticsNotPlayed_whenHapticsDisabledInRepository_butAnimationRuns() = kosmos.runTest { val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = false // Haptics explicitly disabled fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true runCurrent() advanceTime((initialDelay + 1).milliseconds) Loading @@ -367,7 +356,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { assertThat(vibratorHelper.timesCancelled).isEqualTo(timesCancelledBefore) // Release power button (should not change anything as animation is finished) fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() } Loading @@ -375,13 +365,12 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun fullAnimationCycle_completesSuccessfully_withoutInterruption() = kosmos.runTest { val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true runCurrent() // Advance past initial delay advanceTime((initialDelay + 1).milliseconds) Loading @@ -402,7 +391,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { assertThat(vibratorHelper.timesCancelled).isEqualTo(timesCancelledBefore) // Release power button (does not affect completed animation) fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() } Loading @@ -410,13 +400,12 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { fun animationInterruptsMidway_andHapticsAreCorrectlyCancelled() = kosmos.runTest { val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isSqueezeEffectHapticEnabled = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false underTest.start() fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true runCurrent() // Advance time past initial delay to start the animation Loading @@ -432,7 +421,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { assertThat(vibratorHelper.hasVibratedWithEffects(invocationHaptics.vibration)).isTrue() // Release power button before long press is detected fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() // Process button release, triggers cancelSqueeze // cancelSqueeze calls hapticPlayer.cancel() Loading @@ -450,10 +440,9 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { // Setup: Enable effect and trigger power button down val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false // Action: Start the effect and advance time past initial delay to start animation underTest.start() Loading @@ -469,10 +458,9 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { // Setup: Enable effect and trigger power button down val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false // Action: Start the effect underTest.start() Loading @@ -499,10 +487,9 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { kosmos.runTest { // Setup: Enable effect and trigger power button down val initialDelay = 50L fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true fakeSqueezeEffectRepository.invocationEffectInitialDelayMs = initialDelay fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false // Action: Start the effect underTest.start() Loading @@ -517,7 +504,8 @@ class TopLevelWindowEffectsTest : SysuiTestCase() { reset(kosmos.mockTopUiController, kosmos.notificationShadeWindowController) // Action: Release power button to cancel the animation fakeKeyEventRepository.setPowerButtonDown(false) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false runCurrent() // Allow cancellation animation to complete animatorTestRule.advanceTimeBy(DEFAULT_OUTWARD_EFFECT_DURATION.toLong()) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/topwindoweffects/data/repository/SqueezeEffectRepositoryTest.kt +73 −32 File changed.Preview size limit exceeded, changes collapsed. Show changes
packages/SystemUI/multivalentTests/src/com/android/systemui/topwindoweffects/domain/interactor/SqueezeEffectInteractorTest.kt +22 −25 Original line number Diff line number Diff line Loading @@ -19,12 +19,9 @@ package com.android.systemui.topwindoweffects.domain.interactor import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.keyevent.data.repository.fakeKeyEventRepository import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos import com.android.systemui.topwindoweffects.data.repository.fakeSqueezeEffectRepository Loading @@ -40,54 +37,54 @@ class SqueezeEffectInteractorTest : SysuiTestCase() { private val Kosmos.underTest by Kosmos.Fixture { SqueezeEffectInteractor( squeezeEffectRepository = fakeSqueezeEffectRepository, keyEventInteractor = KeyEventInteractor(fakeKeyEventRepository), coroutineContext = testScope.testScheduler, ) SqueezeEffectInteractor(squeezeEffectRepository = fakeSqueezeEffectRepository) } @Test fun testIsSqueezeEffectDisabled_whenDisabledInRepository() = kosmos.runTest { fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = false fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false val isSqueezeEffectEnabled by collectLastValue(underTest.isSqueezeEffectEnabled) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(isSqueezeEffectEnabled).isFalse() assertThat(isEffectEnabledAndPowerButtonPressed).isFalse() } @Test fun testIsSqueezeEffectEnabled_whenEnabledInRepository() = fun testShowInvocationEffect_whenEnabledInRepository() = kosmos.runTest { fakeSqueezeEffectRepository.isSqueezeEffectEnabled.value = true fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true val isSqueezeEffectEnabled by collectLastValue(underTest.isSqueezeEffectEnabled) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(isSqueezeEffectEnabled).isTrue() assertThat(isEffectEnabledAndPowerButtonPressed).isTrue() } @Test fun testPowerKeyInKeyCombination_powerKeyNotDownAsSingleGesture() = kosmos.runTest { fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = true fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = false val isPowerButtonDownAsSingleKeyGesture by collectLastValue(underTest.isPowerButtonDownAsSingleKeyGesture) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(isPowerButtonDownAsSingleKeyGesture).isFalse() assertThat(isEffectEnabledAndPowerButtonPressed).isFalse() } @Test fun testPowerKeyNotInKeyCombination_powerKeyDownAsSingleGesture() = kosmos.runTest { fakeSqueezeEffectRepository.isPowerButtonDownInKeyCombination.value = false fakeKeyEventRepository.setPowerButtonDown(true) fakeSqueezeEffectRepository.isEffectEnabledAndPowerButtonPressedAsSingleGesture.value = true val isPowerButtonDownAsSingleKeyGesture by collectLastValue(underTest.isPowerButtonDownAsSingleKeyGesture) val isEffectEnabledAndPowerButtonPressed by collectLastValue(underTest.isEffectEnabledAndPowerButtonPressedAsSingleGesture) assertThat(isPowerButtonDownAsSingleKeyGesture).isTrue() assertThat(isEffectEnabledAndPowerButtonPressed).isTrue() } }
packages/SystemUI/src/com/android/systemui/topwindoweffects/TopLevelWindowEffects.kt +7 −13 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.topui.TopUiController import com.android.systemui.topui.TopUiControllerRefactor Loading @@ -49,7 +48,6 @@ class TopLevelWindowEffects constructor( @Application private val applicationScope: CoroutineScope, private val squeezeEffectInteractor: SqueezeEffectInteractor, private val keyEventInteractor: KeyEventInteractor, // TODO(b/409930584): make AppZoomOut non-optional private val appZoomOutOptional: Optional<AppZoomOut>, squeezeEffectHapticPlayerFactory: SqueezeEffectHapticPlayer.Factory, Loading Loading @@ -79,11 +77,9 @@ constructor( override fun start() { applicationScope.launch { squeezeEffectInteractor.isSqueezeEffectEnabled.collectLatest { enabled -> if (enabled) { squeezeEffectInteractor.isPowerButtonDownAsSingleKeyGesture.collectLatest { down -> if (down) { squeezeEffectInteractor.isEffectEnabledAndPowerButtonPressedAsSingleGesture .collectLatest { enabledAndPressed -> if (enabledAndPressed) { startSqueeze() } else { cancelSqueeze() Loading @@ -91,8 +87,6 @@ constructor( } } } } } private suspend fun startSqueeze() { delay(squeezeEffectInteractor.getInvocationEffectInitialDelayMs()) Loading @@ -113,7 +107,7 @@ constructor( } } hapticPlayer?.start(inwardsAnimationDuration.toInt() + DEFAULT_OUTWARD_EFFECT_DURATION) keyEventInteractor.isPowerButtonLongPressed.collectLatest { isLongPressed -> squeezeEffectInteractor.isPowerButtonLongPressed.collectLatest { isLongPressed -> if (isLongPressed) { isAnimationInterruptible = false } Loading
packages/SystemUI/src/com/android/systemui/topwindoweffects/data/repository/SqueezeEffectRepository.kt +3 −2 Original line number Diff line number Diff line Loading @@ -19,11 +19,12 @@ package com.android.systemui.topwindoweffects.data.repository import kotlinx.coroutines.flow.Flow interface SqueezeEffectRepository { val isSqueezeEffectEnabled: Flow<Boolean> val isSqueezeEffectHapticEnabled: Boolean val isPowerButtonDownInKeyCombination: Flow<Boolean> val isEffectEnabledAndPowerButtonPressedAsSingleGesture: Flow<Boolean> val isPowerButtonLongPressed: Flow<Boolean> suspend fun getInvocationEffectInitialDelayMs(): Long Loading