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

Commit 162d9c0a authored by Matt Pietal's avatar Matt Pietal
Browse files

Rewire setDozing() to use repositories

Testing out the process of convert existing events, which is a mix of
both callbacks and direct calls to injected controllers, over to
flowable streams through the KeyguardRepository.

Test: atest DozeServiceHostTest KeyguardRepositoryImplTest
FoldAodAnimationControllerTest
Test: Manually fold/unfold the device
Bug: 242853098

Change-Id: I8864c413cd136e7cb831736331160bea04e98222
parent b55d403a
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -101,6 +101,11 @@ public interface DozeHost {
         * Called when the always on suppression state changes. See {@link #isAlwaysOnSuppressed()}.
         */
        default void onAlwaysOnSuppressedChanged(boolean suppressed) {}

        /**
         * Called when the dozing state may have been updated.
         */
        default void onDozingChanged(boolean isDozing) {}
    }

    interface PulseCallback {
+16 −11
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLoggin
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.common.shared.model.Position
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.doze.DozeHost
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
@@ -28,6 +29,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged

/** Defines interface for classes that encapsulate application state for the keyguard. */
interface KeyguardRepository {
@@ -102,6 +104,7 @@ class KeyguardRepositoryImpl
constructor(
    statusBarStateController: StatusBarStateController,
    keyguardStateController: KeyguardStateController,
    dozeHost: DozeHost,
) : KeyguardRepository {
    private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
    override val animateBottomAreaDozingTransitions =
@@ -136,19 +139,21 @@ constructor(
        awaitClose { keyguardStateController.removeCallback(callback) }
    }

    override val isDozing: Flow<Boolean> = conflatedCallbackFlow {
    override val isDozing: Flow<Boolean> =
        conflatedCallbackFlow {
                val callback =
            object : StatusBarStateController.StateListener {
                    object : DozeHost.Callback {
                        override fun onDozingChanged(isDozing: Boolean) {
                            trySendWithFailureLogging(isDozing, TAG, "updated isDozing")
                        }
                    }
                dozeHost.addCallback(callback)
                trySendWithFailureLogging(false, TAG, "initial isDozing: false")

        statusBarStateController.addCallback(callback)
        trySendWithFailureLogging(statusBarStateController.isDozing, TAG, "initial isDozing")

        awaitClose { statusBarStateController.removeCallback(callback) }
                awaitClose { dozeHost.removeCallback(callback) }
            }
            .distinctUntilChanged()

    override val dozeAmount: Flow<Float> = conflatedCallbackFlow {
        val callback =
            object : StatusBarStateController.StateListener {
+11 −13
Original line number Diff line number Diff line
@@ -28,8 +28,6 @@ import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.assist.AssistManager;
@@ -50,11 +48,9 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.unfold.FoldAodAnimationController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.android.systemui.util.Assert;

import java.util.ArrayList;
import java.util.Optional;

import javax.inject.Inject;

@@ -80,8 +76,6 @@ public final class DozeServiceHost implements DozeHost {
    private final WakefulnessLifecycle mWakefulnessLifecycle;
    private final SysuiStatusBarStateController mStatusBarStateController;
    private final DeviceProvisionedController mDeviceProvisionedController;
    @Nullable
    private final FoldAodAnimationController mFoldAodAnimationController;
    private final HeadsUpManagerPhone mHeadsUpManagerPhone;
    private final BatteryController mBatteryController;
    private final ScrimController mScrimController;
@@ -114,7 +108,6 @@ public final class DozeServiceHost implements DozeHost {
            Lazy<AssistManager> assistManagerLazy,
            DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor,
            PulseExpansionHandler pulseExpansionHandler,
            Optional<SysUIUnfoldComponent> sysUIUnfoldComponent,
            NotificationShadeWindowController notificationShadeWindowController,
            NotificationWakeUpCoordinator notificationWakeUpCoordinator,
            AuthController authController,
@@ -138,8 +131,6 @@ public final class DozeServiceHost implements DozeHost {
        mNotificationWakeUpCoordinator = notificationWakeUpCoordinator;
        mAuthController = authController;
        mNotificationIconAreaController = notificationIconAreaController;
        mFoldAodAnimationController = sysUIUnfoldComponent
                .map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null);
    }

    // TODO: we should try to not pass status bar in here if we can avoid it.
@@ -167,6 +158,7 @@ public final class DozeServiceHost implements DozeHost {
    }

    void firePowerSaveChanged(boolean active) {
        Assert.isMainThread();
        for (Callback callback : mCallbacks) {
            callback.onPowerSaveChanged(active);
        }
@@ -177,6 +169,7 @@ public final class DozeServiceHost implements DozeHost {
            entry.setPulseSuppressed(true);
            mNotificationIconAreaController.updateAodNotificationIcons();
        };
        Assert.isMainThread();
        for (Callback callback : mCallbacks) {
            callback.onNotificationAlerted(pulseSuppressedListener);
        }
@@ -193,11 +186,13 @@ public final class DozeServiceHost implements DozeHost {

    @Override
    public void addCallback(@NonNull Callback callback) {
        Assert.isMainThread();
        mCallbacks.add(callback);
    }

    @Override
    public void removeCallback(@NonNull Callback callback) {
        Assert.isMainThread();
        mCallbacks.remove(callback);
    }

@@ -212,6 +207,8 @@ public final class DozeServiceHost implements DozeHost {
    }

    void updateDozing() {
        Assert.isMainThread();

        // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked.
        boolean
                dozing =
@@ -225,10 +222,10 @@ public final class DozeServiceHost implements DozeHost {
            dozing = false;
        }

        mStatusBarStateController.setIsDozing(dozing);
        if (mFoldAodAnimationController != null) {
            mFoldAodAnimationController.setIsDozing(dozing);
        for (Callback callback : mCallbacks) {
            callback.onDozingChanged(dozing);
        }
        mStatusBarStateController.setIsDozing(dozing);
    }

    @Override
@@ -452,6 +449,7 @@ public final class DozeServiceHost implements DozeHost {
            return;
        }
        mAlwaysOnSuppressed = suppressed;
        Assert.isMainThread();
        for (Callback callback : mCallbacks) {
            callback.onAlwaysOnSuppressedChanged(suppressed);
        }
+33 −18
Original line number Diff line number Diff line
@@ -18,22 +18,31 @@ package com.android.systemui.unfold

import android.content.Context
import android.hardware.devicestate.DeviceStateManager
import android.os.Handler
import android.os.PowerManager
import android.provider.Settings
import androidx.annotation.VisibleForTesting
import androidx.core.view.OneShotPreDrawListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.internal.util.LatencyTracker
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.ScreenOffAnimation
import com.android.systemui.statusbar.policy.CallbackController
import com.android.systemui.unfold.FoldAodAnimationController.FoldAodAnimationStatus
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.settings.GlobalSettings
import java.util.concurrent.Executor
import dagger.Lazy
import java.util.function.Consumer
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

/**
 * Controls folding to AOD animation: when AOD is enabled and foldable device is folded we play a
@@ -43,16 +52,16 @@ import javax.inject.Inject
class FoldAodAnimationController
@Inject
constructor(
    @Main private val handler: Handler,
    @Main private val executor: Executor,
    @Main private val executor: DelayableExecutor,
    private val context: Context,
    private val deviceStateManager: DeviceStateManager,
    private val wakefulnessLifecycle: WakefulnessLifecycle,
    private val globalSettings: GlobalSettings,
    private val latencyTracker: LatencyTracker,
    private val keyguardInteractor: Lazy<KeyguardInteractor>,
) : CallbackController<FoldAodAnimationStatus>, ScreenOffAnimation, WakefulnessLifecycle.Observer {

    private lateinit var mCentralSurfaces: CentralSurfaces
    private lateinit var centralSurfaces: CentralSurfaces

    private var isFolded = false
    private var isFoldHandled = true
@@ -64,12 +73,13 @@ constructor(

    private var shouldPlayAnimation = false
    private var isAnimationPlaying = false
    private var cancelAnimation: Runnable? = null

    private val statusListeners = arrayListOf<FoldAodAnimationStatus>()
    private val foldToAodLatencyTracker = FoldToAodLatencyTracker()

    private val startAnimationRunnable = Runnable {
        mCentralSurfaces.notificationPanelViewController.startFoldToAodAnimation(
        centralSurfaces.notificationPanelViewController.startFoldToAodAnimation(
            /* startAction= */ { foldToAodLatencyTracker.onAnimationStarted() },
            /* endAction= */ { setAnimationState(playing = false) },
            /* cancelAction= */ { setAnimationState(playing = false) },
@@ -77,10 +87,14 @@ constructor(
    }

    override fun initialize(centralSurfaces: CentralSurfaces, lightRevealScrim: LightRevealScrim) {
        this.mCentralSurfaces = centralSurfaces
        this.centralSurfaces = centralSurfaces

        deviceStateManager.registerCallback(executor, FoldListener())
        wakefulnessLifecycle.addObserver(this)

        centralSurfaces.notificationPanelViewController.view.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.STARTED) { listenForDozing(this) }
        }
    }

    /** Returns true if we should run fold to AOD animation */
@@ -94,7 +108,7 @@ constructor(
    override fun startAnimation(): Boolean =
        if (shouldStartAnimation()) {
            setAnimationState(playing = true)
            mCentralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation()
            centralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation()
            true
        } else {
            setAnimationState(playing = false)
@@ -104,8 +118,8 @@ constructor(
    override fun onStartedWakingUp() {
        if (isAnimationPlaying) {
            foldToAodLatencyTracker.cancel()
            handler.removeCallbacks(startAnimationRunnable)
            mCentralSurfaces.notificationPanelViewController.cancelFoldToAodAnimation()
            cancelAnimation?.run()
            centralSurfaces.notificationPanelViewController.cancelFoldToAodAnimation()
        }

        setAnimationState(playing = false)
@@ -138,13 +152,13 @@ constructor(
            // We should play the folding to AOD animation

            setAnimationState(playing = true)
            mCentralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation()
            centralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation()

            // We don't need to wait for the scrim as it is already displayed
            // but we should wait for the initial animation preparations to be drawn
            // (setting initial alpha/translation)
            OneShotPreDrawListener.add(
                mCentralSurfaces.notificationPanelViewController.view,
                centralSurfaces.notificationPanelViewController.view,
                onReady
            )
        } else {
@@ -165,18 +179,14 @@ constructor(

    fun onScreenTurnedOn() {
        if (shouldPlayAnimation) {
            handler.removeCallbacks(startAnimationRunnable)
            cancelAnimation?.run()

            // Post starting the animation to the next frame to avoid junk due to inset changes
            handler.post(startAnimationRunnable)
            cancelAnimation = executor.executeDelayed(startAnimationRunnable, /* delayMillis= */ 0)
            shouldPlayAnimation = false
        }
    }

    fun setIsDozing(dozing: Boolean) {
        isDozing = dozing
    }

    override fun isAnimationPlaying(): Boolean = isAnimationPlaying

    override fun isKeyguardHideDelayed(): Boolean = isAnimationPlaying()
@@ -204,6 +214,11 @@ constructor(
        statusListeners.remove(listener)
    }

    @VisibleForTesting
    internal suspend fun listenForDozing(scope: CoroutineScope): Job {
        return scope.launch { keyguardInteractor.get().isDozing.collect { isDozing = it } }
    }

    interface FoldAodAnimationStatus {
        fun onFoldToAodAnimationChanged()
    }
+11 −4
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.data.repository
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Position
import com.android.systemui.doze.DozeHost
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.argumentCaptor
@@ -40,6 +41,7 @@ import org.mockito.MockitoAnnotations
class KeyguardRepositoryImplTest : SysuiTestCase() {

    @Mock private lateinit var statusBarStateController: StatusBarStateController
    @Mock private lateinit var dozeHost: DozeHost
    @Mock private lateinit var keyguardStateController: KeyguardStateController

    private lateinit var underTest: KeyguardRepositoryImpl
@@ -48,7 +50,12 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
    fun setUp() {
        MockitoAnnotations.initMocks(this)

        underTest = KeyguardRepositoryImpl(statusBarStateController, keyguardStateController)
        underTest =
            KeyguardRepositoryImpl(
                statusBarStateController,
                keyguardStateController,
                dozeHost,
            )
    }

    @Test
@@ -129,8 +136,8 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
        var latest: Boolean? = null
        val job = underTest.isDozing.onEach { latest = it }.launchIn(this)

        val captor = argumentCaptor<StatusBarStateController.StateListener>()
        verify(statusBarStateController).addCallback(captor.capture())
        val captor = argumentCaptor<DozeHost.Callback>()
        verify(dozeHost).addCallback(captor.capture())

        captor.value.onDozingChanged(true)
        assertThat(latest).isTrue()
@@ -139,7 +146,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
        assertThat(latest).isFalse()

        job.cancel()
        verify(statusBarStateController).removeCallback(captor.value)
        verify(dozeHost).removeCallback(captor.value)
    }

    @Test
Loading