From f93ff02d21159772e4d9f6e48514d777454f7ef1 Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Thu, 4 Aug 2022 07:36:40 +0000 Subject: [PATCH] Add setForceTranslucent API Add this api for split screen improve enter transition. When we start intent on side stage task, the top split root task will go to top and current top one task will be set as invisible then cause black screen due to split root task is full screen. Solve this by use new wct api setForceTranslucent to make split root task as translucent when split inactive. We need to reset it when split active otherwise it cause flicker when back to home. Bug: 223325631 Bug: 235029020 Test: atest WmTests Change-Id: I28df2879345718b726af9fdb7ea54644c77ab925 --- .../window/WindowContainerTransaction.java | 30 +++++++++++++++++++ .../core/java/com/android/server/wm/Task.java | 10 +++++++ .../com/android/server/wm/TaskFragment.java | 6 +++- .../server/wm/WindowOrganizerController.java | 6 ++++ .../server/wm/WindowOrganizerTests.java | 16 ++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java index 3bffa890122ac..e3430a6868647 100644 --- a/core/java/android/window/WindowContainerTransaction.java +++ b/core/java/android/window/WindowContainerTransaction.java @@ -268,6 +268,20 @@ public final class WindowContainerTransaction implements Parcelable { return this; } + /** + * Sets whether a task should be translucent. When {@code false}, the existing translucent of + * the task applies, but when {@code true} the task will be forced to be translucent. + * @hide + */ + @NonNull + public WindowContainerTransaction setForceTranslucent( + @NonNull WindowContainerToken container, boolean forceTranslucent) { + Change chg = getOrCreateChange(container.asBinder()); + chg.mForceTranslucent = forceTranslucent; + chg.mChangeMask |= Change.CHANGE_FORCE_TRANSLUCENT; + return this; + } + /** * Used in conjunction with a shell-transition call (usually finishTransition). This is * basically a message to the transition system that a particular task should NOT go into @@ -834,11 +848,13 @@ public final class WindowContainerTransaction implements Parcelable { public static final int CHANGE_BOUNDS_TRANSACTION_RECT = 1 << 4; public static final int CHANGE_IGNORE_ORIENTATION_REQUEST = 1 << 5; public static final int CHANGE_FORCE_NO_PIP = 1 << 6; + public static final int CHANGE_FORCE_TRANSLUCENT = 1 << 7; private final Configuration mConfiguration = new Configuration(); private boolean mFocusable = true; private boolean mHidden = false; private boolean mIgnoreOrientationRequest = false; + private boolean mForceTranslucent = false; private int mChangeMask = 0; private @ActivityInfo.Config int mConfigSetMask = 0; @@ -858,6 +874,7 @@ public final class WindowContainerTransaction implements Parcelable { mFocusable = in.readBoolean(); mHidden = in.readBoolean(); mIgnoreOrientationRequest = in.readBoolean(); + mForceTranslucent = in.readBoolean(); mChangeMask = in.readInt(); mConfigSetMask = in.readInt(); mWindowSetMask = in.readInt(); @@ -903,6 +920,9 @@ public final class WindowContainerTransaction implements Parcelable { if ((other.mChangeMask & CHANGE_IGNORE_ORIENTATION_REQUEST) != 0) { mIgnoreOrientationRequest = other.mIgnoreOrientationRequest; } + if ((other.mChangeMask & CHANGE_FORCE_TRANSLUCENT) != 0) { + mForceTranslucent = other.mForceTranslucent; + } mChangeMask |= other.mChangeMask; if (other.mActivityWindowingMode >= 0) { mActivityWindowingMode = other.mActivityWindowingMode; @@ -953,6 +973,15 @@ public final class WindowContainerTransaction implements Parcelable { return mIgnoreOrientationRequest; } + /** Gets the requested force translucent state. */ + public boolean getForceTranslucent() { + if ((mChangeMask & CHANGE_FORCE_TRANSLUCENT) == 0) { + throw new RuntimeException("Force translucent not set. " + + "Check CHANGE_FORCE_TRANSLUCENT first"); + } + return mForceTranslucent; + } + public int getChangeMask() { return mChangeMask; } @@ -1030,6 +1059,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeBoolean(mFocusable); dest.writeBoolean(mHidden); dest.writeBoolean(mIgnoreOrientationRequest); + dest.writeBoolean(mForceTranslucent); dest.writeInt(mChangeMask); dest.writeInt(mConfigSetMask); dest.writeInt(mWindowSetMask); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 2ba0e23f90117..cb90501231c4a 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -489,6 +489,7 @@ class Task extends TaskFragment { 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; + private boolean mForceTranslucent = false; // TODO(b/160201781): Revisit double invocation issue in Task#removeChild. /** @@ -4348,6 +4349,10 @@ class Task extends TaskFragment { return true; } + void setForceTranslucent(boolean set) { + mForceTranslucent = set; + } + @Override public boolean isAlwaysOnTop() { return !isForceHidden() && super.isAlwaysOnTop(); @@ -4365,6 +4370,11 @@ class Task extends TaskFragment { return mForceHiddenFlags != 0; } + @Override + protected boolean isForceTranslucent() { + return mForceTranslucent; + } + @Override long getProtoFieldId() { return TASK; diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 3b25f2876de4e..83929c29eb0ab 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -737,6 +737,10 @@ class TaskFragment extends WindowContainer { return false; } + protected boolean isForceTranslucent() { + return false; + } + boolean isLeafTaskFragment() { for (int i = mChildren.size() - 1; i >= 0; --i) { if (mChildren.get(i).asTaskFragment() != null) { @@ -862,7 +866,7 @@ class TaskFragment extends WindowContainer { */ @VisibleForTesting boolean isTranslucent(ActivityRecord starting) { - if (!isAttached() || isForceHidden()) { + if (!isAttached() || isForceHidden() || isForceTranslucent()) { return true; } final PooledPredicate p = PooledLambda.obtainPredicate(TaskFragment::isOpaqueActivity, diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 29e407fccdb70..5a2100d4ecacd 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -645,6 +645,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } } + if ((c.getChangeMask() + & WindowContainerTransaction.Change.CHANGE_FORCE_TRANSLUCENT) != 0) { + tr.setForceTranslucent(c.getForceTranslucent()); + effects = TRANSACT_EFFECTS_LIFECYCLE; + } + final int childWindowingMode = c.getActivityWindowingMode(); if (childWindowingMode > -1) { tr.setActivityWindowingMode(childWindowingMode); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 84c2c551de85f..7d4e6fa53a64a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -577,6 +577,22 @@ public class WindowOrganizerTests extends WindowTestsBase { assertTrue(rootTask.shouldBeVisible(null)); } + @Test + public void testContainerTranslucentChanges() { + removeGlobalMinSizeRestriction(); + final Task rootTask = new TaskBuilder(mSupervisor).setCreateActivity(true) + .setWindowingMode(WINDOWING_MODE_FULLSCREEN).build(); + final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(rootTask).build(); + WindowContainerTransaction t = new WindowContainerTransaction(); + assertFalse(rootTask.isTranslucent(activity)); + t.setForceTranslucent(rootTask.mRemoteToken.toWindowContainerToken(), true); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); + assertTrue(rootTask.isTranslucent(activity)); + t.setForceTranslucent(rootTask.mRemoteToken.toWindowContainerToken(), false); + mWm.mAtmService.mWindowOrganizerController.applyTransaction(t); + assertFalse(rootTask.isTranslucent(activity)); + } + @Test public void testSetIgnoreOrientationRequest_taskDisplayArea() { removeGlobalMinSizeRestriction();