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

This commit is contained in:
Evan Rosky
2021-03-30 20:19:44 +00:00
committed by Android (Google) Code Review
4 changed files with 98 additions and 11 deletions

View File

@@ -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;
}

View File

@@ -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);
}
private HierarchyOp(int type, @NonNull IBinder container, @Nullable IBinder reparent,
int[] windowingModes, int[] activityTypes, boolean toTop) {
/** 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, @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

View File

@@ -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;
}
}
}

View File

@@ -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.
*/