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

Commit a38706d5 authored by Bryce Lee's avatar Bryce Lee
Browse files

Fade keyguard status bar during transition to and from Glanceable Hub.

This change ties the keyguard status bar alpha to the transition
progress to and from Glanceable Hub.

Fixes: 374017195
Test: atest KeyguardStatusBarViewControllerTest#animateToGlanceableHub_affectsAlpha
Test: atest KeyguardStatusBarViewControllerTest#animateToGlanceableHub_alphaResetOnCommunalNotShowing
Flag: EXEMPT bugfix
Change-Id: Ib24526c8d57bfc5e689a3450402cb7d28f64f109
parent 282bd232
Loading
Loading
Loading
Loading
+69 −30
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone

import android.app.StatusBarManager
import android.graphics.Insets
import android.os.UserHandle
import android.os.UserManager
import android.platform.test.annotations.DisableFlags
@@ -23,6 +24,7 @@ import android.platform.test.annotations.EnableFlags
import android.provider.Settings
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import android.testing.ViewUtils
import android.view.LayoutInflater
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -34,17 +36,21 @@ import com.android.keyguard.logging.KeyguardLogger
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository
import com.android.systemui.communal.domain.interactor.communalSceneInteractor
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.ui.viewmodel.glanceableHubToLockscreenTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.lockscreenToGlanceableHubTransitionViewModel
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.statusBarStateController
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeViewStateProvider
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.data.repository.StatusBarContentInsetsProviderStore
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
@@ -54,13 +60,16 @@ import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.policy.UserInfoController
import com.android.systemui.statusbar.ui.viewmodel.keyguardStatusBarViewModel
import com.android.systemui.statusbar.ui.viewmodel.statusBarUserChipViewModel
import com.android.systemui.testKosmos
import com.android.systemui.user.ui.viewmodel.StatusBarUserChipViewModel
import com.android.systemui.user.data.repository.fakeUserRepository
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Assert
import org.junit.Before
import org.junit.Test
@@ -70,12 +79,11 @@ import org.mockito.ArgumentMatchers
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations

@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper
@RunWithLooper(setAsMainLooper = true)
class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
    private lateinit var kosmos: Kosmos
    private lateinit var testScope: TestScope
@@ -106,17 +114,11 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {

    @Mock private lateinit var biometricUnlockController: BiometricUnlockController

    @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController

    @Mock private lateinit var statusBarContentInsetsProvider: StatusBarContentInsetsProvider

    @Mock
    private lateinit var statusBarContentInsetsProviderStore: StatusBarContentInsetsProviderStore

    @Mock private lateinit var userManager: UserManager

    @Mock private lateinit var statusBarUserChipViewModel: StatusBarUserChipViewModel

    @Captor
    private lateinit var configurationListenerCaptor:
        ArgumentCaptor<ConfigurationController.ConfigurationListener>
@@ -139,21 +141,29 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
    private val fakeExecutor = FakeExecutor(FakeSystemClock())
    private val backgroundExecutor = FakeExecutor(FakeSystemClock())

    private lateinit var looper: TestableLooper

    @Before
    @Throws(Exception::class)
    fun setup() {
        looper = TestableLooper.get(this)
        kosmos = testKosmos()
        testScope = kosmos.testScope
        shadeViewStateProvider = TestShadeViewStateProvider()

        Mockito.`when`(
                kosmos.statusBarContentInsetsProvider.getStatusBarContentInsetsForCurrentRotation()
            )
            .thenReturn(Insets.of(0, 0, 0, 0))

        MockitoAnnotations.initMocks(this)

        Mockito.`when`(iconManagerFactory.create(ArgumentMatchers.any(), ArgumentMatchers.any()))
            .thenReturn(iconManager)
        Mockito.`when`(statusBarContentInsetsProviderStore.defaultDisplay)
            .thenReturn(statusBarContentInsetsProvider)
            .thenReturn(kosmos.statusBarContentInsetsProvider)
        allowTestableLooperAsMainThread()
        TestableLooper.get(this).runWithLooper {
        looper.runWithLooper {
            keyguardStatusBarView =
                Mockito.spy(
                    LayoutInflater.from(mContext).inflate(R.layout.keyguard_status_bar, null)
@@ -167,6 +177,7 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {

    private fun createController(): KeyguardStatusBarViewController {
        return KeyguardStatusBarViewController(
            kosmos.testDispatcher,
            keyguardStatusBarView,
            carrierTextController,
            configurationController,
@@ -182,10 +193,10 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
            keyguardUpdateMonitor,
            kosmos.keyguardStatusBarViewModel,
            biometricUnlockController,
            statusBarStateController,
            kosmos.statusBarStateController,
            statusBarContentInsetsProviderStore,
            userManager,
            statusBarUserChipViewModel,
            kosmos.statusBarUserChipViewModel,
            secureSettings,
            commandQueue,
            fakeExecutor,
@@ -193,6 +204,8 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
            logger,
            statusOverlayHoverListenerFactory,
            kosmos.communalSceneInteractor,
            kosmos.glanceableHubToLockscreenTransitionViewModel,
            kosmos.lockscreenToGlanceableHubTransitionViewModel,
        )
    }

@@ -682,9 +695,10 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
    }

    @Test
    fun testNewUserSwitcherDisablesAvatar_newUiOn() {
    fun testNewUserSwitcherDisablesAvatar_newUiOn() =
        testScope.runTest {
            // GIVEN the status bar user switcher chip is enabled
        Mockito.`when`(statusBarUserChipViewModel.chipEnabled).thenReturn(true)
            kosmos.fakeUserRepository.isStatusBarUserChipEnabled = true

            // WHEN the controller is created
            controller = createController()
@@ -696,7 +710,7 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
    @Test
    fun testNewUserSwitcherDisablesAvatar_newUiOff() {
        // GIVEN the status bar user switcher chip is disabled
        Mockito.`when`(statusBarUserChipViewModel.chipEnabled).thenReturn(false)
        kosmos.fakeUserRepository.isStatusBarUserChipEnabled = false

        // WHEN the controller is created
        controller = createController()
@@ -752,12 +766,7 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
    }

    private fun updateStatusBarState(state: Int) {
        val statusBarStateListenerCaptor =
            ArgumentCaptor.forClass(StatusBarStateController.StateListener::class.java)
        Mockito.verify(statusBarStateController).addCallback(statusBarStateListenerCaptor.capture())
        val callback = statusBarStateListenerCaptor.value

        callback.onStateChanged(state)
        kosmos.statusBarStateController.setState(state)
    }

    @Test
@@ -774,6 +783,36 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() {
        Truth.assertThat(keyguardStatusBarView.visibility).isEqualTo(View.INVISIBLE)
    }

    @Test
    fun animateToGlanceableHub_affectsAlpha() =
        testScope.runTest {
            controller.init()
            val transitionAlphaAmount = .5f
            ViewUtils.attachView(keyguardStatusBarView)
            looper.processAllMessages()
            updateStateToKeyguard()
            kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Communal)
            runCurrent()
            controller.updateCommunalAlphaTransition(transitionAlphaAmount)
            Truth.assertThat(keyguardStatusBarView.getAlpha()).isEqualTo(transitionAlphaAmount)
        }

    @Test
    fun animateToGlanceableHub_alphaResetOnCommunalNotShowing() =
        testScope.runTest {
            controller.init()
            val transitionAlphaAmount = .5f
            ViewUtils.attachView(keyguardStatusBarView)
            looper.processAllMessages()
            updateStateToKeyguard()
            kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Communal)
            runCurrent()
            controller.updateCommunalAlphaTransition(transitionAlphaAmount)
            kosmos.fakeCommunalSceneRepository.snapToScene(CommunalScenes.Blank)
            runCurrent()
            Truth.assertThat(keyguardStatusBarView.getAlpha()).isNotEqualTo(transitionAlphaAmount)
        }

    /**
     * Calls [com.android.keyguard.KeyguardUpdateMonitorCallback.onFinishedGoingToSleep] to ensure
     * values are updated properly.
+5 −5
Original line number Diff line number Diff line
@@ -54,9 +54,7 @@ constructor(
                duration = TO_LOCKSCREEN_DURATION,
                edge = Edge.create(from = Scenes.Communal, to = LOCKSCREEN),
            )
            .setupWithoutSceneContainer(
                edge = Edge.create(from = GLANCEABLE_HUB, to = LOCKSCREEN),
            )
            .setupWithoutSceneContainer(edge = Edge.create(from = GLANCEABLE_HUB, to = LOCKSCREEN))

    val keyguardAlpha: Flow<Float> =
        transitionAnimation.sharedFlow(
@@ -75,7 +73,7 @@ constructor(
        configurationInteractor
            .directionalDimensionPixelSize(
                LayoutDirection.LTR,
                R.dimen.hub_to_lockscreen_transition_lockscreen_translation_x
                R.dimen.hub_to_lockscreen_transition_lockscreen_translation_x,
            )
            .flatMapLatest { translatePx: Int ->
                transitionAnimation.sharedFlowWithState(
@@ -87,7 +85,7 @@ constructor(
                    // is cancelled.
                    onFinish = { 0f },
                    onCancel = { 0f },
                    name = "GLANCEABLE_HUB->LOCKSCREEN: keyguardTranslationX"
                    name = "GLANCEABLE_HUB->LOCKSCREEN: keyguardTranslationX",
                )
            }

@@ -95,6 +93,8 @@ constructor(

    val shortcutsAlpha: Flow<Float> = keyguardAlpha

    val statusBarAlpha: Flow<Float> = keyguardAlpha

    val notificationTranslationX: Flow<Float> =
        keyguardTranslationX.map { it.value }.filterNotNull()
}
+5 −5
Original line number Diff line number Diff line
@@ -54,9 +54,7 @@ constructor(
                duration = FromLockscreenTransitionInteractor.TO_GLANCEABLE_HUB_DURATION,
                edge = Edge.create(from = LOCKSCREEN, to = Scenes.Communal),
            )
            .setupWithoutSceneContainer(
                edge = Edge.create(from = LOCKSCREEN, to = GLANCEABLE_HUB),
            )
            .setupWithoutSceneContainer(edge = Edge.create(from = LOCKSCREEN, to = GLANCEABLE_HUB))

    val keyguardAlpha: Flow<Float> =
        transitionAnimation.sharedFlow(
@@ -74,7 +72,7 @@ constructor(
        configurationInteractor
            .directionalDimensionPixelSize(
                LayoutDirection.LTR,
                R.dimen.lockscreen_to_hub_transition_lockscreen_translation_x
                R.dimen.lockscreen_to_hub_transition_lockscreen_translation_x,
            )
            .flatMapLatest { translatePx: Int ->
                transitionAnimation.sharedFlowWithState(
@@ -86,7 +84,7 @@ constructor(
                    onFinish = { 0f },
                    onCancel = { 0f },
                    interpolator = EMPHASIZED,
                    name = "LOCKSCREEN->GLANCEABLE_HUB: keyguardTranslationX"
                    name = "LOCKSCREEN->GLANCEABLE_HUB: keyguardTranslationX",
                )
            }

@@ -94,6 +92,8 @@ constructor(

    val shortcutsAlpha: Flow<Float> = keyguardAlpha

    val statusBarAlpha: Flow<Float> = keyguardAlpha

    val notificationTranslationX: Flow<Float> =
        keyguardTranslationX.map { it.value }.filterNotNull()
}
+44 −4
Original line number Diff line number Diff line
@@ -50,6 +50,8 @@ import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToLockscreenTransitionViewModel;
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToGlanceableHubTransitionViewModel;
import com.android.systemui.log.core.LogLevel;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
@@ -82,6 +84,8 @@ import com.android.systemui.util.settings.SecureSettings;

import kotlin.Unit;

import kotlinx.coroutines.CoroutineDispatcher;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -108,6 +112,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
            R.id.keyguard_hun_animator_end_tag,
            R.id.keyguard_hun_animator_start_tag);

    private final CoroutineDispatcher mCoroutineDispatcher;
    private final CarrierTextController mCarrierTextController;
    private final ConfigurationController mConfigurationController;
    private final SystemStatusAnimationScheduler mAnimationScheduler;
@@ -133,6 +138,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
    private final Object mLock = new Object();
    private final KeyguardLogger mLogger;
    private final CommunalSceneInteractor mCommunalSceneInteractor;
    private final GlanceableHubToLockscreenTransitionViewModel mHubToLockscreenTransitionViewModel;
    private final LockscreenToGlanceableHubTransitionViewModel mLockscreenToHubTransitionViewModel;

    private View mSystemIconsContainer;
    private final StatusOverlayHoverListenerFactory mStatusOverlayHoverListenerFactory;
@@ -249,9 +256,20 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
    private boolean mCommunalShowing;

    private final Consumer<Boolean> mCommunalConsumer = (communalShowing) -> {
        updateCommunalShowing(communalShowing);
    };

    @VisibleForTesting
    void updateCommunalShowing(boolean communalShowing) {
        mCommunalShowing = communalShowing;

        // When communal is hidden (either by transition or state change), set alpha to fully
        // visible.
        if (!mCommunalShowing) {
            setAlpha(-1f);
        }
        updateViewState();
    };
    }

    private final DisableStateTracker mDisableStateTracker;

@@ -277,6 +295,15 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
    private boolean mShowingKeyguardHeadsUp;
    private StatusBarSystemEventDefaultAnimator mSystemEventAnimator;
    private float mSystemEventAnimatorAlpha = 1;
    private final Consumer<Float> mToGlanceableHubStatusBarAlphaConsumer = (alpha) ->
            updateCommunalAlphaTransition(alpha);

    private final Consumer<Float> mFromGlanceableHubStatusBarAlphaConsumer = (alpha) ->
            updateCommunalAlphaTransition(alpha);

    @VisibleForTesting  void updateCommunalAlphaTransition(float alpha) {
        setAlpha(!mCommunalShowing || alpha == 0 ? -1 : alpha);
    }

    /**
     * The alpha value to be set on the View. If -1, this value is to be ignored.
@@ -285,6 +312,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat

    @Inject
    public KeyguardStatusBarViewController(
            @Main CoroutineDispatcher dispatcher,
            KeyguardStatusBarView view,
            CarrierTextController carrierTextController,
            ConfigurationController configurationController,
@@ -310,9 +338,14 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
            @Background Executor backgroundExecutor,
            KeyguardLogger logger,
            StatusOverlayHoverListenerFactory statusOverlayHoverListenerFactory,
            CommunalSceneInteractor communalSceneInteractor
            CommunalSceneInteractor communalSceneInteractor,
            GlanceableHubToLockscreenTransitionViewModel
                    glanceableHubToLockscreenTransitionViewModel,
            LockscreenToGlanceableHubTransitionViewModel
                    lockscreenToGlanceableHubTransitionViewModel
    ) {
        super(view);
        mCoroutineDispatcher = dispatcher;
        mCarrierTextController = carrierTextController;
        mConfigurationController = configurationController;
        mAnimationScheduler = animationScheduler;
@@ -337,6 +370,8 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
        mBackgroundExecutor = backgroundExecutor;
        mLogger = logger;
        mCommunalSceneInteractor = communalSceneInteractor;
        mHubToLockscreenTransitionViewModel = glanceableHubToLockscreenTransitionViewModel;
        mLockscreenToHubTransitionViewModel = lockscreenToGlanceableHubTransitionViewModel;

        mFirstBypassAttempt = mKeyguardBypassController.getBypassEnabled();
        mKeyguardStateController.addCallback(
@@ -418,7 +453,12 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
                UserHandle.USER_ALL);
        updateUserSwitcher();
        onThemeChanged();
        collectFlow(mView, mCommunalSceneInteractor.isCommunalVisible(), mCommunalConsumer);
        collectFlow(mView, mCommunalSceneInteractor.isCommunalVisible(), mCommunalConsumer,
                mCoroutineDispatcher);
        collectFlow(mView, mLockscreenToHubTransitionViewModel.getStatusBarAlpha(),
                mToGlanceableHubStatusBarAlphaConsumer, mCoroutineDispatcher);
        collectFlow(mView, mHubToLockscreenTransitionViewModel.getStatusBarAlpha(),
                mFromGlanceableHubStatusBarAlphaConsumer, mCoroutineDispatcher);
    }

    @Override
@@ -573,7 +613,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat
                        && !mDozing
                        && !hideForBypass
                        && !mDisableStateTracker.isDisabled()
                        && !mCommunalShowing
                        && (!mCommunalShowing || mExplicitAlpha != -1)
                        ? View.VISIBLE : View.INVISIBLE;

        updateViewState(newAlpha, newVisibility);
+35 −75

File changed.

Preview size limit exceeded, changes collapsed.

Loading