Merge "Add an extra colored layer when animating launches (1/2)" into sc-dev am: d17c68d57c

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

Change-Id: I2b50de4828b797dac706feb5d298030a11c76b59
This commit is contained in:
TreeHugger Robot
2021-06-01 20:55:16 +00:00
committed by Automerger Merge Worker
7 changed files with 170 additions and 81 deletions

View File

@@ -135,7 +135,7 @@ public class SplashscreenContentDrawer {
com.android.wm.shell.R.dimen.starting_surface_exit_animation_window_shift_length); com.android.wm.shell.R.dimen.starting_surface_exit_animation_window_shift_length);
} }
private int getSystemBGColor() { private static int getSystemBGColor() {
final Context systemContext = ActivityThread.currentApplication(); final Context systemContext = ActivityThread.currentApplication();
if (systemContext == null) { if (systemContext == null) {
Slog.e(TAG, "System context does not exist!"); Slog.e(TAG, "System context does not exist!");
@@ -145,17 +145,18 @@ public class SplashscreenContentDrawer {
return res.getColor(com.android.wm.shell.R.color.splash_window_background_default); return res.getColor(com.android.wm.shell.R.color.splash_window_background_default);
} }
private Drawable createDefaultBackgroundDrawable() { private static Drawable createDefaultBackgroundDrawable() {
return new ColorDrawable(getSystemBGColor()); return new ColorDrawable(getSystemBGColor());
} }
private @ColorInt int peekWindowBGColor(Context context) { /** Extract the window background color from {@code attrs}. */
public static int peekWindowBGColor(Context context, SplashScreenWindowAttrs attrs) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "peekWindowBGColor"); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "peekWindowBGColor");
final Drawable themeBGDrawable; final Drawable themeBGDrawable;
if (mTmpAttrs.mWindowBgColor != 0) { if (attrs.mWindowBgColor != 0) {
themeBGDrawable = new ColorDrawable(mTmpAttrs.mWindowBgColor); themeBGDrawable = new ColorDrawable(attrs.mWindowBgColor);
} else if (mTmpAttrs.mWindowBgResId != 0) { } else if (attrs.mWindowBgResId != 0) {
themeBGDrawable = context.getDrawable(mTmpAttrs.mWindowBgResId); themeBGDrawable = context.getDrawable(attrs.mWindowBgResId);
} else { } else {
themeBGDrawable = createDefaultBackgroundDrawable(); themeBGDrawable = createDefaultBackgroundDrawable();
Slog.w(TAG, "Window background does not exist, using " + themeBGDrawable); Slog.w(TAG, "Window background does not exist, using " + themeBGDrawable);
@@ -165,7 +166,7 @@ public class SplashscreenContentDrawer {
return estimatedWindowBGColor; return estimatedWindowBGColor;
} }
private int estimateWindowBGColor(Drawable themeBGDrawable) { private static int estimateWindowBGColor(Drawable themeBGDrawable) {
final DrawableColorTester themeBGTester = final DrawableColorTester themeBGTester =
new DrawableColorTester(themeBGDrawable, true /* filterTransparent */); new DrawableColorTester(themeBGDrawable, true /* filterTransparent */);
if (themeBGTester.nonTransparentRatio() == 0) { if (themeBGTester.nonTransparentRatio() == 0) {
@@ -183,7 +184,7 @@ public class SplashscreenContentDrawer {
getWindowAttrs(context, mTmpAttrs); getWindowAttrs(context, mTmpAttrs);
final StartingWindowViewBuilder builder = new StartingWindowViewBuilder(); final StartingWindowViewBuilder builder = new StartingWindowViewBuilder();
final int themeBGColor = peekWindowBGColor(context); final int themeBGColor = peekWindowBGColor(context, this.mTmpAttrs);
// TODO (b/173975965) Tracking the performance on improved splash screen. // TODO (b/173975965) Tracking the performance on improved splash screen.
return builder return builder
.setContext(context) .setContext(context)
@@ -193,7 +194,11 @@ public class SplashscreenContentDrawer {
.build(); .build();
} }
private static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) { /**
* Get the {@link SplashScreenWindowAttrs} from {@code context} and fill them into
* {@code attrs}.
*/
public static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) {
final TypedArray typedArray = context.obtainStyledAttributes( final TypedArray typedArray = context.obtainStyledAttributes(
com.android.internal.R.styleable.Window); com.android.internal.R.styleable.Window);
attrs.mWindowBgResId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0); attrs.mWindowBgResId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
@@ -216,7 +221,8 @@ public class SplashscreenContentDrawer {
} }
} }
private static class SplashScreenWindowAttrs { /** The configuration of the splash screen window. */
public static class SplashScreenWindowAttrs {
private int mWindowBgResId = 0; private int mWindowBgResId = 0;
private int mWindowBgColor = Color.TRANSPARENT; private int mWindowBgColor = Color.TRANSPARENT;
private Drawable mReplaceIcon = null; private Drawable mReplaceIcon = null;

View File

@@ -36,6 +36,7 @@ android_library {
static_libs: [ static_libs: [
"PluginCoreLib", "PluginCoreLib",
"WindowManager-Shell",
], ],
manifest: "AndroidManifest.xml", manifest: "AndroidManifest.xml",

View File

@@ -5,13 +5,18 @@ import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.app.ActivityManager import android.app.ActivityManager
import android.app.ActivityTaskManager import android.app.ActivityTaskManager
import android.app.AppGlobals
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.graphics.Matrix import android.graphics.Matrix
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.Rect import android.graphics.Rect
import android.graphics.RectF import android.graphics.RectF
import android.graphics.drawable.GradientDrawable
import android.os.Looper import android.os.Looper
import android.os.RemoteException import android.os.RemoteException
import android.os.UserHandle
import android.util.Log import android.util.Log
import android.util.MathUtils import android.util.MathUtils
import android.view.IRemoteAnimationFinishedCallback import android.view.IRemoteAnimationFinishedCallback
@@ -26,6 +31,8 @@ import android.view.animation.AnimationUtils
import android.view.animation.PathInterpolator import android.view.animation.PathInterpolator
import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting
import com.android.internal.policy.ScreenDecorationsUtils import com.android.internal.policy.ScreenDecorationsUtils
import com.android.wm.shell.startingsurface.SplashscreenContentDrawer
import com.android.wm.shell.startingsurface.SplashscreenContentDrawer.SplashScreenWindowAttrs
import kotlin.math.roundToInt import kotlin.math.roundToInt
/** /**
@@ -40,9 +47,9 @@ class ActivityLaunchAnimator(
companion object { companion object {
const val ANIMATION_DURATION = 500L const val ANIMATION_DURATION = 500L
const val ANIMATION_DURATION_FADE_OUT_CONTENT = 183L private const val ANIMATION_DURATION_FADE_OUT_CONTENT = 150L
const val ANIMATION_DURATION_FADE_IN_WINDOW = 217L private const val ANIMATION_DURATION_FADE_IN_WINDOW = 183L
const val ANIMATION_DELAY_FADE_IN_WINDOW = 167L private const val ANIMATION_DELAY_FADE_IN_WINDOW = ANIMATION_DURATION_FADE_OUT_CONTENT
private const val ANIMATION_DURATION_NAV_FADE_IN = 266L private const val ANIMATION_DURATION_NAV_FADE_IN = 266L
private const val ANIMATION_DURATION_NAV_FADE_OUT = 133L private const val ANIMATION_DURATION_NAV_FADE_OUT = 133L
private const val ANIMATION_DELAY_NAV_FADE_IN = private const val ANIMATION_DELAY_NAV_FADE_IN =
@@ -54,6 +61,8 @@ class ActivityLaunchAnimator(
private val NAV_FADE_IN_INTERPOLATOR = PathInterpolator(0f, 0f, 0f, 1f) private val NAV_FADE_IN_INTERPOLATOR = PathInterpolator(0f, 0f, 0f, 1f)
private val NAV_FADE_OUT_INTERPOLATOR = PathInterpolator(0.2f, 0f, 1f, 1f) private val NAV_FADE_OUT_INTERPOLATOR = PathInterpolator(0.2f, 0f, 1f, 1f)
private val SRC_MODE = PorterDuffXfermode(PorterDuff.Mode.SRC)
/** /**
* Given the [linearProgress] of a launch animation, return the linear progress of the * Given the [linearProgress] of a launch animation, return the linear progress of the
* sub-animation starting [delay] ms after the launch animation and that lasts [duration]. * sub-animation starting [delay] ms after the launch animation and that lasts [duration].
@@ -68,6 +77,8 @@ class ActivityLaunchAnimator(
} }
} }
private val packageManager = AppGlobals.getPackageManager()
/** The interpolator used for the width, height, Y position and corner radius. */ /** The interpolator used for the width, height, Y position and corner radius. */
private val animationInterpolator = AnimationUtils.loadInterpolator(context, private val animationInterpolator = AnimationUtils.loadInterpolator(context,
R.interpolator.launch_animation_interpolator_y) R.interpolator.launch_animation_interpolator_y)
@@ -76,6 +87,8 @@ class ActivityLaunchAnimator(
private val animationInterpolatorX = AnimationUtils.loadInterpolator(context, private val animationInterpolatorX = AnimationUtils.loadInterpolator(context,
R.interpolator.launch_animation_interpolator_x) R.interpolator.launch_animation_interpolator_x)
private val cornerRadii = FloatArray(8)
/** /**
* Start an intent and animate the opening window. The intent will be started by running * Start an intent and animate the opening window. The intent will be started by running
* [intentStarter], which should use the provided [RemoteAnimationAdapter] and return the launch * [intentStarter], which should use the provided [RemoteAnimationAdapter] and return the launch
@@ -288,10 +301,7 @@ class ActivityLaunchAnimator(
var right: Int, var right: Int,
var topCornerRadius: Float = 0f, var topCornerRadius: Float = 0f,
var bottomCornerRadius: Float = 0f, var bottomCornerRadius: Float = 0f
var contentAlpha: Float = 1f,
var backgroundAlpha: Float = 1f
) { ) {
private val startTop = top private val startTop = top
private val startBottom = bottom private val startBottom = bottom
@@ -331,6 +341,9 @@ class ActivityLaunchAnimator(
val centerY: Float val centerY: Float
get() = top + height / 2f get() = top + height / 2f
/** Whether the expanded view should be visible or hidden. */
var visible: Boolean = true
} }
@VisibleForTesting @VisibleForTesting
@@ -452,22 +465,39 @@ class ActivityLaunchAnimator(
0f 0f
} }
// We add an extra layer with the same color as the app splash screen background color,
// which is usually the same color of the app background. We first fade in this layer
// to hide the expanding view, then we fade it out with SRC mode to draw a hole in the
// launch container and reveal the opening window.
val windowBackgroundColor = extractSplashScreenBackgroundColor(window)
val windowBackgroundLayer = GradientDrawable().apply {
setColor(windowBackgroundColor)
alpha = 0
}
// Update state. // Update state.
val animator = ValueAnimator.ofFloat(0f, 1f) val animator = ValueAnimator.ofFloat(0f, 1f)
this.animator = animator this.animator = animator
animator.duration = ANIMATION_DURATION animator.duration = ANIMATION_DURATION
animator.interpolator = Interpolators.LINEAR animator.interpolator = Interpolators.LINEAR
val launchContainerOverlay = launchContainer.overlay
animator.addListener(object : AnimatorListenerAdapter() { animator.addListener(object : AnimatorListenerAdapter() {
override fun onAnimationStart(animation: Animator?, isReverse: Boolean) { override fun onAnimationStart(animation: Animator?, isReverse: Boolean) {
Log.d(TAG, "Animation started") Log.d(TAG, "Animation started")
controller.onLaunchAnimationStart(isExpandingFullyAbove) controller.onLaunchAnimationStart(isExpandingFullyAbove)
// Add the drawable to the launch container overlay. Overlays always draw
// drawables after views, so we know that it will be drawn above any view added
// by the controller.
launchContainerOverlay.add(windowBackgroundLayer)
} }
override fun onAnimationEnd(animation: Animator?) { override fun onAnimationEnd(animation: Animator?) {
Log.d(TAG, "Animation ended") Log.d(TAG, "Animation ended")
iCallback?.invoke() iCallback?.invoke()
controller.onLaunchAnimationEnd(isExpandingFullyAbove) controller.onLaunchAnimationEnd(isExpandingFullyAbove)
launchContainerOverlay.remove(windowBackgroundLayer)
} }
}) })
@@ -491,24 +521,61 @@ class ActivityLaunchAnimator(
state.bottomCornerRadius = state.bottomCornerRadius =
MathUtils.lerp(startBottomCornerRadius, endRadius, progress) MathUtils.lerp(startBottomCornerRadius, endRadius, progress)
val contentAlphaProgress = getProgress(linearProgress, 0, // The expanding view can/should be hidden once it is completely coverred by the
ANIMATION_DURATION_FADE_OUT_CONTENT) // windowBackgroundLayer.
state.contentAlpha = state.visible =
1 - CONTENT_FADE_OUT_INTERPOLATOR.getInterpolation(contentAlphaProgress) getProgress(linearProgress, 0, ANIMATION_DURATION_FADE_OUT_CONTENT) < 1
val backgroundAlphaProgress = getProgress(linearProgress,
ANIMATION_DELAY_FADE_IN_WINDOW, ANIMATION_DURATION_FADE_IN_WINDOW)
state.backgroundAlpha =
1 - WINDOW_FADE_IN_INTERPOLATOR.getInterpolation(backgroundAlphaProgress)
applyStateToWindow(window, state) applyStateToWindow(window, state)
applyStateToWindowBackgroundLayer(windowBackgroundLayer, state, linearProgress)
navigationBar?.let { applyStateToNavigationBar(it, state, linearProgress) } navigationBar?.let { applyStateToNavigationBar(it, state, linearProgress) }
// If we started expanding the view, we make it 1 pixel smaller on all sides to
// avoid artefacts on the corners caused by anti-aliasing of the view background and
// the window background layer.
if (state.top != startTop && state.left != startLeft &&
state.bottom != startBottom && state.right != startRight) {
state.top += 1
state.left += 1
state.right -= 1
state.bottom -= 1
}
controller.onLaunchAnimationProgress(state, progress, linearProgress) controller.onLaunchAnimationProgress(state, progress, linearProgress)
} }
animator.start() animator.start()
} }
/** Extract the background color of the app splash screen. */
private fun extractSplashScreenBackgroundColor(window: RemoteAnimationTarget): Int {
val taskInfo = window.taskInfo
val windowPackage = taskInfo.topActivity.packageName
val userId = taskInfo.userId
val windowContext = context.createPackageContextAsUser(
windowPackage, Context.CONTEXT_RESTRICTED, UserHandle.of(userId))
val activityInfo = taskInfo.topActivityInfo
val splashScreenThemeName = packageManager.getSplashScreenTheme(windowPackage, userId)
val splashScreenThemeId = if (splashScreenThemeName != null) {
windowContext.resources.getIdentifier(splashScreenThemeName, null, null)
} else {
0
}
val themeResId = when {
splashScreenThemeId != 0 -> splashScreenThemeId
activityInfo.themeResource != 0 -> activityInfo.themeResource
else -> com.android.internal.R.style.Theme_DeviceDefault_DayNight
}
if (themeResId != windowContext.themeResId) {
windowContext.setTheme(themeResId)
}
val windowAttrs = SplashScreenWindowAttrs()
SplashscreenContentDrawer.getWindowAttrs(windowContext, windowAttrs)
return SplashscreenContentDrawer.peekWindowBGColor(windowContext, windowAttrs)
}
private fun applyStateToWindow(window: RemoteAnimationTarget, state: State) { private fun applyStateToWindow(window: RemoteAnimationTarget, state: State) {
val screenBounds = window.screenSpaceBounds val screenBounds = window.screenSpaceBounds
val centerX = (screenBounds.left + screenBounds.right) / 2f val centerX = (screenBounds.left + screenBounds.right) / 2f
@@ -563,6 +630,41 @@ class ActivityLaunchAnimator(
transactionApplier.scheduleApply(params) transactionApplier.scheduleApply(params)
} }
private fun applyStateToWindowBackgroundLayer(
drawable: GradientDrawable,
state: State,
linearProgress: Float
) {
// Update position.
drawable.setBounds(state.left, state.top, state.right, state.bottom)
// Update radius.
cornerRadii[0] = state.topCornerRadius
cornerRadii[1] = state.topCornerRadius
cornerRadii[2] = state.topCornerRadius
cornerRadii[3] = state.topCornerRadius
cornerRadii[4] = state.bottomCornerRadius
cornerRadii[5] = state.bottomCornerRadius
cornerRadii[6] = state.bottomCornerRadius
cornerRadii[7] = state.bottomCornerRadius
drawable.cornerRadii = cornerRadii
// We first fade in the background layer to hide the expanding view, then fade it out
// with SRC mode to draw a hole punch in the status bar and reveal the opening window.
val fadeInProgress = getProgress(linearProgress, 0, ANIMATION_DURATION_FADE_OUT_CONTENT)
if (fadeInProgress < 1) {
val alpha = CONTENT_FADE_OUT_INTERPOLATOR.getInterpolation(fadeInProgress)
drawable.alpha = (alpha * 0xFF).roundToInt()
drawable.setXfermode(null)
} else {
val fadeOutProgress = getProgress(linearProgress,
ANIMATION_DELAY_FADE_IN_WINDOW, ANIMATION_DURATION_FADE_IN_WINDOW)
val alpha = 1 - WINDOW_FADE_IN_INTERPOLATOR.getInterpolation(fadeOutProgress)
drawable.alpha = (alpha * 0xFF).roundToInt()
drawable.setXfermode(SRC_MODE)
}
}
private fun applyStateToNavigationBar( private fun applyStateToNavigationBar(
navigationBar: RemoteAnimationTarget, navigationBar: RemoteAnimationTarget,
state: State, state: State,

View File

@@ -4,8 +4,6 @@ import android.graphics.Canvas
import android.graphics.ColorFilter import android.graphics.ColorFilter
import android.graphics.Matrix import android.graphics.Matrix
import android.graphics.PixelFormat import android.graphics.PixelFormat
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.graphics.Rect import android.graphics.Rect
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable import android.graphics.drawable.GradientDrawable
@@ -111,9 +109,7 @@ open class GhostedViewLaunchAnimatorController(
} }
override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) { override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
backgroundView = FrameLayout(launchContainer.context).apply { backgroundView = FrameLayout(launchContainer.context)
forceHasOverlappingRendering(false)
}
launchContainerOverlay.add(backgroundView) launchContainerOverlay.add(backgroundView)
// We wrap the ghosted view background and use it to draw the expandable background. Its // We wrap the ghosted view background and use it to draw the expandable background. Its
@@ -125,9 +121,7 @@ open class GhostedViewLaunchAnimatorController(
// Create a ghost of the view that will be moving and fading out. This allows to fade out // Create a ghost of the view that will be moving and fading out. This allows to fade out
// the content before fading out the background. // the content before fading out the background.
ghostView = GhostView.addGhost(ghostedView, launchContainer).apply { ghostView = GhostView.addGhost(ghostedView, launchContainer)
setLayerType(View.LAYER_TYPE_HARDWARE, null)
}
val matrix = ghostView?.animationMatrix ?: Matrix.IDENTITY_MATRIX val matrix = ghostView?.animationMatrix ?: Matrix.IDENTITY_MATRIX
matrix.getValues(initialGhostViewMatrixValues) matrix.getValues(initialGhostViewMatrixValues)
@@ -139,7 +133,18 @@ open class GhostedViewLaunchAnimatorController(
linearProgress: Float linearProgress: Float
) { ) {
val ghostView = this.ghostView!! val ghostView = this.ghostView!!
ghostView.alpha = state.contentAlpha val backgroundView = this.backgroundView!!
if (!state.visible) {
if (ghostView.visibility == View.VISIBLE) {
// Making the ghost view invisible will make the ghosted view visible, so order is
// important here.
ghostView.visibility = View.INVISIBLE
ghostedView.visibility = View.INVISIBLE
backgroundView.visibility = View.INVISIBLE
}
return
}
val scale = min(state.widthRatio, state.heightRatio) val scale = min(state.widthRatio, state.heightRatio)
ghostViewMatrix.setValues(initialGhostViewMatrixValues) ghostViewMatrix.setValues(initialGhostViewMatrixValues)
@@ -150,14 +155,12 @@ open class GhostedViewLaunchAnimatorController(
) )
ghostView.animationMatrix = ghostViewMatrix ghostView.animationMatrix = ghostViewMatrix
val backgroundView = this.backgroundView!!
backgroundView.top = state.top backgroundView.top = state.top
backgroundView.bottom = state.bottom backgroundView.bottom = state.bottom
backgroundView.left = state.left backgroundView.left = state.left
backgroundView.right = state.right backgroundView.right = state.right
val backgroundDrawable = backgroundDrawable!! val backgroundDrawable = backgroundDrawable!!
backgroundDrawable.alpha = (0xFF * state.backgroundAlpha).toInt()
backgroundDrawable.wrapped?.let { backgroundDrawable.wrapped?.let {
setBackgroundCornerRadius(it, state.topCornerRadius, state.bottomCornerRadius) setBackgroundCornerRadius(it, state.topCornerRadius, state.bottomCornerRadius)
} }
@@ -168,6 +171,7 @@ open class GhostedViewLaunchAnimatorController(
GhostView.removeGhost(ghostedView) GhostView.removeGhost(ghostedView)
launchContainerOverlay.remove(backgroundView) launchContainerOverlay.remove(backgroundView)
ghostedView.visibility = View.VISIBLE
ghostedView.invalidate() ghostedView.invalidate()
} }
@@ -203,10 +207,6 @@ open class GhostedViewLaunchAnimatorController(
} }
private class WrappedDrawable(val wrapped: Drawable?) : Drawable() { private class WrappedDrawable(val wrapped: Drawable?) : Drawable() {
companion object {
private val SRC_MODE = PorterDuffXfermode(PorterDuff.Mode.SRC)
}
private var currentAlpha = 0xFF private var currentAlpha = 0xFF
private var previousBounds = Rect() private var previousBounds = Rect()
@@ -220,7 +220,6 @@ open class GhostedViewLaunchAnimatorController(
wrapped.alpha = currentAlpha wrapped.alpha = currentAlpha
wrapped.bounds = bounds wrapped.bounds = bounds
setXfermode(wrapped, SRC_MODE)
applyBackgroundRadii() applyBackgroundRadii()
wrapped.draw(canvas) wrapped.draw(canvas)
@@ -230,7 +229,6 @@ open class GhostedViewLaunchAnimatorController(
// background. // background.
wrapped.alpha = 0 wrapped.alpha = 0
wrapped.bounds = previousBounds wrapped.bounds = previousBounds
setXfermode(wrapped, null)
restoreBackgroundRadii() restoreBackgroundRadii()
} }
@@ -257,27 +255,6 @@ open class GhostedViewLaunchAnimatorController(
wrapped?.colorFilter = filter wrapped?.colorFilter = filter
} }
private fun setXfermode(background: Drawable, mode: PorterDuffXfermode?) {
if (background is InsetDrawable) {
background.drawable?.let { setXfermode(it, mode) }
return
}
if (background !is LayerDrawable) {
background.setXfermode(mode)
return
}
// We set the xfermode on the first layer that is not a mask. Most of the time it will
// be the "background layer".
for (i in 0 until background.numberOfLayers) {
if (background.getId(i) != android.R.id.mask) {
background.getDrawable(i).setXfermode(mode)
break
}
}
}
fun setBackgroundRadius(topCornerRadius: Float, bottomCornerRadius: Float) { fun setBackgroundRadius(topCornerRadius: Float, bottomCornerRadius: Float) {
updateRadii(cornerRadii, topCornerRadius, bottomCornerRadius) updateRadii(cornerRadii, topCornerRadius, bottomCornerRadius)
invalidateSelf() invalidateSelf()

View File

@@ -73,7 +73,6 @@ import com.android.internal.widget.CachingIconView;
import com.android.internal.widget.CallLayout; import com.android.internal.widget.CallLayout;
import com.android.systemui.Dependency; import com.android.systemui.Dependency;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.Interpolators; import com.android.systemui.animation.Interpolators;
import com.android.systemui.classifier.FalsingCollector; import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingManager;
@@ -2020,6 +2019,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
if (params == null) { if (params == null) {
return; return;
} }
if (!params.getVisible()) {
if (getVisibility() == View.VISIBLE) {
setVisibility(View.INVISIBLE);
}
return;
}
float zProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation( float zProgress = Interpolators.FAST_OUT_SLOW_IN.getInterpolation(
params.getProgress(0, 50)); params.getProgress(0, 50));
float translationZ = MathUtils.lerp(params.getStartTranslationZ(), float translationZ = MathUtils.lerp(params.getStartTranslationZ(),
@@ -2077,10 +2084,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
contentView = mGuts; contentView = mGuts;
} }
if (expandAnimationRunning) { if (expandAnimationRunning) {
contentView.animate()
.alpha(0f)
.setDuration(ActivityLaunchAnimator.ANIMATION_DURATION_FADE_OUT_CONTENT)
.setInterpolator(ActivityLaunchAnimator.CONTENT_FADE_OUT_INTERPOLATOR);
setAboveShelf(true); setAboveShelf(true);
mExpandAnimationRunning = true; mExpandAnimationRunning = true;
getViewState().cancelAnimations(this); getViewState().cancelAnimations(this);
@@ -2088,6 +2091,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
} else { } else {
mExpandAnimationRunning = false; mExpandAnimationRunning = false;
setAboveShelf(isAboveShelf()); setAboveShelf(isAboveShelf());
setVisibility(View.VISIBLE);
if (mGuts != null) { if (mGuts != null) {
mGuts.setAlpha(1.0f); mGuts.setAlpha(1.0f);
} }

View File

@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.LayerDrawable;
@@ -30,8 +29,6 @@ import android.view.View;
import com.android.internal.util.ArrayUtils; import com.android.internal.util.ArrayUtils;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.animation.ActivityLaunchAnimator;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters; import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
/** /**
@@ -281,11 +278,6 @@ public class NotificationBackgroundView extends View {
public void setExpandAnimationParams(ExpandAnimationParameters params) { public void setExpandAnimationParams(ExpandAnimationParameters params) {
mActualHeight = params.getHeight(); mActualHeight = params.getHeight();
mActualWidth = params.getWidth(); mActualWidth = params.getWidth();
float alphaProgress = Interpolators.ALPHA_IN.getInterpolation(
params.getProgress(
ActivityLaunchAnimator.ANIMATION_DELAY_FADE_IN_WINDOW /* delay */,
ActivityLaunchAnimator.ANIMATION_DURATION_FADE_IN_WINDOW /* duration */));
mBackground.setAlpha((int) (mDrawableAlpha * (1.0f - alphaProgress)));
invalidate(); invalidate();
} }
@@ -294,8 +286,6 @@ public class NotificationBackgroundView extends View {
if (mBackground instanceof LayerDrawable) { if (mBackground instanceof LayerDrawable) {
GradientDrawable gradientDrawable = GradientDrawable gradientDrawable =
(GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0); (GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0);
gradientDrawable.setXfermode(
running ? new PorterDuffXfermode(PorterDuff.Mode.SRC) : null);
// Speed optimization: disable AA if transfer mode is not SRC_OVER. AA is not easy to // Speed optimization: disable AA if transfer mode is not SRC_OVER. AA is not easy to
// spot during animation anyways. // spot during animation anyways.
gradientDrawable.setAntiAlias(!running); gradientDrawable.setAntiAlias(!running);

View File

@@ -2,6 +2,9 @@ package com.android.systemui.animation
import android.app.ActivityManager import android.app.ActivityManager
import android.app.WindowConfiguration import android.app.WindowConfiguration
import android.content.ComponentName
import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.graphics.Point import android.graphics.Point
import android.graphics.Rect import android.graphics.Rect
import android.os.Looper import android.os.Looper
@@ -167,10 +170,16 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
private fun fakeWindow(): RemoteAnimationTarget { private fun fakeWindow(): RemoteAnimationTarget {
val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */) val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
val taskInfo = ActivityManager.RunningTaskInfo()
taskInfo.topActivity = ComponentName("com.android.systemui", "FakeActivity")
taskInfo.topActivityInfo = ActivityInfo().apply {
applicationInfo = ApplicationInfo()
}
return RemoteAnimationTarget( return RemoteAnimationTarget(
0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0, 0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0,
Point(), Rect(), bounds, WindowConfiguration(), false, SurfaceControl(), Rect(), Point(), Rect(), bounds, WindowConfiguration(), false, SurfaceControl(), Rect(),
ActivityManager.RunningTaskInfo() taskInfo
) )
} }
} }