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

Commit 66403987 authored by Automerger Merge Worker's avatar Automerger Merge Worker Committed by Android (Google) Code Review
Browse files

Merge "Merge "Move more utils into TransitionUtil" into udc-dev am: b5670b76 am: 17c1dc20"

parents 477b0916 8c54dcdc
Loading
Loading
Loading
Loading
+207 −0
Original line number Diff line number Diff line
@@ -16,18 +16,40 @@

package com.android.wm.shell.util;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.view.RemoteAnimationTarget.MODE_CHANGING;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
import static android.window.TransitionInfo.FLAG_IS_DISPLAY;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;

import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.SparseBooleanArray;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;

import java.util.function.Predicate;

/** Various utility functions for transitions. */
public class TransitionUtil {

@@ -54,4 +76,189 @@ public class TransitionUtil {
        return false;
    }

    /** Returns `true` if `change` is a wallpaper. */
    public static boolean isWallpaper(TransitionInfo.Change change) {
        return (change.getTaskInfo() == null)
                && change.hasFlags(FLAG_IS_WALLPAPER)
                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
    }

    /** Returns `true` if `change` is not an app window or wallpaper. */
    public static boolean isNonApp(TransitionInfo.Change change) {
        return (change.getTaskInfo() == null)
                && !change.hasFlags(FLAG_IS_WALLPAPER)
                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
    }

    /**
     * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
     * MUST call `test` in the same order that the changes appear in the TransitionInfo.
     */
    public static class LeafTaskFilter implements Predicate<TransitionInfo.Change> {
        private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();

        @Override
        public boolean test(TransitionInfo.Change change) {
            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
            // Children always come before parent since changes are in top-to-bottom z-order.
            if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
                // has children, so not a leaf. Skip.
                return false;
            }
            if (taskInfo.hasParentTask()) {
                mChildTaskTargets.put(taskInfo.parentTaskId, true);
            }
            return true;
        }
    }


    private static int newModeToLegacyMode(int newMode) {
        switch (newMode) {
            case WindowManager.TRANSIT_OPEN:
            case WindowManager.TRANSIT_TO_FRONT:
                return MODE_OPENING;
            case WindowManager.TRANSIT_CLOSE:
            case WindowManager.TRANSIT_TO_BACK:
                return MODE_CLOSING;
            default:
                return MODE_CHANGING;
        }
    }

    /**
     * Very similar to Transitions#setupAnimHierarchy but specialized for leashes.
     */
    @SuppressLint("NewApi")
    private static void setupLeash(@NonNull SurfaceControl leash,
            @NonNull TransitionInfo.Change change, int layer,
            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
        final boolean isOpening = TransitionUtil.isOpeningType(info.getType());
        // Put animating stuff above this line and put static stuff below it.
        int zSplitLine = info.getChanges().size();
        // changes should be ordered top-to-bottom in z
        final int mode = change.getMode();

        t.reparent(leash, info.getRootLeash());
        final Rect absBounds =
                (mode == TRANSIT_OPEN) ? change.getEndAbsBounds() : change.getStartAbsBounds();
        t.setPosition(leash, absBounds.left - info.getRootOffset().x,
                absBounds.top - info.getRootOffset().y);

        // Put all the OPEN/SHOW on top
        if (TransitionUtil.isOpeningType(mode)) {
            if (isOpening) {
                t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
                if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
                    // if transferred, it should be left visible.
                    t.setAlpha(leash, 0.f);
                }
            } else {
                // put on bottom and leave it visible
                t.setLayer(leash, zSplitLine - layer);
            }
        } else if (TransitionUtil.isClosingType(mode)) {
            if (isOpening) {
                // put on bottom and leave visible
                t.setLayer(leash, zSplitLine - layer);
            } else {
                // put on top
                t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
            }
        } else { // CHANGE
            t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
        }
    }

    @SuppressLint("NewApi")
    private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
            int order, SurfaceControl.Transaction t) {
        // TODO: once we can properly sync transactions across process, then get rid of this leash.
        if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
            // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
            // making leashes means we have to handle them specially.
            return change.getLeash();
        }
        SurfaceControl leashSurface = new SurfaceControl.Builder()
                .setName(change.getLeash().toString() + "_transition-leash")
                .setContainerLayer()
                // Initial the surface visible to respect the visibility of the original surface.
                .setHidden(false)
                .setParent(info.getRootLeash())
                .build();
        // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
        setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
        t.reparent(change.getLeash(), leashSurface);
        t.setAlpha(change.getLeash(), 1.0f);
        t.show(change.getLeash());
        t.setPosition(change.getLeash(), 0, 0);
        t.setLayer(change.getLeash(), 0);
        return leashSurface;
    }

    /**
     * Creates a new RemoteAnimationTarget from the provided change info
     */
    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
            TransitionInfo info, SurfaceControl.Transaction t,
            @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
        final SurfaceControl leash = createLeash(info, change, order, t);
        if (leashMap != null) {
            leashMap.put(change.getLeash(), leash);
        }
        return newTarget(change, order, leash);
    }

    /**
     * Creates a new RemoteAnimationTarget from the provided change and leash
     */
    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
            SurfaceControl leash) {
        int taskId;
        boolean isNotInRecents;
        ActivityManager.RunningTaskInfo taskInfo;
        WindowConfiguration windowConfiguration;

        taskInfo = change.getTaskInfo();
        if (taskInfo != null) {
            taskId = taskInfo.taskId;
            isNotInRecents = !taskInfo.isRunning;
            windowConfiguration = taskInfo.configuration.windowConfiguration;
        } else {
            taskId = INVALID_TASK_ID;
            isNotInRecents = true;
            windowConfiguration = new WindowConfiguration();
        }

        Rect localBounds = new Rect(change.getEndAbsBounds());
        localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);

        RemoteAnimationTarget target = new RemoteAnimationTarget(
                taskId,
                newModeToLegacyMode(change.getMode()),
                // TODO: once we can properly sync transactions across process,
                // then get rid of this leash.
                leash,
                (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
                null,
                // TODO(shell-transitions): we need to send content insets? evaluate how its used.
                new Rect(0, 0, 0, 0),
                order,
                null,
                localBounds,
                new Rect(change.getEndAbsBounds()),
                windowConfiguration,
                isNotInRecents,
                null,
                new Rect(change.getStartAbsBounds()),
                taskInfo,
                change.getAllowEnterPip(),
                (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
                        ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
        );
        target.setWillShowImeOnTarget(
                (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
        target.setRotationChange(change.getEndRotation() - change.getStartRotation());
        return target;
    }
}
+5 −211
Original line number Diff line number Diff line
@@ -16,30 +16,9 @@

package com.android.systemui.shared.system;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.view.RemoteAnimationTarget.MODE_CHANGING;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;

import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.SparseBooleanArray;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
import android.window.TransitionInfo.Change;

@@ -53,156 +32,6 @@ import java.util.function.Predicate;
 */
public class RemoteAnimationTargetCompat {

    private static int newModeToLegacyMode(int newMode) {
        switch (newMode) {
            case WindowManager.TRANSIT_OPEN:
            case WindowManager.TRANSIT_TO_FRONT:
                return MODE_OPENING;
            case WindowManager.TRANSIT_CLOSE:
            case WindowManager.TRANSIT_TO_BACK:
                return MODE_CLOSING;
            default:
                return MODE_CHANGING;
        }
    }

    /**
     * Almost a copy of Transitions#setupStartState.
     * TODO: remove when there is proper cross-process transaction sync.
     */
    @SuppressLint("NewApi")
    private static void setupLeash(@NonNull SurfaceControl leash,
            @NonNull TransitionInfo.Change change, int layer,
            @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
        final boolean isOpening = TransitionUtil.isOpeningType(info.getType());
        // Put animating stuff above this line and put static stuff below it.
        int zSplitLine = info.getChanges().size();
        // changes should be ordered top-to-bottom in z
        final int mode = change.getMode();

        t.reparent(leash, info.getRootLeash());
        final Rect absBounds =
                (mode == TRANSIT_OPEN) ? change.getEndAbsBounds() : change.getStartAbsBounds();
        t.setPosition(leash, absBounds.left - info.getRootOffset().x,
                absBounds.top - info.getRootOffset().y);

        // Put all the OPEN/SHOW on top
        if (TransitionUtil.isOpeningType(mode)) {
            if (isOpening) {
                t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
                if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
                    // if transferred, it should be left visible.
                    t.setAlpha(leash, 0.f);
                }
            } else {
                // put on bottom and leave it visible
                t.setLayer(leash, zSplitLine - layer);
            }
        } else if (TransitionUtil.isClosingType(mode)) {
            if (isOpening) {
                // put on bottom and leave visible
                t.setLayer(leash, zSplitLine - layer);
            } else {
                // put on top
                t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
            }
        } else { // CHANGE
            t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
        }
    }

    @SuppressLint("NewApi")
    private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
            int order, SurfaceControl.Transaction t) {
        // TODO: once we can properly sync transactions across process, then get rid of this leash.
        if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
            // Special case for wallpaper atm. Normally these are left alone; but, a quirk of
            // making leashes means we have to handle them specially.
            return change.getLeash();
        }
        SurfaceControl leashSurface = new SurfaceControl.Builder()
                .setName(change.getLeash().toString() + "_transition-leash")
                .setContainerLayer()
                // Initial the surface visible to respect the visibility of the original surface.
                .setHidden(false)
                .setParent(info.getRootLeash())
                .build();
        // Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
        setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
        t.reparent(change.getLeash(), leashSurface);
        t.setAlpha(change.getLeash(), 1.0f);
        t.show(change.getLeash());
        t.setPosition(change.getLeash(), 0, 0);
        t.setLayer(change.getLeash(), 0);
        return leashSurface;
    }

    /**
     * Creates a new RemoteAnimationTarget from the provided change info
     */
    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
            TransitionInfo info, SurfaceControl.Transaction t,
            @Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
        final SurfaceControl leash = createLeash(info, change, order, t);
        if (leashMap != null) {
            leashMap.put(change.getLeash(), leash);
        }
        return newTarget(change, order, leash);
    }

    /**
     * Creates a new RemoteAnimationTarget from the provided change and leash
     */
    public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
            SurfaceControl leash) {
        int taskId;
        boolean isNotInRecents;
        ActivityManager.RunningTaskInfo taskInfo;
        WindowConfiguration windowConfiguration;

        taskInfo = change.getTaskInfo();
        if (taskInfo != null) {
            taskId = taskInfo.taskId;
            isNotInRecents = !taskInfo.isRunning;
            windowConfiguration = taskInfo.configuration.windowConfiguration;
        } else {
            taskId = INVALID_TASK_ID;
            isNotInRecents = true;
            windowConfiguration = new WindowConfiguration();
        }

        Rect localBounds = new Rect(change.getEndAbsBounds());
        localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);

        RemoteAnimationTarget target = new RemoteAnimationTarget(
                taskId,
                newModeToLegacyMode(change.getMode()),
                // TODO: once we can properly sync transactions across process,
                // then get rid of this leash.
                leash,
                (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
                null,
                // TODO(shell-transitions): we need to send content insets? evaluate how its used.
                new Rect(0, 0, 0, 0),
                order,
                null,
                localBounds,
                new Rect(change.getEndAbsBounds()),
                windowConfiguration,
                isNotInRecents,
                null,
                new Rect(change.getStartAbsBounds()),
                taskInfo,
                change.getAllowEnterPip(),
                (change.getFlags() & FLAG_IS_DIVIDER_BAR) != 0
                        ? TYPE_DOCK_DIVIDER : INVALID_WINDOW_TYPE
        );
        target.setWillShowImeOnTarget(
                (change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
        target.setRotationChange(change.getEndRotation() - change.getStartRotation());
        return target;
    }

    /**
     * Represents a TransitionInfo object as an array of old-style app targets
     *
@@ -211,7 +40,7 @@ public class RemoteAnimationTargetCompat {
     */
    public static RemoteAnimationTarget[] wrapApps(TransitionInfo info,
            SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
        return wrap(info, t, leashMap, new LeafTaskFilter());
        return wrap(info, t, leashMap, new TransitionUtil.LeafTaskFilter());
    }

    /**
@@ -224,8 +53,8 @@ public class RemoteAnimationTargetCompat {
     */
    public static RemoteAnimationTarget[] wrapNonApps(TransitionInfo info, boolean wallpapers,
            SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
        return wrap(info, t, leashMap, (change) ->
                (wallpapers ? isWallpaper(change) : isNonApp(change)));
        return wrap(info, t, leashMap, (change) -> (wallpapers
                ? TransitionUtil.isWallpaper(change) : TransitionUtil.isNonApp(change)));
    }

    private static RemoteAnimationTarget[] wrap(TransitionInfo info,
@@ -235,45 +64,10 @@ public class RemoteAnimationTargetCompat {
        for (int i = 0; i < info.getChanges().size(); i++) {
            TransitionInfo.Change change = info.getChanges().get(i);
            if (filter.test(change)) {
                out.add(newTarget(change, info.getChanges().size() - i, info, t, leashMap));
                out.add(TransitionUtil.newTarget(
                        change, info.getChanges().size() - i, info, t, leashMap));
            }
        }
        return out.toArray(new RemoteAnimationTarget[out.size()]);
    }

    /** Returns `true` if `change` is a wallpaper. */
    public static boolean isWallpaper(Change change) {
        return (change.getTaskInfo() == null)
                && change.hasFlags(FLAG_IS_WALLPAPER)
                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
    }

    /** Returns `true` if `change` is not an app window or wallpaper. */
    public static boolean isNonApp(Change change) {
        return (change.getTaskInfo() == null)
                && !change.hasFlags(FLAG_IS_WALLPAPER)
                && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
    }

    /**
     * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
     * MUST call `test` in the same order that the changes appear in the TransitionInfo.
     */
    public static class LeafTaskFilter implements Predicate<Change> {
        private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();

        @Override
        public boolean test(Change change) {
            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
            // Children always come before parent since changes are in top-to-bottom z-order.
            if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
                // has children, so not a leaf. Skip.
                return false;
            }
            if (taskInfo.hasParentTask()) {
                mChildTaskTargets.put(taskInfo.parentTaskId, true);
            }
            return true;
        }
    }
}
+9 −11
Original line number Diff line number Diff line
@@ -21,8 +21,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;

import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.newTarget;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
@@ -160,16 +158,15 @@ public class RemoteTransitionCompat {

            final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
            final ArrayList<RemoteAnimationTarget> wallpapers = new ArrayList<>();
            RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
                    new RemoteAnimationTargetCompat.LeafTaskFilter();
            TransitionUtil.LeafTaskFilter leafTaskFilter = new TransitionUtil.LeafTaskFilter();
            // About layering: we divide up the "layer space" into 3 regions (each the size of
            // the change count). This lets us categorize things into above/below/between
            // while maintaining their relative ordering.
            for (int i = 0; i < info.getChanges().size(); ++i) {
                final TransitionInfo.Change change = info.getChanges().get(i);
                final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                if (RemoteAnimationTargetCompat.isWallpaper(change)) {
                    final RemoteAnimationTarget target = newTarget(change,
                if (TransitionUtil.isWallpaper(change)) {
                    final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
                            // wallpapers go into the "below" layer space
                            info.getChanges().size() - i, info, t, mLeashMap);
                    wallpapers.add(target);
@@ -177,7 +174,7 @@ public class RemoteTransitionCompat {
                    t.setAlpha(target.leash, 1);
                } else if (leafTaskFilter.test(change)) {
                    // start by putting everything into the "below" layer space.
                    final RemoteAnimationTarget target = newTarget(change,
                    final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
                            info.getChanges().size() - i, info, t, mLeashMap);
                    apps.add(target);
                    if (TransitionUtil.isClosingType(change.getMode())) {
@@ -217,8 +214,8 @@ public class RemoteTransitionCompat {
            TransitionInfo.Change recentsOpening = null;
            boolean foundRecentsClosing = false;
            boolean hasChangingApp = false;
            final RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
                    new RemoteAnimationTargetCompat.LeafTaskFilter();
            final TransitionUtil.LeafTaskFilter leafTaskFilter =
                    new TransitionUtil.LeafTaskFilter();
            for (int i = 0; i < info.getChanges().size(); ++i) {
                final TransitionInfo.Change change = info.getChanges().get(i);
                final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
@@ -308,7 +305,8 @@ public class RemoteTransitionCompat {
                    int pausingIdx = TaskState.indexOf(mPausingTasks, change);
                    if (pausingIdx >= 0) {
                        // Something is showing/opening a previously-pausing app.
                        targets[i] = newTarget(change, layer, mPausingTasks.get(pausingIdx).mLeash);
                        targets[i] = TransitionUtil.newTarget(change, layer,
                                mPausingTasks.get(pausingIdx).mLeash);
                        mOpeningTasks.add(mPausingTasks.remove(pausingIdx));
                        // Setup hides opening tasks initially, so make it visible again (since we
                        // are already showing it).
@@ -316,7 +314,7 @@ public class RemoteTransitionCompat {
                        t.setAlpha(change.getLeash(), 1.f);
                    } else {
                        // We are receiving new opening tasks, so convert to onTasksAppeared.
                        targets[i] = newTarget(change, layer, info, t, mLeashMap);
                        targets[i] = TransitionUtil.newTarget(change, layer, info, t, mLeashMap);
                        t.reparent(targets[i].leash, mInfo.getRootLeash());
                        t.setLayer(targets[i].leash, layer);
                        mOpeningTasks.add(new TaskState(change, targets[i].leash));
+2 −1

File changed.

Preview size limit exceeded, changes collapsed.