Loading services/core/java/com/android/server/display/DisplayManagerService.java +17 −4 Original line number Diff line number Diff line Loading @@ -284,6 +284,7 @@ public final class DisplayManagerService extends SystemService { // Temporary display info, used for comparing display configurations. private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); private final DisplayInfo mTempNonOverrideDisplayInfo = new DisplayInfo(); // Temporary viewports, used when sending new viewport information to the // input system. May be used outside of the lock but only on the handler thread. Loading Loading @@ -508,7 +509,8 @@ public final class DisplayManagerService extends SystemService { mDisplayTransactionListeners.remove(listener); } private void setDisplayInfoOverrideFromWindowManagerInternal( @VisibleForTesting void setDisplayInfoOverrideFromWindowManagerInternal( int displayId, DisplayInfo info) { synchronized (mSyncRoot) { LogicalDisplay display = mLogicalDisplays.get(displayId); Loading Loading @@ -936,7 +938,8 @@ public final class DisplayManagerService extends SystemService { adapter.registerLocked(); } private void handleDisplayDeviceAdded(DisplayDevice device) { @VisibleForTesting void handleDisplayDeviceAdded(DisplayDevice device) { synchronized (mSyncRoot) { handleDisplayDeviceAddedLocked(device); } Loading @@ -948,7 +951,6 @@ public final class DisplayManagerService extends SystemService { Slog.w(TAG, "Attempted to add already added display device: " + info); return; } Slog.i(TAG, "Display device added: " + info); device.mDebugLastLoggedDeviceInfo = info; Loading @@ -961,7 +963,8 @@ public final class DisplayManagerService extends SystemService { scheduleTraversalLocked(false); } private void handleDisplayDeviceChanged(DisplayDevice device) { @VisibleForTesting void handleDisplayDeviceChanged(DisplayDevice device) { synchronized (mSyncRoot) { DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (!mDisplayDevices.contains(device)) { Loading Loading @@ -1235,6 +1238,7 @@ public final class DisplayManagerService extends SystemService { LogicalDisplay display = mLogicalDisplays.valueAt(i); mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo); display.updateLocked(mDisplayDevices); if (!display.isValidLocked()) { mLogicalDisplays.removeAt(i); Loading @@ -1243,6 +1247,15 @@ public final class DisplayManagerService extends SystemService { } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { handleLogicalDisplayChanged(displayId, display); changed = true; } else { // While applications shouldn't know nor care about the non-overridden info, we // still need to let WindowManager know so it can update its own internal state for // things like display cutouts. display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo); if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) { handleLogicalDisplayChanged(displayId, display); changed = true; } } } return changed; Loading services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +106 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.display; import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; Loading @@ -28,18 +29,23 @@ import static org.mockito.Mockito.when; import android.app.PropertyInvalidatedCache; import android.content.Context; import android.graphics.Insets; import android.graphics.Rect; import android.hardware.display.BrightnessConfiguration; import android.hardware.display.Curve; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; import android.hardware.display.IDisplayManagerCallback; import android.hardware.display.IVirtualDisplayCallback; import android.hardware.display.VirtualDisplayConfig; import android.hardware.input.InputManagerInternal; import android.os.Handler; import android.os.IBinder; import android.view.Display; import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceControl; Loading Loading @@ -281,6 +287,68 @@ public class DisplayManagerServiceTest { displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); } /** * Tests that there should be a display change notification to WindowManager to update its own * internal state for things like display cutout when nonOverrideDisplayInfo is changed. */ @Test public void testShouldNotifyChangeWhenNonOverrideDisplayInfoChanged() throws Exception { DisplayManagerService displayManager = new DisplayManagerService(mContext, mShortMockedInjector); registerDefaultDisplays(displayManager); displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); // Add the FakeDisplayDevice FakeDisplayDevice displayDevice = new FakeDisplayDevice(); DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo(); displayDeviceInfo.width = 100; displayDeviceInfo.height = 200; final Rect zeroRect = new Rect(); displayDeviceInfo.displayCutout = new DisplayCutout( Insets.of(0, 10, 0, 0), zeroRect, new Rect(0, 0, 10, 10), zeroRect, zeroRect); displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY; displayDevice.setDisplayDeviceInfo(displayDeviceInfo); displayManager.handleDisplayDeviceAdded(displayDevice); // Find the display id of the added FakeDisplayDevice DisplayManagerService.BinderService bs = displayManager.new BinderService(); final int[] displayIds = bs.getDisplayIds(); assertTrue(displayIds.length > 0); int displayId = Display.INVALID_DISPLAY; for (int i = 0; i < displayIds.length; i++) { DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayIds[i]); if (displayDeviceInfo.equals(ddi)) { displayId = displayIds[i]; break; } } assertFalse(displayId == Display.INVALID_DISPLAY); // Setup override DisplayInfo DisplayInfo overrideInfo = bs.getDisplayInfo(displayId); displayManager.setDisplayInfoOverrideFromWindowManagerInternal(displayId, overrideInfo); Handler handler = displayManager.getDisplayHandler(); handler.runWithScissors(() -> { }, 0 /* now */); // register display listener callback FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId); bs.registerCallback(callback); // Simulate DisplayDevice change DisplayDeviceInfo displayDeviceInfo2 = new DisplayDeviceInfo(); displayDeviceInfo2.copyFrom(displayDeviceInfo); displayDeviceInfo2.displayCutout = null; displayDevice.setDisplayDeviceInfo(displayDeviceInfo2); displayManager.handleDisplayDeviceChanged(displayDevice); handler.runWithScissors(() -> { }, 0 /* now */); assertTrue(callback.mCalled); } /** * Tests that we get a Runtime exception when we cannot initialize the default display. */ Loading Loading @@ -512,4 +580,42 @@ public class DisplayManagerServiceTest { // flush the handler handler.runWithScissors(() -> {}, 0 /* now */); } private class FakeDisplayManagerCallback extends IDisplayManagerCallback.Stub { int mDisplayId; boolean mCalled = false; FakeDisplayManagerCallback(int displayId) { mDisplayId = displayId; } @Override public void onDisplayEvent(int displayId, int event) { if (displayId == mDisplayId && event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) { mCalled = true; } } } private class FakeDisplayDevice extends DisplayDevice { private DisplayDeviceInfo mDisplayDeviceInfo; FakeDisplayDevice() { super(null, null, ""); } public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) { mDisplayDeviceInfo = displayDeviceInfo; } @Override public boolean hasStableUniqueId() { return false; } @Override public DisplayDeviceInfo getDisplayDeviceInfoLocked() { return mDisplayDeviceInfo; } } } Loading
services/core/java/com/android/server/display/DisplayManagerService.java +17 −4 Original line number Diff line number Diff line Loading @@ -284,6 +284,7 @@ public final class DisplayManagerService extends SystemService { // Temporary display info, used for comparing display configurations. private final DisplayInfo mTempDisplayInfo = new DisplayInfo(); private final DisplayInfo mTempNonOverrideDisplayInfo = new DisplayInfo(); // Temporary viewports, used when sending new viewport information to the // input system. May be used outside of the lock but only on the handler thread. Loading Loading @@ -508,7 +509,8 @@ public final class DisplayManagerService extends SystemService { mDisplayTransactionListeners.remove(listener); } private void setDisplayInfoOverrideFromWindowManagerInternal( @VisibleForTesting void setDisplayInfoOverrideFromWindowManagerInternal( int displayId, DisplayInfo info) { synchronized (mSyncRoot) { LogicalDisplay display = mLogicalDisplays.get(displayId); Loading Loading @@ -936,7 +938,8 @@ public final class DisplayManagerService extends SystemService { adapter.registerLocked(); } private void handleDisplayDeviceAdded(DisplayDevice device) { @VisibleForTesting void handleDisplayDeviceAdded(DisplayDevice device) { synchronized (mSyncRoot) { handleDisplayDeviceAddedLocked(device); } Loading @@ -948,7 +951,6 @@ public final class DisplayManagerService extends SystemService { Slog.w(TAG, "Attempted to add already added display device: " + info); return; } Slog.i(TAG, "Display device added: " + info); device.mDebugLastLoggedDeviceInfo = info; Loading @@ -961,7 +963,8 @@ public final class DisplayManagerService extends SystemService { scheduleTraversalLocked(false); } private void handleDisplayDeviceChanged(DisplayDevice device) { @VisibleForTesting void handleDisplayDeviceChanged(DisplayDevice device) { synchronized (mSyncRoot) { DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); if (!mDisplayDevices.contains(device)) { Loading Loading @@ -1235,6 +1238,7 @@ public final class DisplayManagerService extends SystemService { LogicalDisplay display = mLogicalDisplays.valueAt(i); mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo); display.updateLocked(mDisplayDevices); if (!display.isValidLocked()) { mLogicalDisplays.removeAt(i); Loading @@ -1243,6 +1247,15 @@ public final class DisplayManagerService extends SystemService { } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { handleLogicalDisplayChanged(displayId, display); changed = true; } else { // While applications shouldn't know nor care about the non-overridden info, we // still need to let WindowManager know so it can update its own internal state for // things like display cutouts. display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo); if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) { handleLogicalDisplayChanged(displayId, display); changed = true; } } } return changed; Loading
services/tests/servicestests/src/com/android/server/display/DisplayManagerServiceTest.java +106 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.display; import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; Loading @@ -28,18 +29,23 @@ import static org.mockito.Mockito.when; import android.app.PropertyInvalidatedCache; import android.content.Context; import android.graphics.Insets; import android.graphics.Rect; import android.hardware.display.BrightnessConfiguration; import android.hardware.display.Curve; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.hardware.display.DisplayViewport; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; import android.hardware.display.IDisplayManagerCallback; import android.hardware.display.IVirtualDisplayCallback; import android.hardware.display.VirtualDisplayConfig; import android.hardware.input.InputManagerInternal; import android.os.Handler; import android.os.IBinder; import android.view.Display; import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceControl; Loading Loading @@ -281,6 +287,68 @@ public class DisplayManagerServiceTest { displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); } /** * Tests that there should be a display change notification to WindowManager to update its own * internal state for things like display cutout when nonOverrideDisplayInfo is changed. */ @Test public void testShouldNotifyChangeWhenNonOverrideDisplayInfoChanged() throws Exception { DisplayManagerService displayManager = new DisplayManagerService(mContext, mShortMockedInjector); registerDefaultDisplays(displayManager); displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); // Add the FakeDisplayDevice FakeDisplayDevice displayDevice = new FakeDisplayDevice(); DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo(); displayDeviceInfo.width = 100; displayDeviceInfo.height = 200; final Rect zeroRect = new Rect(); displayDeviceInfo.displayCutout = new DisplayCutout( Insets.of(0, 10, 0, 0), zeroRect, new Rect(0, 0, 10, 10), zeroRect, zeroRect); displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY; displayDevice.setDisplayDeviceInfo(displayDeviceInfo); displayManager.handleDisplayDeviceAdded(displayDevice); // Find the display id of the added FakeDisplayDevice DisplayManagerService.BinderService bs = displayManager.new BinderService(); final int[] displayIds = bs.getDisplayIds(); assertTrue(displayIds.length > 0); int displayId = Display.INVALID_DISPLAY; for (int i = 0; i < displayIds.length; i++) { DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayIds[i]); if (displayDeviceInfo.equals(ddi)) { displayId = displayIds[i]; break; } } assertFalse(displayId == Display.INVALID_DISPLAY); // Setup override DisplayInfo DisplayInfo overrideInfo = bs.getDisplayInfo(displayId); displayManager.setDisplayInfoOverrideFromWindowManagerInternal(displayId, overrideInfo); Handler handler = displayManager.getDisplayHandler(); handler.runWithScissors(() -> { }, 0 /* now */); // register display listener callback FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId); bs.registerCallback(callback); // Simulate DisplayDevice change DisplayDeviceInfo displayDeviceInfo2 = new DisplayDeviceInfo(); displayDeviceInfo2.copyFrom(displayDeviceInfo); displayDeviceInfo2.displayCutout = null; displayDevice.setDisplayDeviceInfo(displayDeviceInfo2); displayManager.handleDisplayDeviceChanged(displayDevice); handler.runWithScissors(() -> { }, 0 /* now */); assertTrue(callback.mCalled); } /** * Tests that we get a Runtime exception when we cannot initialize the default display. */ Loading Loading @@ -512,4 +580,42 @@ public class DisplayManagerServiceTest { // flush the handler handler.runWithScissors(() -> {}, 0 /* now */); } private class FakeDisplayManagerCallback extends IDisplayManagerCallback.Stub { int mDisplayId; boolean mCalled = false; FakeDisplayManagerCallback(int displayId) { mDisplayId = displayId; } @Override public void onDisplayEvent(int displayId, int event) { if (displayId == mDisplayId && event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) { mCalled = true; } } } private class FakeDisplayDevice extends DisplayDevice { private DisplayDeviceInfo mDisplayDeviceInfo; FakeDisplayDevice() { super(null, null, ""); } public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) { mDisplayDeviceInfo = displayDeviceInfo; } @Override public boolean hasStableUniqueId() { return false; } @Override public DisplayDeviceInfo getDisplayDeviceInfoLocked() { return mDisplayDeviceInfo; } } }