Merge "Add task-launch support to WindowContainerTransaction" into sc-dev
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user