Loading core/java/android/window/WindowContainerTransaction.java +53 −0 Original line number Diff line number Diff line Loading @@ -693,7 +693,39 @@ public final class WindowContainerTransaction implements Parcelable { .build(); mHierarchyOps.add(hierarchyOp); return this; } /** * Sets/removes the always on top flag for this {@code windowContainer}. See * {@link com.android.server.wm.ConfigurationContainer#setAlwaysOnTop(boolean)}. * Please note that this method is only intended to be used for a * {@link com.android.server.wm.DisplayArea}. * * <p> * Setting always on top to {@code True} will also make the {@code windowContainer} to move * to the top. * </p> * <p> * Setting always on top to {@code False} will make this {@code windowContainer} to move * below the other always on top sibling containers. * </p> * * @param windowContainer the container which the flag need to be updated for. * @param alwaysOnTop denotes whether or not always on top flag should be set. * @hide */ @NonNull public WindowContainerTransaction setAlwaysOnTop( @NonNull WindowContainerToken windowContainer, boolean alwaysOnTop) { final HierarchyOp hierarchyOp = new HierarchyOp.Builder( HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP) .setContainer(windowContainer.asBinder()) .setAlwaysOnTop(alwaysOnTop) .build(); mHierarchyOps.add(hierarchyOp); return this; } /** Loading Loading @@ -1121,6 +1153,7 @@ public final class WindowContainerTransaction implements Parcelable { public static final int HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER = 16; public static final int HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER = 17; public static final int HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 18; public static final int HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP = 19; // The following key(s) are for use with mLaunchOptions: // When launching a task (eg. from recents), this is the taskId to be launched. Loading Loading @@ -1171,6 +1204,8 @@ public final class WindowContainerTransaction implements Parcelable { @Nullable private ShortcutInfo mShortcutInfo; private boolean mAlwaysOnTop; public static HierarchyOp createForReparent( @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT) Loading Loading @@ -1268,6 +1303,7 @@ public final class WindowContainerTransaction implements Parcelable { mTaskFragmentCreationOptions = copy.mTaskFragmentCreationOptions; mPendingIntent = copy.mPendingIntent; mShortcutInfo = copy.mShortcutInfo; mAlwaysOnTop = copy.mAlwaysOnTop; } protected HierarchyOp(Parcel in) { Loading @@ -1289,6 +1325,7 @@ public final class WindowContainerTransaction implements Parcelable { mTaskFragmentCreationOptions = in.readTypedObject(TaskFragmentCreationParams.CREATOR); mPendingIntent = in.readTypedObject(PendingIntent.CREATOR); mShortcutInfo = in.readTypedObject(ShortcutInfo.CREATOR); mAlwaysOnTop = in.readBoolean(); } public int getType() { Loading Loading @@ -1354,6 +1391,10 @@ public final class WindowContainerTransaction implements Parcelable { return mActivityIntent; } public boolean isAlwaysOnTop() { return mAlwaysOnTop; } @Nullable public TaskFragmentCreationParams getTaskFragmentCreationOptions() { return mTaskFragmentCreationOptions; Loading Loading @@ -1422,6 +1463,9 @@ public final class WindowContainerTransaction implements Parcelable { + " insetsType=" + Arrays.toString(mInsetsTypes) + "}"; case HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT: return "{requestFocusOnTaskFragment: container=" + mContainer + "}"; case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: return "{setAlwaysOnTop: container=" + mContainer + " alwaysOnTop=" + mAlwaysOnTop + "}"; default: return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent + " mToTop=" + mToTop Loading Loading @@ -1451,6 +1495,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeTypedObject(mTaskFragmentCreationOptions, flags); dest.writeTypedObject(mPendingIntent, flags); dest.writeTypedObject(mShortcutInfo, flags); dest.writeBoolean(mAlwaysOnTop); } @Override Loading Loading @@ -1509,6 +1554,8 @@ public final class WindowContainerTransaction implements Parcelable { @Nullable private ShortcutInfo mShortcutInfo; private boolean mAlwaysOnTop; Builder(int type) { mType = type; } Loading Loading @@ -1568,6 +1615,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } Builder setAlwaysOnTop(boolean alwaysOnTop) { mAlwaysOnTop = alwaysOnTop; return this; } Builder setTaskFragmentCreationOptions( @Nullable TaskFragmentCreationParams taskFragmentCreationOptions) { mTaskFragmentCreationOptions = taskFragmentCreationOptions; Loading Loading @@ -1596,6 +1648,7 @@ public final class WindowContainerTransaction implements Parcelable { hierarchyOp.mLaunchOptions = mLaunchOptions; hierarchyOp.mActivityIntent = mActivityIntent; hierarchyOp.mPendingIntent = mPendingIntent; hierarchyOp.mAlwaysOnTop = mAlwaysOnTop; hierarchyOp.mTaskFragmentCreationOptions = mTaskFragmentCreationOptions; hierarchyOp.mShortcutInfo = mShortcutInfo; Loading services/core/java/com/android/server/wm/DisplayArea.java +29 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,23 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { return false; } @Override public void setAlwaysOnTop(boolean alwaysOnTop) { if (isAlwaysOnTop() == alwaysOnTop) { return; } super.setAlwaysOnTop(alwaysOnTop); // positionChildAtTop() must be called even when always on top gets turned off because // we need to make sure that the display area is moved from among always on top containers // to below other always on top containers. Since the position the display area should be // inserted into is calculated properly in {@link DisplayContent#getTopInsertPosition()} // in both cases, we can just request that the root task is put at top here. if (getParent().asDisplayArea() != null) { getParent().asDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */); } } boolean getIgnoreOrientationRequest() { // Adding an exception for when ignoreOrientationRequest is overridden at runtime for all // DisplayArea-s. For example, this is needed for the Kids Mode since many Kids apps aren't Loading Loading @@ -234,6 +251,18 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { // The min possible position we can insert the child at. int minPosition = findMinPositionForChildDisplayArea(child); // Place all non-always-on-top containers below always-on-top ones. int alwaysOnTopCount = 0; for (int i = minPosition; i <= maxPosition; i++) { if (mChildren.get(i).isAlwaysOnTop()) { alwaysOnTopCount++; } } if (child.isAlwaysOnTop()) { minPosition = maxPosition - alwaysOnTopCount + 1; } else { maxPosition -= alwaysOnTopCount; } return Math.max(Math.min(requestPosition, maxPosition), minPosition); } Loading services/core/java/com/android/server/wm/WindowOrganizerController.java +13 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT; Loading Loading @@ -1079,6 +1080,18 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub WindowContainer.fromBinder(hop.getContainer()) .removeLocalInsetsSourceProvider(hop.getInsetsTypes()); break; case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: final WindowContainer container = WindowContainer.fromBinder(hop.getContainer()); if (container == null || container.asDisplayArea() == null || !container.isAttached()) { Slog.e(TAG, "Attempt to operate on unknown or detached display area: " + container); break; } container.setAlwaysOnTop(hop.isAlwaysOnTop()); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; } return effects; } Loading services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +64 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; Loading Loading @@ -399,9 +400,9 @@ public class DisplayAreaTest extends WindowTestsBase { parentBounds.right / 2, parentBounds.bottom); final Rect childBounds2 = new Rect(parentBounds.right / 2, parentBounds.top, parentBounds.right, parentBounds.bottom); TestDisplayArea parentDa = new TestDisplayArea(mWm, parentBounds); TestDisplayArea childDa1 = new TestDisplayArea(mWm, childBounds1); TestDisplayArea childDa2 = new TestDisplayArea(mWm, childBounds2); TestDisplayArea parentDa = new TestDisplayArea(mWm, parentBounds, "Parent"); TestDisplayArea childDa1 = new TestDisplayArea(mWm, childBounds1, "Child1"); TestDisplayArea childDa2 = new TestDisplayArea(mWm, childBounds2, "Child2"); parentDa.addChild(childDa1, 0); parentDa.addChild(childDa2, 1); Loading Loading @@ -619,9 +620,67 @@ public class DisplayAreaTest extends WindowTestsBase { controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST); } @Test public void testSetAlwaysOnTop_movesDisplayAreaToTop() { final Rect bounds = new Rect(0, 0, 100, 100); DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent"); parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> child1 = new TestDisplayArea(mWm, bounds, "Child1"); child1.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> child2 = new TestDisplayArea(mWm, bounds, "Child2"); child2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); parent.addChild(child2, 0); parent.addChild(child1, 1); child2.setAlwaysOnTop(true); assertEquals(parent.getChildAt(1), child2); assertThat(child2.isAlwaysOnTop()).isTrue(); } @Test public void testDisplayAreaRequestsTopPosition_alwaysOnTopSiblingExists_doesNotMoveToTop() { final Rect bounds = new Rect(0, 0, 100, 100); DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent"); parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> alwaysOnTopChild = new TestDisplayArea(mWm, bounds, "AlwaysOnTopChild"); alwaysOnTopChild.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> child = new TestDisplayArea(mWm, bounds, "Child"); child.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); parent.addChild(alwaysOnTopChild, 0); parent.addChild(child, 1); alwaysOnTopChild.setAlwaysOnTop(true); parent.positionChildAt(POSITION_TOP, child, false /* includingParents */); assertEquals(parent.getChildAt(1), alwaysOnTopChild); assertEquals(parent.getChildAt(0), child); } @Test public void testAlwaysOnTopDisplayArea_requestsNonTopLocation_doesNotMove() { final Rect bounds = new Rect(0, 0, 100, 100); DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent"); parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> alwaysOnTopChild = new TestDisplayArea(mWm, bounds, "AlwaysOnTopChild"); alwaysOnTopChild.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> child = new TestDisplayArea(mWm, bounds, "Child"); child.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); parent.addChild(alwaysOnTopChild, 0); parent.addChild(child, 1); alwaysOnTopChild.setAlwaysOnTop(true); parent.positionChildAt(POSITION_BOTTOM, alwaysOnTopChild, false /* includingParents */); assertEquals(parent.getChildAt(1), alwaysOnTopChild); assertEquals(parent.getChildAt(0), child); } private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> { private TestDisplayArea(WindowManagerService wms, Rect bounds) { super(wms, ANY, "half display area"); private TestDisplayArea(WindowManagerService wms, Rect bounds, String name) { super(wms, ANY, name); setBounds(bounds); } Loading Loading
core/java/android/window/WindowContainerTransaction.java +53 −0 Original line number Diff line number Diff line Loading @@ -693,7 +693,39 @@ public final class WindowContainerTransaction implements Parcelable { .build(); mHierarchyOps.add(hierarchyOp); return this; } /** * Sets/removes the always on top flag for this {@code windowContainer}. See * {@link com.android.server.wm.ConfigurationContainer#setAlwaysOnTop(boolean)}. * Please note that this method is only intended to be used for a * {@link com.android.server.wm.DisplayArea}. * * <p> * Setting always on top to {@code True} will also make the {@code windowContainer} to move * to the top. * </p> * <p> * Setting always on top to {@code False} will make this {@code windowContainer} to move * below the other always on top sibling containers. * </p> * * @param windowContainer the container which the flag need to be updated for. * @param alwaysOnTop denotes whether or not always on top flag should be set. * @hide */ @NonNull public WindowContainerTransaction setAlwaysOnTop( @NonNull WindowContainerToken windowContainer, boolean alwaysOnTop) { final HierarchyOp hierarchyOp = new HierarchyOp.Builder( HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP) .setContainer(windowContainer.asBinder()) .setAlwaysOnTop(alwaysOnTop) .build(); mHierarchyOps.add(hierarchyOp); return this; } /** Loading Loading @@ -1121,6 +1153,7 @@ public final class WindowContainerTransaction implements Parcelable { public static final int HIERARCHY_OP_TYPE_ADD_RECT_INSETS_PROVIDER = 16; public static final int HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER = 17; public static final int HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 18; public static final int HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP = 19; // The following key(s) are for use with mLaunchOptions: // When launching a task (eg. from recents), this is the taskId to be launched. Loading Loading @@ -1171,6 +1204,8 @@ public final class WindowContainerTransaction implements Parcelable { @Nullable private ShortcutInfo mShortcutInfo; private boolean mAlwaysOnTop; public static HierarchyOp createForReparent( @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT) Loading Loading @@ -1268,6 +1303,7 @@ public final class WindowContainerTransaction implements Parcelable { mTaskFragmentCreationOptions = copy.mTaskFragmentCreationOptions; mPendingIntent = copy.mPendingIntent; mShortcutInfo = copy.mShortcutInfo; mAlwaysOnTop = copy.mAlwaysOnTop; } protected HierarchyOp(Parcel in) { Loading @@ -1289,6 +1325,7 @@ public final class WindowContainerTransaction implements Parcelable { mTaskFragmentCreationOptions = in.readTypedObject(TaskFragmentCreationParams.CREATOR); mPendingIntent = in.readTypedObject(PendingIntent.CREATOR); mShortcutInfo = in.readTypedObject(ShortcutInfo.CREATOR); mAlwaysOnTop = in.readBoolean(); } public int getType() { Loading Loading @@ -1354,6 +1391,10 @@ public final class WindowContainerTransaction implements Parcelable { return mActivityIntent; } public boolean isAlwaysOnTop() { return mAlwaysOnTop; } @Nullable public TaskFragmentCreationParams getTaskFragmentCreationOptions() { return mTaskFragmentCreationOptions; Loading Loading @@ -1422,6 +1463,9 @@ public final class WindowContainerTransaction implements Parcelable { + " insetsType=" + Arrays.toString(mInsetsTypes) + "}"; case HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT: return "{requestFocusOnTaskFragment: container=" + mContainer + "}"; case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: return "{setAlwaysOnTop: container=" + mContainer + " alwaysOnTop=" + mAlwaysOnTop + "}"; default: return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent + " mToTop=" + mToTop Loading Loading @@ -1451,6 +1495,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeTypedObject(mTaskFragmentCreationOptions, flags); dest.writeTypedObject(mPendingIntent, flags); dest.writeTypedObject(mShortcutInfo, flags); dest.writeBoolean(mAlwaysOnTop); } @Override Loading Loading @@ -1509,6 +1554,8 @@ public final class WindowContainerTransaction implements Parcelable { @Nullable private ShortcutInfo mShortcutInfo; private boolean mAlwaysOnTop; Builder(int type) { mType = type; } Loading Loading @@ -1568,6 +1615,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } Builder setAlwaysOnTop(boolean alwaysOnTop) { mAlwaysOnTop = alwaysOnTop; return this; } Builder setTaskFragmentCreationOptions( @Nullable TaskFragmentCreationParams taskFragmentCreationOptions) { mTaskFragmentCreationOptions = taskFragmentCreationOptions; Loading Loading @@ -1596,6 +1648,7 @@ public final class WindowContainerTransaction implements Parcelable { hierarchyOp.mLaunchOptions = mLaunchOptions; hierarchyOp.mActivityIntent = mActivityIntent; hierarchyOp.mPendingIntent = mPendingIntent; hierarchyOp.mAlwaysOnTop = mAlwaysOnTop; hierarchyOp.mTaskFragmentCreationOptions = mTaskFragmentCreationOptions; hierarchyOp.mShortcutInfo = mShortcutInfo; Loading
services/core/java/com/android/server/wm/DisplayArea.java +29 −0 Original line number Diff line number Diff line Loading @@ -207,6 +207,23 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { return false; } @Override public void setAlwaysOnTop(boolean alwaysOnTop) { if (isAlwaysOnTop() == alwaysOnTop) { return; } super.setAlwaysOnTop(alwaysOnTop); // positionChildAtTop() must be called even when always on top gets turned off because // we need to make sure that the display area is moved from among always on top containers // to below other always on top containers. Since the position the display area should be // inserted into is calculated properly in {@link DisplayContent#getTopInsertPosition()} // in both cases, we can just request that the root task is put at top here. if (getParent().asDisplayArea() != null) { getParent().asDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */); } } boolean getIgnoreOrientationRequest() { // Adding an exception for when ignoreOrientationRequest is overridden at runtime for all // DisplayArea-s. For example, this is needed for the Kids Mode since many Kids apps aren't Loading Loading @@ -234,6 +251,18 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { // The min possible position we can insert the child at. int minPosition = findMinPositionForChildDisplayArea(child); // Place all non-always-on-top containers below always-on-top ones. int alwaysOnTopCount = 0; for (int i = minPosition; i <= maxPosition; i++) { if (mChildren.get(i).isAlwaysOnTop()) { alwaysOnTopCount++; } } if (child.isAlwaysOnTop()) { minPosition = maxPosition - alwaysOnTopCount + 1; } else { maxPosition -= alwaysOnTopCount; } return Math.max(Math.min(requestPosition, maxPosition), minPosition); } Loading
services/core/java/com/android/server/wm/WindowOrganizerController.java +13 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_RESTORE_TRANSIENT_ORDER; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_ROOTS; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ADJACENT_FLAG_ROOT; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT; import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT; Loading Loading @@ -1079,6 +1080,18 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub WindowContainer.fromBinder(hop.getContainer()) .removeLocalInsetsSourceProvider(hop.getInsetsTypes()); break; case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP: final WindowContainer container = WindowContainer.fromBinder(hop.getContainer()); if (container == null || container.asDisplayArea() == null || !container.isAttached()) { Slog.e(TAG, "Attempt to operate on unknown or detached display area: " + container); break; } container.setAlwaysOnTop(hop.isAlwaysOnTop()); effects |= TRANSACT_EFFECTS_LIFECYCLE; break; } return effects; } Loading
services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +64 −5 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; Loading Loading @@ -399,9 +400,9 @@ public class DisplayAreaTest extends WindowTestsBase { parentBounds.right / 2, parentBounds.bottom); final Rect childBounds2 = new Rect(parentBounds.right / 2, parentBounds.top, parentBounds.right, parentBounds.bottom); TestDisplayArea parentDa = new TestDisplayArea(mWm, parentBounds); TestDisplayArea childDa1 = new TestDisplayArea(mWm, childBounds1); TestDisplayArea childDa2 = new TestDisplayArea(mWm, childBounds2); TestDisplayArea parentDa = new TestDisplayArea(mWm, parentBounds, "Parent"); TestDisplayArea childDa1 = new TestDisplayArea(mWm, childBounds1, "Child1"); TestDisplayArea childDa2 = new TestDisplayArea(mWm, childBounds2, "Child2"); parentDa.addChild(childDa1, 0); parentDa.addChild(childDa2, 1); Loading Loading @@ -619,9 +620,67 @@ public class DisplayAreaTest extends WindowTestsBase { controller.registerOrganizer(mockDisplayAreaOrganizer, FEATURE_VENDOR_FIRST); } @Test public void testSetAlwaysOnTop_movesDisplayAreaToTop() { final Rect bounds = new Rect(0, 0, 100, 100); DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent"); parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> child1 = new TestDisplayArea(mWm, bounds, "Child1"); child1.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> child2 = new TestDisplayArea(mWm, bounds, "Child2"); child2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); parent.addChild(child2, 0); parent.addChild(child1, 1); child2.setAlwaysOnTop(true); assertEquals(parent.getChildAt(1), child2); assertThat(child2.isAlwaysOnTop()).isTrue(); } @Test public void testDisplayAreaRequestsTopPosition_alwaysOnTopSiblingExists_doesNotMoveToTop() { final Rect bounds = new Rect(0, 0, 100, 100); DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent"); parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> alwaysOnTopChild = new TestDisplayArea(mWm, bounds, "AlwaysOnTopChild"); alwaysOnTopChild.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> child = new TestDisplayArea(mWm, bounds, "Child"); child.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); parent.addChild(alwaysOnTopChild, 0); parent.addChild(child, 1); alwaysOnTopChild.setAlwaysOnTop(true); parent.positionChildAt(POSITION_TOP, child, false /* includingParents */); assertEquals(parent.getChildAt(1), alwaysOnTopChild); assertEquals(parent.getChildAt(0), child); } @Test public void testAlwaysOnTopDisplayArea_requestsNonTopLocation_doesNotMove() { final Rect bounds = new Rect(0, 0, 100, 100); DisplayArea<WindowContainer> parent = new TestDisplayArea(mWm, bounds, "Parent"); parent.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> alwaysOnTopChild = new TestDisplayArea(mWm, bounds, "AlwaysOnTopChild"); alwaysOnTopChild.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); DisplayArea<WindowContainer> child = new TestDisplayArea(mWm, bounds, "Child"); child.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); parent.addChild(alwaysOnTopChild, 0); parent.addChild(child, 1); alwaysOnTopChild.setAlwaysOnTop(true); parent.positionChildAt(POSITION_BOTTOM, alwaysOnTopChild, false /* includingParents */); assertEquals(parent.getChildAt(1), alwaysOnTopChild); assertEquals(parent.getChildAt(0), child); } private static class TestDisplayArea<T extends WindowContainer> extends DisplayArea<T> { private TestDisplayArea(WindowManagerService wms, Rect bounds) { super(wms, ANY, "half display area"); private TestDisplayArea(WindowManagerService wms, Rect bounds, String name) { super(wms, ANY, name); setBounds(bounds); } Loading