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

Commit 0876cbf5 authored by Lucas Silva's avatar Lucas Silva Committed by Automerger Merge Worker
Browse files

Merge "Implement dream to bouncer animation." into tm-dev am: 7dc1b2d6

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17138853

Change-Id: Iea77ed40e7d8db06449d9f235faaf8147778e8a1
parents 7678f534 7dc1b2d6
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.complication.ComplicationHostViewController;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.dreams.dagger.DreamOverlayModule;
import com.android.systemui.statusbar.BlurUtils;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.util.ViewController;

import javax.inject.Inject;
@@ -38,6 +41,8 @@ import javax.inject.Named;
@DreamOverlayComponent.DreamOverlayScope
public class DreamOverlayContainerViewController extends ViewController<DreamOverlayContainerView> {
    private final DreamOverlayStatusBarViewController mStatusBarViewController;
    private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
    private final BlurUtils mBlurUtils;

    private final ComplicationHostViewController mComplicationHostViewController;

@@ -60,12 +65,57 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve

    private long mJitterStartTimeMillis;

    private boolean mBouncerAnimating;

    private final KeyguardBouncer.BouncerExpansionCallback mBouncerExpansionCallback =
            new KeyguardBouncer.BouncerExpansionCallback() {

                @Override
                public void onStartingToShow() {
                    mBouncerAnimating = true;
                }

                @Override
                public void onStartingToHide() {
                    mBouncerAnimating = true;
                }

                @Override
                public void onFullyHidden() {
                    mBouncerAnimating = false;
                }

                @Override
                public void onFullyShown() {
                    mBouncerAnimating = false;
                }

                @Override
                public void onExpansionChanged(float bouncerHideAmount) {
                    if (!mBouncerAnimating) return;
                    final int blurRadius =
                            (int) mBlurUtils.blurRadiusOfRatio(1 - bouncerHideAmount);
                    updateTransitionState(blurRadius, bouncerHideAmount);
                }

                @Override
                public void onVisibilityChanged(boolean isVisible) {
                    // The bouncer may be hidden abruptly without triggering onExpansionChanged.
                    // In this case, we should reset the transition state.
                    if (!isVisible) {
                        updateTransitionState(0, 1f);
                    }
                }
            };

    @Inject
    public DreamOverlayContainerViewController(
            DreamOverlayContainerView containerView,
            ComplicationHostViewController complicationHostViewController,
            @Named(DreamOverlayModule.DREAM_OVERLAY_CONTENT_VIEW) ViewGroup contentView,
            DreamOverlayStatusBarViewController statusBarViewController,
            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
            BlurUtils blurUtils,
            @Main Handler handler,
            @Named(DreamOverlayModule.MAX_BURN_IN_OFFSET) int maxBurnInOffset,
            @Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
@@ -74,6 +124,8 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
        super(containerView);
        mDreamOverlayContentView = contentView;
        mStatusBarViewController = statusBarViewController;
        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
        mBlurUtils = blurUtils;

        mComplicationHostViewController = complicationHostViewController;
        final View view = mComplicationHostViewController.getView();
@@ -98,11 +150,19 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
    protected void onViewAttached() {
        mJitterStartTimeMillis = System.currentTimeMillis();
        mHandler.postDelayed(this::updateBurnInOffsets, mBurnInProtectionUpdateInterval);
        final KeyguardBouncer bouncer = mStatusBarKeyguardViewManager.getBouncer();
        if (bouncer != null) {
            bouncer.addBouncerExpansionCallback(mBouncerExpansionCallback);
        }
    }

    @Override
    protected void onViewDetached() {
        mHandler.removeCallbacks(this::updateBurnInOffsets);
        final KeyguardBouncer bouncer = mStatusBarKeyguardViewManager.getBouncer();
        if (bouncer != null) {
            bouncer.removeBouncerExpansionCallback(mBouncerExpansionCallback);
        }
    }

    View getContainerView() {
@@ -131,4 +191,9 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve

        mHandler.postDelayed(this::updateBurnInOffsets, mBurnInProtectionUpdateInterval);
    }

    private void updateTransitionState(int blurRadiusPixels, float alpha) {
        mBlurUtils.applyBlur(mView.getViewRootImpl(), blurRadiusPixels, false);
        mView.setAlpha(alpha);
    }
}
+40 −4
Original line number Diff line number Diff line
@@ -606,11 +606,47 @@ public class KeyguardBouncer {
        mResetCallbacks.remove(callback);
    }

    /**
     * Adds a callback to listen to bouncer expansion updates.
     */
    public void addBouncerExpansionCallback(BouncerExpansionCallback callback) {
        if (!mExpansionCallbacks.contains(callback)) {
            mExpansionCallbacks.add(callback);
        }
    }

    /**
     * Removes a previously added callback. If the callback was never added, this methood
     * does nothing.
     */
    public void removeBouncerExpansionCallback(BouncerExpansionCallback callback) {
        mExpansionCallbacks.remove(callback);
    }

    public interface BouncerExpansionCallback {
        void onFullyShown();
        void onStartingToHide();
        void onStartingToShow();
        void onFullyHidden();
        /**
         * Invoked when the bouncer expansion reaches {@link KeyguardBouncer#EXPANSION_VISIBLE}.
         */
        default void onFullyShown() {
        }

        /**
         * Invoked when the bouncer is starting to transition to a hidden state.
         */
        default void onStartingToHide() {
        }

        /**
         * Invoked when the bouncer is starting to transition to a visible state.
         */
        default void onStartingToShow() {
        }

        /**
         * Invoked when the bouncer expansion reaches {@link KeyguardBouncer#EXPANSION_HIDDEN}.
         */
        default void onFullyHidden() {
        }

        /**
         * From 0f {@link KeyguardBouncer#EXPANSION_VISIBLE} when fully visible
+54 −0
Original line number Diff line number Diff line
@@ -17,7 +17,10 @@
package com.android.systemui.dreams;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@@ -25,12 +28,17 @@ import android.content.res.Resources;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;

import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.complication.ComplicationHostViewController;
import com.android.systemui.statusbar.BlurUtils;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;

import org.junit.Before;
import org.junit.Test;
@@ -67,6 +75,18 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
    @Mock
    Handler mHandler;

    @Mock
    BlurUtils mBlurUtils;

    @Mock
    StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;

    @Mock
    KeyguardBouncer mBouncer;

    @Mock
    ViewRootImpl mViewRoot;

    DreamOverlayContainerViewController mController;

    @Before
@@ -75,12 +95,16 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {

        when(mDreamOverlayContainerView.getResources()).thenReturn(mResources);
        when(mDreamOverlayContainerView.getViewTreeObserver()).thenReturn(mViewTreeObserver);
        when(mStatusBarKeyguardViewManager.getBouncer()).thenReturn(mBouncer);
        when(mDreamOverlayContainerView.getViewRootImpl()).thenReturn(mViewRoot);

        mController = new DreamOverlayContainerViewController(
                mDreamOverlayContainerView,
                mComplicationHostViewController,
                mDreamOverlayContentView,
                mDreamOverlayStatusBarViewController,
                mStatusBarKeyguardViewManager,
                mBlurUtils,
                mHandler,
                MAX_BURN_IN_OFFSET,
                BURN_IN_PROTECTION_UPDATE_INTERVAL,
@@ -125,4 +149,34 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
        runnableCaptor.getValue().run();
        verify(mHandler).postDelayed(runnableCaptor.getValue(), BURN_IN_PROTECTION_UPDATE_INTERVAL);
    }

    @Test
    public void testBouncerAnimation_doesNotApply() {
        final ArgumentCaptor<BouncerExpansionCallback> bouncerExpansionCaptor =
                ArgumentCaptor.forClass(BouncerExpansionCallback.class);
        mController.onViewAttached();
        verify(mBouncer).addBouncerExpansionCallback(bouncerExpansionCaptor.capture());

        bouncerExpansionCaptor.getValue().onExpansionChanged(0.5f);
        verify(mBlurUtils, never()).applyBlur(eq(mViewRoot), anyInt(), eq(false));
        verify(mDreamOverlayContainerView, never()).setAlpha(anyFloat());
    }

    @Test
    public void testBouncerAnimation_updateBlurAndAlpha() {
        final ArgumentCaptor<BouncerExpansionCallback> bouncerExpansionCaptor =
                ArgumentCaptor.forClass(BouncerExpansionCallback.class);
        mController.onViewAttached();
        verify(mBouncer).addBouncerExpansionCallback(bouncerExpansionCaptor.capture());

        final float blurRadius = 1337f;
        when(mBlurUtils.blurRadiusOfRatio(anyFloat())).thenReturn(blurRadius);

        bouncerExpansionCaptor.getValue().onStartingToShow();
        final float bouncerHideAmount = 0.1f;
        bouncerExpansionCaptor.getValue().onExpansionChanged(bouncerHideAmount);
        verify(mBlurUtils).blurRadiusOfRatio(1 - bouncerHideAmount);
        verify(mBlurUtils).applyBlur(mViewRoot, (int) blurRadius, false);
        verify(mDreamOverlayContainerView).setAlpha(bouncerHideAmount);
    }
}
+45 −5
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.systemui.statusbar.phone;

import static com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_HIDDEN;
import static com.android.systemui.statusbar.phone.KeyguardBouncer.EXPANSION_VISIBLE;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
@@ -24,9 +27,11 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -53,6 +58,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
import com.android.systemui.statusbar.policy.KeyguardStateController;

import org.junit.Assert;
@@ -62,6 +68,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

@@ -79,7 +86,7 @@ public class KeyguardBouncerTest extends SysuiTestCase {
    @Mock
    private KeyguardHostViewController mKeyguardHostViewController;
    @Mock
    private KeyguardBouncer.BouncerExpansionCallback mExpansionCallback;
    private BouncerExpansionCallback mExpansionCallback;
    @Mock
    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    @Mock
@@ -197,11 +204,11 @@ public class KeyguardBouncerTest extends SysuiTestCase {
        mBouncer.ensureView();
        mBouncer.setExpansion(0.5f);

        mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
        mBouncer.setExpansion(EXPANSION_HIDDEN);
        verify(mFalsingCollector).onBouncerHidden();
        verify(mExpansionCallback).onFullyHidden();

        mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
        mBouncer.setExpansion(EXPANSION_VISIBLE);
        verify(mFalsingCollector).onBouncerShown();
        verify(mExpansionCallback).onFullyShown();

@@ -410,11 +417,11 @@ public class KeyguardBouncerTest extends SysuiTestCase {
    @Test
    public void testInTransit_whenTranslation() {
        mBouncer.show(true);
        mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
        mBouncer.setExpansion(EXPANSION_HIDDEN);
        assertThat(mBouncer.inTransit()).isFalse();
        mBouncer.setExpansion(0.5f);
        assertThat(mBouncer.inTransit()).isTrue();
        mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
        mBouncer.setExpansion(EXPANSION_VISIBLE);
        assertThat(mBouncer.inTransit()).isFalse();
    }

@@ -435,4 +442,37 @@ public class KeyguardBouncerTest extends SysuiTestCase {

        verify(mKeyguardHostViewController).updateKeyguardPosition(1.0f);
    }

    @Test
    public void testExpansion_notifiesCallback() {
        mBouncer.ensureView();
        mBouncer.setExpansion(0.5f);

        final BouncerExpansionCallback callback = mock(BouncerExpansionCallback.class);
        mBouncer.addBouncerExpansionCallback(callback);

        mBouncer.setExpansion(EXPANSION_HIDDEN);
        verify(callback).onFullyHidden();
        verify(callback).onExpansionChanged(EXPANSION_HIDDEN);

        Mockito.clearInvocations(callback);
        mBouncer.setExpansion(EXPANSION_VISIBLE);
        verify(callback).onFullyShown();
        verify(callback).onExpansionChanged(EXPANSION_VISIBLE);

        Mockito.clearInvocations(callback);
        float bouncerHideAmount = 0.9f;
        // Ensure the callback only triggers once despite multiple calls to setExpansion
        // with the same value.
        mBouncer.setExpansion(bouncerHideAmount);
        mBouncer.setExpansion(bouncerHideAmount);
        verify(callback, times(1)).onStartingToHide();
        verify(callback, times(1)).onExpansionChanged(bouncerHideAmount);

        Mockito.clearInvocations(callback);
        mBouncer.removeBouncerExpansionCallback(callback);
        bouncerHideAmount = 0.5f;
        mBouncer.setExpansion(bouncerHideAmount);
        verify(callback, never()).onExpansionChanged(bouncerHideAmount);
    }
}