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

Commit aa55dda1 authored by Nicolo' Mazzucato's avatar Nicolo' Mazzucato
Browse files

Trigger unfold animation without treshold while on keyguard

When folding, the fold animation triggers at different angles based on what's on the screen. Before this cl, it was triggering regardless of the angle only while on launcher, and after a certain threshold in all other cases.

While on keyguard, the angle depended by the app that was in foreground. (e.g. if calculator was open, and device locked, the threshold was 60 degrees).

After this change, while the keyguard is visible, there is no threshold.

It has been needed to create the intermediate UnfoldKeyguardVisibilityListener as DeviceFoldStateProvider is in the global dagger scope, while KeyguardStateController in the sysui subcomponent (so, injecting KeyguardStateController directly in DeviceFoldStateProvider is not possible).

From launcher, it is expected we don't have the information whether keyguard is visible (as we don't need it).

Bug: 261313897
Test: DeviceFoldStateProviderTest & manual
Change-Id: I07f133e96b16572448754ce2009f55e9e316b136
parent b4c0f42b
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import com.android.keyguard.KeyguardUnfoldTransition
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.shade.NotificationPanelUnfoldAnimationController
import com.android.systemui.statusbar.phone.StatusBarMoveFromCenterAnimationController
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
import com.android.systemui.util.kotlin.getOrNull
@@ -95,4 +96,6 @@ interface SysUIUnfoldComponent {
    fun getUnfoldHapticsPlayer(): UnfoldHapticsPlayer

    fun getUnfoldLightRevealOverlayAnimation(): UnfoldLightRevealOverlayAnimation

    fun getUnfoldKeyguardVisibilityManager(): UnfoldKeyguardVisibilityManager
}
+39 −0
Original line number Diff line number Diff line
package com.android.systemui.unfold

import android.util.Log
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
import com.android.systemui.util.kotlin.getOrNull
import java.util.Optional
import javax.inject.Inject

/**
 * Used to set the keyguard visibility state to [UnfoldKeyguardVisibilityManager].
 *
 * It is not possible to directly inject a sysui class (e.g. [KeyguardStateController]) into
 * [DeviceStateProvider], as it can't depend on google sysui directly. So,
 * [UnfoldKeyguardVisibilityManager] is provided to clients, that can set the keyguard visibility
 * accordingly.
 */
@SysUISingleton
class UnfoldKeyguardVisibilityListener
@Inject
constructor(
    keyguardStateController: KeyguardStateController,
    unfoldComponent: Optional<SysUIUnfoldComponent>,
) {

    private val unfoldKeyguardVisibilityManager =
        unfoldComponent.getOrNull()?.getUnfoldKeyguardVisibilityManager()

    private val delegate = { keyguardStateController.isVisible }

    fun init() {
        unfoldKeyguardVisibilityManager?.setKeyguardVisibleDelegate(delegate).also {
            Log.d(TAG, "setKeyguardVisibleDelegate set")
        }
    }
}

private const val TAG = "UnfoldKeyguardVisibilityListener"
+50 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.systemui.unfold.updates.RotationChangeProvider.RotationListen
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider.ScreenListener
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.google.common.truth.Truth.assertThat
@@ -56,6 +57,9 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
    @Mock
    private lateinit var rotationChangeProvider: RotationChangeProvider

    @Mock
    private lateinit var unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider

    @Captor
    private lateinit var rotationListener: ArgumentCaptor<RotationListener>

@@ -87,6 +91,7 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
                screenOnStatusProvider,
                foldProvider,
                activityTypeProvider,
                unfoldKeyguardVisibilityProvider,
                rotationChangeProvider,
                context.mainExecutor,
                handler
@@ -379,6 +384,47 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
    }

    @Test
    fun startClosingEvent_whileNotOnKeyguardAndNotOnLauncher_doesNotTriggerBeforeThreshold() {
        setKeyguardVisibility(visible = false)
        setupForegroundActivityType(isHomeActivity = false)
        sendHingeAngleEvent(180)

        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)

        assertThat(foldUpdates).isEmpty()
    }

    @Test
    fun startClosingEvent_whileKeyguardStateNotAvailable_triggerBeforeThreshold() {
        setKeyguardVisibility(visible = null)
        sendHingeAngleEvent(180)

        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)

        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
    }

    @Test
    fun startClosingEvent_whileonKeyguard_doesTriggerBeforeThreshold() {
        setKeyguardVisibility(visible = true)
        sendHingeAngleEvent(180)

        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES + 1)

        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
    }

    @Test
    fun startClosingEvent_whileNotOnKeyguard_triggersAfterThreshold() {
        setKeyguardVisibility(visible = false)
        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES)

        sendHingeAngleEvent(START_CLOSING_ON_APPS_THRESHOLD_DEGREES - 1)

        assertThat(foldUpdates).containsExactly(FOLD_UPDATE_START_CLOSING)
    }

    @Test
    fun screenOff_whileFolded_hingeAngleProviderRemainsOff() {
        setFoldState(folded = true)
@@ -445,6 +491,10 @@ class DeviceFoldStateProviderTest : SysuiTestCase() {
        whenever(activityTypeProvider.isHomeActivity).thenReturn(isHomeActivity)
    }

    private fun setKeyguardVisibility(visible: Boolean?) {
        whenever(unfoldKeyguardVisibilityProvider.isKeyguardVisible).thenReturn(visible)
    }

    private fun simulateTimeout(waitTime: Long = HALF_OPENED_TIMEOUT_MILLIS) {
        val runnableDelay = scheduledRunnableDelay ?: throw Exception("No runnable scheduled.")
        if (waitTime >= runnableDelay) {
+17 −1
Original line number Diff line number Diff line
@@ -28,6 +28,9 @@ import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.hinge.HingeSensorAngleProvider
import com.android.systemui.unfold.util.ATraceLoggerTransitionProgressListener
import com.android.systemui.unfold.util.ScaleAwareTransitionProgressProvider
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManager
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityManagerImpl
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
import dagger.Module
import dagger.Provides
import java.util.Optional
@@ -57,7 +60,8 @@ class UnfoldSharedModule {
                scaleAwareProviderFactory.wrap(baseProgressProvider).apply {
                    // Always present callback that logs animation beginning and end.
                    addCallback(tracingListener)
                })
                }
            )
        }

    @Provides
@@ -77,4 +81,16 @@ class UnfoldSharedModule {
        } else {
            EmptyHingeAngleProvider
        }

    @Provides
    @Singleton
    fun unfoldKeyguardVisibilityProvider(
        impl: UnfoldKeyguardVisibilityManagerImpl
    ): UnfoldKeyguardVisibilityProvider = impl

    @Provides
    @Singleton
    fun unfoldKeyguardVisibilityManager(
        impl: UnfoldKeyguardVisibilityManagerImpl
    ): UnfoldKeyguardVisibilityManager = impl
}
+6 −3
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.systemui.unfold.updates.hinge.FULLY_OPEN_DEGREES
import com.android.systemui.unfold.updates.hinge.HingeAngleProvider
import com.android.systemui.unfold.updates.screen.ScreenStatusProvider
import com.android.systemui.unfold.util.CurrentActivityTypeProvider
import com.android.systemui.unfold.util.UnfoldKeyguardVisibilityProvider
import java.util.concurrent.Executor
import javax.inject.Inject

@@ -42,6 +43,7 @@ constructor(
    private val screenStatusProvider: ScreenStatusProvider,
    private val foldProvider: FoldProvider,
    private val activityTypeProvider: CurrentActivityTypeProvider,
    private val unfoldKeyguardVisibilityProvider: UnfoldKeyguardVisibilityProvider,
    private val rotationChangeProvider: RotationChangeProvider,
    @UnfoldMain private val mainExecutor: Executor,
    @UnfoldMain private val handler: Handler
@@ -152,12 +154,13 @@ constructor(
     */
    private fun getClosingThreshold(): Int? {
        val isHomeActivity = activityTypeProvider.isHomeActivity ?: return null
        val isKeyguardVisible = unfoldKeyguardVisibilityProvider.isKeyguardVisible == true

        if (DEBUG) {
            Log.d(TAG, "isHomeActivity=$isHomeActivity")
            Log.d(TAG, "isHomeActivity=$isHomeActivity, isOnKeyguard=$isKeyguardVisible")
        }

        return if (isHomeActivity) {
        return if (isHomeActivity || isKeyguardVisible) {
            null
        } else {
            START_CLOSING_ON_APPS_THRESHOLD_DEGREES
@@ -257,7 +260,7 @@ fun @receiver:FoldUpdate Int.name() =
    }

private const val TAG = "DeviceFoldProvider"
private const val DEBUG = false
private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)

/** Threshold after which we consider the device fully unfolded. */
@VisibleForTesting const val FULLY_OPEN_THRESHOLD_DEGREES = 15f
Loading