summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/test-current.txt6
-rw-r--r--core/java/android/window/WindowContainerTransaction.java29
-rw-r--r--graphics/java/android/graphics/Rect.java35
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java2
-rw-r--r--services/core/java/com/android/server/wm/ConfigurationContainer.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java31
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java15
8 files changed, 130 insertions, 2 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 9f57502d5cf0..1f941436ae8b 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -728,6 +728,11 @@ package android.graphics {
method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(android.content.res.Resources, java.io.InputStream, int);
}
+ public final class Rect implements android.os.Parcelable {
+ method public void splitHorizontally(@NonNull android.graphics.Rect...);
+ method public void splitVertically(@NonNull android.graphics.Rect...);
+ }
+
}
package android.graphics.drawable {
@@ -2561,6 +2566,7 @@ package android.window {
method @NonNull public android.window.WindowContainerTransaction reparentTasks(@Nullable android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken, @Nullable int[], @Nullable int[], boolean);
method @NonNull public android.window.WindowContainerTransaction scheduleFinishEnterPip(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setActivityWindowingMode(@NonNull android.window.WindowContainerToken, int);
+ method @NonNull public android.window.WindowContainerTransaction setAdjacentRoots(@NonNull android.window.WindowContainerToken, @NonNull android.window.WindowContainerToken);
method @NonNull public android.window.WindowContainerTransaction setAppBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
method @NonNull public android.window.WindowContainerTransaction setBoundsChangeTransaction(@NonNull android.window.WindowContainerToken, @NonNull android.view.SurfaceControl.Transaction);
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index 6bc31107bddf..f6cd7e240bd2 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -323,6 +323,21 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
+ * Sets to containers adjacent to each other. Containers below two visible adjacent roots will
+ * be made invisible. This currently only applies to Task containers created by organizer.
+ * @param root1 the first root.
+ * @param root2 the second root.
+ */
+ @NonNull
+ public WindowContainerTransaction setAdjacentRoots(
+ @NonNull WindowContainerToken root1, @NonNull WindowContainerToken root2) {
+ mHierarchyOps.add(HierarchyOp.createForAdjacentRoots(
+ root1.asBinder(),
+ root2.asBinder()));
+ return this;
+ }
+
+ /**
* Merges another WCT into this one.
* @param transfer When true, this will transfer everything from other potentially leaving
* other in an unusable state. When false, other is left alone, but
@@ -642,6 +657,7 @@ public final class WindowContainerTransaction implements Parcelable {
public static final int HIERARCHY_OP_TYPE_REORDER = 1;
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;
private final int mType;
@@ -680,6 +696,11 @@ public final class WindowContainerTransaction implements Parcelable {
container, null, windowingModes, activityTypes, false);
}
+ public static HierarchyOp createForAdjacentRoots(IBinder root1, IBinder root2) {
+ return new HierarchyOp(HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS,
+ root1, root2, null, null, false);
+ }
+
private HierarchyOp(int type, @NonNull IBinder container, @Nullable IBinder reparent,
int[] windowingModes, int[] activityTypes, boolean toTop) {
mType = type;
@@ -728,6 +749,11 @@ public final class WindowContainerTransaction implements Parcelable {
return mContainer;
}
+ @NonNull
+ public IBinder getAdjacentRoot() {
+ return mReparent;
+ }
+
public boolean getToTop() {
return mToTop;
}
@@ -756,6 +782,9 @@ public final class WindowContainerTransaction implements Parcelable {
+ mReparent + "}";
case HIERARCHY_OP_TYPE_REORDER:
return "{reorder: " + mContainer + " to " + (mToTop ? "top" : "bottom") + "}";
+ case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS:
+ return "{SetAdjacentRoot: container=" + mContainer
+ + " adjacentRoot=" + mReparent + "}";
default:
return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
+ " mToTop=" + mToTop + " mWindowingMode=" + mWindowingModes
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 87ca9607dbce..7e68bc06d506 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -19,6 +19,7 @@ package android.graphics;
import android.annotation.CheckResult;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -702,6 +703,40 @@ public final class Rect implements Parcelable {
}
/**
+ * Splits this Rect into small rects of the same width.
+ * @hide
+ */
+ @TestApi
+ public void splitVertically(@NonNull Rect ...splits) {
+ final int count = splits.length;
+ final int splitWidth = width() / count;
+ for (int i = 0; i < count; i++) {
+ final Rect split = splits[i];
+ split.left = left + (splitWidth * i);
+ split.top = top;
+ split.right = split.left + splitWidth;
+ split.bottom = bottom;
+ }
+ }
+
+ /**
+ * Splits this Rect into small rects of the same height.
+ * @hide
+ */
+ @TestApi
+ public void splitHorizontally(@NonNull Rect ...outSplits) {
+ final int count = outSplits.length;
+ final int splitHeight = height() / count;
+ for (int i = 0; i < count; i++) {
+ final Rect split = outSplits[i];
+ split.left = left;
+ split.top = top + (splitHeight * i);
+ split.right = right;
+ split.bottom = split.top + splitHeight;
+ }
+ }
+
+ /**
* Parcelable interface methods
*/
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index bdac37ab737e..5c1d18e71800 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -142,6 +142,15 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
mTaskOrganizer.applyTransaction(wct);
}
+ private void onStageRootTaskAppeared(StageListenerImpl stageListener) {
+ if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) {
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ // Make the stages adjacent to each other so they occlude what's behind them.
+ wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
+ mTaskOrganizer.applyTransaction(wct);
+ }
+ }
+
private void onStageRootTaskVanished(StageListenerImpl stageListener) {
if (stageListener == mMainStageListener || stageListener == mSideStageListener) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -357,6 +366,7 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
@Override
public void onRootTaskAppeared() {
mHasRootTask = true;
+ StageCoordinator.this.onStageRootTaskAppeared(this);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 30f2701151d7..efd42ce552b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -70,9 +70,9 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
@CallSuper
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
if (!taskInfo.hasParentTask()) {
- mCallbacks.onRootTaskAppeared();
mRootLeash = leash;
mRootTaskInfo = taskInfo;
+ mCallbacks.onRootTaskAppeared();
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
mChildrenLeashes.put(taskInfo.taskId, leash);
mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 0fc4cdb6a928..d90e88576909 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -662,7 +662,9 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
pw.println(getName()
+ " type=" + activityTypeToString(getActivityType())
+ " mode=" + windowingModeToString(getWindowingMode())
- + " override-mode=" + windowingModeToString(getRequestedOverrideWindowingMode()));
+ + " override-mode=" + windowingModeToString(getRequestedOverrideWindowingMode())
+ + " requested-bounds=" + getRequestedOverrideBounds().toShortString()
+ + " bounds=" + getBounds().toShortString());
for (int i = getChildCount() - 1; i >= 0; --i) {
final E cc = getChildAt(i);
pw.print(childPrefix + "#" + i + " ");
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index f24c3ad0836f..2295ee35a4fb 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -29,6 +29,7 @@ import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -433,6 +434,7 @@ class Task extends WindowContainer<WindowContainer> {
CharSequence lastDescription; // Last description captured for this item.
+ Task mAdjacentTask; // Task adjacent to this one.
int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Task mPrevAffiliate; // previous task in affiliated chain.
int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
@@ -1564,6 +1566,11 @@ class Task extends WindowContainer<WindowContainer> {
mTaskId, mUserId);
}
+ void setAdjacentTask(Task adjacent) {
+ mAdjacentTask = adjacent;
+ adjacent.mAdjacentTask = this;
+ }
+
void setTaskToAffiliateWith(Task taskToAffiliateWith) {
closeRecentsChain();
mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
@@ -4244,6 +4251,7 @@ class Task extends WindowContainer<WindowContainer> {
}
}
+ final List<Task> adjacentTasks = new ArrayList<>();
final int windowingMode = getWindowingMode();
final boolean isAssistantType = isActivityTypeAssistant();
for (int i = parent.getChildCount() - 1; i >= 0; --i) {
@@ -4273,6 +4281,15 @@ class Task extends WindowContainer<WindowContainer> {
continue;
}
return TASK_VISIBILITY_INVISIBLE;
+ } else if (otherWindowingMode == WINDOWING_MODE_MULTI_WINDOW
+ && other.matchParentBounds()) {
+ if (other.isTranslucent(starting)) {
+ // Can be visible behind a translucent task.
+ gotTranslucentFullscreen = true;
+ continue;
+ }
+ // Multi-window task that matches parent bounds would occlude other children.
+ return TASK_VISIBILITY_INVISIBLE;
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& !gotOpaqueSplitScreenPrimary) {
gotSplitScreenStack = true;
@@ -4305,6 +4322,20 @@ class Task extends WindowContainer<WindowContainer> {
// assistant window surfaces in window manager whenever it is visible.
return TASK_VISIBILITY_INVISIBLE;
}
+ if (other.mAdjacentTask != null) {
+ if (adjacentTasks.contains(other.mAdjacentTask)) {
+ if (other.isTranslucent(starting)
+ || other.mAdjacentTask.isTranslucent(starting)) {
+ // Can be visible behind a translucent adjacent tasks.
+ gotTranslucentFullscreen = true;
+ continue;
+ }
+ // Can not be visible behind adjacent tasks.
+ return TASK_VISIBILITY_INVISIBLE;
+ } else {
+ adjacentTasks.add(other);
+ }
+ }
}
if (!shouldBeVisible) {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 1509ff67a529..dcab478ad7a8 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -20,6 +20,7 @@ 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_REORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
@@ -279,6 +280,9 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
case HIERARCHY_OP_TYPE_CHILDREN_TASKS_REPARENT:
effects |= reparentChildrenTasksHierarchyOp(hop, transition, syncId);
break;
+ case HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS:
+ effects |= setAdjacentRootsHierarchyOp(hop);
+ break;
case HIERARCHY_OP_TYPE_REORDER:
case HIERARCHY_OP_TYPE_REPARENT:
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
@@ -597,6 +601,17 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
return TRANSACT_EFFECTS_LIFECYCLE;
}
+ private int setAdjacentRootsHierarchyOp(WindowContainerTransaction.HierarchyOp hop) {
+ final Task root1 = WindowContainer.fromBinder(hop.getContainer()).asTask();
+ final Task root2 = WindowContainer.fromBinder(hop.getAdjacentRoot()).asTask();
+ if (!root1.mCreatedByOrganizer || !root2.mCreatedByOrganizer) {
+ throw new IllegalArgumentException("setAdjacentRootsHierarchyOp: Not created by"
+ + " organizer root1=" + root1 + " root2=" + root2);
+ }
+ root1.setAdjacentTask(root2);
+ return TRANSACT_EFFECTS_LIFECYCLE;
+ }
+
private void sanitizeWindowContainer(WindowContainer wc) {
if (!(wc instanceof Task) && !(wc instanceof DisplayArea)) {
throw new RuntimeException("Invalid token in task or displayArea transaction");