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

Commit d90d158e authored by Garfield Tan's avatar Garfield Tan Committed by Automerger Merge Worker
Browse files

Merge "Put window decors at one place" into tm-qpr-dev am: 16b78301 am: de69a867

parents e3f42cfc de69a867
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -293,17 +293,17 @@ public abstract class WMShellBaseModule {
    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
    @BindsOptionalOf
    @DynamicOverride
    abstract FullscreenTaskListener<?> optionalFullscreenTaskListener();
    abstract FullscreenTaskListener optionalFullscreenTaskListener();

    @WMSingleton
    @Provides
    static FullscreenTaskListener<?> provideFullscreenTaskListener(
            @DynamicOverride Optional<FullscreenTaskListener<?>> fullscreenTaskListener,
    static FullscreenTaskListener provideFullscreenTaskListener(
            @DynamicOverride Optional<FullscreenTaskListener> fullscreenTaskListener,
            ShellInit shellInit,
            ShellTaskOrganizer shellTaskOrganizer,
            SyncTransactionQueue syncQueue,
            Optional<RecentTasksController> recentTasksOptional,
            Optional<WindowDecorViewModel<?>> windowDecorViewModelOptional) {
            Optional<WindowDecorViewModel> windowDecorViewModelOptional) {
        if (fullscreenTaskListener.isPresent()) {
            return fullscreenTaskListener.get();
        } else {
@@ -317,7 +317,7 @@ public abstract class WMShellBaseModule {
    //

    @BindsOptionalOf
    abstract WindowDecorViewModel<?> optionalWindowDecorViewModel();
    abstract WindowDecorViewModel optionalWindowDecorViewModel();

    //
    // Unfold transition
@@ -769,7 +769,7 @@ public abstract class WMShellBaseModule {
            Optional<SplitScreenController> splitScreenOptional,
            Optional<Pip> pipOptional,
            Optional<PipTouchHandler> pipTouchHandlerOptional,
            FullscreenTaskListener<?> fullscreenTaskListener,
            FullscreenTaskListener fullscreenTaskListener,
            Optional<UnfoldAnimationController> unfoldAnimationController,
            Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
            Optional<FreeformComponents> freeformComponents,
+8 −10
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.freeform.FreeformTaskTransitionHandler;
import com.android.wm.shell.freeform.FreeformTaskTransitionObserver;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
@@ -183,7 +182,7 @@ public abstract class WMShellModule {

    @WMSingleton
    @Provides
    static WindowDecorViewModel<?> provideWindowDecorViewModel(
    static WindowDecorViewModel provideWindowDecorViewModel(
            Context context,
            @ShellMainThread Handler mainHandler,
            @ShellMainThread Choreographer mainChoreographer,
@@ -209,7 +208,7 @@ public abstract class WMShellModule {
    @Provides
    @DynamicOverride
    static FreeformComponents provideFreeformComponents(
            FreeformTaskListener<?> taskListener,
            FreeformTaskListener taskListener,
            FreeformTaskTransitionHandler transitionHandler,
            FreeformTaskTransitionObserver transitionObserver) {
        return new FreeformComponents(
@@ -218,18 +217,18 @@ public abstract class WMShellModule {

    @WMSingleton
    @Provides
    static FreeformTaskListener<?> provideFreeformTaskListener(
    static FreeformTaskListener provideFreeformTaskListener(
            Context context,
            ShellInit shellInit,
            ShellTaskOrganizer shellTaskOrganizer,
            Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
            WindowDecorViewModel<?> windowDecorViewModel) {
            WindowDecorViewModel windowDecorViewModel) {
        // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
        //                    override for this controller from the base module
        ShellInit init = FreeformComponents.isFreeformEnabled(context)
                ? shellInit
                : null;
        return new FreeformTaskListener<>(init, shellTaskOrganizer, desktopModeTaskRepository,
        return new FreeformTaskListener(init, shellTaskOrganizer, desktopModeTaskRepository,
                windowDecorViewModel);
    }

@@ -238,7 +237,7 @@ public abstract class WMShellModule {
    static FreeformTaskTransitionHandler provideFreeformTaskTransitionHandler(
            ShellInit shellInit,
            Transitions transitions,
            WindowDecorViewModel<?> windowDecorViewModel) {
            WindowDecorViewModel windowDecorViewModel) {
        return new FreeformTaskTransitionHandler(shellInit, transitions, windowDecorViewModel);
    }

@@ -248,10 +247,9 @@ public abstract class WMShellModule {
            Context context,
            ShellInit shellInit,
            Transitions transitions,
            FullscreenTaskListener<?> fullscreenTaskListener,
            FreeformTaskListener<?> freeformTaskListener) {
            WindowDecorViewModel windowDecorViewModel) {
        return new FreeformTaskTransitionObserver(
                context, shellInit, transitions, fullscreenTaskListener, freeformTaskListener);
                context, shellInit, transitions, windowDecorViewModel);
    }

    //
+18 −156
Original line number Diff line number Diff line
@@ -19,12 +19,8 @@ package com.android.wm.shell.freeform;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM;

import android.app.ActivityManager.RunningTaskInfo;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceControl;
import android.window.TransitionInfo;

import androidx.annotation.Nullable;

import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -41,31 +37,26 @@ import java.util.Optional;
/**
 * {@link ShellTaskOrganizer.TaskListener} for {@link
 * ShellTaskOrganizer#TASK_LISTENER_TYPE_FREEFORM}.
 *
 * @param <T> the type of window decoration instance
 */
public class FreeformTaskListener<T extends AutoCloseable>
        implements ShellTaskOrganizer.TaskListener {
public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener {
    private static final String TAG = "FreeformTaskListener";

    private final ShellTaskOrganizer mShellTaskOrganizer;
    private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository;
    private final WindowDecorViewModel<T> mWindowDecorationViewModel;
    private final WindowDecorViewModel mWindowDecorationViewModel;

    private final SparseArray<State<T>> mTasks = new SparseArray<>();
    private final SparseArray<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
    private final SparseArray<State> mTasks = new SparseArray<>();

    private static class State<T extends AutoCloseable> {
    private static class State {
        RunningTaskInfo mTaskInfo;
        SurfaceControl mLeash;
        T mWindowDecoration;
    }

    public FreeformTaskListener(
            ShellInit shellInit,
            ShellTaskOrganizer shellTaskOrganizer,
            Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
            WindowDecorViewModel<T> windowDecorationViewModel) {
            WindowDecorViewModel windowDecorationViewModel) {
        mShellTaskOrganizer = shellTaskOrganizer;
        mWindowDecorationViewModel = windowDecorationViewModel;
        mDesktopModeTaskRepository = desktopModeTaskRepository;
@@ -80,12 +71,17 @@ public class FreeformTaskListener<T extends AutoCloseable>

    @Override
    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
        if (mTasks.get(taskInfo.taskId) != null) {
            throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
        }
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
                taskInfo.taskId);
        final State<T> state = createOrUpdateTaskState(taskInfo, leash);
        final State state = new State();
        state.mTaskInfo = taskInfo;
        state.mLeash = leash;
        mTasks.put(taskInfo.taskId, state);
        if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
            SurfaceControl.Transaction t = new SurfaceControl.Transaction();
            state.mWindowDecoration =
            mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t);
            t.apply();
        }
@@ -97,28 +93,8 @@ public class FreeformTaskListener<T extends AutoCloseable>
        }
    }

    private State<T> createOrUpdateTaskState(RunningTaskInfo taskInfo, SurfaceControl leash) {
        State<T> state = mTasks.get(taskInfo.taskId);
        if (state != null) {
            updateTaskInfo(taskInfo);
            return state;
        }

        state = new State<>();
        state.mTaskInfo = taskInfo;
        state.mLeash = leash;
        mTasks.put(taskInfo.taskId, state);

        return state;
    }

    @Override
    public void onTaskVanished(RunningTaskInfo taskInfo) {
        final State<T> state = mTasks.get(taskInfo.taskId);
        if (state == null) {
            // This is possible if the transition happens before this method.
            return;
        }
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
                taskInfo.taskId);
        mTasks.remove(taskInfo.taskId);
@@ -129,26 +105,18 @@ public class FreeformTaskListener<T extends AutoCloseable>
            mDesktopModeTaskRepository.ifPresent(it -> it.removeActiveTask(taskInfo.taskId));
        }

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            // Save window decorations of closing tasks so that we can hand them over to the
            // transition system if this method happens before the transition. In case where the
            // transition didn't happen, it'd be cleared when the next transition finished.
            if (state.mWindowDecoration != null) {
                mWindowDecorOfVanishedTasks.put(taskInfo.taskId, state.mWindowDecoration);
            }
            return;
        if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
            mWindowDecorationViewModel.destroyWindowDecoration(taskInfo);
        }
        releaseWindowDecor(state.mWindowDecoration);
    }

    @Override
    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
        final State<T> state = updateTaskInfo(taskInfo);
        final State state = mTasks.get(taskInfo.taskId);
        state.mTaskInfo = taskInfo;
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
                taskInfo.taskId);
        if (state.mWindowDecoration != null) {
            mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration);
        }
        mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo);

        if (DesktopModeStatus.IS_SUPPORTED) {
            if (taskInfo.isVisible) {
@@ -159,15 +127,6 @@ public class FreeformTaskListener<T extends AutoCloseable>
        }
    }

    private State<T> updateTaskInfo(RunningTaskInfo taskInfo) {
        final State<T> state = mTasks.get(taskInfo.taskId);
        if (state == null) {
            throw new RuntimeException("Task info changed before appearing: #" + taskInfo.taskId);
        }
        state.mTaskInfo = taskInfo;
        return state;
    }

    @Override
    public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
        b.setParent(findTaskSurface(taskId));
@@ -186,103 +145,6 @@ public class FreeformTaskListener<T extends AutoCloseable>
        return mTasks.get(taskId).mLeash;
    }

    /**
     * Creates a window decoration for a transition.
     *
     * @param change the change of this task transition that needs to have the task layer as the
     *               leash
     * @return {@code true} if it creates the window decoration; {@code false} otherwise
     */
    boolean createWindowDecoration(
            TransitionInfo.Change change,
            SurfaceControl.Transaction startT,
            SurfaceControl.Transaction finishT) {
        final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
        if (state.mWindowDecoration != null) {
            return false;
        }
        state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration(
                state.mTaskInfo, state.mLeash, startT, finishT);
        return true;
    }

    /**
     * Gives out the ownership of the task's window decoration. The given task is leaving (of has
     * left) this task listener. This is the transition system asking for the ownership.
     *
     * @param taskInfo the maximizing task
     * @return the window decor of the maximizing task if any
     */
    T giveWindowDecoration(
            RunningTaskInfo taskInfo,
            SurfaceControl.Transaction startT,
            SurfaceControl.Transaction finishT) {
        T windowDecor;
        final State<T> state = mTasks.get(taskInfo.taskId);
        if (state != null) {
            windowDecor = state.mWindowDecoration;
            state.mWindowDecoration = null;
        } else {
            windowDecor =
                    mWindowDecorOfVanishedTasks.removeReturnOld(taskInfo.taskId);
        }
        if (windowDecor == null) {
            return null;
        }
        mWindowDecorationViewModel.setupWindowDecorationForTransition(
                taskInfo, startT, finishT, windowDecor);
        return windowDecor;
    }

    /**
     * Adopt the incoming window decoration and lets the window decoration prepare for a transition.
     *
     * @param change the change of this task transition that needs to have the task layer as the
     *               leash
     * @param startT the start transaction of this transition
     * @param finishT the finish transaction of this transition
     * @param windowDecor the window decoration to adopt
     * @return {@code true} if it adopts the window decoration; {@code false} otherwise
     */
    boolean adoptWindowDecoration(
            TransitionInfo.Change change,
            SurfaceControl.Transaction startT,
            SurfaceControl.Transaction finishT,
            @Nullable AutoCloseable windowDecor) {
        final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
        state.mWindowDecoration = mWindowDecorationViewModel.adoptWindowDecoration(windowDecor);
        if (state.mWindowDecoration != null) {
            mWindowDecorationViewModel.setupWindowDecorationForTransition(
                    state.mTaskInfo, startT, finishT, state.mWindowDecoration);
            return true;
        } else {
            state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration(
                    state.mTaskInfo, state.mLeash, startT, finishT);
            return false;
        }
    }

    void onTaskTransitionFinished() {
        if (mWindowDecorOfVanishedTasks.size() == 0) {
            return;
        }
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
                "Clearing window decors of vanished tasks. There could be visual defects "
                + "if any of them is used later in transitions.");
        for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) {
            releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i));
        }
        mWindowDecorOfVanishedTasks.clear();
    }

    private void releaseWindowDecor(T windowDecor) {
        try {
            windowDecor.close();
        } catch (Exception e) {
            Log.e(TAG, "Failed to release window decoration.", e);
        }
    }

    @Override
    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
+2 −2
Original line number Diff line number Diff line
@@ -46,14 +46,14 @@ public class FreeformTaskTransitionHandler
        implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {

    private final Transitions mTransitions;
    private final WindowDecorViewModel<?> mWindowDecorViewModel;
    private final WindowDecorViewModel mWindowDecorViewModel;

    private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();

    public FreeformTaskTransitionHandler(
            ShellInit shellInit,
            Transitions transitions,
            WindowDecorViewModel<?> windowDecorViewModel) {
            WindowDecorViewModel windowDecorViewModel) {
        mTransitions = transitions;
        mWindowDecorViewModel = windowDecorViewModel;
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+31 −102
Original line number Diff line number Diff line
@@ -16,13 +16,9 @@

package com.android.wm.shell.freeform;

import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;

import android.app.ActivityManager;
import android.content.Context;
import android.os.IBinder;
import android.util.Log;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
@@ -31,9 +27,9 @@ import android.window.WindowContainerToken;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;

import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;

import java.util.ArrayList;
import java.util.Collections;
@@ -47,23 +43,19 @@ import java.util.Map;
 * be a part of transitions.
 */
public class FreeformTaskTransitionObserver implements Transitions.TransitionObserver {
    private static final String TAG = "FreeformTO";

    private final Transitions mTransitions;
    private final FreeformTaskListener<?> mFreeformTaskListener;
    private final FullscreenTaskListener<?> mFullscreenTaskListener;
    private final WindowDecorViewModel mWindowDecorViewModel;

    private final Map<IBinder, List<AutoCloseable>> mTransitionToWindowDecors = new HashMap<>();
    private final Map<IBinder, List<ActivityManager.RunningTaskInfo>> mTransitionToTaskInfo =
            new HashMap<>();

    public FreeformTaskTransitionObserver(
            Context context,
            ShellInit shellInit,
            Transitions transitions,
            FullscreenTaskListener<?> fullscreenTaskListener,
            FreeformTaskListener<?> freeformTaskListener) {
            WindowDecorViewModel windowDecorViewModel) {
        mTransitions = transitions;
        mFreeformTaskListener = freeformTaskListener;
        mFullscreenTaskListener = fullscreenTaskListener;
        mWindowDecorViewModel = windowDecorViewModel;
        if (Transitions.ENABLE_SHELL_TRANSITIONS && FreeformComponents.isFreeformEnabled(context)) {
            shellInit.addInitCallback(this::onInit, this);
        }
@@ -80,7 +72,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs
            @NonNull TransitionInfo info,
            @NonNull SurfaceControl.Transaction startT,
            @NonNull SurfaceControl.Transaction finishT) {
        final ArrayList<AutoCloseable> windowDecors = new ArrayList<>();
        final ArrayList<ActivityManager.RunningTaskInfo> taskInfoList = new ArrayList<>();
        final ArrayList<WindowContainerToken> taskParents = new ArrayList<>();
        for (TransitionInfo.Change change : info.getChanges()) {
            if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
@@ -110,92 +102,40 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs
                    onOpenTransitionReady(change, startT, finishT);
                    break;
                case WindowManager.TRANSIT_CLOSE: {
                    onCloseTransitionReady(change, windowDecors, startT, finishT);
                    taskInfoList.add(change.getTaskInfo());
                    onCloseTransitionReady(change, startT, finishT);
                    break;
                }
                case WindowManager.TRANSIT_CHANGE:
                    onChangeTransitionReady(info.getType(), change, startT, finishT);
                    onChangeTransitionReady(change, startT, finishT);
                    break;
            }
        }
        if (!windowDecors.isEmpty()) {
            mTransitionToWindowDecors.put(transition, windowDecors);
        }
        mTransitionToTaskInfo.put(transition, taskInfoList);
    }

    private void onOpenTransitionReady(
            TransitionInfo.Change change,
            SurfaceControl.Transaction startT,
            SurfaceControl.Transaction finishT) {
        switch (change.getTaskInfo().getWindowingMode()){
            case WINDOWING_MODE_FREEFORM:
                mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
                break;
            case WINDOWING_MODE_FULLSCREEN:
                mFullscreenTaskListener.createWindowDecoration(change, startT, finishT);
                break;
        }
        mWindowDecorViewModel.createWindowDecoration(
                change.getTaskInfo(), change.getLeash(), startT, finishT);
    }

    private void onCloseTransitionReady(
            TransitionInfo.Change change,
            ArrayList<AutoCloseable> windowDecors,
            SurfaceControl.Transaction startT,
            SurfaceControl.Transaction finishT) {
        final AutoCloseable windowDecor;
        switch (change.getTaskInfo().getWindowingMode()) {
            case WINDOWING_MODE_FREEFORM:
                windowDecor = mFreeformTaskListener.giveWindowDecoration(change.getTaskInfo(),
                        startT, finishT);
                break;
            case WINDOWING_MODE_FULLSCREEN:
                windowDecor = mFullscreenTaskListener.giveWindowDecoration(change.getTaskInfo(),
                        startT, finishT);
                break;
            default:
                windowDecor = null;
        }
        if (windowDecor != null) {
            windowDecors.add(windowDecor);
        }
        mWindowDecorViewModel.setupWindowDecorationForTransition(
                change.getTaskInfo(), startT, finishT);
    }

    private void onChangeTransitionReady(
            int type,
            TransitionInfo.Change change,
            SurfaceControl.Transaction startT,
            SurfaceControl.Transaction finishT) {
        AutoCloseable windowDecor = null;

        boolean adopted = false;
        final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
        if (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
            windowDecor = mFreeformTaskListener.giveWindowDecoration(
                    change.getTaskInfo(), startT, finishT);
            if (windowDecor != null) {
                adopted = mFullscreenTaskListener.adoptWindowDecoration(
                        change, startT, finishT, windowDecor);
            } else {
                // will return false if it already has the window decor.
                adopted = mFullscreenTaskListener.createWindowDecoration(change, startT, finishT);
            }
        }

        if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
            windowDecor = mFullscreenTaskListener.giveWindowDecoration(
        mWindowDecorViewModel.setupWindowDecorationForTransition(
                change.getTaskInfo(), startT, finishT);
            if (windowDecor != null) {
                adopted = mFreeformTaskListener.adoptWindowDecoration(
                        change, startT, finishT, windowDecor);
            } else {
                // will return false if it already has the window decor.
                adopted = mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
            }
        }

        if (!adopted) {
            releaseWindowDecor(windowDecor);
        }
    }

    @Override
@@ -203,43 +143,32 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs

    @Override
    public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {
        final List<AutoCloseable> windowDecorsOfMerged = mTransitionToWindowDecors.get(merged);
        if (windowDecorsOfMerged == null) {
        final List<ActivityManager.RunningTaskInfo> infoOfMerged =
                mTransitionToTaskInfo.get(merged);
        if (infoOfMerged == null) {
            // We are adding window decorations of the merged transition to them of the playing
            // transition so if there is none of them there is nothing to do.
            return;
        }
        mTransitionToWindowDecors.remove(merged);
        mTransitionToTaskInfo.remove(merged);

        final List<AutoCloseable> windowDecorsOfPlaying = mTransitionToWindowDecors.get(playing);
        if (windowDecorsOfPlaying != null) {
            windowDecorsOfPlaying.addAll(windowDecorsOfMerged);
        final List<ActivityManager.RunningTaskInfo> infoOfPlaying =
                mTransitionToTaskInfo.get(playing);
        if (infoOfPlaying != null) {
            infoOfPlaying.addAll(infoOfMerged);
        } else {
            mTransitionToWindowDecors.put(playing, windowDecorsOfMerged);
            mTransitionToTaskInfo.put(playing, infoOfMerged);
        }
    }

    @Override
    public void onTransitionFinished(@NonNull IBinder transition, boolean aborted) {
        final List<AutoCloseable> windowDecors = mTransitionToWindowDecors.getOrDefault(
                transition, Collections.emptyList());
        mTransitionToWindowDecors.remove(transition);
        final List<ActivityManager.RunningTaskInfo> taskInfo =
                mTransitionToTaskInfo.getOrDefault(transition, Collections.emptyList());
        mTransitionToTaskInfo.remove(transition);

        for (AutoCloseable windowDecor : windowDecors) {
            releaseWindowDecor(windowDecor);
        }
        mFullscreenTaskListener.onTaskTransitionFinished();
        mFreeformTaskListener.onTaskTransitionFinished();
    }

    private static void releaseWindowDecor(AutoCloseable windowDecor) {
        if (windowDecor == null) {
            return;
        }
        try {
            windowDecor.close();
        } catch (Exception e) {
            Log.e(TAG, "Failed to release window decoration.", e);
        for (int i = 0; i < taskInfo.size(); ++i) {
            mWindowDecorViewModel.destroyWindowDecoration(taskInfo.get(i));
        }
    }
}
Loading