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

Commit 9bca6b43 authored by lumark's avatar lumark
Browse files

Unify animation methods into new WindowContainer#isAnimating()

In previous design, WindowContainer defined 3 types of checking animating methods:
- isSelfAnimating: check if container its self is animating.
- isAnimating: check if container its self or its parent is animating.
- isSelfOrChildAnimating: check if container its self or its child is animating.

But in ActivityRecord overrides isSelfAnimating to check if container is waiting for
App transition start or container its self animating.
Moreover, in ActivityRecord added isReallyAnimating method but it actually called
WC#isSelfAnimating, which is a bit weird and affect readibility.

As above mentioned, overrides isSelfAnimating will change the original method definition
behavior, like when WindowState calling isAnimating will also check if the parent is
waiting for app transition.

Or, when the container which is upper than ActivityRecord calling isSelfOrChildAnimating,
will Also need to check if child is waiting for app transition.

To disambiguate the method behavior, we unified animation methods into
new WindowContainer#isAnimating method, and defined TRANSITION / PARENTS / CHILDREN
checking scenarios, so the new method mapping will be:
- isSelfAnimating (from ActivityRecord) -> isAnimating(TRANSITION)
- isSelfAnimating (from WindowState) or isReallyAnimating -> WC#isAnimating(0)
- isAnimating -> isAnimating(TRANSITION | PARENTS)
- isSelfOrChildAnimating -> isAnimating(TRANSITION | CHILDREN)

Bug: 142617871
Bug: 131661052
Test: all existing tests passed
Change-Id: I3f8719c7d9f4607d03a6ea672a5fbfdcdfb0d967
parent d6e55406
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -231,7 +231,7 @@ message AppWindowTokenProto {
    optional WindowTokenProto window_token = 2;
    optional bool last_surface_showing = 3;
    optional bool is_waiting_for_transition_start = 4;
    optional bool is_really_animating = 5;
    optional bool is_animating = 5;
    optional AppWindowThumbnailProto thumbnail = 6;
    optional bool fills_parent = 7;
    optional bool app_stopped = 8;
+26 −53
Original line number Diff line number Diff line
@@ -179,7 +179,7 @@ import static com.android.server.wm.AppWindowTokenProto.FILLS_PARENT;
import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
@@ -205,6 +205,9 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.TaskPersister.DEBUG;
import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
@@ -297,10 +300,10 @@ import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
import com.android.internal.R;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.XmlUtils;
import com.android.server.AttributeCache;
@@ -332,7 +335,6 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * An entry in the history stack, representing an activity.
@@ -2305,7 +2307,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     * 2. App is delayed closing since it might enter PIP.
     */
    boolean isClosingOrEnteringPip() {
        return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
        return (isAnimating(TRANSITION | PARENTS) && hiddenRequested) || mWillCloseOrEnterPip;
    }
    /**
     * @return Whether AppOps allows this package to enter picture-in-picture.
@@ -3108,7 +3110,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
                getAnimation(), isSelfAnimating());
                getAnimation(), isAnimating(TRANSITION));

        ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
                + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
@@ -3120,7 +3122,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // If this window was animating, then we need to ensure that the app transition notifies
        // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
        // so add to that list now
        if (isSelfAnimating()) {
        if (isAnimating(TRANSITION)) {
            getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
        }

@@ -3468,7 +3470,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     *         color mode set to avoid jank in the middle of the transition.
     */
    boolean canShowWindows() {
        return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
        return allDrawn && !(isAnimating() && hasNonDefaultColorWindow());
    }

    /**
@@ -3530,16 +3532,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return forAllWindowsUnchecked(callback, traverseTopToBottom);
    }

    @Override
    void forAllActivities(Consumer<ActivityRecord> callback) {
        callback.accept(this);
    }

    boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
            boolean traverseTopToBottom) {
        return super.forAllWindows(callback, traverseTopToBottom);
    }

    @Override
    boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
        return callback.apply(this);
    }

    @Override
    protected void setLayer(Transaction t, int layer) {
        if (!mSurfaceAnimator.hasLeash()) {
@@ -4121,7 +4123,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

            if (transit != WindowManager.TRANSIT_UNSET) {
                if (mUseTransferredAnimation) {
                    runningAppAnimation = isReallyAnimating();
                    runningAppAnimation = isAnimating();
                } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
                    runningAppAnimation = true;
                }
@@ -4173,21 +4175,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
        mUseTransferredAnimation = false;

        if (isReallyAnimating()) {
            delayed = true;
        } else {
        delayed = isAnimating(CHILDREN);
        if (!delayed) {
            // We aren't animating anything, but exiting windows rely on the animation finished
            // callback being called in case the ActivityRecord was pretending to be animating,
            // which we might have done because we were in closing/opening apps list.
            onAnimationFinished();
        }

        for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
            if ((mChildren.get(i)).isSelfOrChildAnimating()) {
                delayed = true;
            }
        }

        if (visibilityChanged) {
            if (visible && !delayed) {
                // The token was made immediately visible, there will be no entrance animation.
@@ -4202,7 +4197,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            // updated.
            // If we're becoming invisible, update the client visibility if we are not running an
            // animation. Otherwise, we'll update client visibility in onAnimationFinished.
            if (visible || !isReallyAnimating()) {
            if (visible || !isAnimating()) {
                setClientHidden(!visible);
            }

@@ -5286,13 +5281,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (!allDrawn && w.mightAffectAllDrawn()) {
            if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
                Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
                        + ", isAnimationSet=" + isSelfAnimating());
                        + ", isAnimationSet=" + isAnimating(TRANSITION));
                if (!w.isDrawnLw()) {
                    Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
                            + " pv=" + w.isVisibleByPolicy()
                            + " mDrawState=" + winAnimator.drawStateToString()
                            + " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
                            + " a=" + isSelfAnimating());
                            + " a=" + isAnimating(TRANSITION));
                }
            }

@@ -5838,7 +5833,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);

        return isReallyAnimating();
        return isAnimating();
    }

    private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
@@ -5925,6 +5920,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
    }

    @Override
    boolean isWaitingForTransitionStart() {
        final DisplayContent dc = getDisplayContent();
        // TODO: Test for null can be removed once unification is done.
@@ -6053,10 +6049,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    @Override
    void prepareSurfaces() {
        // isSelfAnimating also returns true when we are about to start a transition, so we need
        // to check super here.
        final boolean reallyAnimating = super.isSelfAnimating();
        final boolean show = !isHidden() || reallyAnimating;
        final boolean show = !isHidden() || isAnimating();

        if (mSurfaceControl != null) {
            if (show && !mLastSurfaceShowing) {
@@ -6084,7 +6077,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    }

    void attachThumbnailAnimation() {
        if (!isReallyAnimating()) {
        if (!isAnimating()) {
            return;
        }
        final int taskId = getTask().mTaskId;
@@ -6105,7 +6098,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
     */
    void attachCrossProfileAppsThumbnailAnimation() {
        if (!isReallyAnimating()) {
        if (!isAnimating()) {
            return;
        }
        clearThumbnail();
@@ -6149,17 +6142,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                displayConfig.orientation);
    }

    @Override
    boolean isAppAnimating() {
        return isSelfAnimating();
    }

    @Override
    boolean isSelfAnimating() {
        // If we are about to start a transition, we also need to be considered animating.
        return isWaitingForTransitionStart() || isReallyAnimating();
    }

    @Override
    public void onAnimationLeashLost(Transaction t) {
        super.onAnimationLeashLost(t);
@@ -6265,15 +6247,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }

    /**
     * @return True if and only if we are actually running an animation. Note that
     *         {@link #isSelfAnimating} also returns true if we are waiting for an animation to
     *         start.
     */
    private boolean isReallyAnimating() {
        return super.isSelfAnimating();
    }

    @Override
    void cancelAnimation() {
        cancelAnimationOnly();
@@ -7627,7 +7600,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        super.writeToProto(proto, WINDOW_TOKEN, logLevel);
        proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
        proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
        proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
        proto.write(IS_ANIMATING, isAnimating());
        if (mThumbnail != null){
            mThumbnail.writeToProto(proto, THUMBNAIL);
        }
+2 −1
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;

import android.Manifest;
import android.app.Activity;
@@ -2134,7 +2135,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
        for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
            ActivityRecord s = mStoppingActivities.get(activityNdx);

            final boolean animating = s.isSelfAnimating();
            final boolean animating = s.isAnimating(TRANSITION);

            if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
                    + " animating=" + animating + " finishing=" + s.finishing);
+11 −6
Original line number Diff line number Diff line
@@ -106,6 +106,8 @@ import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
@@ -2363,7 +2365,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

    @Override
    void removeIfPossible() {
        if (isAnimating()) {
        if (isAnimating(TRANSITION | PARENTS)) {
            mDeferredRemoval = true;
            return;
        }
@@ -3165,13 +3167,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                // to look at all windows below the current target that are in this app, finding the
                // highest visible one in layering.
                WindowState highestTarget = null;
                if (activity.isSelfAnimating()) {
                if (activity.isAnimating(TRANSITION)) {
                    highestTarget = activity.getHighestAnimLayerWindow(curTarget);
                }

                if (highestTarget != null) {
                    if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget
                            + " animating=" + highestTarget.isAnimating());
                    if (DEBUG_INPUT_METHOD) {
                        Slog.v(TAG_WM, mAppTransition + " " + highestTarget + " animating="
                                + highestTarget.isAnimating(TRANSITION | PARENTS));
                    }

                    if (mAppTransition.isTransitionSet()) {
                        // If we are currently setting up for an animation, hold everything until we
@@ -4322,7 +4326,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                    // The split screen divider anchor is located above the split screen window.
                    layerForSplitScreenDividerAnchor = layer++;
                }
                if (s.isTaskAnimating() || s.isAppAnimating()) {
                if (s.isTaskAnimating() || s.isAppTransitioning()) {
                    // The animation layer is located above the highest animating stack and no
                    // higher.
                    layerForAnimationLayer = layer++;
@@ -4651,7 +4655,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        // so it get's layered above the starting window.
        if (imeTarget != null
                && !(imeTarget.mActivityRecord != null && imeTarget.mActivityRecord.hasStartingWindow())
                && (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating())
                && (!(imeTarget.inSplitScreenWindowingMode()
                             || imeTarget.mToken.isAppTransitioning())
                && (imeTarget.getSurfaceControl() != null))) {
            mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
                    // TODO: We need to use an extra level on the app surface to ensure
+4 −1
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.server.wm;

import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;

import android.util.ArraySet;
import android.view.Display.Mode;
import android.view.DisplayInfo;
@@ -67,7 +70,7 @@ class RefreshRatePolicy {

        // If app is animating, it's not able to control refresh rate because we want the animation
        // to run in default refresh rate.
        if (w.isAnimating()) {
        if (w.isAnimating(TRANSITION | PARENTS)) {
            return 0;
        }

Loading