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

Commit 14ac3583 authored by Chris Li's avatar Chris Li
Browse files

Allow TaskFragmentOrganizer to set remote animation

When all windows in the transition is belong to organized TaskFragments,
have the TaskFragmentOrganizer to control the animation on client side.

Bug: 196173550
Test: atest WmTests:TaskFragmentOrganizerControllerTest
Test: atest WmTests:AppTransitionControllerTest
Change-Id: I835467e23863286a5bd34380424cc9eca2c7372f
parent 118428b6
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.window;

import android.view.RemoteAnimationDefinition;
import android.window.ITaskFragmentOrganizer;

/** @hide */
@@ -30,4 +31,17 @@ interface ITaskFragmentOrganizerController {
     * Unregisters a previously registered TaskFragmentOrganizer.
     */
    void unregisterOrganizer(in ITaskFragmentOrganizer organizer);

    /**
     * Registers remote animations per transition type for the organizer. It will override the
     * animations if the transition only contains windows that belong to the organized
     * TaskFragments.
     */
    void registerRemoteAnimations(in ITaskFragmentOrganizer organizer,
        in RemoteAnimationDefinition definition);

    /**
     * Unregisters remote animations per transition type for the organizer.
     */
    void unregisterRemoteAnimations(in ITaskFragmentOrganizer organizer);
}
+29 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.RemoteAnimationDefinition;

import java.util.concurrent.Executor;

@@ -90,6 +91,34 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
        }
    }

    /**
     * Registers remote animations per transition type for the organizer. It will override the
     * animations if the transition only contains windows that belong to the organized
     * TaskFragments.
     * @hide
     */
    @CallSuper
    public void registerRemoteAnimations(@NonNull RemoteAnimationDefinition definition) {
        try {
            getController().registerRemoteAnimations(mInterface, definition);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Unregisters remote animations per transition type for the organizer.
     * @hide
     */
    @CallSuper
    public void unregisterRemoteAnimations() {
        try {
            getController().unregisterRemoteAnimations(mInterface);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /** Called when a TaskFragment is created and organized by this organizer. */
    public void onTaskFragmentAppeared(
            @NonNull TaskFragmentAppearedInfo taskFragmentAppearedInfo) {}
+18 −0
Original line number Diff line number Diff line
@@ -1249,6 +1249,12 @@
      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
      "at": "com\/android\/server\/wm\/Transition.java"
    },
    "-702650156": {
      "message": "Override with TaskFragment remote animation for transit=%s",
      "level": "VERBOSE",
      "group": "WM_DEBUG_APP_TRANSITIONS",
      "at": "com\/android\/server\/wm\/AppTransitionController.java"
    },
    "-701167286": {
      "message": "applyAnimation: transit=%s, enter=%b, wc=%s",
      "level": "VERBOSE",
@@ -1789,6 +1795,12 @@
      "group": "WM_DEBUG_STATES",
      "at": "com\/android\/server\/wm\/TaskFragment.java"
    },
    "-70719599": {
      "message": "Unregister remote animations for organizer=%s uid=%d pid=%d",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_ORGANIZER",
      "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
    },
    "-55185509": {
      "message": "setFocusedTask: taskId=%d touchedActivity=%s",
      "level": "DEBUG",
@@ -2941,6 +2953,12 @@
      "group": "WM_ERROR",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "1210037962": {
      "message": "Register remote animations for organizer=%s uid=%d pid=%d",
      "level": "VERBOSE",
      "group": "WM_DEBUG_WINDOW_ORGANIZER",
      "at": "com\/android\/server\/wm\/TaskFragmentOrganizerController.java"
    },
    "1219600119": {
      "message": "addWindow: win=%s Callers=%s",
      "level": "DEBUG",
+7 −0
Original line number Diff line number Diff line
@@ -2595,6 +2595,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return task != null ? task.getOrganizedTask() : null;
    }

    /** Returns the organized parent {@link TaskFragment}. */
    @Nullable
    TaskFragment getOrganizedTaskFragment() {
        final TaskFragment parent = getTaskFragment();
        return parent != null ? parent.getOrganizedTaskFragment() : null;
    }

    @Override
    @Nullable
    TaskDisplayArea getDisplayArea() {
+65 −3
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@ import android.view.WindowManager.TransitionFlags;
import android.view.WindowManager.TransitionOldType;
import android.view.WindowManager.TransitionType;
import android.view.animation.Animation;
import android.window.ITaskFragmentOrganizer;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
@@ -233,7 +234,11 @@ public class AppTransitionController {
        final ActivityRecord topChangingApp =
                getTopApp(mDisplayContent.mChangingContainers, false /* ignoreHidden */);
        final WindowManager.LayoutParams animLp = getAnimLp(animLpActivity);

        // Check if there is any override
        if (!overrideWithTaskFragmentRemoteAnimation(transit, activityTypes)) {
            overrideWithRemoteAnimationIfSet(animLpActivity, transit, activityTypes);
        }

        final boolean voiceInteraction = containsVoiceInteraction(mDisplayContent.mOpeningApps)
                || containsVoiceInteraction(mDisplayContent.mOpeningApps);
@@ -483,6 +488,7 @@ public class AppTransitionController {
        return TYPE_NONE;
    }

    @Nullable
    private static WindowManager.LayoutParams getAnimLp(ActivityRecord activity) {
        final WindowState mainWindow = activity != null ? activity.findMainWindow() : null;
        return mainWindow != null ? mainWindow.mAttrs : null;
@@ -505,6 +511,61 @@ public class AppTransitionController {
                : null;
    }

    /**
     * Overrides the pending transition with the remote animation defined by the
     * {@link ITaskFragmentOrganizer} if all windows in the transition are children of
     * {@link TaskFragment} that are organized by the same organizer.
     *
     * @return {@code true} if the transition is overridden.
     */
    @VisibleForTesting
    boolean overrideWithTaskFragmentRemoteAnimation(@TransitionOldType int transit,
            ArraySet<Integer> activityTypes) {
        final ArrayList<WindowContainer> allWindows = new ArrayList<>();
        allWindows.addAll(mDisplayContent.mClosingApps);
        allWindows.addAll(mDisplayContent.mOpeningApps);
        allWindows.addAll(mDisplayContent.mChangingContainers);

        // Find the common TaskFragmentOrganizer of all windows.
        ITaskFragmentOrganizer organizer = null;
        for (int i = allWindows.size() - 1; i >= 0; i--) {
            final ActivityRecord r = getAppFromContainer(allWindows.get(i));
            if (r == null) {
                return false;
            }
            final TaskFragment organizedTaskFragment = r.getOrganizedTaskFragment();
            final ITaskFragmentOrganizer curOrganizer = organizedTaskFragment != null
                    ? organizedTaskFragment.getTaskFragmentOrganizer()
                    : null;
            if (curOrganizer == null) {
                // All windows must below an organized TaskFragment.
                return false;
            }
            if (organizer == null) {
                organizer = curOrganizer;
            } else if (!organizer.asBinder().equals(curOrganizer.asBinder())) {
                // They must be controlled by the same organizer.
                return false;
            }
        }

        final RemoteAnimationDefinition definition = organizer != null
                ? mDisplayContent.mAtmService.mTaskFragmentOrganizerController
                    .getRemoteAnimationDefinition(organizer)
                : null;
        final RemoteAnimationAdapter adapter = definition != null
                ? definition.getAdapter(transit, activityTypes)
                : null;
        if (adapter == null) {
            return false;
        }
        mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(adapter);
        ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                "Override with TaskFragment remote animation for transit=%s",
                AppTransition.appTransitionOldToString(transit));
        return true;
    }

    /**
     * Overrides the pending transition with the remote animation defined for the transition in the
     * set of defined remote animations in the app window token.
@@ -524,13 +585,14 @@ public class AppTransitionController {
    }

    static ActivityRecord getAppFromContainer(WindowContainer wc) {
        return wc.asTask() != null ? wc.asTask().getTopNonFinishingActivity()
        return wc.asTaskFragment() != null ? wc.asTaskFragment().getTopNonFinishingActivity()
                : wc.asActivityRecord();
    }

    /**
     * @return The window token that determines the animation theme.
     */
    @Nullable
    private ActivityRecord findAnimLayoutParamsToken(@TransitionOldType int transit,
            ArraySet<Integer> activityTypes) {
        ActivityRecord result;
@@ -543,7 +605,7 @@ public class AppTransitionController {
                w -> w.getRemoteAnimationDefinition() != null
                        && w.getRemoteAnimationDefinition().hasTransition(transit, activityTypes));
        if (result != null) {
            return getAppFromContainer(result);
            return result;
        }
        result = lookForHighestTokenWithFilter(closingApps, openingApps, changingApps,
                w -> w.fillsParent() && w.findMainWindow() != null);
Loading