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

Commit 5e55e397 authored by Charles Chen's avatar Charles Chen
Browse files

Reland "Introduce TaskFragment transition type"

Previously AppTransitionController didn't recognize TaskFragment
transitions, so it uses Task opening/closing animation for
TaskFragment transitions.
This CL introduces and uses TaskFragment transition if the animation
target is TaskFragment. The new transition type can be used for registering
RemoteAnimation implemented by TaskFragmentOrganizer as well.
It also provides a fallback mechanism for TaskFragment transitions
if the RemoteAnimation fails or one of opening/closing animation target
is not a pure organized TaskFragment.

Note that previous reverted CL[1] didn't cover the case that the
animation target is promoted to TaskDisplayArea. This CL fixes it by
introducing WindowContainer#canBeAnimationTarget to filter out the case.

Bug: 194649929
Test: manual - the reproducible step in b/194649929#comment1
Test: atest WmTests:AppTransitionTests AppTransitionControllerTest
Test: atest MultiDisplayPolicyTests#testAppTransitionForActivityOnDifferentDisplay
[1]: I0094694fa5cd95d8bbb7da94d2aaf7aac6e1fe09

Change-Id: I5520803f3018d2dd67c96db55daceef740b2cf0b
parent a6a85a9b
Loading
Loading
Loading
Loading
+16 −1
Original line number Diff line number Diff line
@@ -319,6 +319,19 @@ public interface WindowManager extends ViewManager {
     */
    int TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE = 27;

    /**
     * A window in a new task fragment is being opened.
     * @hide
     */
    int TRANSIT_OLD_TASK_FRAGMENT_OPEN = 28;

    /**
     * A window in the top-most activity of task fragment is being closed to reveal the activity
     * below.
     * @hide
     */
    int TRANSIT_OLD_TASK_FRAGMENT_CLOSE = 29;

    /**
     * @hide
     */
@@ -344,7 +357,9 @@ public interface WindowManager extends ViewManager {
            TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN,
            TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE,
            TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE,
            TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE
            TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE,
            TRANSIT_OLD_TASK_FRAGMENT_OPEN,
            TRANSIT_OLD_TASK_FRAGMENT_CLOSE
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface TransitionOldType {}
+1 −0
Original line number Diff line number Diff line
@@ -756,6 +756,7 @@ final class AccessibilityController {
            if (magnifying) {
                switch (transition) {
                    case WindowManager.TRANSIT_OLD_ACTIVITY_OPEN:
                    case WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN:
                    case WindowManager.TRANSIT_OLD_TASK_OPEN:
                    case WindowManager.TRANSIT_OLD_TASK_TO_FRONT:
                    case WindowManager.TRANSIT_OLD_WALLPAPER_OPEN:
+5 −0
Original line number Diff line number Diff line
@@ -9195,6 +9195,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        super.finishSync(outMergedTransaction, cancel);
    }

    @Override
    boolean canBeAnimationTarget() {
        return true;
    }

    static class Builder {
        private final ActivityTaskManagerService mAtmService;
        private WindowProcessController mCallerApp;
+23 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OLD_NONE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
@@ -1005,6 +1007,21 @@ public class AppTransition implements Dump {
                    animAttr = enter
                            ? WindowAnimation_launchTaskBehindSourceAnimation
                            : WindowAnimation_launchTaskBehindTargetAnimation;
                    break;
                // TODO(b/189386466): Use activity transition as the fallback. Investigate if we
                //  need new TaskFragment transition.
                case TRANSIT_OLD_TASK_FRAGMENT_OPEN:
                    animAttr = enter
                            ? WindowAnimation_activityOpenEnterAnimation
                            : WindowAnimation_activityOpenExitAnimation;
                    break;
                // TODO(b/189386466): Use activity transition as the fallback. Investigate if we
                //  need new TaskFragment transition.
                case TRANSIT_OLD_TASK_FRAGMENT_CLOSE:
                    animAttr = enter
                            ? WindowAnimation_activityCloseEnterAnimation
                            : WindowAnimation_activityCloseExitAnimation;
                    break;
            }
            a = animAttr != 0 ? loadAnimationAttr(lp, animAttr, transit) : null;
            ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
@@ -1315,6 +1332,12 @@ public class AppTransition implements Dump {
            case TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE: {
                return "TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE";
            }
            case TRANSIT_OLD_TASK_FRAGMENT_OPEN: {
                return "TRANSIT_OLD_TASK_FRAGMENT_OPEN";
            }
            case TRANSIT_OLD_TASK_FRAGMENT_CLOSE: {
                return "TRANSIT_OLD_TASK_FRAGMENT_CLOSE";
            }
            default: {
                return "<UNKNOWN: " + transition + ">";
            }
+55 −13
Original line number Diff line number Diff line
@@ -39,6 +39,8 @@ import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OLD_NONE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
@@ -68,6 +70,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACT
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.os.Trace;
import android.util.ArrayMap;
@@ -86,6 +89,8 @@ import android.view.animation.Animation;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.function.Predicate;
@@ -102,6 +107,20 @@ public class AppTransitionController {
    private RemoteAnimationDefinition mRemoteAnimationDefinition = null;
    private static final int KEYGUARD_GOING_AWAY_ANIMATION_DURATION = 400;

    private static final int TYPE_NONE = 0;
    private static final int TYPE_ACTIVITY = 1;
    private static final int TYPE_TASK_FRAGMENT = 2;
    private static final int TYPE_TASK = 3;

    @IntDef(prefix = { "TYPE_" }, value = {
            TYPE_NONE,
            TYPE_ACTIVITY,
            TYPE_TASK_FRAGMENT,
            TYPE_TASK
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface TransitContainerType {}

    private final ArrayMap<WindowContainer, Integer> mTempTransitionReasons = new ArrayMap<>();

    AppTransitionController(WindowManagerService service, DisplayContent displayContent) {
@@ -387,33 +406,38 @@ public class AppTransitionController {
                openingApps, closingApps, true /* visible */);
        final ArraySet<WindowContainer> closingWcs = getAnimationTargets(
                openingApps, closingApps, false /* visible */);
        final boolean isActivityOpening = !openingWcs.isEmpty()
                && openingWcs.valueAt(0).asActivityRecord() != null;
        final boolean isActivityClosing = !closingWcs.isEmpty()
                && closingWcs.valueAt(0).asActivityRecord() != null;
        final boolean isTaskOpening = !openingWcs.isEmpty() && !isActivityOpening;
        final boolean isTaskClosing = !closingWcs.isEmpty() && !isActivityClosing;

        if (appTransition.containsTransitRequest(TRANSIT_TO_FRONT) && isTaskOpening) {
        final WindowContainer<?> openingContainer = !openingWcs.isEmpty()
                ? openingWcs.valueAt(0) : null;
        final WindowContainer<?> closingContainer = !closingWcs.isEmpty()
                ? closingWcs.valueAt(0) : null;
        @TransitContainerType int openingType = getTransitContainerType(openingContainer);
        @TransitContainerType int closingType = getTransitContainerType(closingContainer);
        if (appTransition.containsTransitRequest(TRANSIT_TO_FRONT) && openingType == TYPE_TASK) {
            return TRANSIT_OLD_TASK_TO_FRONT;
        }
        if (appTransition.containsTransitRequest(TRANSIT_TO_BACK) && isTaskClosing) {
        if (appTransition.containsTransitRequest(TRANSIT_TO_BACK) && closingType == TYPE_TASK) {
            return TRANSIT_OLD_TASK_TO_BACK;
        }
        if (appTransition.containsTransitRequest(TRANSIT_OPEN)) {
            if (isTaskOpening) {
            if (openingType == TYPE_TASK) {
                return (appTransition.getTransitFlags() & TRANSIT_FLAG_OPEN_BEHIND) != 0
                        ? TRANSIT_OLD_TASK_OPEN_BEHIND : TRANSIT_OLD_TASK_OPEN;
            }
            if (isActivityOpening) {
            if (openingType == TYPE_ACTIVITY) {
                return TRANSIT_OLD_ACTIVITY_OPEN;
            }
            if (openingType == TYPE_TASK_FRAGMENT) {
                return TRANSIT_OLD_TASK_FRAGMENT_OPEN;
            }
        }
        if (appTransition.containsTransitRequest(TRANSIT_CLOSE)) {
            if (isTaskClosing) {
            if (closingType == TYPE_TASK) {
                return TRANSIT_OLD_TASK_CLOSE;
            }
            if (isActivityClosing) {
            if (closingType == TYPE_TASK_FRAGMENT) {
                return TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
            }
            if (closingType == TYPE_ACTIVITY) {
                for (int i = closingApps.size() - 1; i >= 0; i--) {
                    if (closingApps.valueAt(i).visibleIgnoringKeyguard) {
                        return TRANSIT_OLD_ACTIVITY_CLOSE;
@@ -430,6 +454,23 @@ public class AppTransitionController {
        return TRANSIT_OLD_NONE;
    }

    @TransitContainerType
    private static int getTransitContainerType(@Nullable WindowContainer<?> container) {
        if (container == null) {
            return TYPE_NONE;
        }
        if (container.asTask() != null) {
            return TYPE_TASK;
        }
        if (container.asTaskFragment() != null) {
            return TYPE_TASK_FRAGMENT;
        }
        if (container.asActivityRecord() != null) {
            return TYPE_ACTIVITY;
        }
        return TYPE_NONE;
    }

    private static WindowManager.LayoutParams getAnimLp(ActivityRecord activity) {
        final WindowState mainWindow = activity != null ? activity.findMainWindow() : null;
        return mainWindow != null ? mainWindow.mAttrs : null;
@@ -633,6 +674,7 @@ public class AppTransitionController {
            boolean canPromote = true;

            if (parent == null || !parent.canCreateRemoteAnimationTarget()
                    || !parent.canBeAnimationTarget()
                    // We cannot promote the animation on Task's parent when the task is in
                    // clearing task in case the animating get stuck when performing the opening
                    // task that behind it.
Loading