Merge "Implement dream out overlay transition" into tm-qpr-dev
This commit is contained in:
@@ -49,6 +49,17 @@ public abstract class DreamOverlayService extends Service {
|
|||||||
mShowComplications = shouldShowComplications;
|
mShowComplications = shouldShowComplications;
|
||||||
onStartDream(layoutParams);
|
onStartDream(layoutParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wakeUp() {
|
||||||
|
onWakeUp(() -> {
|
||||||
|
try {
|
||||||
|
mDreamOverlayCallback.onWakeUpComplete();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Could not notify dream of wakeUp:" + e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IDreamOverlayCallback mDreamOverlayCallback;
|
IDreamOverlayCallback mDreamOverlayCallback;
|
||||||
@@ -70,6 +81,17 @@ public abstract class DreamOverlayService extends Service {
|
|||||||
*/
|
*/
|
||||||
public abstract void onStartDream(@NonNull WindowManager.LayoutParams layoutParams);
|
public abstract void onStartDream(@NonNull WindowManager.LayoutParams layoutParams);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is overridden by implementations to handle when the dream has been requested
|
||||||
|
* to wakeup. This allows any overlay animations to run.
|
||||||
|
*
|
||||||
|
* @param onCompleteCallback The callback to trigger to notify the dream service that the
|
||||||
|
* overlay has completed waking up.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void onWakeUp(@NonNull Runnable onCompleteCallback) {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is invoked to request the dream exit.
|
* This method is invoked to request the dream exit.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -312,7 +312,14 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
@Override
|
@Override
|
||||||
public void onExitRequested() {
|
public void onExitRequested() {
|
||||||
// Simply finish dream when exit is requested.
|
// Simply finish dream when exit is requested.
|
||||||
finish();
|
mHandler.post(() -> finish());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWakeUpComplete() {
|
||||||
|
// Finish the dream once overlay animations are complete. Execute on handler since
|
||||||
|
// this is coming in on the overlay binder.
|
||||||
|
mHandler.post(() -> finish());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -975,7 +982,18 @@ public class DreamService extends Service implements Window.Callback {
|
|||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public void onWakeUp() {
|
public void onWakeUp() {
|
||||||
finish();
|
if (mOverlayConnection != null) {
|
||||||
|
mOverlayConnection.addConsumer(overlay -> {
|
||||||
|
try {
|
||||||
|
overlay.wakeUp();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Error waking the overlay service", e);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
|
|||||||
@@ -38,4 +38,7 @@ interface IDreamOverlay {
|
|||||||
*/
|
*/
|
||||||
void startDream(in LayoutParams params, in IDreamOverlayCallback callback,
|
void startDream(in LayoutParams params, in IDreamOverlayCallback callback,
|
||||||
in String dreamComponent, in boolean shouldShowComplications);
|
in String dreamComponent, in boolean shouldShowComplications);
|
||||||
|
|
||||||
|
/** Called when the dream is waking, to do any exit animations */
|
||||||
|
void wakeUp();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,4 +28,7 @@ interface IDreamOverlayCallback {
|
|||||||
* Invoked to request the dream exit.
|
* Invoked to request the dream exit.
|
||||||
*/
|
*/
|
||||||
void onExitRequested();
|
void onExitRequested();
|
||||||
|
|
||||||
|
/** Invoked when the dream overlay wakeUp animation is complete. */
|
||||||
|
void onWakeUpComplete();
|
||||||
}
|
}
|
||||||
@@ -2485,7 +2485,7 @@
|
|||||||
<!-- The duration in milliseconds of the dream opening animation. -->
|
<!-- The duration in milliseconds of the dream opening animation. -->
|
||||||
<integer name="config_dreamOpenAnimationDuration">250</integer>
|
<integer name="config_dreamOpenAnimationDuration">250</integer>
|
||||||
<!-- The duration in milliseconds of the dream closing animation. -->
|
<!-- The duration in milliseconds of the dream closing animation. -->
|
||||||
<integer name="config_dreamCloseAnimationDuration">100</integer>
|
<integer name="config_dreamCloseAnimationDuration">300</integer>
|
||||||
|
|
||||||
<!-- Whether to dismiss the active dream when an activity is started. Doesn't apply to
|
<!-- Whether to dismiss the active dream when an activity is started. Doesn't apply to
|
||||||
assistant activities (ACTIVITY_TYPE_ASSISTANT) -->
|
assistant activities (ACTIVITY_TYPE_ASSISTANT) -->
|
||||||
|
|||||||
@@ -743,12 +743,35 @@
|
|||||||
<!-- How long in milliseconds before full burn-in protection is achieved. -->
|
<!-- How long in milliseconds before full burn-in protection is achieved. -->
|
||||||
<integer name="config_dreamOverlayMillisUntilFullJitter">240000</integer>
|
<integer name="config_dreamOverlayMillisUntilFullJitter">240000</integer>
|
||||||
|
|
||||||
|
<!-- The duration in milliseconds of the y-translation animation when waking up from
|
||||||
|
the dream -->
|
||||||
|
<integer name="config_dreamOverlayOutTranslationYDurationMs">333</integer>
|
||||||
|
<!-- The delay in milliseconds of the y-translation animation when waking up from
|
||||||
|
the dream for the complications at the bottom of the screen -->
|
||||||
|
<integer name="config_dreamOverlayOutTranslationYDelayBottomMs">33</integer>
|
||||||
|
<!-- The delay in milliseconds of the y-translation animation when waking up from
|
||||||
|
the dream for the complications at the top of the screen -->
|
||||||
|
<integer name="config_dreamOverlayOutTranslationYDelayTopMs">117</integer>
|
||||||
|
<!-- The duration in milliseconds of the alpha animation when waking up from the dream -->
|
||||||
|
<integer name="config_dreamOverlayOutAlphaDurationMs">200</integer>
|
||||||
|
<!-- The delay in milliseconds of the alpha animation when waking up from the dream for the
|
||||||
|
complications at the top of the screen -->
|
||||||
|
<integer name="config_dreamOverlayOutAlphaDelayTopMs">217</integer>
|
||||||
|
<!-- The delay in milliseconds of the alpha animation when waking up from the dream for the
|
||||||
|
complications at the bottom of the screen -->
|
||||||
|
<integer name="config_dreamOverlayOutAlphaDelayBottomMs">133</integer>
|
||||||
|
<!-- The duration in milliseconds of the blur animation when waking up from
|
||||||
|
the dream -->
|
||||||
|
<integer name="config_dreamOverlayOutBlurDurationMs">250</integer>
|
||||||
|
|
||||||
<integer name="complicationFadeOutMs">500</integer>
|
<integer name="complicationFadeOutMs">500</integer>
|
||||||
|
|
||||||
<integer name="complicationFadeInMs">500</integer>
|
<integer name="complicationFadeInMs">500</integer>
|
||||||
|
|
||||||
<integer name="complicationRestoreMs">1000</integer>
|
<integer name="complicationRestoreMs">1000</integer>
|
||||||
|
|
||||||
|
<integer name="complicationFadeOutDelayMs">200</integer>
|
||||||
|
|
||||||
<!-- Duration in milliseconds of the dream in un-blur animation. -->
|
<!-- Duration in milliseconds of the dream in un-blur animation. -->
|
||||||
<integer name="config_dreamOverlayInBlurDurationMs">249</integer>
|
<integer name="config_dreamOverlayInBlurDurationMs">249</integer>
|
||||||
<!-- Delay in milliseconds of the dream in un-blur animation. -->
|
<!-- Delay in milliseconds of the dream in un-blur animation. -->
|
||||||
@@ -780,27 +803,6 @@
|
|||||||
<item>com.android.systemui</item>
|
<item>com.android.systemui</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<!-- The thresholds which determine the color used by the AQI dream overlay.
|
|
||||||
NOTE: This must always be kept sorted from low to high -->
|
|
||||||
<integer-array name="config_dreamAqiThresholds">
|
|
||||||
<item>-1</item>
|
|
||||||
<item>50</item>
|
|
||||||
<item>100</item>
|
|
||||||
<item>150</item>
|
|
||||||
<item>200</item>
|
|
||||||
<item>300</item>
|
|
||||||
</integer-array>
|
|
||||||
|
|
||||||
<!-- The color values which correspond to the thresholds above -->
|
|
||||||
<integer-array name="config_dreamAqiColorValues">
|
|
||||||
<item>@color/dream_overlay_aqi_good</item>
|
|
||||||
<item>@color/dream_overlay_aqi_moderate</item>
|
|
||||||
<item>@color/dream_overlay_aqi_unhealthy_sensitive</item>
|
|
||||||
<item>@color/dream_overlay_aqi_unhealthy</item>
|
|
||||||
<item>@color/dream_overlay_aqi_very_unhealthy</item>
|
|
||||||
<item>@color/dream_overlay_aqi_hazardous</item>
|
|
||||||
</integer-array>
|
|
||||||
|
|
||||||
<!-- Whether the device should display hotspot UI. If true, UI will display only when tethering
|
<!-- Whether the device should display hotspot UI. If true, UI will display only when tethering
|
||||||
is available. If false, UI will never show regardless of tethering availability" -->
|
is available. If false, UI will never show regardless of tethering availability" -->
|
||||||
<bool name="config_show_wifi_tethering">true</bool>
|
<bool name="config_show_wifi_tethering">true</bool>
|
||||||
|
|||||||
@@ -1534,6 +1534,7 @@
|
|||||||
<dimen name="dream_overlay_complication_margin">0dp</dimen>
|
<dimen name="dream_overlay_complication_margin">0dp</dimen>
|
||||||
|
|
||||||
<dimen name="dream_overlay_y_offset">80dp</dimen>
|
<dimen name="dream_overlay_y_offset">80dp</dimen>
|
||||||
|
<dimen name="dream_overlay_exit_y_offset">40dp</dimen>
|
||||||
|
|
||||||
<dimen name="dream_aqi_badge_corner_radius">28dp</dimen>
|
<dimen name="dream_aqi_badge_corner_radius">28dp</dimen>
|
||||||
<dimen name="dream_aqi_badge_padding_vertical">6dp</dimen>
|
<dimen name="dream_aqi_badge_padding_vertical">6dp</dimen>
|
||||||
|
|||||||
@@ -17,17 +17,19 @@
|
|||||||
package com.android.systemui.dreams
|
package com.android.systemui.dreams
|
||||||
|
|
||||||
import android.animation.Animator
|
import android.animation.Animator
|
||||||
import android.animation.AnimatorListenerAdapter
|
|
||||||
import android.animation.AnimatorSet
|
import android.animation.AnimatorSet
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.animation.Interpolator
|
||||||
|
import androidx.annotation.FloatRange
|
||||||
import androidx.core.animation.doOnEnd
|
import androidx.core.animation.doOnEnd
|
||||||
import com.android.systemui.animation.Interpolators
|
import com.android.systemui.animation.Interpolators
|
||||||
import com.android.systemui.dreams.complication.ComplicationHostViewController
|
import com.android.systemui.dreams.complication.ComplicationHostViewController
|
||||||
import com.android.systemui.dreams.complication.ComplicationLayoutParams
|
import com.android.systemui.dreams.complication.ComplicationLayoutParams
|
||||||
|
import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position
|
||||||
import com.android.systemui.dreams.dagger.DreamOverlayModule
|
import com.android.systemui.dreams.dagger.DreamOverlayModule
|
||||||
import com.android.systemui.statusbar.BlurUtils
|
import com.android.systemui.statusbar.BlurUtils
|
||||||
import java.util.function.Consumer
|
import com.android.systemui.statusbar.CrossFadeHelper
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Named
|
import javax.inject.Named
|
||||||
|
|
||||||
@@ -40,108 +42,239 @@ constructor(
|
|||||||
private val mStatusBarViewController: DreamOverlayStatusBarViewController,
|
private val mStatusBarViewController: DreamOverlayStatusBarViewController,
|
||||||
private val mOverlayStateController: DreamOverlayStateController,
|
private val mOverlayStateController: DreamOverlayStateController,
|
||||||
@Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION)
|
@Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DURATION)
|
||||||
private val mDreamInBlurAnimDuration: Int,
|
private val mDreamInBlurAnimDurationMs: Long,
|
||||||
@Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DELAY) private val mDreamInBlurAnimDelay: Int,
|
@Named(DreamOverlayModule.DREAM_IN_BLUR_ANIMATION_DELAY)
|
||||||
|
private val mDreamInBlurAnimDelayMs: Long,
|
||||||
@Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
|
@Named(DreamOverlayModule.DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
|
||||||
private val mDreamInComplicationsAnimDuration: Int,
|
private val mDreamInComplicationsAnimDurationMs: Long,
|
||||||
@Named(DreamOverlayModule.DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
|
@Named(DreamOverlayModule.DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
|
||||||
private val mDreamInTopComplicationsAnimDelay: Int,
|
private val mDreamInTopComplicationsAnimDelayMs: Long,
|
||||||
@Named(DreamOverlayModule.DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
|
@Named(DreamOverlayModule.DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
|
||||||
private val mDreamInBottomComplicationsAnimDelay: Int
|
private val mDreamInBottomComplicationsAnimDelayMs: Long,
|
||||||
|
@Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DISTANCE)
|
||||||
|
private val mDreamOutTranslationYDistance: Int,
|
||||||
|
@Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DURATION)
|
||||||
|
private val mDreamOutTranslationYDurationMs: Long,
|
||||||
|
@Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM)
|
||||||
|
private val mDreamOutTranslationYDelayBottomMs: Long,
|
||||||
|
@Named(DreamOverlayModule.DREAM_OUT_TRANSLATION_Y_DELAY_TOP)
|
||||||
|
private val mDreamOutTranslationYDelayTopMs: Long,
|
||||||
|
@Named(DreamOverlayModule.DREAM_OUT_ALPHA_DURATION) private val mDreamOutAlphaDurationMs: Long,
|
||||||
|
@Named(DreamOverlayModule.DREAM_OUT_ALPHA_DELAY_BOTTOM)
|
||||||
|
private val mDreamOutAlphaDelayBottomMs: Long,
|
||||||
|
@Named(DreamOverlayModule.DREAM_OUT_ALPHA_DELAY_TOP) private val mDreamOutAlphaDelayTopMs: Long,
|
||||||
|
@Named(DreamOverlayModule.DREAM_OUT_BLUR_DURATION) private val mDreamOutBlurDurationMs: Long
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var mEntryAnimations: AnimatorSet? = null
|
private var mAnimator: Animator? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the current alphas at the various positions. This is so that we may resume an animation
|
||||||
|
* at the current alpha.
|
||||||
|
*/
|
||||||
|
private var mCurrentAlphaAtPosition = mutableMapOf<Int, Float>()
|
||||||
|
|
||||||
|
@FloatRange(from = 0.0, to = 1.0) private var mBlurProgress: Float = 0f
|
||||||
|
|
||||||
/** Starts the dream content and dream overlay entry animations. */
|
/** Starts the dream content and dream overlay entry animations. */
|
||||||
fun startEntryAnimations(view: View) {
|
@JvmOverloads
|
||||||
cancelRunningEntryAnimations()
|
fun startEntryAnimations(view: View, animatorBuilder: () -> AnimatorSet = { AnimatorSet() }) {
|
||||||
|
cancelAnimations()
|
||||||
|
|
||||||
mEntryAnimations = AnimatorSet()
|
mAnimator =
|
||||||
mEntryAnimations?.apply {
|
animatorBuilder().apply {
|
||||||
playTogether(
|
playTogether(
|
||||||
buildDreamInBlurAnimator(view),
|
blurAnimator(
|
||||||
buildDreamInTopComplicationsAnimator(),
|
view = view,
|
||||||
buildDreamInBottomComplicationsAnimator()
|
from = 1f,
|
||||||
)
|
to = 0f,
|
||||||
doOnEnd { mOverlayStateController.setEntryAnimationsFinished(true) }
|
durationMs = mDreamInBlurAnimDurationMs,
|
||||||
start()
|
delayMs = mDreamInBlurAnimDelayMs
|
||||||
}
|
),
|
||||||
|
alphaAnimator(
|
||||||
|
from = 0f,
|
||||||
|
to = 1f,
|
||||||
|
durationMs = mDreamInComplicationsAnimDurationMs,
|
||||||
|
delayMs = mDreamInTopComplicationsAnimDelayMs,
|
||||||
|
position = ComplicationLayoutParams.POSITION_TOP
|
||||||
|
),
|
||||||
|
alphaAnimator(
|
||||||
|
from = 0f,
|
||||||
|
to = 1f,
|
||||||
|
durationMs = mDreamInComplicationsAnimDurationMs,
|
||||||
|
delayMs = mDreamInBottomComplicationsAnimDelayMs,
|
||||||
|
position = ComplicationLayoutParams.POSITION_BOTTOM
|
||||||
|
)
|
||||||
|
)
|
||||||
|
doOnEnd {
|
||||||
|
mAnimator = null
|
||||||
|
mOverlayStateController.setEntryAnimationsFinished(true)
|
||||||
|
}
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Starts the dream content and dream overlay exit animations. */
|
||||||
|
@JvmOverloads
|
||||||
|
fun startExitAnimations(
|
||||||
|
view: View,
|
||||||
|
doneCallback: () -> Unit,
|
||||||
|
animatorBuilder: () -> AnimatorSet = { AnimatorSet() }
|
||||||
|
) {
|
||||||
|
cancelAnimations()
|
||||||
|
|
||||||
|
mAnimator =
|
||||||
|
animatorBuilder().apply {
|
||||||
|
playTogether(
|
||||||
|
blurAnimator(
|
||||||
|
view = view,
|
||||||
|
// Start the blurring wherever the entry animation ended, in
|
||||||
|
// case it was cancelled early.
|
||||||
|
from = mBlurProgress,
|
||||||
|
to = 1f,
|
||||||
|
durationMs = mDreamOutBlurDurationMs
|
||||||
|
),
|
||||||
|
translationYAnimator(
|
||||||
|
from = 0f,
|
||||||
|
to = mDreamOutTranslationYDistance.toFloat(),
|
||||||
|
durationMs = mDreamOutTranslationYDurationMs,
|
||||||
|
delayMs = mDreamOutTranslationYDelayBottomMs,
|
||||||
|
position = ComplicationLayoutParams.POSITION_BOTTOM,
|
||||||
|
animInterpolator = Interpolators.EMPHASIZED_ACCELERATE
|
||||||
|
),
|
||||||
|
translationYAnimator(
|
||||||
|
from = 0f,
|
||||||
|
to = mDreamOutTranslationYDistance.toFloat(),
|
||||||
|
durationMs = mDreamOutTranslationYDurationMs,
|
||||||
|
delayMs = mDreamOutTranslationYDelayTopMs,
|
||||||
|
position = ComplicationLayoutParams.POSITION_TOP,
|
||||||
|
animInterpolator = Interpolators.EMPHASIZED_ACCELERATE
|
||||||
|
),
|
||||||
|
alphaAnimator(
|
||||||
|
from =
|
||||||
|
mCurrentAlphaAtPosition.getOrDefault(
|
||||||
|
key = ComplicationLayoutParams.POSITION_BOTTOM,
|
||||||
|
defaultValue = 1f
|
||||||
|
),
|
||||||
|
to = 0f,
|
||||||
|
durationMs = mDreamOutAlphaDurationMs,
|
||||||
|
delayMs = mDreamOutAlphaDelayBottomMs,
|
||||||
|
position = ComplicationLayoutParams.POSITION_BOTTOM
|
||||||
|
),
|
||||||
|
alphaAnimator(
|
||||||
|
from =
|
||||||
|
mCurrentAlphaAtPosition.getOrDefault(
|
||||||
|
key = ComplicationLayoutParams.POSITION_TOP,
|
||||||
|
defaultValue = 1f
|
||||||
|
),
|
||||||
|
to = 0f,
|
||||||
|
durationMs = mDreamOutAlphaDurationMs,
|
||||||
|
delayMs = mDreamOutAlphaDelayTopMs,
|
||||||
|
position = ComplicationLayoutParams.POSITION_TOP
|
||||||
|
)
|
||||||
|
)
|
||||||
|
doOnEnd {
|
||||||
|
mAnimator = null
|
||||||
|
mOverlayStateController.setExitAnimationsRunning(false)
|
||||||
|
doneCallback()
|
||||||
|
}
|
||||||
|
start()
|
||||||
|
}
|
||||||
|
mOverlayStateController.setExitAnimationsRunning(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Cancels the dream content and dream overlay animations, if they're currently running. */
|
/** Cancels the dream content and dream overlay animations, if they're currently running. */
|
||||||
fun cancelRunningEntryAnimations() {
|
fun cancelAnimations() {
|
||||||
if (mEntryAnimations?.isRunning == true) {
|
mAnimator =
|
||||||
mEntryAnimations?.cancel()
|
mAnimator?.let {
|
||||||
}
|
it.cancel()
|
||||||
mEntryAnimations = null
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildDreamInBlurAnimator(view: View): Animator {
|
private fun blurAnimator(
|
||||||
return ValueAnimator.ofFloat(1f, 0f).apply {
|
view: View,
|
||||||
duration = mDreamInBlurAnimDuration.toLong()
|
from: Float,
|
||||||
startDelay = mDreamInBlurAnimDelay.toLong()
|
to: Float,
|
||||||
|
durationMs: Long,
|
||||||
|
delayMs: Long = 0
|
||||||
|
): Animator {
|
||||||
|
return ValueAnimator.ofFloat(from, to).apply {
|
||||||
|
duration = durationMs
|
||||||
|
startDelay = delayMs
|
||||||
interpolator = Interpolators.LINEAR
|
interpolator = Interpolators.LINEAR
|
||||||
addUpdateListener { animator: ValueAnimator ->
|
addUpdateListener { animator: ValueAnimator ->
|
||||||
|
mBlurProgress = animator.animatedValue as Float
|
||||||
mBlurUtils.applyBlur(
|
mBlurUtils.applyBlur(
|
||||||
view.viewRootImpl,
|
viewRootImpl = view.viewRootImpl,
|
||||||
mBlurUtils.blurRadiusOfRatio(animator.animatedValue as Float).toInt(),
|
radius = mBlurUtils.blurRadiusOfRatio(mBlurProgress).toInt(),
|
||||||
false /*opaque*/
|
opaque = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildDreamInTopComplicationsAnimator(): Animator {
|
private fun alphaAnimator(
|
||||||
return ValueAnimator.ofFloat(0f, 1f).apply {
|
from: Float,
|
||||||
duration = mDreamInComplicationsAnimDuration.toLong()
|
to: Float,
|
||||||
startDelay = mDreamInTopComplicationsAnimDelay.toLong()
|
durationMs: Long,
|
||||||
|
delayMs: Long,
|
||||||
|
@Position position: Int
|
||||||
|
): Animator {
|
||||||
|
return ValueAnimator.ofFloat(from, to).apply {
|
||||||
|
duration = durationMs
|
||||||
|
startDelay = delayMs
|
||||||
interpolator = Interpolators.LINEAR
|
interpolator = Interpolators.LINEAR
|
||||||
addUpdateListener { va: ValueAnimator ->
|
addUpdateListener { va: ValueAnimator ->
|
||||||
setTopElementsAlpha(va.animatedValue as Float)
|
setElementsAlphaAtPosition(
|
||||||
|
alpha = va.animatedValue as Float,
|
||||||
|
position = position,
|
||||||
|
fadingOut = to < from
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildDreamInBottomComplicationsAnimator(): Animator {
|
private fun translationYAnimator(
|
||||||
return ValueAnimator.ofFloat(0f, 1f).apply {
|
from: Float,
|
||||||
duration = mDreamInComplicationsAnimDuration.toLong()
|
to: Float,
|
||||||
startDelay = mDreamInBottomComplicationsAnimDelay.toLong()
|
durationMs: Long,
|
||||||
interpolator = Interpolators.LINEAR
|
delayMs: Long,
|
||||||
|
@Position position: Int,
|
||||||
|
animInterpolator: Interpolator
|
||||||
|
): Animator {
|
||||||
|
return ValueAnimator.ofFloat(from, to).apply {
|
||||||
|
duration = durationMs
|
||||||
|
startDelay = delayMs
|
||||||
|
interpolator = animInterpolator
|
||||||
addUpdateListener { va: ValueAnimator ->
|
addUpdateListener { va: ValueAnimator ->
|
||||||
setBottomElementsAlpha(va.animatedValue as Float)
|
setElementsTranslationYAtPosition(va.animatedValue as Float, position)
|
||||||
}
|
}
|
||||||
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. */
|
/** Sets alpha of complications at the specified position. */
|
||||||
private fun setTopElementsAlpha(alpha: Float) {
|
private fun setElementsAlphaAtPosition(alpha: Float, position: Int, fadingOut: Boolean) {
|
||||||
mComplicationHostViewController
|
mCurrentAlphaAtPosition[position] = alpha
|
||||||
.getViewsAtPosition(ComplicationLayoutParams.POSITION_TOP)
|
mComplicationHostViewController.getViewsAtPosition(position).forEach { view ->
|
||||||
.forEach(Consumer { v: View -> setAlphaAndEnsureVisible(v, alpha) })
|
if (fadingOut) {
|
||||||
mStatusBarViewController.setAlpha(alpha)
|
CrossFadeHelper.fadeOut(view, 1 - alpha, /* remap= */ false)
|
||||||
}
|
} else {
|
||||||
|
CrossFadeHelper.fadeIn(view, alpha, /* remap= */ false)
|
||||||
/** 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
|
|
||||||
}
|
}
|
||||||
|
if (position == ComplicationLayoutParams.POSITION_TOP) {
|
||||||
|
mStatusBarViewController.setFadeAmount(alpha, fadingOut)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
view.alpha = alpha
|
/** Sets y translation of complications at the specified position. */
|
||||||
|
private fun setElementsTranslationYAtPosition(translationY: Float, position: Int) {
|
||||||
|
mComplicationHostViewController.getViewsAtPosition(position).forEach { v ->
|
||||||
|
v.translationY = translationY
|
||||||
|
}
|
||||||
|
if (position == ComplicationLayoutParams.POSITION_TOP) {
|
||||||
|
mStatusBarViewController.setTranslationY(translationY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ import android.util.MathUtils;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.animation.Interpolators;
|
import com.android.systemui.animation.Interpolators;
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
@@ -42,6 +44,7 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
|||||||
import com.android.systemui.util.ViewController;
|
import com.android.systemui.util.ViewController;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
@@ -194,7 +197,7 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
|||||||
}
|
}
|
||||||
mPrimaryBouncerCallbackInteractor.removeBouncerExpansionCallback(mBouncerExpansionCallback);
|
mPrimaryBouncerCallbackInteractor.removeBouncerExpansionCallback(mBouncerExpansionCallback);
|
||||||
|
|
||||||
mDreamOverlayAnimationsController.cancelRunningEntryAnimations();
|
mDreamOverlayAnimationsController.cancelAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
View getContainerView() {
|
View getContainerView() {
|
||||||
@@ -251,4 +254,17 @@ public class DreamOverlayContainerViewController extends ViewController<DreamOve
|
|||||||
: aboutToShowBouncerProgress(expansion + 0.03f));
|
: aboutToShowBouncerProgress(expansion + 0.03f));
|
||||||
return MathUtils.lerp(-mDreamOverlayMaxTranslationY, 0, fraction);
|
return MathUtils.lerp(-mDreamOverlayMaxTranslationY, 0, fraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the dream waking up and run any necessary animations.
|
||||||
|
*
|
||||||
|
* @param onAnimationEnd Callback to trigger once animations are finished.
|
||||||
|
* @param callbackExecutor Executor to execute the callback on.
|
||||||
|
*/
|
||||||
|
public void wakeUp(@NonNull Runnable onAnimationEnd, @NonNull Executor callbackExecutor) {
|
||||||
|
mDreamOverlayAnimationsController.startExitAnimations(mView, () -> {
|
||||||
|
callbackExecutor.execute(onAnimationEnd);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -213,6 +213,15 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
|||||||
mLifecycleRegistry.setCurrentState(state);
|
mLifecycleRegistry.setCurrentState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWakeUp(@NonNull Runnable onCompletedCallback) {
|
||||||
|
mExecutor.execute(() -> {
|
||||||
|
if (mDreamOverlayContainerViewController != null) {
|
||||||
|
mDreamOverlayContainerViewController.wakeUp(onCompletedCallback, mExecutor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts {@link Window} to host the dream overlay into the dream's parent window. Must be
|
* Inserts {@link Window} to host the dream overlay into the dream's parent window. Must be
|
||||||
* called from the main executing thread. The window attributes closely mirror those that are
|
* called from the main executing thread. The window attributes closely mirror those that are
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public class DreamOverlayStateController implements
|
|||||||
public static final int STATE_DREAM_OVERLAY_ACTIVE = 1 << 0;
|
public static final int STATE_DREAM_OVERLAY_ACTIVE = 1 << 0;
|
||||||
public static final int STATE_LOW_LIGHT_ACTIVE = 1 << 1;
|
public static final int STATE_LOW_LIGHT_ACTIVE = 1 << 1;
|
||||||
public static final int STATE_DREAM_ENTRY_ANIMATIONS_FINISHED = 1 << 2;
|
public static final int STATE_DREAM_ENTRY_ANIMATIONS_FINISHED = 1 << 2;
|
||||||
|
public static final int STATE_DREAM_EXIT_ANIMATIONS_RUNNING = 1 << 3;
|
||||||
|
|
||||||
private static final int OP_CLEAR_STATE = 1;
|
private static final int OP_CLEAR_STATE = 1;
|
||||||
private static final int OP_SET_STATE = 2;
|
private static final int OP_SET_STATE = 2;
|
||||||
@@ -211,6 +212,14 @@ public class DreamOverlayStateController implements
|
|||||||
return containsState(STATE_DREAM_ENTRY_ANIMATIONS_FINISHED);
|
return containsState(STATE_DREAM_ENTRY_ANIMATIONS_FINISHED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the dream content and dream overlay exit animations are running.
|
||||||
|
* @return {@code true} if animations are running, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean areExitAnimationsRunning() {
|
||||||
|
return containsState(STATE_DREAM_EXIT_ANIMATIONS_RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean containsState(int state) {
|
private boolean containsState(int state) {
|
||||||
return (mState & state) != 0;
|
return (mState & state) != 0;
|
||||||
}
|
}
|
||||||
@@ -256,6 +265,15 @@ public class DreamOverlayStateController implements
|
|||||||
STATE_DREAM_ENTRY_ANIMATIONS_FINISHED);
|
STATE_DREAM_ENTRY_ANIMATIONS_FINISHED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether dream content and dream overlay exit animations are running.
|
||||||
|
* @param running {@code true} if exit animations are running, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public void setExitAnimationsRunning(boolean running) {
|
||||||
|
modifyState(running ? OP_SET_STATE : OP_CLEAR_STATE,
|
||||||
|
STATE_DREAM_EXIT_ANIMATIONS_RUNNING);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the available complication types.
|
* Returns the available complication types.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.android.systemui.R;
|
|||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider.StatusBarItem;
|
import com.android.systemui.dreams.DreamOverlayStatusBarItemsProvider.StatusBarItem;
|
||||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||||
|
import com.android.systemui.statusbar.CrossFadeHelper;
|
||||||
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
|
import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController;
|
||||||
import com.android.systemui.statusbar.policy.NextAlarmController;
|
import com.android.systemui.statusbar.policy.NextAlarmController;
|
||||||
import com.android.systemui.statusbar.policy.ZenModeController;
|
import com.android.systemui.statusbar.policy.ZenModeController;
|
||||||
@@ -217,18 +218,29 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets alpha of the dream overlay status bar.
|
* Sets fade of the dream overlay status bar.
|
||||||
*
|
*
|
||||||
* No-op if the dream overlay status bar should not be shown.
|
* No-op if the dream overlay status bar should not be shown.
|
||||||
*/
|
*/
|
||||||
protected void setAlpha(float alpha) {
|
protected void setFadeAmount(float fadeAmount, boolean fadingOut) {
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
|
|
||||||
if (mView.getVisibility() != View.VISIBLE) {
|
if (mView.getVisibility() != View.VISIBLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mView.setAlpha(alpha);
|
if (fadingOut) {
|
||||||
|
CrossFadeHelper.fadeOut(mView, 1 - fadeAmount, /* remap= */ false);
|
||||||
|
} else {
|
||||||
|
CrossFadeHelper.fadeIn(mView, fadeAmount, /* remap= */ false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the y translation of the dream overlay status bar.
|
||||||
|
*/
|
||||||
|
public void setTranslationY(float translationY) {
|
||||||
|
mView.setTranslationY(translationY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldShowStatusBar() {
|
private boolean shouldShowStatusBar() {
|
||||||
|
|||||||
@@ -197,11 +197,11 @@ public interface Complication {
|
|||||||
*/
|
*/
|
||||||
interface VisibilityController {
|
interface VisibilityController {
|
||||||
/**
|
/**
|
||||||
* Called to set the visibility of all shown and future complications.
|
* Called to set the visibility of all shown and future complications. Changes in visibility
|
||||||
|
* will always be animated.
|
||||||
* @param visibility The desired future visibility.
|
* @param visibility The desired future visibility.
|
||||||
* @param animate whether the change should be animated.
|
|
||||||
*/
|
*/
|
||||||
void setVisibility(@View.Visibility int visibility, boolean animate);
|
void setVisibility(@View.Visibility int visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -21,12 +21,9 @@ import static com.android.systemui.dreams.complication.dagger.ComplicationHostVi
|
|||||||
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATION_MARGIN_DEFAULT;
|
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATION_MARGIN_DEFAULT;
|
||||||
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.SCOPED_COMPLICATIONS_LAYOUT;
|
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.SCOPED_COMPLICATIONS_LAYOUT;
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.AnimatorListenerAdapter;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.ViewPropertyAnimator;
|
|
||||||
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
import androidx.constraintlayout.widget.Constraints;
|
import androidx.constraintlayout.widget.Constraints;
|
||||||
@@ -34,6 +31,7 @@ import androidx.constraintlayout.widget.Constraints;
|
|||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position;
|
import com.android.systemui.dreams.complication.ComplicationLayoutParams.Position;
|
||||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||||
|
import com.android.systemui.statusbar.CrossFadeHelper;
|
||||||
import com.android.systemui.touch.TouchInsetManager;
|
import com.android.systemui.touch.TouchInsetManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -481,7 +479,6 @@ public class ComplicationLayoutEngine implements Complication.VisibilityControll
|
|||||||
private final TouchInsetManager.TouchInsetSession mSession;
|
private final TouchInsetManager.TouchInsetSession mSession;
|
||||||
private final int mFadeInDuration;
|
private final int mFadeInDuration;
|
||||||
private final int mFadeOutDuration;
|
private final int mFadeOutDuration;
|
||||||
private ViewPropertyAnimator mViewPropertyAnimator;
|
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
@Inject
|
@Inject
|
||||||
@@ -498,26 +495,16 @@ public class ComplicationLayoutEngine implements Complication.VisibilityControll
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setVisibility(int visibility, boolean animate) {
|
public void setVisibility(int visibility) {
|
||||||
final boolean appearing = visibility == View.VISIBLE;
|
if (visibility == View.VISIBLE) {
|
||||||
|
CrossFadeHelper.fadeIn(mLayout, mFadeInDuration, /* delay= */ 0);
|
||||||
if (mViewPropertyAnimator != null) {
|
} else {
|
||||||
mViewPropertyAnimator.cancel();
|
CrossFadeHelper.fadeOut(
|
||||||
|
mLayout,
|
||||||
|
mFadeOutDuration,
|
||||||
|
/* delay= */ 0,
|
||||||
|
/* endRunnable= */ null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (appearing) {
|
|
||||||
mLayout.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
mViewPropertyAnimator = mLayout.animate()
|
|
||||||
.alpha(appearing ? 1f : 0f)
|
|
||||||
.setDuration(appearing ? mFadeInDuration : mFadeOutDuration)
|
|
||||||
.setListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
mLayout.setVisibility(visibility);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams {
|
|||||||
POSITION_START,
|
POSITION_START,
|
||||||
})
|
})
|
||||||
|
|
||||||
@interface Position {}
|
public @interface Position {}
|
||||||
/** Align view with the top of parent or bottom of preceding {@link Complication}. */
|
/** Align view with the top of parent or bottom of preceding {@link Complication}. */
|
||||||
public static final int POSITION_TOP = 1 << 0;
|
public static final int POSITION_TOP = 1 << 0;
|
||||||
/** Align view with the bottom of parent or top of preceding {@link Complication}. */
|
/** Align view with the bottom of parent or top of preceding {@link Complication}. */
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public abstract class ComplicationHostViewModule {
|
|||||||
public static final String COMPLICATIONS_FADE_OUT_DURATION = "complications_fade_out_duration";
|
public static final String COMPLICATIONS_FADE_OUT_DURATION = "complications_fade_out_duration";
|
||||||
public static final String COMPLICATIONS_FADE_IN_DURATION = "complications_fade_in_duration";
|
public static final String COMPLICATIONS_FADE_IN_DURATION = "complications_fade_in_duration";
|
||||||
public static final String COMPLICATIONS_RESTORE_TIMEOUT = "complication_restore_timeout";
|
public static final String COMPLICATIONS_RESTORE_TIMEOUT = "complication_restore_timeout";
|
||||||
|
public static final String COMPLICATIONS_FADE_OUT_DELAY = "complication_fade_out_delay";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a {@link ConstraintLayout}, which can host
|
* Generates a {@link ConstraintLayout}, which can host
|
||||||
@@ -74,6 +75,16 @@ public abstract class ComplicationHostViewModule {
|
|||||||
return resources.getInteger(R.integer.complicationFadeOutMs);
|
return resources.getInteger(R.integer.complicationFadeOutMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the delay to wait for before fading out complications.
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@Named(COMPLICATIONS_FADE_OUT_DELAY)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static int providesComplicationsFadeOutDelay(@Main Resources resources) {
|
||||||
|
return resources.getInteger(R.integer.complicationFadeOutDelayMs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides the fade in duration for complications.
|
* Provides the fade in duration for complications.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -55,6 +55,22 @@ public abstract class DreamOverlayModule {
|
|||||||
"dream_in_top_complications_anim_delay";
|
"dream_in_top_complications_anim_delay";
|
||||||
public static final String DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY =
|
public static final String DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY =
|
||||||
"dream_in_bottom_complications_anim_delay";
|
"dream_in_bottom_complications_anim_delay";
|
||||||
|
public static final String DREAM_OUT_TRANSLATION_Y_DISTANCE =
|
||||||
|
"dream_out_complications_translation_y";
|
||||||
|
public static final String DREAM_OUT_TRANSLATION_Y_DURATION =
|
||||||
|
"dream_out_complications_translation_y_duration";
|
||||||
|
public static final String DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM =
|
||||||
|
"dream_out_complications_translation_y_delay_bottom";
|
||||||
|
public static final String DREAM_OUT_TRANSLATION_Y_DELAY_TOP =
|
||||||
|
"dream_out_complications_translation_y_delay_top";
|
||||||
|
public static final String DREAM_OUT_ALPHA_DURATION =
|
||||||
|
"dream_out_complications_alpha_duration";
|
||||||
|
public static final String DREAM_OUT_ALPHA_DELAY_BOTTOM =
|
||||||
|
"dream_out_complications_alpha_delay_bottom";
|
||||||
|
public static final String DREAM_OUT_ALPHA_DELAY_TOP =
|
||||||
|
"dream_out_complications_alpha_delay_top";
|
||||||
|
public static final String DREAM_OUT_BLUR_DURATION =
|
||||||
|
"dream_out_blur_duration";
|
||||||
|
|
||||||
/** */
|
/** */
|
||||||
@Provides
|
@Provides
|
||||||
@@ -127,8 +143,8 @@ public abstract class DreamOverlayModule {
|
|||||||
*/
|
*/
|
||||||
@Provides
|
@Provides
|
||||||
@Named(DREAM_IN_BLUR_ANIMATION_DURATION)
|
@Named(DREAM_IN_BLUR_ANIMATION_DURATION)
|
||||||
static int providesDreamInBlurAnimationDuration(@Main Resources resources) {
|
static long providesDreamInBlurAnimationDuration(@Main Resources resources) {
|
||||||
return resources.getInteger(R.integer.config_dreamOverlayInBlurDurationMs);
|
return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDurationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -136,8 +152,8 @@ public abstract class DreamOverlayModule {
|
|||||||
*/
|
*/
|
||||||
@Provides
|
@Provides
|
||||||
@Named(DREAM_IN_BLUR_ANIMATION_DELAY)
|
@Named(DREAM_IN_BLUR_ANIMATION_DELAY)
|
||||||
static int providesDreamInBlurAnimationDelay(@Main Resources resources) {
|
static long providesDreamInBlurAnimationDelay(@Main Resources resources) {
|
||||||
return resources.getInteger(R.integer.config_dreamOverlayInBlurDelayMs);
|
return (long) resources.getInteger(R.integer.config_dreamOverlayInBlurDelayMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,8 +161,8 @@ public abstract class DreamOverlayModule {
|
|||||||
*/
|
*/
|
||||||
@Provides
|
@Provides
|
||||||
@Named(DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
|
@Named(DREAM_IN_COMPLICATIONS_ANIMATION_DURATION)
|
||||||
static int providesDreamInComplicationsAnimationDuration(@Main Resources resources) {
|
static long providesDreamInComplicationsAnimationDuration(@Main Resources resources) {
|
||||||
return resources.getInteger(R.integer.config_dreamOverlayInComplicationsDurationMs);
|
return (long) resources.getInteger(R.integer.config_dreamOverlayInComplicationsDurationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,8 +170,8 @@ public abstract class DreamOverlayModule {
|
|||||||
*/
|
*/
|
||||||
@Provides
|
@Provides
|
||||||
@Named(DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
|
@Named(DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY)
|
||||||
static int providesDreamInTopComplicationsAnimationDelay(@Main Resources resources) {
|
static long providesDreamInTopComplicationsAnimationDelay(@Main Resources resources) {
|
||||||
return resources.getInteger(R.integer.config_dreamOverlayInTopComplicationsDelayMs);
|
return (long) resources.getInteger(R.integer.config_dreamOverlayInTopComplicationsDelayMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,8 +179,69 @@ public abstract class DreamOverlayModule {
|
|||||||
*/
|
*/
|
||||||
@Provides
|
@Provides
|
||||||
@Named(DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
|
@Named(DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY)
|
||||||
static int providesDreamInBottomComplicationsAnimationDelay(@Main Resources resources) {
|
static long providesDreamInBottomComplicationsAnimationDelay(@Main Resources resources) {
|
||||||
return resources.getInteger(R.integer.config_dreamOverlayInBottomComplicationsDelayMs);
|
return (long) resources.getInteger(
|
||||||
|
R.integer.config_dreamOverlayInBottomComplicationsDelayMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the number of pixels to translate complications when waking up from dream.
|
||||||
|
*/
|
||||||
|
@Provides
|
||||||
|
@Named(DREAM_OUT_TRANSLATION_Y_DISTANCE)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static int providesDreamOutComplicationsTranslationY(@Main Resources resources) {
|
||||||
|
return resources.getDimensionPixelSize(R.dimen.dream_overlay_exit_y_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named(DREAM_OUT_TRANSLATION_Y_DURATION)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static long providesDreamOutComplicationsTranslationYDuration(@Main Resources resources) {
|
||||||
|
return (long) resources.getInteger(R.integer.config_dreamOverlayOutTranslationYDurationMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named(DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static long providesDreamOutComplicationsTranslationYDelayBottom(@Main Resources resources) {
|
||||||
|
return (long) resources.getInteger(
|
||||||
|
R.integer.config_dreamOverlayOutTranslationYDelayBottomMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named(DREAM_OUT_TRANSLATION_Y_DELAY_TOP)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static long providesDreamOutComplicationsTranslationYDelayTop(@Main Resources resources) {
|
||||||
|
return (long) resources.getInteger(R.integer.config_dreamOverlayOutTranslationYDelayTopMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named(DREAM_OUT_ALPHA_DURATION)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static long providesDreamOutComplicationsAlphaDuration(@Main Resources resources) {
|
||||||
|
return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDurationMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named(DREAM_OUT_ALPHA_DELAY_BOTTOM)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static long providesDreamOutComplicationsAlphaDelayBottom(@Main Resources resources) {
|
||||||
|
return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDelayBottomMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named(DREAM_OUT_ALPHA_DELAY_TOP)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static long providesDreamOutComplicationsAlphaDelayTop(@Main Resources resources) {
|
||||||
|
return (long) resources.getInteger(R.integer.config_dreamOverlayOutAlphaDelayTopMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named(DREAM_OUT_BLUR_DURATION)
|
||||||
|
@DreamOverlayComponent.DreamOverlayScope
|
||||||
|
static long providesDreamOutBlurDuration(@Main Resources resources) {
|
||||||
|
return (long) resources.getInteger(R.integer.config_dreamOverlayOutBlurDurationMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|||||||
@@ -16,22 +16,26 @@
|
|||||||
|
|
||||||
package com.android.systemui.dreams.touch;
|
package com.android.systemui.dreams.touch;
|
||||||
|
|
||||||
|
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATIONS_FADE_OUT_DELAY;
|
||||||
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATIONS_RESTORE_TIMEOUT;
|
import static com.android.systemui.dreams.complication.dagger.ComplicationHostViewModule.COMPLICATIONS_RESTORE_TIMEOUT;
|
||||||
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.dreams.DreamOverlayStateController;
|
||||||
import com.android.systemui.dreams.complication.Complication;
|
import com.android.systemui.dreams.complication.Complication;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||||
import com.android.systemui.touch.TouchInsetManager;
|
import com.android.systemui.touch.TouchInsetManager;
|
||||||
|
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
@@ -49,33 +53,58 @@ public class HideComplicationTouchHandler implements DreamTouchHandler {
|
|||||||
private static final String TAG = "HideComplicationHandler";
|
private static final String TAG = "HideComplicationHandler";
|
||||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
|
||||||
private final Complication.VisibilityController mVisibilityController;
|
|
||||||
private final int mRestoreTimeout;
|
private final int mRestoreTimeout;
|
||||||
|
private final int mFadeOutDelay;
|
||||||
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||||
private final Handler mHandler;
|
private final DelayableExecutor mExecutor;
|
||||||
private final Executor mExecutor;
|
private final DreamOverlayStateController mOverlayStateController;
|
||||||
private final TouchInsetManager mTouchInsetManager;
|
private final TouchInsetManager mTouchInsetManager;
|
||||||
|
private final Complication.VisibilityController mVisibilityController;
|
||||||
|
private boolean mHidden = false;
|
||||||
|
@Nullable
|
||||||
|
private Runnable mHiddenCallback;
|
||||||
|
private final ArrayDeque<Runnable> mCancelCallbacks = new ArrayDeque<>();
|
||||||
|
|
||||||
|
|
||||||
private final Runnable mRestoreComplications = new Runnable() {
|
private final Runnable mRestoreComplications = new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mVisibilityController.setVisibility(View.VISIBLE, true);
|
mVisibilityController.setVisibility(View.VISIBLE);
|
||||||
|
mHidden = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Runnable mHideComplications = new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (mOverlayStateController.areExitAnimationsRunning()) {
|
||||||
|
// Avoid interfering with the exit animations.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mVisibilityController.setVisibility(View.INVISIBLE);
|
||||||
|
mHidden = true;
|
||||||
|
if (mHiddenCallback != null) {
|
||||||
|
mHiddenCallback.run();
|
||||||
|
mHiddenCallback = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
HideComplicationTouchHandler(Complication.VisibilityController visibilityController,
|
HideComplicationTouchHandler(Complication.VisibilityController visibilityController,
|
||||||
@Named(COMPLICATIONS_RESTORE_TIMEOUT) int restoreTimeout,
|
@Named(COMPLICATIONS_RESTORE_TIMEOUT) int restoreTimeout,
|
||||||
|
@Named(COMPLICATIONS_FADE_OUT_DELAY) int fadeOutDelay,
|
||||||
TouchInsetManager touchInsetManager,
|
TouchInsetManager touchInsetManager,
|
||||||
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
|
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
|
||||||
@Main Executor executor,
|
@Main DelayableExecutor executor,
|
||||||
@Main Handler handler) {
|
DreamOverlayStateController overlayStateController) {
|
||||||
mVisibilityController = visibilityController;
|
mVisibilityController = visibilityController;
|
||||||
mRestoreTimeout = restoreTimeout;
|
mRestoreTimeout = restoreTimeout;
|
||||||
|
mFadeOutDelay = fadeOutDelay;
|
||||||
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
|
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
|
||||||
mHandler = handler;
|
|
||||||
mTouchInsetManager = touchInsetManager;
|
mTouchInsetManager = touchInsetManager;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
|
mOverlayStateController = overlayStateController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -87,7 +116,8 @@ public class HideComplicationTouchHandler implements DreamTouchHandler {
|
|||||||
final boolean bouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
|
final boolean bouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
|
||||||
|
|
||||||
// If other sessions are interested in this touch, do not fade out elements.
|
// If other sessions are interested in this touch, do not fade out elements.
|
||||||
if (session.getActiveSessionCount() > 1 || bouncerShowing) {
|
if (session.getActiveSessionCount() > 1 || bouncerShowing
|
||||||
|
|| mOverlayStateController.areExitAnimationsRunning()) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "not fading. Active session count: " + session.getActiveSessionCount()
|
Log.d(TAG, "not fading. Active session count: " + session.getActiveSessionCount()
|
||||||
+ ". Bouncer showing: " + bouncerShowing);
|
+ ". Bouncer showing: " + bouncerShowing);
|
||||||
@@ -115,8 +145,11 @@ public class HideComplicationTouchHandler implements DreamTouchHandler {
|
|||||||
touchCheck.addListener(() -> {
|
touchCheck.addListener(() -> {
|
||||||
try {
|
try {
|
||||||
if (!touchCheck.get()) {
|
if (!touchCheck.get()) {
|
||||||
mHandler.removeCallbacks(mRestoreComplications);
|
// Cancel all pending callbacks.
|
||||||
mVisibilityController.setVisibility(View.INVISIBLE, true);
|
while (!mCancelCallbacks.isEmpty()) mCancelCallbacks.pop().run();
|
||||||
|
mCancelCallbacks.add(
|
||||||
|
mExecutor.executeDelayed(
|
||||||
|
mHideComplications, mFadeOutDelay));
|
||||||
} else {
|
} else {
|
||||||
// If a touch occurred inside the dream overlay touch insets, do not
|
// If a touch occurred inside the dream overlay touch insets, do not
|
||||||
// handle the touch.
|
// handle the touch.
|
||||||
@@ -130,7 +163,23 @@ public class HideComplicationTouchHandler implements DreamTouchHandler {
|
|||||||
|| motionEvent.getAction() == MotionEvent.ACTION_UP) {
|
|| motionEvent.getAction() == MotionEvent.ACTION_UP) {
|
||||||
// End session and initiate delayed reappearance of the complications.
|
// End session and initiate delayed reappearance of the complications.
|
||||||
session.pop();
|
session.pop();
|
||||||
mHandler.postDelayed(mRestoreComplications, mRestoreTimeout);
|
runAfterHidden(() -> mCancelCallbacks.add(
|
||||||
|
mExecutor.executeDelayed(mRestoreComplications,
|
||||||
|
mRestoreTimeout)));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers a runnable after complications have been hidden. Will override any previously set
|
||||||
|
* runnable currently waiting for hide to happen.
|
||||||
|
*/
|
||||||
|
private void runAfterHidden(Runnable runnable) {
|
||||||
|
mExecutor.execute(() -> {
|
||||||
|
if (mHidden) {
|
||||||
|
runnable.run();
|
||||||
|
} else {
|
||||||
|
mHiddenCallback = runnable;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -408,6 +408,11 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
|
|||||||
*/
|
*/
|
||||||
private final int mDreamOpenAnimationDuration;
|
private final int mDreamOpenAnimationDuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The duration in milliseconds of the dream close animation.
|
||||||
|
*/
|
||||||
|
private final int mDreamCloseAnimationDuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The animation used for hiding keyguard. This is used to fetch the animation timings if
|
* The animation used for hiding keyguard. This is used to fetch the animation timings if
|
||||||
* WindowManager is not providing us with them.
|
* WindowManager is not providing us with them.
|
||||||
@@ -1054,7 +1059,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mUnoccludeAnimator = ValueAnimator.ofFloat(1f, 0f);
|
mUnoccludeAnimator = ValueAnimator.ofFloat(1f, 0f);
|
||||||
mUnoccludeAnimator.setDuration(UNOCCLUDE_ANIMATION_DURATION);
|
mUnoccludeAnimator.setDuration(isDream ? mDreamCloseAnimationDuration
|
||||||
|
: UNOCCLUDE_ANIMATION_DURATION);
|
||||||
mUnoccludeAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE);
|
mUnoccludeAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE);
|
||||||
mUnoccludeAnimator.addUpdateListener(
|
mUnoccludeAnimator.addUpdateListener(
|
||||||
animation -> {
|
animation -> {
|
||||||
@@ -1204,6 +1210,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
|
|||||||
|
|
||||||
mDreamOpenAnimationDuration = context.getResources().getInteger(
|
mDreamOpenAnimationDuration = context.getResources().getInteger(
|
||||||
com.android.internal.R.integer.config_dreamOpenAnimationDuration);
|
com.android.internal.R.integer.config_dreamOpenAnimationDuration);
|
||||||
|
mDreamCloseAnimationDuration = context.getResources().getInteger(
|
||||||
|
com.android.internal.R.integer.config_dreamCloseAnimationDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void userActivity() {
|
public void userActivity() {
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package com.android.systemui.dreams
|
||||||
|
|
||||||
|
import android.animation.Animator
|
||||||
|
import android.animation.AnimatorSet
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
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.util.mockito.argumentCaptor
|
||||||
|
import com.android.systemui.util.mockito.mock
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.Mockito.never
|
||||||
|
import org.mockito.Mockito.times
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val DREAM_IN_BLUR_ANIMATION_DURATION = 1L
|
||||||
|
private const val DREAM_IN_BLUR_ANIMATION_DELAY = 2L
|
||||||
|
private const val DREAM_IN_COMPLICATIONS_ANIMATION_DURATION = 3L
|
||||||
|
private const val DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY = 4L
|
||||||
|
private const val DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY = 5L
|
||||||
|
private const val DREAM_OUT_TRANSLATION_Y_DISTANCE = 6
|
||||||
|
private const val DREAM_OUT_TRANSLATION_Y_DURATION = 7L
|
||||||
|
private const val DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM = 8L
|
||||||
|
private const val DREAM_OUT_TRANSLATION_Y_DELAY_TOP = 9L
|
||||||
|
private const val DREAM_OUT_ALPHA_DURATION = 10L
|
||||||
|
private const val DREAM_OUT_ALPHA_DELAY_BOTTOM = 11L
|
||||||
|
private const val DREAM_OUT_ALPHA_DELAY_TOP = 12L
|
||||||
|
private const val DREAM_OUT_BLUR_DURATION = 13L
|
||||||
|
}
|
||||||
|
|
||||||
|
@Mock private lateinit var mockAnimator: AnimatorSet
|
||||||
|
@Mock private lateinit var blurUtils: BlurUtils
|
||||||
|
@Mock private lateinit var hostViewController: ComplicationHostViewController
|
||||||
|
@Mock private lateinit var statusBarViewController: DreamOverlayStatusBarViewController
|
||||||
|
@Mock private lateinit var stateController: DreamOverlayStateController
|
||||||
|
private lateinit var controller: DreamOverlayAnimationsController
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
controller =
|
||||||
|
DreamOverlayAnimationsController(
|
||||||
|
blurUtils,
|
||||||
|
hostViewController,
|
||||||
|
statusBarViewController,
|
||||||
|
stateController,
|
||||||
|
DREAM_IN_BLUR_ANIMATION_DURATION,
|
||||||
|
DREAM_IN_BLUR_ANIMATION_DELAY,
|
||||||
|
DREAM_IN_COMPLICATIONS_ANIMATION_DURATION,
|
||||||
|
DREAM_IN_TOP_COMPLICATIONS_ANIMATION_DELAY,
|
||||||
|
DREAM_IN_BOTTOM_COMPLICATIONS_ANIMATION_DELAY,
|
||||||
|
DREAM_OUT_TRANSLATION_Y_DISTANCE,
|
||||||
|
DREAM_OUT_TRANSLATION_Y_DURATION,
|
||||||
|
DREAM_OUT_TRANSLATION_Y_DELAY_BOTTOM,
|
||||||
|
DREAM_OUT_TRANSLATION_Y_DELAY_TOP,
|
||||||
|
DREAM_OUT_ALPHA_DURATION,
|
||||||
|
DREAM_OUT_ALPHA_DELAY_BOTTOM,
|
||||||
|
DREAM_OUT_ALPHA_DELAY_TOP,
|
||||||
|
DREAM_OUT_BLUR_DURATION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testExitAnimationOnEnd() {
|
||||||
|
val mockCallback: () -> Unit = mock()
|
||||||
|
|
||||||
|
controller.startExitAnimations(
|
||||||
|
view = mock(),
|
||||||
|
doneCallback = mockCallback,
|
||||||
|
animatorBuilder = { mockAnimator }
|
||||||
|
)
|
||||||
|
|
||||||
|
val captor = argumentCaptor<Animator.AnimatorListener>()
|
||||||
|
verify(mockAnimator).addListener(captor.capture())
|
||||||
|
val listener = captor.value
|
||||||
|
|
||||||
|
verify(mockCallback, never()).invoke()
|
||||||
|
listener.onAnimationEnd(mockAnimator)
|
||||||
|
verify(mockCallback, times(1)).invoke()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testCancellation() {
|
||||||
|
controller.startExitAnimations(
|
||||||
|
view = mock(),
|
||||||
|
doneCallback = mock(),
|
||||||
|
animatorBuilder = { mockAnimator }
|
||||||
|
)
|
||||||
|
|
||||||
|
verify(mockAnimator, never()).cancel()
|
||||||
|
controller.cancelAnimations()
|
||||||
|
verify(mockAnimator, times(1)).cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testExitAfterStartWillCancel() {
|
||||||
|
val mockStartAnimator: AnimatorSet = mock()
|
||||||
|
val mockExitAnimator: AnimatorSet = mock()
|
||||||
|
|
||||||
|
controller.startEntryAnimations(view = mock(), animatorBuilder = { mockStartAnimator })
|
||||||
|
|
||||||
|
verify(mockStartAnimator, never()).cancel()
|
||||||
|
|
||||||
|
controller.startExitAnimations(
|
||||||
|
view = mock(),
|
||||||
|
doneCallback = mock(),
|
||||||
|
animatorBuilder = { mockExitAnimator }
|
||||||
|
)
|
||||||
|
|
||||||
|
// Verify that we cancelled the start animator in favor of the exit
|
||||||
|
// animator.
|
||||||
|
verify(mockStartAnimator, times(1)).cancel()
|
||||||
|
verify(mockExitAnimator, never()).cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -204,7 +204,7 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
|||||||
mController.onViewAttached();
|
mController.onViewAttached();
|
||||||
|
|
||||||
verify(mAnimationsController).startEntryAnimations(mDreamOverlayContainerView);
|
verify(mAnimationsController).startEntryAnimations(mDreamOverlayContainerView);
|
||||||
verify(mAnimationsController, never()).cancelRunningEntryAnimations();
|
verify(mAnimationsController, never()).cancelAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -221,6 +221,6 @@ public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
|
|||||||
mController.onViewAttached();
|
mController.onViewAttached();
|
||||||
mController.onViewDetached();
|
mController.onViewDetached();
|
||||||
|
|
||||||
verify(mAnimationsController).cancelRunningEntryAnimations();
|
verify(mAnimationsController).cancelAnimations();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.Mockito.clearInvocations;
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -337,4 +338,28 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
|||||||
verify(mDreamOverlayComponent).getDreamOverlayContainerViewController();
|
verify(mDreamOverlayComponent).getDreamOverlayContainerViewController();
|
||||||
verify(mDreamOverlayComponent).getDreamOverlayTouchMonitor();
|
verify(mDreamOverlayComponent).getDreamOverlayTouchMonitor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWakeUp() throws RemoteException {
|
||||||
|
final IBinder proxy = mService.onBind(new Intent());
|
||||||
|
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||||
|
|
||||||
|
// Inform the overlay service of dream starting.
|
||||||
|
overlay.startDream(mWindowParams, mDreamOverlayCallback, DREAM_COMPONENT,
|
||||||
|
true /*shouldShowComplication*/);
|
||||||
|
mMainExecutor.runAllReady();
|
||||||
|
|
||||||
|
final Runnable callback = mock(Runnable.class);
|
||||||
|
mService.onWakeUp(callback);
|
||||||
|
mMainExecutor.runAllReady();
|
||||||
|
verify(mDreamOverlayContainerViewController).wakeUp(callback, mMainExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWakeUpBeforeStartDoesNothing() {
|
||||||
|
final Runnable callback = mock(Runnable.class);
|
||||||
|
mService.onWakeUp(callback);
|
||||||
|
mMainExecutor.runAllReady();
|
||||||
|
verify(mDreamOverlayContainerViewController, never()).wakeUp(callback, mMainExecutor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.systemui.dreams.touch;
|
package com.android.systemui.dreams.touch;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
@@ -33,6 +31,7 @@ import androidx.concurrent.futures.CallbackToFutureAdapter;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.dreams.DreamOverlayStateController;
|
||||||
import com.android.systemui.dreams.complication.Complication;
|
import com.android.systemui.dreams.complication.Complication;
|
||||||
import com.android.systemui.shared.system.InputChannelCompat;
|
import com.android.systemui.shared.system.InputChannelCompat;
|
||||||
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
|
||||||
@@ -52,6 +51,7 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
||||||
private static final int RESTORE_TIMEOUT = 1000;
|
private static final int RESTORE_TIMEOUT = 1000;
|
||||||
|
private static final int HIDE_DELAY = 500;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
Complication.VisibilityController mVisibilityController;
|
Complication.VisibilityController mVisibilityController;
|
||||||
@@ -71,11 +71,18 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
@Mock
|
@Mock
|
||||||
DreamTouchHandler.TouchSession mSession;
|
DreamTouchHandler.TouchSession mSession;
|
||||||
|
|
||||||
FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
@Mock
|
||||||
|
DreamOverlayStateController mStateController;
|
||||||
|
|
||||||
|
FakeSystemClock mClock;
|
||||||
|
|
||||||
|
FakeExecutor mFakeExecutor;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
mClock = new FakeSystemClock();
|
||||||
|
mFakeExecutor = new FakeExecutor(mClock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,10 +93,11 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
|
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
|
||||||
mVisibilityController,
|
mVisibilityController,
|
||||||
RESTORE_TIMEOUT,
|
RESTORE_TIMEOUT,
|
||||||
|
HIDE_DELAY,
|
||||||
mTouchInsetManager,
|
mTouchInsetManager,
|
||||||
mStatusBarKeyguardViewManager,
|
mStatusBarKeyguardViewManager,
|
||||||
mFakeExecutor,
|
mFakeExecutor,
|
||||||
mHandler);
|
mStateController);
|
||||||
|
|
||||||
// Report multiple active sessions.
|
// Report multiple active sessions.
|
||||||
when(mSession.getActiveSessionCount()).thenReturn(2);
|
when(mSession.getActiveSessionCount()).thenReturn(2);
|
||||||
@@ -103,8 +111,10 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
// Verify session end.
|
// Verify session end.
|
||||||
verify(mSession).pop();
|
verify(mSession).pop();
|
||||||
|
|
||||||
|
mClock.advanceTime(HIDE_DELAY);
|
||||||
|
|
||||||
// Verify no interaction with visibility controller.
|
// Verify no interaction with visibility controller.
|
||||||
verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
|
verify(mVisibilityController, never()).setVisibility(anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,10 +125,11 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
|
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
|
||||||
mVisibilityController,
|
mVisibilityController,
|
||||||
RESTORE_TIMEOUT,
|
RESTORE_TIMEOUT,
|
||||||
|
HIDE_DELAY,
|
||||||
mTouchInsetManager,
|
mTouchInsetManager,
|
||||||
mStatusBarKeyguardViewManager,
|
mStatusBarKeyguardViewManager,
|
||||||
mFakeExecutor,
|
mFakeExecutor,
|
||||||
mHandler);
|
mStateController);
|
||||||
|
|
||||||
// Report one session.
|
// Report one session.
|
||||||
when(mSession.getActiveSessionCount()).thenReturn(1);
|
when(mSession.getActiveSessionCount()).thenReturn(1);
|
||||||
@@ -132,8 +143,10 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
// Verify session end.
|
// Verify session end.
|
||||||
verify(mSession).pop();
|
verify(mSession).pop();
|
||||||
|
|
||||||
|
mClock.advanceTime(HIDE_DELAY);
|
||||||
|
|
||||||
// Verify no interaction with visibility controller.
|
// Verify no interaction with visibility controller.
|
||||||
verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
|
verify(mVisibilityController, never()).setVisibility(anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -144,10 +157,11 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
|
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
|
||||||
mVisibilityController,
|
mVisibilityController,
|
||||||
RESTORE_TIMEOUT,
|
RESTORE_TIMEOUT,
|
||||||
|
HIDE_DELAY,
|
||||||
mTouchInsetManager,
|
mTouchInsetManager,
|
||||||
mStatusBarKeyguardViewManager,
|
mStatusBarKeyguardViewManager,
|
||||||
mFakeExecutor,
|
mFakeExecutor,
|
||||||
mHandler);
|
mStateController);
|
||||||
|
|
||||||
// Report one session
|
// Report one session
|
||||||
when(mSession.getActiveSessionCount()).thenReturn(1);
|
when(mSession.getActiveSessionCount()).thenReturn(1);
|
||||||
@@ -177,8 +191,10 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
// Verify session ended.
|
// Verify session ended.
|
||||||
verify(mSession).pop();
|
verify(mSession).pop();
|
||||||
|
|
||||||
|
mClock.advanceTime(HIDE_DELAY);
|
||||||
|
|
||||||
// Verify no interaction with visibility controller.
|
// Verify no interaction with visibility controller.
|
||||||
verify(mVisibilityController, never()).setVisibility(anyInt(), anyBoolean());
|
verify(mVisibilityController, never()).setVisibility(anyInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -189,10 +205,11 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
|
final HideComplicationTouchHandler touchHandler = new HideComplicationTouchHandler(
|
||||||
mVisibilityController,
|
mVisibilityController,
|
||||||
RESTORE_TIMEOUT,
|
RESTORE_TIMEOUT,
|
||||||
|
HIDE_DELAY,
|
||||||
mTouchInsetManager,
|
mTouchInsetManager,
|
||||||
mStatusBarKeyguardViewManager,
|
mStatusBarKeyguardViewManager,
|
||||||
mFakeExecutor,
|
mFakeExecutor,
|
||||||
mHandler);
|
mStateController);
|
||||||
|
|
||||||
// Report one session
|
// Report one session
|
||||||
when(mSession.getActiveSessionCount()).thenReturn(1);
|
when(mSession.getActiveSessionCount()).thenReturn(1);
|
||||||
@@ -221,11 +238,11 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
inputEventListenerCaptor.getValue().onInputEvent(mMotionEvent);
|
inputEventListenerCaptor.getValue().onInputEvent(mMotionEvent);
|
||||||
mFakeExecutor.runAllReady();
|
mFakeExecutor.runAllReady();
|
||||||
|
|
||||||
// Verify callback to restore visibility cancelled.
|
// Verify visibility controller doesn't hide until after timeout
|
||||||
verify(mHandler).removeCallbacks(any());
|
verify(mVisibilityController, never()).setVisibility(eq(View.INVISIBLE));
|
||||||
|
mClock.advanceTime(HIDE_DELAY);
|
||||||
// Verify visibility controller told to hide complications.
|
// Verify visibility controller told to hide complications.
|
||||||
verify(mVisibilityController).setVisibility(eq(View.INVISIBLE), anyBoolean());
|
verify(mVisibilityController).setVisibility(eq(View.INVISIBLE));
|
||||||
|
|
||||||
Mockito.clearInvocations(mVisibilityController, mHandler);
|
Mockito.clearInvocations(mVisibilityController, mHandler);
|
||||||
|
|
||||||
@@ -235,11 +252,8 @@ public class HideComplicationTouchHandlerTest extends SysuiTestCase {
|
|||||||
mFakeExecutor.runAllReady();
|
mFakeExecutor.runAllReady();
|
||||||
|
|
||||||
// Verify visibility controller told to show complications.
|
// Verify visibility controller told to show complications.
|
||||||
ArgumentCaptor<Runnable> delayRunnableCaptor = ArgumentCaptor.forClass(Runnable.class);
|
mClock.advanceTime(RESTORE_TIMEOUT);
|
||||||
verify(mHandler).postDelayed(delayRunnableCaptor.capture(),
|
verify(mVisibilityController).setVisibility(eq(View.VISIBLE));
|
||||||
eq(Long.valueOf(RESTORE_TIMEOUT)));
|
|
||||||
delayRunnableCaptor.getValue().run();
|
|
||||||
verify(mVisibilityController).setVisibility(eq(View.VISIBLE), anyBoolean());
|
|
||||||
|
|
||||||
// Verify session ended.
|
// Verify session ended.
|
||||||
verify(mSession).pop();
|
verify(mSession).pop();
|
||||||
|
|||||||
Reference in New Issue
Block a user