Merge "Ensure to trigger Activity#onEnterAnimationComplete" into rvc-dev am: b749be45c7
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11838100 Change-Id: Id86cf8c2b0dd45d1205dd1d851636612401a5e47
This commit is contained in:
@@ -311,7 +311,6 @@ import com.android.server.uri.UriPermissionOwner;
|
||||
import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot;
|
||||
import com.android.server.wm.ActivityStack.ActivityState;
|
||||
import com.android.server.wm.SurfaceAnimator.AnimationType;
|
||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
import com.android.server.wm.WindowManagerService.H;
|
||||
import com.android.server.wm.utils.InsetUtils;
|
||||
|
||||
@@ -4166,14 +4165,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||
boolean isVoiceInteraction,
|
||||
@Nullable OnAnimationFinishedCallback animationFinishedCallback) {
|
||||
boolean applyAnimation(LayoutParams lp, int transit, boolean enter,
|
||||
boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
|
||||
if (mUseTransferredAnimation) {
|
||||
return false;
|
||||
}
|
||||
return super.applyAnimation(lp, transit, enter, isVoiceInteraction,
|
||||
animationFinishedCallback);
|
||||
return super.applyAnimation(lp, transit, enter, isVoiceInteraction, sources);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,7 +49,7 @@ import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_W
|
||||
import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
|
||||
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
@@ -75,7 +75,6 @@ import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
|
||||
/**
|
||||
* Checks for app transition readiness, resolves animation attributes and performs visibility
|
||||
* change for apps that animate as part of an app transition.
|
||||
@@ -375,18 +374,14 @@ public class AppTransitionController {
|
||||
// triggers WC#onAnimationFinished only on the promoted target. So we need to take care
|
||||
// of triggering AR#onAnimationFinished on each ActivityRecord which is a part of the
|
||||
// app transition.
|
||||
final ArrayList<ActivityRecord> transitioningDecendants = new ArrayList<>();
|
||||
final ArrayList<ActivityRecord> transitioningDescendants = new ArrayList<>();
|
||||
for (int j = 0; j < apps.size(); ++j) {
|
||||
final ActivityRecord app = apps.valueAt(j);
|
||||
if (app.isDescendantOf(wc)) {
|
||||
transitioningDecendants.add(app);
|
||||
transitioningDescendants.add(app);
|
||||
}
|
||||
}
|
||||
wc.applyAnimation(animLp, transit, visible, voiceInteraction, (type, anim) -> {
|
||||
for (int j = 0; j < transitioningDecendants.size(); ++j) {
|
||||
transitioningDecendants.get(j).onAnimationFinished(type, anim);
|
||||
}
|
||||
});
|
||||
wc.applyAnimation(animLp, transit, visible, voiceInteraction, transitioningDescendants);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,7 +535,14 @@ public class AppTransitionController {
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", app);
|
||||
|
||||
app.commitVisibility(true /* visible */, false /* performLayout */);
|
||||
if (!app.isAnimating(PARENTS | CHILDREN)) {
|
||||
|
||||
// In case a trampoline activity is used, it can happen that a new ActivityRecord is
|
||||
// added and a new app transition starts before the previous app transition animation
|
||||
// ends. So we cannot simply use app.isAnimating(PARENTS) to determine if the app must
|
||||
// to be added to the list of tokens to be notified of app transition complete.
|
||||
final WindowContainer wc = app.getAnimatingContainer(PARENTS,
|
||||
ANIMATION_TYPE_APP_TRANSITION);
|
||||
if (wc == null || !wc.getAnimationSources().contains(app)) {
|
||||
// This token isn't going to be animating. Add it to the list of tokens to
|
||||
// be notified of app transition complete since the notification will not be
|
||||
// sent be the app window animator.
|
||||
@@ -599,8 +601,7 @@ public class AppTransitionController {
|
||||
for (int i = 0; i < appsCount; i++) {
|
||||
WindowContainer wc = apps.valueAt(i);
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", wc);
|
||||
wc.applyAnimation(null, transit, true, false,
|
||||
null /* animationFinishedCallback */);
|
||||
wc.applyAnimation(null, transit, true, false, null /* sources */);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import static com.android.server.wm.AlphaAnimationSpecProto.TO;
|
||||
import static com.android.server.wm.AnimationSpecProto.ALPHA;
|
||||
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
@@ -31,7 +30,6 @@ import android.view.SurfaceControl;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.wm.SurfaceAnimator.AnimationType;
|
||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -160,8 +158,7 @@ class Dimmer {
|
||||
@VisibleForTesting
|
||||
interface SurfaceAnimatorStarter {
|
||||
void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t,
|
||||
AnimationAdapter anim, boolean hidden, @AnimationType int type,
|
||||
@Nullable OnAnimationFinishedCallback animationFinishedCallback);
|
||||
AnimationAdapter anim, boolean hidden, @AnimationType int type);
|
||||
}
|
||||
|
||||
Dimmer(WindowContainer host) {
|
||||
@@ -348,7 +345,7 @@ class Dimmer {
|
||||
mSurfaceAnimatorStarter.startAnimation(animator, t, new LocalAnimationAdapter(
|
||||
new AlphaAnimationSpec(startAlpha, endAlpha, getDimDuration(container)),
|
||||
mHost.mWmService.mSurfaceAnimationRunner), false /* hidden */,
|
||||
ANIMATION_TYPE_DIMMER, null /* animationFinishedCallback */);
|
||||
ANIMATION_TYPE_DIMMER);
|
||||
}
|
||||
|
||||
private long getDimDuration(WindowContainer container) {
|
||||
|
||||
@@ -280,7 +280,7 @@ class InsetsSourceProvider {
|
||||
}
|
||||
final Transaction t = mDisplayContent.getPendingTransaction();
|
||||
mWin.startAnimation(t, mAdapter, !mClientVisible /* hidden */,
|
||||
ANIMATION_TYPE_INSETS_CONTROL, null /* animationFinishedCallback */);
|
||||
ANIMATION_TYPE_INSETS_CONTROL);
|
||||
|
||||
// The leash was just created. We cannot dispatch it until its surface transaction is
|
||||
// applied. Otherwise, the client's operation to the leash might be overwritten by us.
|
||||
|
||||
@@ -104,7 +104,7 @@ public class ShellRoot {
|
||||
0 /* windowCornerRadius */),
|
||||
mDisplayContent.mWmService.mSurfaceAnimationRunner);
|
||||
mToken.startAnimation(mToken.getPendingTransaction(), adapter, false /* hidden */,
|
||||
ANIMATION_TYPE_WINDOW_ANIMATION, null /* animationFinishedCallback */);
|
||||
ANIMATION_TYPE_WINDOW_ANIMATION);
|
||||
}
|
||||
|
||||
WindowInfo getWindowInfo() {
|
||||
|
||||
@@ -85,7 +85,6 @@ import static com.android.server.wm.IdentifierProto.TITLE;
|
||||
import static com.android.server.wm.IdentifierProto.USER_ID;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
|
||||
import static com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
|
||||
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
|
||||
import static com.android.server.wm.WindowContainerChildProto.TASK;
|
||||
@@ -3495,7 +3494,7 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
@Override
|
||||
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
|
||||
int transit, boolean isVoiceInteraction,
|
||||
@Nullable OnAnimationFinishedCallback finishedCallback) {
|
||||
@Nullable ArrayList<WindowContainer> sources) {
|
||||
final RecentsAnimationController control = mWmService.getRecentsAnimationController();
|
||||
if (control != null) {
|
||||
// We let the transition to be controlled by RecentsAnimation, and callback task's
|
||||
@@ -3504,10 +3503,14 @@ class Task extends WindowContainer<WindowContainer> {
|
||||
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
|
||||
"applyAnimationUnchecked, control: %s, task: %s, transit: %s",
|
||||
control, asTask(), AppTransition.appTransitionToString(transit));
|
||||
control.addTaskToTargets(this, finishedCallback);
|
||||
control.addTaskToTargets(this, (type, anim) -> {
|
||||
for (int i = 0; i < sources.size(); ++i) {
|
||||
sources.get(i).onAnimationFinished(type, anim);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
|
||||
super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ import android.graphics.Rect;
|
||||
import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
import android.os.Trace;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Pair;
|
||||
import android.util.Pools;
|
||||
import android.util.Slog;
|
||||
@@ -181,6 +182,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
final SurfaceFreezer mSurfaceFreezer;
|
||||
protected final WindowManagerService mWmService;
|
||||
|
||||
/**
|
||||
* Sources which triggered a surface animation on this container. An animation target can be
|
||||
* promoted to higher level, for example, from a set of {@link ActivityRecord}s to
|
||||
* {@link ActivityStack}. In this case, {@link ActivityRecord}s are set on this variable while
|
||||
* the animation is running, and reset after finishing it.
|
||||
*/
|
||||
private final ArraySet<WindowContainer> mSurfaceAnimationSources = new ArraySet<>();
|
||||
|
||||
private final Point mTmpPos = new Point();
|
||||
protected final Point mLastSurfacePosition = new Point();
|
||||
|
||||
@@ -193,8 +202,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
*/
|
||||
private boolean mCommittedReparentToAnimationLeash;
|
||||
|
||||
private final Configuration mTmpConfig = new Configuration();
|
||||
|
||||
/** Interface for {@link #isAnimating} to check which cases for the container is animating. */
|
||||
public interface AnimationFlags {
|
||||
/**
|
||||
@@ -872,29 +879,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
* @see AnimationFlags#PARENTS
|
||||
* @see AnimationFlags#CHILDREN
|
||||
*/
|
||||
boolean isAnimating(int flags, int typesToCheck) {
|
||||
int animationType = mSurfaceAnimator.getAnimationType();
|
||||
if (mSurfaceAnimator.isAnimating() && (animationType & typesToCheck) > 0) {
|
||||
return true;
|
||||
}
|
||||
if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
|
||||
return true;
|
||||
}
|
||||
if ((flags & PARENTS) != 0) {
|
||||
final WindowContainer parent = getParent();
|
||||
if (parent != null && parent.isAnimating(flags & ~CHILDREN, typesToCheck)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if ((flags & CHILDREN) != 0) {
|
||||
for (int i = 0; i < mChildren.size(); ++i) {
|
||||
final WindowContainer wc = mChildren.get(i);
|
||||
if (wc.isAnimating(flags & ~PARENTS, typesToCheck)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
final boolean isAnimating(int flags, int typesToCheck) {
|
||||
return getAnimatingContainer(flags, typesToCheck) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -904,16 +890,20 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
* checking animating status.
|
||||
* @param typesToExclude The combination of bitmask {@link AnimationType} to exclude when
|
||||
* checking if animating.
|
||||
*
|
||||
* @deprecated Use {@link #isAnimating(int, int)}
|
||||
*/
|
||||
boolean isAnimatingExcluding(int flags, int typesToExclude) {
|
||||
@Deprecated
|
||||
final boolean isAnimatingExcluding(int flags, int typesToExclude) {
|
||||
return isAnimating(flags, ANIMATION_TYPE_ALL & ~typesToExclude);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #isAnimating(int, int)
|
||||
* @deprecated Use {@link #isAnimating(int, int)}
|
||||
* TODO (b/152333373): Migrate calls to use isAnimating with specified animation type
|
||||
*/
|
||||
boolean isAnimating(int flags) {
|
||||
@Deprecated
|
||||
final boolean isAnimating(int flags) {
|
||||
return isAnimating(flags, ANIMATION_TYPE_ALL);
|
||||
}
|
||||
|
||||
@@ -2107,10 +2097,15 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
}
|
||||
|
||||
void cancelAnimation() {
|
||||
doAnimationFinished(mSurfaceAnimator.getAnimationType(), mSurfaceAnimator.getAnimation());
|
||||
mSurfaceAnimator.cancelAnimation();
|
||||
mSurfaceFreezer.unfreeze(getPendingTransaction());
|
||||
}
|
||||
|
||||
ArraySet<WindowContainer> getAnimationSources() {
|
||||
return mSurfaceAnimationSources;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceControl getFreezeSnapshotTarget() {
|
||||
return null;
|
||||
@@ -2156,6 +2151,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
* @param transit The app transition type indicates what kind of transition to be applied.
|
||||
* @param enter Whether the app transition is entering transition or not.
|
||||
* @param isVoiceInteraction Whether the container is participating in voice interaction or not.
|
||||
* @param sources {@link ActivityRecord}s which causes this app transition animation.
|
||||
*
|
||||
* @return {@code true} when the container applied the app transition, {@code false} if the
|
||||
* app transition is disabled or skipped.
|
||||
@@ -2163,7 +2159,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
* @see #getAnimationAdapter
|
||||
*/
|
||||
boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||
boolean isVoiceInteraction, @Nullable OnAnimationFinishedCallback finishedCallback) {
|
||||
boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
|
||||
if (mWmService.mDisableTransitionAnimation) {
|
||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
|
||||
"applyAnimation: transition animation is disabled or skipped. "
|
||||
@@ -2178,7 +2174,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
try {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
|
||||
if (okToAnimate()) {
|
||||
applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
|
||||
applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
|
||||
} else {
|
||||
cancelAnimation();
|
||||
}
|
||||
@@ -2276,14 +2272,17 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
|
||||
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
|
||||
int transit, boolean isVoiceInteraction,
|
||||
@Nullable OnAnimationFinishedCallback finishedCallback) {
|
||||
@Nullable ArrayList<WindowContainer> sources) {
|
||||
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
|
||||
transit, enter, isVoiceInteraction);
|
||||
AnimationAdapter adapter = adapters.first;
|
||||
AnimationAdapter thumbnailAdapter = adapters.second;
|
||||
if (adapter != null) {
|
||||
if (sources != null) {
|
||||
mSurfaceAnimationSources.addAll(sources);
|
||||
}
|
||||
startAnimation(getPendingTransaction(), adapter, !isVisible(),
|
||||
ANIMATION_TYPE_APP_TRANSITION, finishedCallback);
|
||||
ANIMATION_TYPE_APP_TRANSITION);
|
||||
if (adapter.getShowWallpaper()) {
|
||||
getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
|
||||
}
|
||||
@@ -2411,10 +2410,18 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
updateSurfacePosition(t);
|
||||
}
|
||||
|
||||
private void doAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
|
||||
for (int i = 0; i < mSurfaceAnimationSources.size(); ++i) {
|
||||
mSurfaceAnimationSources.valueAt(i).onAnimationFinished(type, anim);
|
||||
}
|
||||
mSurfaceAnimationSources.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an animation has finished running.
|
||||
*/
|
||||
protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
|
||||
doAnimationFinished(type, anim);
|
||||
mWmService.onAnimationFinished();
|
||||
}
|
||||
|
||||
@@ -2428,16 +2435,66 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
/**
|
||||
* @return The {@link WindowContainer} which is running an animation.
|
||||
*
|
||||
* It traverses from the current container to its parents recursively. If nothing is animating,
|
||||
* it will return {@code null}.
|
||||
* By default this only checks if this container itself is actually running an animation, but
|
||||
* you can extend the check target over its relatives, or relax the condition so that this can
|
||||
* return {@code WindowContainer} if an animation starts soon by giving a combination
|
||||
* of {@link AnimationFlags}.
|
||||
*
|
||||
* Note that you can give a combination of bitmask flags to specify targets and condition for
|
||||
* checking animating status.
|
||||
* e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
|
||||
* container itself or one of its parents is running an animation or waiting for an app
|
||||
* transition.
|
||||
*
|
||||
* Note that TRANSITION propagates to parents and children as well.
|
||||
*
|
||||
* @param flags The combination of bitmask flags to specify targets and condition for
|
||||
* checking animating status.
|
||||
* @param typesToCheck The combination of bitmask {@link AnimationType} to compare when
|
||||
* determining if animating.
|
||||
*
|
||||
* @see AnimationFlags#TRANSITION
|
||||
* @see AnimationFlags#PARENTS
|
||||
* @see AnimationFlags#CHILDREN
|
||||
*/
|
||||
@Nullable
|
||||
WindowContainer getAnimatingContainer() {
|
||||
if (isAnimating()) {
|
||||
WindowContainer getAnimatingContainer(int flags, int typesToCheck) {
|
||||
int animationType = mSurfaceAnimator.getAnimationType();
|
||||
if (mSurfaceAnimator.isAnimating() && (animationType & typesToCheck) > 0) {
|
||||
return this;
|
||||
}
|
||||
final WindowContainer parent = getParent();
|
||||
return (parent != null) ? parent.getAnimatingContainer() : null;
|
||||
if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
|
||||
return this;
|
||||
}
|
||||
if ((flags & PARENTS) != 0) {
|
||||
final WindowContainer parent = getParent();
|
||||
if (parent != null) {
|
||||
final WindowContainer wc = parent.getAnimatingContainer(
|
||||
flags & ~CHILDREN, typesToCheck);
|
||||
if (wc != null) {
|
||||
return wc;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((flags & CHILDREN) != 0) {
|
||||
for (int i = 0; i < mChildren.size(); ++i) {
|
||||
final WindowContainer wc = mChildren.get(i).getAnimatingContainer(
|
||||
flags & ~PARENTS, typesToCheck);
|
||||
if (wc != null) {
|
||||
return wc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getAnimatingContainer(int, int)} instead.
|
||||
*/
|
||||
@Nullable
|
||||
@Deprecated
|
||||
final WindowContainer getAnimatingContainer() {
|
||||
return getAnimatingContainer(PARENTS, ANIMATION_TYPE_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -133,15 +133,14 @@ class WindowContainerThumbnail implements Animatable {
|
||||
mWindowContainer.getDisplayContent().mAppTransition.canSkipFirstFrame(),
|
||||
mWindowContainer.getDisplayContent().getWindowCornerRadius()),
|
||||
mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */,
|
||||
ANIMATION_TYPE_RECENTS, null /* animationFinishedCallback */);
|
||||
ANIMATION_TYPE_RECENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start animation with existing adapter.
|
||||
*/
|
||||
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
|
||||
mSurfaceAnimator.startAnimation(t, anim, hidden, ANIMATION_TYPE_RECENTS,
|
||||
null /* animationFinishedCallback */);
|
||||
mSurfaceAnimator.startAnimation(t, anim, hidden, ANIMATION_TYPE_RECENTS);
|
||||
}
|
||||
|
||||
private void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
|
||||
|
||||
@@ -5049,16 +5049,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
mWindowFrames.updateLastInsetValues();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
boolean isAnimating(int flags, int typesToCheck) {
|
||||
|
||||
// If we are an inset provider, all our animations are driven by the inset client, so we
|
||||
// aren't really animating.
|
||||
// TODO: Replace this with a proper animation type system.
|
||||
WindowContainer<WindowState> getAnimatingContainer(int flags, int typesToCheck) {
|
||||
if (mControllableInsetProvider != null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
return super.isAnimating(flags, typesToCheck);
|
||||
return super.getAnimatingContainer(flags, typesToCheck);
|
||||
}
|
||||
|
||||
void startAnimation(Animation anim) {
|
||||
@@ -5101,8 +5098,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
private void startAnimation(Transaction t, AnimationAdapter adapter) {
|
||||
startAnimation(t, adapter, mWinAnimator.mLastHidden, ANIMATION_TYPE_WINDOW_ANIMATION,
|
||||
null /* animationFinishedCallback */);
|
||||
startAnimation(t, adapter, mWinAnimator.mLastHidden, ANIMATION_TYPE_WINDOW_ANIMATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,7 +38,6 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
|
||||
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
|
||||
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
|
||||
@@ -65,12 +64,12 @@ import android.view.WindowManager;
|
||||
import androidx.test.filters.FlakyTest;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Tests for the {@link ActivityRecord} class.
|
||||
*
|
||||
@@ -406,12 +405,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
assertHasStartingWindow(activity2);
|
||||
|
||||
// Assert that bottom activity is allowed to do animation.
|
||||
ArrayList<WindowContainer> sources = new ArrayList<>();
|
||||
sources.add(activity2);
|
||||
doReturn(true).when(activity2).okToAnimate();
|
||||
doReturn(true).when(activity2).isAnimating();
|
||||
final OnAnimationFinishedCallback onAnimationFinishedCallback =
|
||||
mock(OnAnimationFinishedCallback.class);
|
||||
assertTrue(activity2.applyAnimation(null, TRANSIT_ACTIVITY_OPEN, true, false,
|
||||
onAnimationFinishedCallback));
|
||||
assertTrue(activity2.applyAnimation(null, TRANSIT_ACTIVITY_OPEN, true, false, sources));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -29,18 +29,14 @@ import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.isNull;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Rect;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceSession;
|
||||
|
||||
import com.android.server.wm.SurfaceAnimator.AnimationType;
|
||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -119,12 +115,8 @@ public class DimmerTests extends WindowTestsBase {
|
||||
private static class SurfaceAnimatorStarterImpl implements Dimmer.SurfaceAnimatorStarter {
|
||||
@Override
|
||||
public void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t,
|
||||
AnimationAdapter anim, boolean hidden, @AnimationType int type,
|
||||
@Nullable OnAnimationFinishedCallback animationFinishedCallback) {
|
||||
AnimationAdapter anim, boolean hidden, @AnimationType int type) {
|
||||
surfaceAnimator.mStaticAnimationFinishedCallback.onAnimationFinished(type, anim);
|
||||
if (animationFinishedCallback != null) {
|
||||
animationFinishedCallback.onAnimationFinished(type, anim);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +221,7 @@ public class DimmerTests extends WindowTestsBase {
|
||||
mDimmer.updateDims(mTransaction, new Rect());
|
||||
verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any(
|
||||
SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean(),
|
||||
eq(ANIMATION_TYPE_DIMMER), isNull());
|
||||
eq(ANIMATION_TYPE_DIMMER));
|
||||
verify(mHost.getPendingTransaction()).remove(dimLayer);
|
||||
}
|
||||
|
||||
@@ -287,7 +279,7 @@ public class DimmerTests extends WindowTestsBase {
|
||||
mDimmer.updateDims(mTransaction, new Rect());
|
||||
verify(mSurfaceAnimatorStarter, never()).startAnimation(any(SurfaceAnimator.class), any(
|
||||
SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean(),
|
||||
eq(ANIMATION_TYPE_DIMMER), isNull());
|
||||
eq(ANIMATION_TYPE_DIMMER));
|
||||
verify(mTransaction).remove(dimLayer);
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,8 @@ public class TaskStackTests extends WindowTestsBase {
|
||||
|
||||
// Stack removal is deferred if one of its child is animating.
|
||||
doReturn(true).when(stack).hasWindowsAlive();
|
||||
doReturn(true).when(task).isAnimating(eq(TRANSITION | CHILDREN), anyInt());
|
||||
doReturn(stack).when(task).getAnimatingContainer(
|
||||
eq(TRANSITION | CHILDREN), anyInt());
|
||||
|
||||
stack.removeIfPossible();
|
||||
// For the case of deferred removal the task controller will still be connected to the its
|
||||
|
||||
@@ -66,14 +66,14 @@ import android.view.SurfaceSession;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
|
||||
|
||||
/**
|
||||
* Test class for {@link WindowContainer}.
|
||||
*
|
||||
@@ -828,17 +828,21 @@ public class WindowContainerTests extends WindowTestsBase {
|
||||
public void testTaskCanApplyAnimation() {
|
||||
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
|
||||
final Task task = createTaskInStack(stack, 0 /* userId */);
|
||||
final ActivityRecord activity =
|
||||
final ActivityRecord activity2 =
|
||||
WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
|
||||
verifyWindowContainerApplyAnimation(task, activity);
|
||||
final ActivityRecord activity1 =
|
||||
WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
|
||||
verifyWindowContainerApplyAnimation(task, activity1, activity2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStackCanApplyAnimation() {
|
||||
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
|
||||
final ActivityRecord activity = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
|
||||
final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
|
||||
createTaskInStack(stack, 0 /* userId */));
|
||||
verifyWindowContainerApplyAnimation(stack, activity);
|
||||
final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
|
||||
createTaskInStack(stack, 0 /* userId */));
|
||||
verifyWindowContainerApplyAnimation(stack, activity1, activity2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -871,7 +875,8 @@ public class WindowContainerTests extends WindowTestsBase {
|
||||
assertEquals(displayArea, displayArea.getDisplayArea());
|
||||
}
|
||||
|
||||
private void verifyWindowContainerApplyAnimation(WindowContainer wc, ActivityRecord act) {
|
||||
private void verifyWindowContainerApplyAnimation(WindowContainer wc, ActivityRecord act,
|
||||
ActivityRecord act2) {
|
||||
// Initial remote animation for app transition.
|
||||
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
|
||||
new IRemoteAnimationRunner.Stub() {
|
||||
@@ -895,17 +900,23 @@ public class WindowContainerTests extends WindowTestsBase {
|
||||
wc.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(adapter);
|
||||
spyOn(wc);
|
||||
doReturn(true).when(wc).okToAnimate();
|
||||
final OnAnimationFinishedCallback onAnimationFinishedCallback =
|
||||
mock(OnAnimationFinishedCallback.class);
|
||||
|
||||
// Make sure animating state is as expected after applied animation.
|
||||
assertTrue(wc.applyAnimation(null, TRANSIT_TASK_OPEN, true, false,
|
||||
onAnimationFinishedCallback));
|
||||
assertEquals(wc.getTopMostActivity(), act);
|
||||
|
||||
// Animation target is promoted from act to wc. act2 is a descendant of wc, but not a source
|
||||
// of the animation.
|
||||
ArrayList<WindowContainer<WindowState>> sources = new ArrayList<>();
|
||||
sources.add(act);
|
||||
assertTrue(wc.applyAnimation(null, TRANSIT_TASK_OPEN, true, false, sources));
|
||||
|
||||
assertEquals(act, wc.getTopMostActivity());
|
||||
assertTrue(wc.isAnimating());
|
||||
assertTrue(wc.isAnimating(0, ANIMATION_TYPE_APP_TRANSITION));
|
||||
assertTrue(wc.getAnimationSources().contains(act));
|
||||
assertFalse(wc.getAnimationSources().contains(act2));
|
||||
assertTrue(act.isAnimating(PARENTS));
|
||||
verify(onAnimationFinishedCallback, times(0)).onAnimationFinished(
|
||||
eq(ANIMATION_TYPE_APP_TRANSITION), any());
|
||||
assertTrue(act.isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION));
|
||||
assertEquals(wc, act.getAnimatingContainer(PARENTS, ANIMATION_TYPE_APP_TRANSITION));
|
||||
|
||||
// Make sure animation finish callback will be received and reset animating state after
|
||||
// animation finish.
|
||||
@@ -914,8 +925,6 @@ public class WindowContainerTests extends WindowTestsBase {
|
||||
verify(wc).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION), any());
|
||||
assertFalse(wc.isAnimating());
|
||||
assertFalse(act.isAnimating(PARENTS));
|
||||
verify(onAnimationFinishedCallback, times(1)).onAnimationFinished(
|
||||
eq(ANIMATION_TYPE_APP_TRANSITION), any());
|
||||
}
|
||||
|
||||
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
|
||||
|
||||
Reference in New Issue
Block a user