From 2bed621c15871260d7822f18024e6b4ee6b268ff Mon Sep 17 00:00:00 2001 From: Robert Carr Date: Thu, 20 Feb 2020 16:55:07 -0800 Subject: [PATCH] WindowContainerTransaction: Support PIP Transition We support the PIP transition by adding setChildWindowingMode and setWindowingMode primitives. This allows the organizer to replicate the old behavior during the enter pip animation of switching the Task to PIP but having the activity continue to render it's full-screen UI, or the opposite on the other transition. This is a temporary solution to handle the boundaries between Fullscreen and PIP states and the trade-off between TaskOrg and WindowManager. Once TaskOrganizer controls all windowing modes it won't be needed. Bug: 149947030 Test: TaskOrganizerTests Change-Id: I7eeb1b5fb8c5d00a00b6de976f61484f1d067048 --- .../view/WindowContainerTransaction.java | 42 +++++++++++++++++++ .../core/java/com/android/server/wm/Task.java | 8 ++++ .../server/wm/TaskOrganizerController.java | 14 ++++++- .../android/server/wm/TaskOrganizerTests.java | 26 ++++++++++++ 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java index e05c3743565c6..9c16e1334e00d 100644 --- a/core/java/android/view/WindowContainerTransaction.java +++ b/core/java/android/view/WindowContainerTransaction.java @@ -130,6 +130,31 @@ public class WindowContainerTransaction implements Parcelable { return this; } + /** + * Set the windowing mode of children of a given root task, without changing + * the windowing mode of the Task itself. This can be used during transitions + * for example to make the activity render it's fullscreen configuration + * while the Task is still in PIP, so you can complete the animation. + * + * TODO(b/134365562): Can be removed once TaskOrg drives full-screen + */ + public WindowContainerTransaction setActivityWindowingMode(IWindowContainer container, + int windowingMode) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mActivityWindowingMode = windowingMode; + return this; + } + + /** + * Sets the windowing mode of the given container. + */ + public WindowContainerTransaction setWindowingMode(IWindowContainer container, + int windowingMode) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mWindowingMode = windowingMode; + return this; + } + /** * Sets whether a container or any of its children can be focusable. When {@code false}, no * child can be focused; however, when {@code true}, it is still possible for children to be @@ -235,6 +260,9 @@ public class WindowContainerTransaction implements Parcelable { private Rect mPinnedBounds = null; private SurfaceControl.Transaction mBoundsChangeTransaction = null; + private int mActivityWindowingMode = -1; + private int mWindowingMode = -1; + public Change() {} protected Change(Parcel in) { @@ -251,6 +279,17 @@ public class WindowContainerTransaction implements Parcelable { mBoundsChangeTransaction = SurfaceControl.Transaction.CREATOR.createFromParcel(in); } + + mWindowingMode = in.readInt(); + mActivityWindowingMode = in.readInt(); + } + + public int getWindowingMode() { + return mWindowingMode; + } + + public int getActivityWindowingMode() { + return mActivityWindowingMode; } public Configuration getConfiguration() { @@ -340,6 +379,9 @@ public class WindowContainerTransaction implements Parcelable { if (mBoundsChangeTransaction != null) { mBoundsChangeTransaction.writeToParcel(dest, flags); } + + dest.writeInt(mWindowingMode); + dest.writeInt(mActivityWindowingMode); } @Override diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 2d9a3792f45fd..a9a4d9fb5e691 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4123,8 +4123,16 @@ class Task extends WindowContainer { return mMainWindowSizeChangeTransaction; } + void setActivityWindowingMode(int windowingMode) { + PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode, + PooledLambda.__(ActivityRecord.class), windowingMode); + forAllActivities(c); + c.recycle(); + } + @Override long getProtoFieldId() { return TASK; } + } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index b38c18bf15f3a..aa17666d0de83 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -553,18 +553,28 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub WindowContainerTransaction.Change c) { int effects = sanitizeAndApplyChange(wc, c); + final Task tr = wc.asTask(); + final SurfaceControl.Transaction t = c.getBoundsChangeTransaction(); if (t != null) { - Task tr = (Task) wc; tr.setMainWindowSizeChangeTransaction(t); } Rect enterPipBounds = c.getEnterPipBounds(); if (enterPipBounds != null) { - Task tr = (Task) wc; mService.mStackSupervisor.updatePictureInPictureMode(tr, enterPipBounds, true); } + + final int windowingMode = c.getWindowingMode(); + if (windowingMode > -1) { + tr.setWindowingMode(windowingMode); + } + final int childWindowingMode = c.getActivityWindowingMode(); + if (childWindowingMode > -1) { + tr.setActivityWindowingMode(childWindowingMode); + } + return effects; } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java index 48a583cad7a37..a1f1412e4c624 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -240,6 +240,32 @@ public class TaskOrganizerTests extends WindowTestsBase { assertEquals(newBounds, stack.getBounds()); } + @Test + public void testSetWindowingMode() { + final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot) + .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); + final WindowContainerTransaction t = new WindowContainerTransaction(); + + t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + + assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode()); + } + + @Test + public void testSetActivityWindowingMode() { + final ActivityRecord record = makePipableActivity(); + final ActivityStack stack = record.getStack(); + final WindowContainerTransaction t = new WindowContainerTransaction(); + + t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED); + t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + + assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode()); + assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode()); + } + @Test public void testContainerChanges() { removeGlobalMinSizeRestriction();