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

Commit 6c48dabf authored by Evan Rosky's avatar Evan Rosky Committed by Android (Google) Code Review
Browse files

Merge "Add task-launch support to WindowContainerTransaction" into sc-dev

parents 0b095b1e 7fe3ce53
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -76,6 +76,9 @@ public final class TransitionInfo implements Parcelable {
    /** The container is the recipient of a transferred starting-window */
    public static final int FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT = 1 << 3;

    /** The first unused bit. This can be used by remotes to attach custom flags to this change. */
    public static final int FLAG_FIRST_CUSTOM = 1 << 4;

    /** @hide */
    @IntDef(prefix = { "FLAG_" }, value = {
            FLAG_NONE,
@@ -252,7 +255,8 @@ public final class TransitionInfo implements Parcelable {
     * Indication that `change` is independent of parents (ie. it has a different type of
     * transition vs. "going along for the ride")
     */
    public static boolean isIndependent(TransitionInfo.Change change, TransitionInfo info) {
    public static boolean isIndependent(@NonNull TransitionInfo.Change change,
            @NonNull TransitionInfo info) {
        // If the change has no parent (it is root), then it is independent
        if (change.getParent() == null) return true;

@@ -343,7 +347,7 @@ public final class TransitionInfo implements Parcelable {
         * Sets the taskinfo of this container if this is a task. WARNING: this takes the
         * reference, so don't modify it afterwards.
         */
        public void setTaskInfo(ActivityManager.RunningTaskInfo taskInfo) {
        public void setTaskInfo(@Nullable ActivityManager.RunningTaskInfo taskInfo) {
            mTaskInfo = taskInfo;
        }

@@ -424,8 +428,8 @@ public final class TransitionInfo implements Parcelable {
            return mEndRotation;
        }

        @Override
        /** @hide */
        @Override
        public void writeToParcel(@NonNull Parcel dest, int flags) {
            dest.writeTypedObject(mContainer, flags);
            dest.writeTypedObject(mParent, flags);
@@ -454,8 +458,8 @@ public final class TransitionInfo implements Parcelable {
                    }
                };

        @Override
        /** @hide */
        @Override
        public int describeContents() {
            return 0;
        }
+47 −7
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -337,6 +338,18 @@ public final class WindowContainerTransaction implements Parcelable {
        return this;
    }

    /**
     * Starts a task by id. The task is expected to already exist (eg. as a recent task).
     * @param taskId Id of task to start.
     * @param options bundle containing ActivityOptions for the task's top activity.
     * @hide
     */
    @NonNull
    public WindowContainerTransaction startTask(int taskId, @Nullable Bundle options) {
        mHierarchyOps.add(HierarchyOp.createForTaskLaunch(taskId, options));
        return this;
    }

    /**
     * Merges another WCT into this one.
     * @param transfer When true, this will transfer everything from other potentially leaving
@@ -663,6 +676,11 @@ public final class WindowContainerTransaction implements Parcelable {
        public static final int HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT = 2;
        public static final int HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT = 3;
        public static final int HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS = 4;
        public static final int HIERARCHY_OP_TYPE_LAUNCH_TASK = 5;

        // The following key(s) are for use with mLaunchOptions:
        // When launching a task (eg. from recents), this is the taskId to be launched.
        public static final String LAUNCH_KEY_TASK_ID = "android:transaction.hop.taskId";

        private final int mType;

@@ -678,36 +696,47 @@ public final class WindowContainerTransaction implements Parcelable {
        final private int[]  mWindowingModes;
        final private int[] mActivityTypes;

        private final Bundle mLaunchOptions;

        public static HierarchyOp createForReparent(
                @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) {
            return new HierarchyOp(HIERARCHY_OP_TYPE_REPARENT,
                    container, reparent, null, null, toTop);
                    container, reparent, null, null, toTop, null);
        }

        public static HierarchyOp createForReorder(@NonNull IBinder container, boolean toTop) {
            return new HierarchyOp(HIERARCHY_OP_TYPE_REORDER,
                    container, container, null, null, toTop);
                    container, container, null, null, toTop, null);
        }

        public static HierarchyOp createForChildrenTasksReparent(IBinder currentParent,
                IBinder newParent, int[] windowingModes, int[] activityTypes, boolean onTop) {
            return new HierarchyOp(HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT,
                    currentParent, newParent, windowingModes, activityTypes, onTop);
                    currentParent, newParent, windowingModes, activityTypes, onTop, null);
        }

        public static HierarchyOp createForSetLaunchRoot(IBinder container,
                int[] windowingModes, int[] activityTypes) {
            return new HierarchyOp(HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT,
                    container, null, windowingModes, activityTypes, false);
                    container, null, windowingModes, activityTypes, false, null);
        }

        public static HierarchyOp createForAdjacentRoots(IBinder root1, IBinder root2) {
            return new HierarchyOp(HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS,
                    root1, root2, null, null, false);
                    root1, root2, null, null, false, null);
        }

        /** Create a hierarchy op for launching a task. */
        public static HierarchyOp createForTaskLaunch(int taskId, @Nullable Bundle options) {
            final Bundle fullOptions = options == null ? new Bundle() : options;
            fullOptions.putInt(LAUNCH_KEY_TASK_ID, taskId);
            return new HierarchyOp(HIERARCHY_OP_TYPE_LAUNCH_TASK, null, null, null, null, true,
                    fullOptions);
        }

        private HierarchyOp(int type, @NonNull IBinder container, @Nullable IBinder reparent,
                int[] windowingModes, int[] activityTypes, boolean toTop) {
        private HierarchyOp(int type, @Nullable IBinder container, @Nullable IBinder reparent,
                int[] windowingModes, int[] activityTypes, boolean toTop,
                @Nullable Bundle launchOptions) {
            mType = type;
            mContainer = container;
            mReparent = reparent;
@@ -716,6 +745,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mActivityTypes = activityTypes != null ?
                    Arrays.copyOf(activityTypes, activityTypes.length) : null;
            mToTop = toTop;
            mLaunchOptions = launchOptions;
        }

        public HierarchyOp(@NonNull HierarchyOp copy) {
@@ -725,6 +755,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mToTop = copy.mToTop;
            mWindowingModes = copy.mWindowingModes;
            mActivityTypes = copy.mActivityTypes;
            mLaunchOptions = copy.mLaunchOptions;
        }

        protected HierarchyOp(Parcel in) {
@@ -734,6 +765,7 @@ public final class WindowContainerTransaction implements Parcelable {
            mToTop = in.readBoolean();
            mWindowingModes = in.createIntArray();
            mActivityTypes = in.createIntArray();
            mLaunchOptions = in.readBundle();
        }

        public int getType() {
@@ -771,6 +803,11 @@ public final class WindowContainerTransaction implements Parcelable {
            return mActivityTypes;
        }

        @Nullable
        public Bundle getLaunchOptions() {
            return mLaunchOptions;
        }

        @Override
        public String toString() {
            switch (mType) {
@@ -790,6 +827,8 @@ public final class WindowContainerTransaction implements Parcelable {
                case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS:
                    return "{SetAdjacentRoot: container=" + mContainer
                            + " adjacentRoot=" + mReparent + "}";
                case HIERARCHY_OP_TYPE_LAUNCH_TASK:
                    return "{LaunchTask: " + mLaunchOptions + "}";
                default:
                    return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
                            + " mToTop=" + mToTop + " mWindowingMode=" + mWindowingModes
@@ -805,6 +844,7 @@ public final class WindowContainerTransaction implements Parcelable {
            dest.writeBoolean(mToTop);
            dest.writeIntArray(mWindowingModes);
            dest.writeIntArray(mActivityTypes);
            dest.writeBundle(mLaunchOptions);
        }

        @Override
+20 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.wm;

import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_LAUNCH_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS;
@@ -38,6 +39,7 @@ import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
@@ -191,6 +193,15 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                    if (type < 0) {
                        throw new IllegalArgumentException("Can't create transition with no type");
                    }
                    if (mTransitionController.getTransitionPlayer() == null) {
                        Slog.w(TAG, "Using shell transitions API for legacy transitions.");
                        if (t == null) {
                            throw new IllegalArgumentException("Can't use legacy transitions in"
                                    + " compatibility mode with no WCT.");
                        }
                        applyTransaction(t, -1 /* syncId */, null);
                        return null;
                    }
                    transition = mTransitionController.createTransition(type);
                }
                transition.start();
@@ -346,6 +357,15 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
                                }
                            }
                            effects |= sanitizeAndApplyHierarchyOp(wc, hop);
                            break;
                        case HIERARCHY_OP_TYPE_LAUNCH_TASK:
                            Bundle launchOpts = hop.getLaunchOptions();
                            int taskId = launchOpts.getInt(
                                    WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
                            launchOpts.remove(
                                    WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID);
                            mService.startActivityFromRecents(taskId, launchOpts);
                            break;
                    }
                }
            }
+23 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import static android.app.ActivityManager.START_CANCELED;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -55,6 +56,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;

@@ -68,6 +70,7 @@ import android.content.pm.ParceledListSlice;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
@@ -1315,6 +1318,26 @@ public class WindowOrganizerTests extends WindowTestsBase {
        assertFalse(info.topActivityInSizeCompat);
    }

    @Test
    public void testStartTasksInTransaction() {
        WindowContainerTransaction wct = new WindowContainerTransaction();
        Bundle testOptions = new Bundle();
        testOptions.putInt("test", 20);
        wct.startTask(1, null /* options */);
        wct.startTask(2, testOptions);
        spyOn(mWm.mAtmService);
        doReturn(START_CANCELED).when(mWm.mAtmService).startActivityFromRecents(anyInt(), any());
        clearInvocations(mWm.mAtmService);
        mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);

        final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
        verify(mWm.mAtmService, times(1)).startActivityFromRecents(eq(1), bundleCaptor.capture());
        assertTrue(bundleCaptor.getValue().isEmpty());

        verify(mWm.mAtmService, times(1)).startActivityFromRecents(eq(2), bundleCaptor.capture());
        assertEquals(20, bundleCaptor.getValue().getInt("test"));
    }

    /**
     * Verifies that task vanished is called for a specific task.
     */