diff options
6 files changed, 96 insertions, 10 deletions
diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java index 9c16e1334e00..56b49515f419 100644 --- a/core/java/android/view/WindowContainerTransaction.java +++ b/core/java/android/view/WindowContainerTransaction.java @@ -168,6 +168,18 @@ public class WindowContainerTransaction implements Parcelable { } /** + * Sets whether a container or its children should be hidden. When {@code false}, the existing + * visibility of the container applies, but when {@code true} the container will be forced + * to be hidden. + */ + public WindowContainerTransaction setHidden(IWindowContainer container, boolean hidden) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mHidden = hidden; + chg.mChangeMask |= Change.CHANGE_HIDDEN; + return this; + } + + /** * Set the smallestScreenWidth of a container. */ public WindowContainerTransaction setSmallestScreenWidthDp(IWindowContainer container, @@ -250,9 +262,11 @@ public class WindowContainerTransaction implements Parcelable { public static final int CHANGE_FOCUSABLE = 1; public static final int CHANGE_BOUNDS_TRANSACTION = 1 << 1; public static final int CHANGE_PIP_CALLBACK = 1 << 2; + public static final int CHANGE_HIDDEN = 1 << 3; private final Configuration mConfiguration = new Configuration(); private boolean mFocusable = true; + private boolean mHidden = false; private int mChangeMask = 0; private @ActivityInfo.Config int mConfigSetMask = 0; private @WindowConfiguration.WindowConfig int mWindowSetMask = 0; @@ -268,6 +282,7 @@ public class WindowContainerTransaction implements Parcelable { protected Change(Parcel in) { mConfiguration.readFromParcel(in); mFocusable = in.readBoolean(); + mHidden = in.readBoolean(); mChangeMask = in.readInt(); mConfigSetMask = in.readInt(); mWindowSetMask = in.readInt(); @@ -296,7 +311,7 @@ public class WindowContainerTransaction implements Parcelable { return mConfiguration; } - /** Gets the requested focusable value */ + /** Gets the requested focusable state */ public boolean getFocusable() { if ((mChangeMask & CHANGE_FOCUSABLE) == 0) { throw new RuntimeException("Focusable not set. check CHANGE_FOCUSABLE first"); @@ -304,6 +319,14 @@ public class WindowContainerTransaction implements Parcelable { return mFocusable; } + /** Gets the requested hidden state */ + public boolean getHidden() { + if ((mChangeMask & CHANGE_HIDDEN) == 0) { + throw new RuntimeException("Hidden not set. check CHANGE_HIDDEN first"); + } + return mHidden; + } + public int getChangeMask() { return mChangeMask; } @@ -369,6 +392,7 @@ public class WindowContainerTransaction implements Parcelable { public void writeToParcel(Parcel dest, int flags) { mConfiguration.writeToParcel(dest, flags); dest.writeBoolean(mFocusable); + dest.writeBoolean(mHidden); dest.writeInt(mChangeMask); dest.writeInt(mConfigSetMask); dest.writeInt(mWindowSetMask); diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 4ebb4236b84f..e8bfe8ef63ac 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -1510,7 +1510,7 @@ class ActivityStack extends Task { */ @StackVisibility int getVisibility(ActivityRecord starting) { - if (!isAttached() || mForceHidden) { + if (!isAttached() || isForceHidden()) { return STACK_VISIBILITY_INVISIBLE; } diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 6d7f8fb6adde..57f357d384b5 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -75,6 +75,7 @@ import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_ONL import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; import static com.android.server.wm.RootWindowContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE; import static com.android.server.wm.RootWindowContainer.TAG_STATES; +import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK; import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE; import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.wm.Task.LOCK_TASK_AUTH_WHITELISTED; @@ -1565,9 +1566,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { * stopping list by handling the idle. */ stack.cancelAnimation(); - stack.mForceHidden = true; + stack.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, true /* set */); stack.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); - stack.mForceHidden = false; + stack.setForceHidden(FLAG_FORCE_HIDDEN_FOR_PINNED_TASK, false /* set */); activityIdleInternal(null /* idleActivity */, false /* fromTimeout */, true /* processPausingActivities */, null /* configuration */); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 5ab5fbcf693d..33d15ca038f9 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -431,7 +431,10 @@ class Task extends WindowContainer<WindowContainer> { private boolean mForceShowForAllUsers; /** When set, will force the task to report as invisible. */ - boolean mForceHidden = false; + static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1; + static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1; + private int mForceHiddenFlags = 0; + SurfaceControl.Transaction mMainWindowSizeChangeTransaction; @@ -3031,7 +3034,7 @@ class Task extends WindowContainer<WindowContainer> { */ @VisibleForTesting boolean isTranslucent(ActivityRecord starting) { - if (!isAttached() || mForceHidden) { + if (!isAttached() || isForceHidden()) { return true; } final PooledPredicate p = PooledLambda.obtainPredicate(Task::isOpaqueActivity, @@ -4026,17 +4029,17 @@ class Task extends WindowContainer<WindowContainer> { return; } // Let the old organizer know it has lost control. - if (mTaskOrganizer != null) { - sendTaskVanished(); - } + sendTaskVanished(); mTaskOrganizer = organizer; sendTaskAppeared(); + onTaskOrganizerChanged(); } // Called on Binder death. void taskOrganizerDied() { mTaskOrganizer = null; mLastTaskOrganizerWindowingMode = -1; + onTaskOrganizerChanged(); } /** @@ -4071,6 +4074,14 @@ class Task extends WindowContainer<WindowContainer> { mLastTaskOrganizerWindowingMode = windowingMode; } + private void onTaskOrganizerChanged() { + if (mTaskOrganizer == null) { + // If this task is no longer controlled by a task organizer, then reset the force hidden + // state + setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */); + } + } + @Override void setSurfaceControl(SurfaceControl sc) { super.setSurfaceControl(sc); @@ -4181,6 +4192,31 @@ class Task extends WindowContainer<WindowContainer> { c.recycle(); } + /** + * Sets/unsets the forced-hidden state flag for this task depending on {@param set}. + * @return Whether the force hidden state changed + */ + boolean setForceHidden(int flags, boolean set) { + int newFlags = mForceHiddenFlags; + if (set) { + newFlags |= flags; + } else { + newFlags &= ~flags; + } + if (mForceHiddenFlags == newFlags) { + return false; + } + mForceHiddenFlags = newFlags; + return true; + } + + /** + * Returns whether this task is currently forced to be hidden for any reason. + */ + protected boolean isForceHidden() { + return mForceHiddenFlags != 0; + } + @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 9cbc9ee3f9ee..8f09f3faae29 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -23,6 +23,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG; import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; import static com.android.server.wm.WindowContainer.POSITION_TOP; @@ -475,6 +476,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub if (!(container instanceof Task)) { throw new RuntimeException("Invalid token in task transaction"); } + final Task task = (Task) container; // The "client"-facing API should prevent bad changes; however, just in case, sanitize // masks here. int configMask = change.getConfigSetMask(); @@ -498,6 +500,11 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub effects |= TRANSACT_EFFECTS_LIFECYCLE; } } + if ((change.getChangeMask() & WindowContainerTransaction.Change.CHANGE_HIDDEN) != 0) { + if (task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, change.getHidden())) { + effects |= TRANSACT_EFFECTS_LIFECYCLE; + } + } 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 19ed7a9101de..98ab9023f4dd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java @@ -277,7 +277,7 @@ public class TaskOrganizerTests extends WindowTestsBase { } @Test - public void testContainerChanges() { + public void testContainerFocusableChanges() { removeGlobalMinSizeRestriction(); final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot) .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); @@ -287,6 +287,24 @@ public class TaskOrganizerTests extends WindowTestsBase { t.setFocusable(stack.mRemoteToken, false); mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); assertFalse(task.isFocusable()); + t.setFocusable(stack.mRemoteToken, true); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + assertTrue(task.isFocusable()); + } + + @Test + public void testContainerHiddenChanges() { + removeGlobalMinSizeRestriction(); + final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot) + .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); + WindowContainerTransaction t = new WindowContainerTransaction(); + assertTrue(stack.shouldBeVisible(null)); + t.setHidden(stack.mRemoteToken, true); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + assertFalse(stack.shouldBeVisible(null)); + t.setHidden(stack.mRemoteToken, false); + mWm.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null); + assertTrue(stack.shouldBeVisible(null)); } @Test |