diff options
9 files changed, 97 insertions, 46 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 343e4b5668c0..0c8a9ed56ae8 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -476,6 +476,16 @@ public abstract class DisplayManagerInternal { public abstract boolean isDisplayReadyForMirroring(int displayId); /** + * Called by {@link com.android.server.wm.WindowManagerService} to notify whether a display + * should be in the topology. + * @param displayId The logical ID of the display + * @param inTopology Whether the display should be in the topology. This being true does not + * guarantee that the display will be in the topology - Display Manager might + * also check other parameters. + */ + public abstract void onDisplayBelongToTopologyChanged(int displayId, boolean inTopology); + + /** * Called by {@link com.android.server.display.DisplayBackupHelper} when backup files were * restored and are ready to be reloaded. */ diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index d402f010281f..7016c11b69e7 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2442,7 +2442,10 @@ public final class DisplayManagerService extends SystemService { applyDisplayChangedLocked(display); } - if (mDisplayTopologyCoordinator != null) { + // The default display should always be added to the topology. Other displays will be added + // upon calling onDisplayBelongToTopologyChanged(). + if (mDisplayTopologyCoordinator != null + && display.getDisplayIdLocked() == Display.DEFAULT_DISPLAY) { mDisplayTopologyCoordinator.onDisplayAdded(display.getDisplayInfoLocked()); } } @@ -6037,6 +6040,18 @@ public final class DisplayManagerService extends SystemService { } @Override + public void onDisplayBelongToTopologyChanged(int displayId, boolean inTopology) { + if (mDisplayTopologyCoordinator == null) { + return; + } + if (inTopology) { + mDisplayTopologyCoordinator.onDisplayAdded(getDisplayInfo(displayId)); + } else { + mDisplayTopologyCoordinator.onDisplayRemoved(displayId); + } + } + + @Override public void reloadTopologies(final int userId) { // Reload topologies only if the userId matches the current user id. if (userId == mCurrentUserId) { diff --git a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java index 2618cf40d113..997fff58b952 100644 --- a/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java +++ b/services/core/java/com/android/server/display/DisplayTopologyCoordinator.java @@ -267,11 +267,6 @@ class DisplayTopologyCoordinator { + "type is EXTERNAL or OVERLAY and !mIsExtendedDisplayEnabled"); return false; } - if (info.displayGroupId != Display.DEFAULT_DISPLAY_GROUP) { - Slog.d(TAG, "Display " + info.displayId + " not allowed in topology because " - + "it is not in the default display group"); - return false; - } return true; } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 530b507bcc0f..353ccd5836c8 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -3262,12 +3262,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp Slog.e(TAG, "ShouldShowSystemDecors shouldn't be updated when the flag is off."); } - final boolean shouldShowContent; if (!allowContentModeSwitch()) { return; } - shouldShowContent = mDisplay.canHostTasks(); + final boolean shouldShowContent = mDisplay.canHostTasks(); if (shouldShowContent == mWmService.mDisplayWindowSettings .shouldShowSystemDecorsLocked(this)) { return; @@ -3277,6 +3276,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (!shouldShowContent) { clearAllTasksOnDisplay(null /* clearTasksCallback */, false /* isRemovingDisplay */); } + + // If the display is allowed to show content, then it belongs to the display topology; + // vice versa. + mWmService.mDisplayManagerInternal.onDisplayBelongToTopologyChanged(mDisplayId, + /* inTopology= */ shouldShowContent); } /** @@ -3302,6 +3306,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return false; } + if (shouldNeverShowSystemDecorations()) { + return false; + } + // TODO(b/391965805): Remove this after introducing FLAG_ALLOW_CONTENT_MODE_SWITCH. if ((mDisplay.getFlags() & Display.FLAG_REAR) != 0) { return false; @@ -5666,16 +5674,23 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return type == TRANSIT_OPEN || type == TRANSIT_TO_FRONT; } - /** - * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS - */ - boolean isSystemDecorationsSupported() { + private boolean shouldNeverShowSystemDecorations() { if (mDisplayId == mWmService.mVr2dDisplayId) { // VR virtual display will be used to run and render 2D app within a VR experience. - return false; + return true; } if (!isTrusted()) { // Do not show system decorations on untrusted virtual display. + return true; + } + return false; + } + + /** + * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS + */ + boolean isSystemDecorationsSupported() { + if (shouldNeverShowSystemDecorations()) { return false; } if (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this) diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index 48ffccbca935..56579206566f 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -240,6 +240,11 @@ class DisplayWindowSettings { mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); } + /** + * Returns {@code true} if either the display is the default display, or the display is allowed + * to dynamically add/remove system decorations and the system decorations should be shown on it + * currently. + */ boolean shouldShowSystemDecorsLocked(@NonNull DisplayContent dc) { if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) { // Default display should show system decors. diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 394fe6f0e8ed..cf201c9f34f0 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -2772,11 +2772,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return; } - if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue() - && display.allowContentModeSwitch()) { - mWindowManager.mDisplayWindowSettings - .setShouldShowSystemDecorsInternalLocked(display, - display.mDisplay.canHostTasks()); + if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) { + if (display.allowContentModeSwitch()) { + mWindowManager.mDisplayWindowSettings + .setShouldShowSystemDecorsInternalLocked(display, + display.mDisplay.canHostTasks()); + } + + final boolean inTopology = mWindowManager.mDisplayWindowSettings + .shouldShowSystemDecorsLocked(display); + mWmService.mDisplayManagerInternal.onDisplayBelongToTopologyChanged(displayId, + inTopology); } startSystemDecorations(display, "displayAdded"); diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java index 65585d06ff06..1f8ccde98d35 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -3914,6 +3914,7 @@ public class DisplayManagerServiceTest { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerService.BinderService displayManagerBinderService = displayManager.new BinderService(); + DisplayManagerInternal localService = displayManager.new LocalService(); Handler handler = displayManager.getDisplayHandler(); waitForIdleHandler(handler); @@ -3922,8 +3923,8 @@ public class DisplayManagerServiceTest { INTERNAL_EVENT_FLAG_TOPOLOGY_UPDATED); waitForIdleHandler(handler); - var topology = initDisplayTopology(displayManager, displayManagerBinderService, callback, - handler, /*shouldEmitTopologyChangeEvent=*/ true); + var topology = initDisplayTopology(displayManager, displayManagerBinderService, + localService, callback, handler, /*shouldEmitTopologyChangeEvent=*/ true); callback.clear(); callback.expectsEvent(TOPOLOGY_CHANGED_EVENT); displayManagerBinderService.setDisplayTopology(topology); @@ -3938,6 +3939,7 @@ public class DisplayManagerServiceTest { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); DisplayManagerService.BinderService displayManagerBinderService = displayManager.new BinderService(); + DisplayManagerInternal localService = displayManager.new LocalService(); Handler handler = displayManager.getDisplayHandler(); waitForIdleHandler(handler); @@ -3947,8 +3949,8 @@ public class DisplayManagerServiceTest { STANDARD_DISPLAY_EVENTS); waitForIdleHandler(handler); - var topology = initDisplayTopology(displayManager, displayManagerBinderService, callback, - handler, /*shouldEmitTopologyChangeEvent=*/ false); + var topology = initDisplayTopology(displayManager, displayManagerBinderService, + localService, callback, handler, /*shouldEmitTopologyChangeEvent=*/ false); callback.clear(); callback.expectsEvent(TOPOLOGY_CHANGED_EVENT); // should not happen displayManagerBinderService.setDisplayTopology(topology); @@ -4706,15 +4708,16 @@ public class DisplayManagerServiceTest { private DisplayTopology initDisplayTopology(DisplayManagerService displayManager, DisplayManagerService.BinderService displayManagerBinderService, - FakeDisplayManagerCallback callback, + DisplayManagerInternal localService, FakeDisplayManagerCallback callback, Handler handler, boolean shouldEmitTopologyChangeEvent) { Settings.Global.putInt(mContext.getContentResolver(), DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 1); callback.expectsEvent(TOPOLOGY_CHANGED_EVENT); FakeDisplayDevice displayDevice0 = - createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_INTERNAL); + createFakeDisplayDevice(displayManager, new float[]{60f}, Display.TYPE_EXTERNAL); int displayId0 = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService, displayDevice0); + waitForIdleHandler(handler); if (shouldEmitTopologyChangeEvent) { callback.waitForExpectedEvent(); } else { @@ -4728,6 +4731,11 @@ public class DisplayManagerServiceTest { int displayId1 = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService, displayDevice1); waitForIdleHandler(handler); + // Non-default display should not be added until onDisplayBelongToTopologyChanged is called + // with true + callback.waitForNonExpectedEvent(); + localService.onDisplayBelongToTopologyChanged(displayId1, true); + waitForIdleHandler(handler); if (shouldEmitTopologyChangeEvent) { callback.waitForExpectedEvent(); } else { diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt index 3c134b5d5482..206c90d0481a 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayTopologyCoordinatorTest.kt @@ -220,17 +220,6 @@ class DisplayTopologyCoordinatorTest { } @Test - fun addDisplay_notInDefaultDisplayGroup() { - displayInfos[0].displayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1 - - coordinator.onDisplayAdded(displayInfos[0]) - - verify(mockTopology, never()).addDisplay(anyInt(), anyFloat(), anyFloat()) - verify(mockTopologyChangedCallback, never()).invoke(any()) - verify(mockTopologyStore, never()).restoreTopology(any()) - } - - @Test fun updateDisplay() { whenever(mockTopology.updateDisplay(eq(displayInfos[0].displayId), anyFloat(), anyFloat())) .thenReturn(true) @@ -349,17 +338,6 @@ class DisplayTopologyCoordinatorTest { } @Test - fun updateDisplay_notInDefaultDisplayGroup() { - displayInfos[0].displayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1 - - coordinator.onDisplayChanged(displayInfos[0]) - - verify(mockTopology, never()).updateDisplay(anyInt(), anyFloat(), anyFloat()) - verify(mockTopologyCopy, never()).getGraph(any()) - verify(mockTopologyChangedCallback, never()).invoke(any()) - } - - @Test fun removeDisplay() { addDisplay() diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index e4a1bf603cf0..34e9bed8463a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -31,6 +31,7 @@ import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.server.display.feature.flags.Flags.FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT; import static com.android.server.wm.ActivityRecord.State.FINISHING; import static com.android.server.wm.ActivityRecord.State.PAUSED; import static com.android.server.wm.ActivityRecord.State.PAUSING; @@ -82,6 +83,7 @@ import android.os.UserHandle; import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.util.Pair; +import android.view.DisplayInfo; import androidx.test.filters.MediumTest; @@ -1379,6 +1381,23 @@ public class RootWindowContainerTests extends WindowTestsBase { verify(controller, never()).notifyTaskProfileLocked(any(), anyInt()); } + @EnableFlags(FLAG_ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT) + @Test + public void testOnDisplayBelongToTopologyChanged() { + final DisplayInfo displayInfo = new DisplayInfo(); + displayInfo.copyFrom(mDisplayInfo); + displayInfo.displayId = DEFAULT_DISPLAY + 1; + final DisplayContent dc = createNewDisplay(displayInfo); + final int displayId = dc.getDisplayId(); + + doReturn(dc).when(mRootWindowContainer).getDisplayContentOrCreate(displayId); + doReturn(true).when(mWm.mDisplayWindowSettings).shouldShowSystemDecorsLocked(dc); + + mRootWindowContainer.onDisplayAdded(displayId); + verify(mWm.mDisplayManagerInternal, times(1)).onDisplayBelongToTopologyChanged(anyInt(), + anyBoolean()); + } + /** * Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity * info for test cases. |