Merge "Ensure to trigger Activity#onEnterAnimationComplete" into rvc-dev
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.ActivityMetricsLogger.TransitionInfoSnapshot;
|
||||||
import com.android.server.wm.ActivityStack.ActivityState;
|
import com.android.server.wm.ActivityStack.ActivityState;
|
||||||
import com.android.server.wm.SurfaceAnimator.AnimationType;
|
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.WindowManagerService.H;
|
||||||
import com.android.server.wm.utils.InsetUtils;
|
import com.android.server.wm.utils.InsetUtils;
|
||||||
|
|
||||||
@@ -4166,14 +4165,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
boolean applyAnimation(LayoutParams lp, int transit, boolean enter,
|
||||||
boolean isVoiceInteraction,
|
boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
|
||||||
@Nullable OnAnimationFinishedCallback animationFinishedCallback) {
|
|
||||||
if (mUseTransferredAnimation) {
|
if (mUseTransferredAnimation) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return super.applyAnimation(lp, transit, enter, isVoiceInteraction,
|
return super.applyAnimation(lp, transit, enter, isVoiceInteraction, sources);
|
||||||
animationFinishedCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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.AppTransition.isKeyguardGoingAwayTransit;
|
||||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
|
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.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.WindowContainer.AnimationFlags.PARENTS;
|
||||||
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
|
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
|
||||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
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.LinkedList;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for app transition readiness, resolves animation attributes and performs visibility
|
* Checks for app transition readiness, resolves animation attributes and performs visibility
|
||||||
* change for apps that animate as part of an app transition.
|
* 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
|
// 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
|
// of triggering AR#onAnimationFinished on each ActivityRecord which is a part of the
|
||||||
// app transition.
|
// app transition.
|
||||||
final ArrayList<ActivityRecord> transitioningDecendants = new ArrayList<>();
|
final ArrayList<ActivityRecord> transitioningDescendants = new ArrayList<>();
|
||||||
for (int j = 0; j < apps.size(); ++j) {
|
for (int j = 0; j < apps.size(); ++j) {
|
||||||
final ActivityRecord app = apps.valueAt(j);
|
final ActivityRecord app = apps.valueAt(j);
|
||||||
if (app.isDescendantOf(wc)) {
|
if (app.isDescendantOf(wc)) {
|
||||||
transitioningDecendants.add(app);
|
transitioningDescendants.add(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wc.applyAnimation(animLp, transit, visible, voiceInteraction, (type, anim) -> {
|
wc.applyAnimation(animLp, transit, visible, voiceInteraction, transitioningDescendants);
|
||||||
for (int j = 0; j < transitioningDecendants.size(); ++j) {
|
|
||||||
transitioningDecendants.get(j).onAnimationFinished(type, anim);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +535,14 @@ public class AppTransitionController {
|
|||||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", app);
|
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now opening app %s", app);
|
||||||
|
|
||||||
app.commitVisibility(true /* visible */, false /* performLayout */);
|
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
|
// 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
|
// be notified of app transition complete since the notification will not be
|
||||||
// sent be the app window animator.
|
// sent be the app window animator.
|
||||||
@@ -599,8 +601,7 @@ public class AppTransitionController {
|
|||||||
for (int i = 0; i < appsCount; i++) {
|
for (int i = 0; i < appsCount; i++) {
|
||||||
WindowContainer wc = apps.valueAt(i);
|
WindowContainer wc = apps.valueAt(i);
|
||||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", wc);
|
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", wc);
|
||||||
wc.applyAnimation(null, transit, true, false,
|
wc.applyAnimation(null, transit, true, false, null /* sources */);
|
||||||
null /* animationFinishedCallback */);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.AnimationSpecProto.ALPHA;
|
||||||
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER;
|
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_DIMMER;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.proto.ProtoOutputStream;
|
import android.util.proto.ProtoOutputStream;
|
||||||
@@ -31,7 +30,6 @@ import android.view.SurfaceControl;
|
|||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.server.wm.SurfaceAnimator.AnimationType;
|
import com.android.server.wm.SurfaceAnimator.AnimationType;
|
||||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
@@ -160,8 +158,7 @@ class Dimmer {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
interface SurfaceAnimatorStarter {
|
interface SurfaceAnimatorStarter {
|
||||||
void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t,
|
void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t,
|
||||||
AnimationAdapter anim, boolean hidden, @AnimationType int type,
|
AnimationAdapter anim, boolean hidden, @AnimationType int type);
|
||||||
@Nullable OnAnimationFinishedCallback animationFinishedCallback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Dimmer(WindowContainer host) {
|
Dimmer(WindowContainer host) {
|
||||||
@@ -348,7 +345,7 @@ class Dimmer {
|
|||||||
mSurfaceAnimatorStarter.startAnimation(animator, t, new LocalAnimationAdapter(
|
mSurfaceAnimatorStarter.startAnimation(animator, t, new LocalAnimationAdapter(
|
||||||
new AlphaAnimationSpec(startAlpha, endAlpha, getDimDuration(container)),
|
new AlphaAnimationSpec(startAlpha, endAlpha, getDimDuration(container)),
|
||||||
mHost.mWmService.mSurfaceAnimationRunner), false /* hidden */,
|
mHost.mWmService.mSurfaceAnimationRunner), false /* hidden */,
|
||||||
ANIMATION_TYPE_DIMMER, null /* animationFinishedCallback */);
|
ANIMATION_TYPE_DIMMER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getDimDuration(WindowContainer container) {
|
private long getDimDuration(WindowContainer container) {
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ class InsetsSourceProvider {
|
|||||||
}
|
}
|
||||||
final Transaction t = mDisplayContent.getPendingTransaction();
|
final Transaction t = mDisplayContent.getPendingTransaction();
|
||||||
mWin.startAnimation(t, mAdapter, !mClientVisible /* hidden */,
|
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
|
// 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.
|
// applied. Otherwise, the client's operation to the leash might be overwritten by us.
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class ShellRoot {
|
|||||||
0 /* windowCornerRadius */),
|
0 /* windowCornerRadius */),
|
||||||
mDisplayContent.mWmService.mSurfaceAnimationRunner);
|
mDisplayContent.mWmService.mSurfaceAnimationRunner);
|
||||||
mToken.startAnimation(mToken.getPendingTransaction(), adapter, false /* hidden */,
|
mToken.startAnimation(mToken.getPendingTransaction(), adapter, false /* hidden */,
|
||||||
ANIMATION_TYPE_WINDOW_ANIMATION, null /* animationFinishedCallback */);
|
ANIMATION_TYPE_WINDOW_ANIMATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowInfo getWindowInfo() {
|
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.IdentifierProto.USER_ID;
|
||||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
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.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.CHILDREN;
|
||||||
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
|
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
|
||||||
import static com.android.server.wm.WindowContainerChildProto.TASK;
|
import static com.android.server.wm.WindowContainerChildProto.TASK;
|
||||||
@@ -3495,7 +3494,7 @@ class Task extends WindowContainer<WindowContainer> {
|
|||||||
@Override
|
@Override
|
||||||
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
|
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
|
||||||
int transit, boolean isVoiceInteraction,
|
int transit, boolean isVoiceInteraction,
|
||||||
@Nullable OnAnimationFinishedCallback finishedCallback) {
|
@Nullable ArrayList<WindowContainer> sources) {
|
||||||
final RecentsAnimationController control = mWmService.getRecentsAnimationController();
|
final RecentsAnimationController control = mWmService.getRecentsAnimationController();
|
||||||
if (control != null) {
|
if (control != null) {
|
||||||
// We let the transition to be controlled by RecentsAnimation, and callback task's
|
// 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,
|
ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
|
||||||
"applyAnimationUnchecked, control: %s, task: %s, transit: %s",
|
"applyAnimationUnchecked, control: %s, task: %s, transit: %s",
|
||||||
control, asTask(), AppTransition.appTransitionToString(transit));
|
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 {
|
} 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.Debug;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.Pools;
|
import android.util.Pools;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -181,6 +182,14 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
final SurfaceFreezer mSurfaceFreezer;
|
final SurfaceFreezer mSurfaceFreezer;
|
||||||
protected final WindowManagerService mWmService;
|
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();
|
private final Point mTmpPos = new Point();
|
||||||
protected final Point mLastSurfacePosition = new Point();
|
protected final Point mLastSurfacePosition = new Point();
|
||||||
|
|
||||||
@@ -193,8 +202,6 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
*/
|
*/
|
||||||
private boolean mCommittedReparentToAnimationLeash;
|
private boolean mCommittedReparentToAnimationLeash;
|
||||||
|
|
||||||
private final Configuration mTmpConfig = new Configuration();
|
|
||||||
|
|
||||||
/** Interface for {@link #isAnimating} to check which cases for the container is animating. */
|
/** Interface for {@link #isAnimating} to check which cases for the container is animating. */
|
||||||
public interface AnimationFlags {
|
public interface AnimationFlags {
|
||||||
/**
|
/**
|
||||||
@@ -872,29 +879,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
* @see AnimationFlags#PARENTS
|
* @see AnimationFlags#PARENTS
|
||||||
* @see AnimationFlags#CHILDREN
|
* @see AnimationFlags#CHILDREN
|
||||||
*/
|
*/
|
||||||
boolean isAnimating(int flags, int typesToCheck) {
|
final boolean isAnimating(int flags, int typesToCheck) {
|
||||||
int animationType = mSurfaceAnimator.getAnimationType();
|
return getAnimatingContainer(flags, typesToCheck) != null;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -904,16 +890,20 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
* checking animating status.
|
* checking animating status.
|
||||||
* @param typesToExclude The combination of bitmask {@link AnimationType} to exclude when
|
* @param typesToExclude The combination of bitmask {@link AnimationType} to exclude when
|
||||||
* checking if animating.
|
* 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);
|
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
|
* 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);
|
return isAnimating(flags, ANIMATION_TYPE_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2107,10 +2097,15 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cancelAnimation() {
|
void cancelAnimation() {
|
||||||
|
doAnimationFinished(mSurfaceAnimator.getAnimationType(), mSurfaceAnimator.getAnimation());
|
||||||
mSurfaceAnimator.cancelAnimation();
|
mSurfaceAnimator.cancelAnimation();
|
||||||
mSurfaceFreezer.unfreeze(getPendingTransaction());
|
mSurfaceFreezer.unfreeze(getPendingTransaction());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArraySet<WindowContainer> getAnimationSources() {
|
||||||
|
return mSurfaceAnimationSources;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SurfaceControl getFreezeSnapshotTarget() {
|
public SurfaceControl getFreezeSnapshotTarget() {
|
||||||
return null;
|
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 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 enter Whether the app transition is entering transition or not.
|
||||||
* @param isVoiceInteraction Whether the container is participating in voice interaction 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
|
* @return {@code true} when the container applied the app transition, {@code false} if the
|
||||||
* app transition is disabled or skipped.
|
* app transition is disabled or skipped.
|
||||||
@@ -2163,7 +2159,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
* @see #getAnimationAdapter
|
* @see #getAnimationAdapter
|
||||||
*/
|
*/
|
||||||
boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
|
||||||
boolean isVoiceInteraction, @Nullable OnAnimationFinishedCallback finishedCallback) {
|
boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
|
||||||
if (mWmService.mDisableTransitionAnimation) {
|
if (mWmService.mDisableTransitionAnimation) {
|
||||||
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
|
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
|
||||||
"applyAnimation: transition animation is disabled or skipped. "
|
"applyAnimation: transition animation is disabled or skipped. "
|
||||||
@@ -2178,7 +2174,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
try {
|
try {
|
||||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
|
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
|
||||||
if (okToAnimate()) {
|
if (okToAnimate()) {
|
||||||
applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
|
applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
|
||||||
} else {
|
} else {
|
||||||
cancelAnimation();
|
cancelAnimation();
|
||||||
}
|
}
|
||||||
@@ -2276,14 +2272,17 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
|
|
||||||
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
|
protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
|
||||||
int transit, boolean isVoiceInteraction,
|
int transit, boolean isVoiceInteraction,
|
||||||
@Nullable OnAnimationFinishedCallback finishedCallback) {
|
@Nullable ArrayList<WindowContainer> sources) {
|
||||||
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
|
final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
|
||||||
transit, enter, isVoiceInteraction);
|
transit, enter, isVoiceInteraction);
|
||||||
AnimationAdapter adapter = adapters.first;
|
AnimationAdapter adapter = adapters.first;
|
||||||
AnimationAdapter thumbnailAdapter = adapters.second;
|
AnimationAdapter thumbnailAdapter = adapters.second;
|
||||||
if (adapter != null) {
|
if (adapter != null) {
|
||||||
|
if (sources != null) {
|
||||||
|
mSurfaceAnimationSources.addAll(sources);
|
||||||
|
}
|
||||||
startAnimation(getPendingTransaction(), adapter, !isVisible(),
|
startAnimation(getPendingTransaction(), adapter, !isVisible(),
|
||||||
ANIMATION_TYPE_APP_TRANSITION, finishedCallback);
|
ANIMATION_TYPE_APP_TRANSITION);
|
||||||
if (adapter.getShowWallpaper()) {
|
if (adapter.getShowWallpaper()) {
|
||||||
getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
|
getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
|
||||||
}
|
}
|
||||||
@@ -2411,10 +2410,18 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
updateSurfacePosition(t);
|
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.
|
* Called when an animation has finished running.
|
||||||
*/
|
*/
|
||||||
protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
|
protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
|
||||||
|
doAnimationFinished(type, anim);
|
||||||
mWmService.onAnimationFinished();
|
mWmService.onAnimationFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2428,16 +2435,66 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
|||||||
/**
|
/**
|
||||||
* @return The {@link WindowContainer} which is running an animation.
|
* @return The {@link WindowContainer} which is running an animation.
|
||||||
*
|
*
|
||||||
* It traverses from the current container to its parents recursively. If nothing is animating,
|
* By default this only checks if this container itself is actually running an animation, but
|
||||||
* it will return {@code null}.
|
* 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
|
@Nullable
|
||||||
WindowContainer getAnimatingContainer() {
|
WindowContainer getAnimatingContainer(int flags, int typesToCheck) {
|
||||||
if (isAnimating()) {
|
int animationType = mSurfaceAnimator.getAnimationType();
|
||||||
|
if (mSurfaceAnimator.isAnimating() && (animationType & typesToCheck) > 0) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
final WindowContainer parent = getParent();
|
if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
|
||||||
return (parent != null) ? parent.getAnimatingContainer() : null;
|
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().mAppTransition.canSkipFirstFrame(),
|
||||||
mWindowContainer.getDisplayContent().getWindowCornerRadius()),
|
mWindowContainer.getDisplayContent().getWindowCornerRadius()),
|
||||||
mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */,
|
mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */,
|
||||||
ANIMATION_TYPE_RECENTS, null /* animationFinishedCallback */);
|
ANIMATION_TYPE_RECENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start animation with existing adapter.
|
* Start animation with existing adapter.
|
||||||
*/
|
*/
|
||||||
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
|
void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
|
||||||
mSurfaceAnimator.startAnimation(t, anim, hidden, ANIMATION_TYPE_RECENTS,
|
mSurfaceAnimator.startAnimation(t, anim, hidden, ANIMATION_TYPE_RECENTS);
|
||||||
null /* animationFinishedCallback */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
|
private void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
|
||||||
|
|||||||
@@ -5049,16 +5049,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
|||||||
mWindowFrames.updateLastInsetValues();
|
mWindowFrames.updateLastInsetValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
boolean isAnimating(int flags, int typesToCheck) {
|
WindowContainer<WindowState> getAnimatingContainer(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.
|
|
||||||
if (mControllableInsetProvider != null) {
|
if (mControllableInsetProvider != null) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
return super.isAnimating(flags, typesToCheck);
|
return super.getAnimatingContainer(flags, typesToCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startAnimation(Animation anim) {
|
void startAnimation(Animation anim) {
|
||||||
@@ -5101,8 +5098,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startAnimation(Transaction t, AnimationAdapter adapter) {
|
private void startAnimation(Transaction t, AnimationAdapter adapter) {
|
||||||
startAnimation(t, adapter, mWinAnimator.mLastHidden, ANIMATION_TYPE_WINDOW_ANIMATION,
|
startAnimation(t, adapter, mWinAnimator.mLastHidden, ANIMATION_TYPE_WINDOW_ANIMATION);
|
||||||
null /* animationFinishedCallback */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.doCallRealMethod;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
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_AFTER_ANIM;
|
||||||
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
|
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
|
||||||
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
|
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.FlakyTest;
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for the {@link ActivityRecord} class.
|
* Tests for the {@link ActivityRecord} class.
|
||||||
*
|
*
|
||||||
@@ -406,12 +405,11 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
|||||||
assertHasStartingWindow(activity2);
|
assertHasStartingWindow(activity2);
|
||||||
|
|
||||||
// Assert that bottom activity is allowed to do animation.
|
// 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).okToAnimate();
|
||||||
doReturn(true).when(activity2).isAnimating();
|
doReturn(true).when(activity2).isAnimating();
|
||||||
final OnAnimationFinishedCallback onAnimationFinishedCallback =
|
assertTrue(activity2.applyAnimation(null, TRANSIT_ACTIVITY_OPEN, true, false, sources));
|
||||||
mock(OnAnimationFinishedCallback.class);
|
|
||||||
assertTrue(activity2.applyAnimation(null, TRANSIT_ACTIVITY_OPEN, true, false,
|
|
||||||
onAnimationFinishedCallback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -29,18 +29,14 @@ import static org.junit.Assert.assertNotNull;
|
|||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
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 static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.SurfaceSession;
|
import android.view.SurfaceSession;
|
||||||
|
|
||||||
import com.android.server.wm.SurfaceAnimator.AnimationType;
|
import com.android.server.wm.SurfaceAnimator.AnimationType;
|
||||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -119,12 +115,8 @@ public class DimmerTests extends WindowTestsBase {
|
|||||||
private static class SurfaceAnimatorStarterImpl implements Dimmer.SurfaceAnimatorStarter {
|
private static class SurfaceAnimatorStarterImpl implements Dimmer.SurfaceAnimatorStarter {
|
||||||
@Override
|
@Override
|
||||||
public void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t,
|
public void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t,
|
||||||
AnimationAdapter anim, boolean hidden, @AnimationType int type,
|
AnimationAdapter anim, boolean hidden, @AnimationType int type) {
|
||||||
@Nullable OnAnimationFinishedCallback animationFinishedCallback) {
|
|
||||||
surfaceAnimator.mStaticAnimationFinishedCallback.onAnimationFinished(type, anim);
|
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());
|
mDimmer.updateDims(mTransaction, new Rect());
|
||||||
verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any(
|
verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any(
|
||||||
SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean(),
|
SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean(),
|
||||||
eq(ANIMATION_TYPE_DIMMER), isNull());
|
eq(ANIMATION_TYPE_DIMMER));
|
||||||
verify(mHost.getPendingTransaction()).remove(dimLayer);
|
verify(mHost.getPendingTransaction()).remove(dimLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +279,7 @@ public class DimmerTests extends WindowTestsBase {
|
|||||||
mDimmer.updateDims(mTransaction, new Rect());
|
mDimmer.updateDims(mTransaction, new Rect());
|
||||||
verify(mSurfaceAnimatorStarter, never()).startAnimation(any(SurfaceAnimator.class), any(
|
verify(mSurfaceAnimatorStarter, never()).startAnimation(any(SurfaceAnimator.class), any(
|
||||||
SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean(),
|
SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean(),
|
||||||
eq(ANIMATION_TYPE_DIMMER), isNull());
|
eq(ANIMATION_TYPE_DIMMER));
|
||||||
verify(mTransaction).remove(dimLayer);
|
verify(mTransaction).remove(dimLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,7 +153,8 @@ public class TaskStackTests extends WindowTestsBase {
|
|||||||
|
|
||||||
// Stack removal is deferred if one of its child is animating.
|
// Stack removal is deferred if one of its child is animating.
|
||||||
doReturn(true).when(stack).hasWindowsAlive();
|
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();
|
stack.removeIfPossible();
|
||||||
// For the case of deferred removal the task controller will still be connected to the its
|
// 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 androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test class for {@link WindowContainer}.
|
* Test class for {@link WindowContainer}.
|
||||||
*
|
*
|
||||||
@@ -828,17 +828,21 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
public void testTaskCanApplyAnimation() {
|
public void testTaskCanApplyAnimation() {
|
||||||
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
|
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
|
||||||
final Task task = createTaskInStack(stack, 0 /* userId */);
|
final Task task = createTaskInStack(stack, 0 /* userId */);
|
||||||
final ActivityRecord activity =
|
final ActivityRecord activity2 =
|
||||||
WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
|
WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
|
||||||
verifyWindowContainerApplyAnimation(task, activity);
|
final ActivityRecord activity1 =
|
||||||
|
WindowTestUtils.createActivityRecordInTask(mDisplayContent, task);
|
||||||
|
verifyWindowContainerApplyAnimation(task, activity1, activity2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStackCanApplyAnimation() {
|
public void testStackCanApplyAnimation() {
|
||||||
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
|
final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
|
||||||
final ActivityRecord activity = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
|
final ActivityRecord activity2 = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
|
||||||
createTaskInStack(stack, 0 /* userId */));
|
createTaskInStack(stack, 0 /* userId */));
|
||||||
verifyWindowContainerApplyAnimation(stack, activity);
|
final ActivityRecord activity1 = WindowTestUtils.createActivityRecordInTask(mDisplayContent,
|
||||||
|
createTaskInStack(stack, 0 /* userId */));
|
||||||
|
verifyWindowContainerApplyAnimation(stack, activity1, activity2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -871,7 +875,8 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
assertEquals(displayArea, displayArea.getDisplayArea());
|
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.
|
// Initial remote animation for app transition.
|
||||||
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
|
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
|
||||||
new IRemoteAnimationRunner.Stub() {
|
new IRemoteAnimationRunner.Stub() {
|
||||||
@@ -895,17 +900,23 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
wc.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(adapter);
|
wc.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(adapter);
|
||||||
spyOn(wc);
|
spyOn(wc);
|
||||||
doReturn(true).when(wc).okToAnimate();
|
doReturn(true).when(wc).okToAnimate();
|
||||||
final OnAnimationFinishedCallback onAnimationFinishedCallback =
|
|
||||||
mock(OnAnimationFinishedCallback.class);
|
|
||||||
|
|
||||||
// Make sure animating state is as expected after applied animation.
|
// Make sure animating state is as expected after applied animation.
|
||||||
assertTrue(wc.applyAnimation(null, TRANSIT_TASK_OPEN, true, false,
|
|
||||||
onAnimationFinishedCallback));
|
// Animation target is promoted from act to wc. act2 is a descendant of wc, but not a source
|
||||||
assertEquals(wc.getTopMostActivity(), act);
|
// 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());
|
||||||
|
assertTrue(wc.isAnimating(0, ANIMATION_TYPE_APP_TRANSITION));
|
||||||
|
assertTrue(wc.getAnimationSources().contains(act));
|
||||||
|
assertFalse(wc.getAnimationSources().contains(act2));
|
||||||
assertTrue(act.isAnimating(PARENTS));
|
assertTrue(act.isAnimating(PARENTS));
|
||||||
verify(onAnimationFinishedCallback, times(0)).onAnimationFinished(
|
assertTrue(act.isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION));
|
||||||
eq(ANIMATION_TYPE_APP_TRANSITION), any());
|
assertEquals(wc, act.getAnimatingContainer(PARENTS, ANIMATION_TYPE_APP_TRANSITION));
|
||||||
|
|
||||||
// Make sure animation finish callback will be received and reset animating state after
|
// Make sure animation finish callback will be received and reset animating state after
|
||||||
// animation finish.
|
// animation finish.
|
||||||
@@ -914,8 +925,6 @@ public class WindowContainerTests extends WindowTestsBase {
|
|||||||
verify(wc).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION), any());
|
verify(wc).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION), any());
|
||||||
assertFalse(wc.isAnimating());
|
assertFalse(wc.isAnimating());
|
||||||
assertFalse(act.isAnimating(PARENTS));
|
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 */
|
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
|
||||||
|
|||||||
Reference in New Issue
Block a user