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

Commit 9ecc6277 authored by Darrell Shi's avatar Darrell Shi
Browse files

Dream IN blur + complications fade-in animations.

This change implements the following dream IN animations
- un-blur dream content shortly after dream started fading in
- fade in top complications and status bar, and then bottom
  complications separately

Test: verified on device
Test: atest ComplicationHostViewControllerTest
Test: atest DreamOverlayStateControllerTest
Test: atest DreamOverlayContainerViewControllerTest
Test: atest DreamOverlayStatusBarViewControllerTest
Test: atest DreamOverlayServiceTest
Bug: 222507937
Change-Id: Ia641bf42fe15103953981e43f06fe12ebb518d74
parent c849d793
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/dream_overlay_status_bar"
    android:id="@+id/dream_overlay_status_bar"
    android:visibility="invisible"
    android:layout_width="match_parent"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dream_overlay_status_bar_height"
    android:layout_height="@dimen/dream_overlay_status_bar_height"
    android:paddingEnd="@dimen/dream_overlay_status_bar_margin"
    android:paddingEnd="@dimen/dream_overlay_status_bar_margin"
+11 −0
Original line number Original line Diff line number Diff line
@@ -743,6 +743,17 @@


    <integer name="complicationRestoreMs">1000</integer>
    <integer name="complicationRestoreMs">1000</integer>


    <!-- Duration in milliseconds of the dream in un-blur animation. -->
    <integer name="config_dreamOverlayInBlurDurationMs">249</integer>
    <!-- Delay in milliseconds of the dream in un-blur animation. -->
    <integer name="config_dreamOverlayInBlurDelayMs">133</integer>
    <!-- Duration in milliseconds of the dream in complications fade-in animation. -->
    <integer name="config_dreamOverlayInComplicationsDurationMs">282</integer>
    <!-- Delay in milliseconds of the dream in top complications fade-in animation. -->
    <integer name="config_dreamOverlayInTopComplicationsDelayMs">216</integer>
    <!-- Delay in milliseconds of the dream in bottom complications fade-in animation. -->
    <integer name="config_dreamOverlayInBottomComplicationsDelayMs">299</integer>

    <!-- Icons that don't show in a collapsed non-keyguard statusbar -->
    <!-- Icons that don't show in a collapsed non-keyguard statusbar -->
    <string-array name="config_collapsed_statusbar_icon_blocklist" translatable="false">
    <string-array name="config_collapsed_statusbar_icon_blocklist" translatable="false">
        <item>@*android:string/status_bar_volume</item>
        <item>@*android:string/status_bar_volume</item>
+147 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.dreams

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.view.View
import androidx.core.animation.doOnEnd
import com.android.systemui.animation.Interpolators
import com.android.systemui.dreams.complication.ComplicationHostViewController
import com.android.systemui.dreams.complication.ComplicationLayoutParams
import com.android.systemui.dreams.dagger.DreamOverlayModule
import com.android.systemui.statusbar.BlurUtils
import java.util.function.Consumer
import javax.inject.Inject
import javax.inject.Named

/** Controller for dream overlay animations. */
class DreamOverlayAnimationsController
@Inject
constructor(
    private val mBlurUtils: BlurUtils,
    private val mComplicationHostViewController: ComplicationHostViewController,
    private val mStatusBarViewController: DreamOverlayStatusBarViewController,
    private val mOverlayStateController: DreamOverlayStateController,
    @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION)
    private val mDreamInBlurAnimDuration: Int,
    @Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DELAY) private val mDreamInBlurAnimDelay: Int,
    @Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
    private val mDreamInComplicationsAnimDuration: Int,
    @Named(DreamOverlayModule.DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
    private val mDreamInTopComplicationsAnimDelay: Int,
    @Named(DreamOverlayModule.DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
    private val mDreamInBottomComplicationsAnimDelay: Int
) {

    var mEntryAnimations: AnimatorSet? = null

    /** Starts the dream content and dream overlay entry animations. */
    fun startEntryAnimations(view: View) {
        cancelRunningEntryAnimations()

        mEntryAnimations = AnimatorSet()
        mEntryAnimations?.apply {
            playTogether(
                buildDreamInBlurAnimator(view),
                buildDreamInTopComplicationsAnimator(),
                buildDreamInBottomComplicationsAnimator()
            )
            doOnEnd { mOverlayStateController.setEntryAnimationsFinished(true) }
            start()
        }
    }

    /** Cancels the dream content and dream overlay animations, if they're currently running. */
    fun cancelRunningEntryAnimations() {
        if (mEntryAnimations?.isRunning == true) {
            mEntryAnimations?.cancel()
        }
        mEntryAnimations = null
    }

    private fun buildDreamInBlurAnimator(view: View): Animator {
        return ValueAnimator.ofFloat(1f, 0f).apply {
            duration = mDreamInBlurAnimDuration.toLong()
            startDelay = mDreamInBlurAnimDelay.toLong()
            interpolator = Interpolators.LINEAR
            addUpdateListener { animator: ValueAnimator ->
                mBlurUtils.applyBlur(
                    view.viewRootImpl,
                    mBlurUtils.blurRadiusOfRatio(animator.animatedValue as Float).toInt(),
                    false /*opaque*/
                )
            }
        }
    }

    private fun buildDreamInTopComplicationsAnimator(): Animator {
        return ValueAnimator.ofFloat(0f, 1f).apply {
            duration = mDreamInComplicationsAnimDuration.toLong()
            startDelay = mDreamInTopComplicationsAnimDelay.toLong()
            interpolator = Interpolators.LINEAR
            addUpdateListener { va: ValueAnimator ->
                setTopElementsAlpha(va.animatedValue as Float)
            }
        }
    }

    private fun buildDreamInBottomComplicationsAnimator(): Animator {
        return ValueAnimator.ofFloat(0f, 1f).apply {
            duration = mDreamInComplicationsAnimDuration.toLong()
            startDelay = mDreamInBottomComplicationsAnimDelay.toLong()
            interpolator = Interpolators.LINEAR
            addUpdateListener { va: ValueAnimator ->
                setBottomElementsAlpha(va.animatedValue as Float)
            }
            addListener(
                object : AnimatorListenerAdapter() {
                    override fun onAnimationStart(animation: Animator) {
                        mComplicationHostViewController
                            .getViewsAtPosition(ComplicationLayoutParams.POSITION_BOTTOM)
                            .forEach(Consumer { v: View -> v.visibility = View.VISIBLE })
                    }
                }
            )
        }
    }

    /** Sets alpha of top complications and the status bar. */
    private fun setTopElementsAlpha(alpha: Float) {
        mComplicationHostViewController
            .getViewsAtPosition(ComplicationLayoutParams.POSITION_TOP)
            .forEach(Consumer { v: View -> setAlphaAndEnsureVisible(v, alpha) })
        mStatusBarViewController.setAlpha(alpha)
    }

    /** Sets alpha of bottom complications. */
    private fun setBottomElementsAlpha(alpha: Float) {
        mComplicationHostViewController
            .getViewsAtPosition(ComplicationLayoutParams.POSITION_BOTTOM)
            .forEach(Consumer { v: View -> setAlphaAndEnsureVisible(v, alpha) })
    }

    private fun setAlphaAndEnsureVisible(view: View, alpha: Float) {
        if (alpha > 0 && view.visibility != View.VISIBLE) {
            view.visibility = View.VISIBLE
        }

        view.alpha = alpha
    }
}
+14 −1
Original line number Original line Diff line number Diff line
@@ -54,6 +54,8 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
    private final DreamOverlayStatusBarViewController mStatusBarViewController;
    private final DreamOverlayStatusBarViewController mStatusBarViewController;
    private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
    private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
    private final BlurUtils mBlurUtils;
    private final BlurUtils mBlurUtils;
    private final DreamOverlayAnimationsController mDreamOverlayAnimationsController;
    private final DreamOverlayStateController mStateController;


    private final ComplicationHostViewController mComplicationHostViewController;
    private final ComplicationHostViewController mComplicationHostViewController;


@@ -134,12 +136,16 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
            @Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
            @Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
                    burnInProtectionUpdateInterval,
                    burnInProtectionUpdateInterval,
            @Named(DreamOverlayModule.MILLIS_UNTIL_FULL_JITTER) long millisUntilFullJitter,
            @Named(DreamOverlayModule.MILLIS_UNTIL_FULL_JITTER) long millisUntilFullJitter,
            BouncerCallbackInteractor bouncerCallbackInteractor) {
            BouncerCallbackInteractor bouncerCallbackInteractor,
            DreamOverlayAnimationsController animationsController,
            DreamOverlayStateController stateController) {
        super(containerView);
        super(containerView);
        mDreamOverlayContentView = contentView;
        mDreamOverlayContentView = contentView;
        mStatusBarViewController = statusBarViewController;
        mStatusBarViewController = statusBarViewController;
        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
        mBlurUtils = blurUtils;
        mBlurUtils = blurUtils;
        mDreamOverlayAnimationsController = animationsController;
        mStateController = stateController;


        mComplicationHostViewController = complicationHostViewController;
        mComplicationHostViewController = complicationHostViewController;
        mDreamOverlayMaxTranslationY = resources.getDimensionPixelSize(
        mDreamOverlayMaxTranslationY = resources.getDimensionPixelSize(
@@ -172,6 +178,11 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
            bouncer.addBouncerExpansionCallback(mBouncerExpansionCallback);
            bouncer.addBouncerExpansionCallback(mBouncerExpansionCallback);
        }
        }
        mBouncerCallbackInteractor.addBouncerExpansionCallback(mBouncerExpansionCallback);
        mBouncerCallbackInteractor.addBouncerExpansionCallback(mBouncerExpansionCallback);

        // Start dream entry animations. Skip animations for low light clock.
        if (!mStateController.isLowLightActive()) {
            mDreamOverlayAnimationsController.startEntryAnimations(mView);
        }
    }
    }


    @Override
    @Override
@@ -182,6 +193,8 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
            bouncer.removeBouncerExpansionCallback(mBouncerExpansionCallback);
            bouncer.removeBouncerExpansionCallback(mBouncerExpansionCallback);
        }
        }
        mBouncerCallbackInteractor.removeBouncerExpansionCallback(mBouncerExpansionCallback);
        mBouncerCallbackInteractor.removeBouncerExpansionCallback(mBouncerExpansionCallback);

        mDreamOverlayAnimationsController.cancelRunningEntryAnimations();
    }
    }


    View getContainerView() {
    View getContainerView() {
+1 −0
Original line number Original line Diff line number Diff line
@@ -257,6 +257,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ


        mStateController.setOverlayActive(false);
        mStateController.setOverlayActive(false);
        mStateController.setLowLightActive(false);
        mStateController.setLowLightActive(false);
        mStateController.setEntryAnimationsFinished(false);


        mDreamOverlayContainerViewController = null;
        mDreamOverlayContainerViewController = null;
        mDreamOverlayTouchMonitor = null;
        mDreamOverlayTouchMonitor = null;
Loading