Loading services/core/java/com/android/server/display/LogicalDisplay.java +25 −8 Original line number Diff line number Diff line Loading @@ -161,7 +161,11 @@ final class LogicalDisplay { // Indicates the position of the display, POSITION_UNKNOWN could mean it hasn't been specified, // or this is a virtual display etc. private int mPosition = Layout.Display.POSITION_UNKNOWN; private int mDevicePosition = Layout.Display.POSITION_UNKNOWN; // Indicates that something other than the primary display device info has changed and needs to // be handled in the next update. private boolean mDirty = false; /** * The ID of the brightness throttling data that should be used. This can change e.g. in Loading @@ -181,11 +185,14 @@ final class LogicalDisplay { mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID; } public void setPositionLocked(int position) { mPosition = position; public void setDevicePositionLocked(int position) { if (mDevicePosition != position) { mDevicePosition = position; mDirty = true; } } public int getPositionLocked() { return mPosition; public int getDevicePositionLocked() { return mDevicePosition; } /** Loading Loading @@ -343,9 +350,11 @@ final class LogicalDisplay { // logical display that they are sharing. (eg. Adjust size for pixel-perfect // mirroring over HDMI.) DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked(); if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo)) { if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo) || mDirty) { mBaseDisplayInfo.layerStack = mLayerStack; mBaseDisplayInfo.flags = 0; // Displays default to moving content to the primary display when removed mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY; if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS; } Loading Loading @@ -443,12 +452,20 @@ final class LogicalDisplay { mBaseDisplayInfo.installOrientation = deviceInfo.installOrientation; mBaseDisplayInfo.displayShape = deviceInfo.displayShape; if (mPosition == Layout.Display.POSITION_REAR) { if (mDevicePosition == Layout.Display.POSITION_REAR) { // A rear display is meant to host a specific experience that is essentially // a presentation to another user or users other than the main user since they // can't actually see that display. Given that, it's a suitable display for // presentations but the content should be destroyed rather than moved to a non-rear // display when the rear display is removed. mBaseDisplayInfo.flags |= Display.FLAG_REAR; mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION; mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT; } mPrimaryDisplayDeviceInfo = deviceInfo; mInfo.set(null); mDirty = false; } } Loading Loading @@ -857,7 +874,7 @@ final class LogicalDisplay { pw.println("mIsEnabled=" + mIsEnabled); pw.println("mIsInTransition=" + mIsInTransition); pw.println("mLayerStack=" + mLayerStack); pw.println("mPosition=" + mPosition); pw.println("mPosition=" + mDevicePosition); pw.println("mHasContent=" + mHasContent); pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}"); pw.println("mRequestedColorMode=" + mRequestedColorMode); Loading services/core/java/com/android/server/display/LogicalDisplayMapper.java +1 −1 Original line number Diff line number Diff line Loading @@ -992,7 +992,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { newDisplay.swapDisplaysLocked(oldDisplay); } newDisplay.setPositionLocked(displayLayout.getPosition()); newDisplay.setDevicePositionLocked(displayLayout.getPosition()); newDisplay.setLeadDisplayLocked(displayLayout.getLeadDisplayId()); setLayoutLimitedRefreshRate(newDisplay, device, displayLayout); setEnabledLocked(newDisplay, displayLayout.isEnabled()); Loading services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -836,9 +836,9 @@ public class LogicalDisplayMapperTest { assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked()); assertEquals(POSITION_UNKNOWN, mLogicalDisplayMapper.getDisplayLocked(device1).getPositionLocked()); mLogicalDisplayMapper.getDisplayLocked(device1).getDevicePositionLocked()); assertEquals(POSITION_REAR, mLogicalDisplayMapper.getDisplayLocked(device2).getPositionLocked()); mLogicalDisplayMapper.getDisplayLocked(device2).getDevicePositionLocked()); } ///////////////// Loading services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java +32 −3 Original line number Diff line number Diff line Loading @@ -26,12 +26,15 @@ import static org.mockito.Mockito.when; import android.app.PropertyInvalidatedCache; import android.graphics.Point; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import com.android.server.display.layout.Layout; import org.junit.Before; import org.junit.Test; Loading @@ -47,6 +50,7 @@ public class LogicalDisplayTest { private LogicalDisplay mLogicalDisplay; private DisplayDevice mDisplayDevice; private DisplayDeviceRepository mDeviceRepo; private final DisplayDeviceInfo mDisplayDeviceInfo = new DisplayDeviceInfo(); @Before Loading @@ -66,7 +70,7 @@ public class LogicalDisplayTest { // Disable binder caches in this process. PropertyInvalidatedCache.disableForTestMode(); DisplayDeviceRepository repo = new DisplayDeviceRepository( mDeviceRepo = new DisplayDeviceRepository( new DisplayManagerService.SyncRoot(), new PersistentDataStore(new PersistentDataStore.Injector() { @Override Loading @@ -82,8 +86,8 @@ public class LogicalDisplayTest { @Override public void finishWrite(OutputStream os, boolean success) {} })); repo.onDisplayDeviceEvent(mDisplayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED); mLogicalDisplay.updateLocked(repo); mDeviceRepo.onDisplayDeviceEvent(mDisplayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED); mLogicalDisplay.updateLocked(mDeviceRepo); } @Test Loading Loading @@ -137,4 +141,29 @@ public class LogicalDisplayTest { verify(t).setDisplayFlags(any(), eq(SurfaceControl.DISPLAY_RECEIVES_INPUT)); reset(t); } @Test public void testRearDisplaysArePresentationDisplaysThatDestroyContentOnRemoval() { // Assert that the display isn't a presentation display by default, with a default remove // mode assertEquals(0, mLogicalDisplay.getDisplayInfoLocked().flags); assertEquals(Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY, mLogicalDisplay.getDisplayInfoLocked().removeMode); // Update position and test to see that it's been updated to a rear, presentation display // that destroys content on removal mLogicalDisplay.setDevicePositionLocked(Layout.Display.POSITION_REAR); mLogicalDisplay.updateLocked(mDeviceRepo); assertEquals(Display.FLAG_REAR | Display.FLAG_PRESENTATION, mLogicalDisplay.getDisplayInfoLocked().flags); assertEquals(Display.REMOVE_MODE_DESTROY_CONTENT, mLogicalDisplay.getDisplayInfoLocked().removeMode); // And then check the unsetting the position resets both mLogicalDisplay.setDevicePositionLocked(Layout.Display.POSITION_UNKNOWN); mLogicalDisplay.updateLocked(mDeviceRepo); assertEquals(0, mLogicalDisplay.getDisplayInfoLocked().flags); assertEquals(Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY, mLogicalDisplay.getDisplayInfoLocked().removeMode); } } Loading
services/core/java/com/android/server/display/LogicalDisplay.java +25 −8 Original line number Diff line number Diff line Loading @@ -161,7 +161,11 @@ final class LogicalDisplay { // Indicates the position of the display, POSITION_UNKNOWN could mean it hasn't been specified, // or this is a virtual display etc. private int mPosition = Layout.Display.POSITION_UNKNOWN; private int mDevicePosition = Layout.Display.POSITION_UNKNOWN; // Indicates that something other than the primary display device info has changed and needs to // be handled in the next update. private boolean mDirty = false; /** * The ID of the brightness throttling data that should be used. This can change e.g. in Loading @@ -181,11 +185,14 @@ final class LogicalDisplay { mBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_BRIGHTNESS_THROTTLING_DATA_ID; } public void setPositionLocked(int position) { mPosition = position; public void setDevicePositionLocked(int position) { if (mDevicePosition != position) { mDevicePosition = position; mDirty = true; } } public int getPositionLocked() { return mPosition; public int getDevicePositionLocked() { return mDevicePosition; } /** Loading Loading @@ -343,9 +350,11 @@ final class LogicalDisplay { // logical display that they are sharing. (eg. Adjust size for pixel-perfect // mirroring over HDMI.) DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked(); if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo)) { if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo) || mDirty) { mBaseDisplayInfo.layerStack = mLayerStack; mBaseDisplayInfo.flags = 0; // Displays default to moving content to the primary display when removed mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY; if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS; } Loading Loading @@ -443,12 +452,20 @@ final class LogicalDisplay { mBaseDisplayInfo.installOrientation = deviceInfo.installOrientation; mBaseDisplayInfo.displayShape = deviceInfo.displayShape; if (mPosition == Layout.Display.POSITION_REAR) { if (mDevicePosition == Layout.Display.POSITION_REAR) { // A rear display is meant to host a specific experience that is essentially // a presentation to another user or users other than the main user since they // can't actually see that display. Given that, it's a suitable display for // presentations but the content should be destroyed rather than moved to a non-rear // display when the rear display is removed. mBaseDisplayInfo.flags |= Display.FLAG_REAR; mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION; mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT; } mPrimaryDisplayDeviceInfo = deviceInfo; mInfo.set(null); mDirty = false; } } Loading Loading @@ -857,7 +874,7 @@ final class LogicalDisplay { pw.println("mIsEnabled=" + mIsEnabled); pw.println("mIsInTransition=" + mIsInTransition); pw.println("mLayerStack=" + mLayerStack); pw.println("mPosition=" + mPosition); pw.println("mPosition=" + mDevicePosition); pw.println("mHasContent=" + mHasContent); pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}"); pw.println("mRequestedColorMode=" + mRequestedColorMode); Loading
services/core/java/com/android/server/display/LogicalDisplayMapper.java +1 −1 Original line number Diff line number Diff line Loading @@ -992,7 +992,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { newDisplay.swapDisplaysLocked(oldDisplay); } newDisplay.setPositionLocked(displayLayout.getPosition()); newDisplay.setDevicePositionLocked(displayLayout.getPosition()); newDisplay.setLeadDisplayLocked(displayLayout.getLeadDisplayId()); setLayoutLimitedRefreshRate(newDisplay, device, displayLayout); setEnabledLocked(newDisplay, displayLayout.isEnabled()); Loading
services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java +2 −2 Original line number Diff line number Diff line Loading @@ -836,9 +836,9 @@ public class LogicalDisplayMapperTest { assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked()); assertEquals(POSITION_UNKNOWN, mLogicalDisplayMapper.getDisplayLocked(device1).getPositionLocked()); mLogicalDisplayMapper.getDisplayLocked(device1).getDevicePositionLocked()); assertEquals(POSITION_REAR, mLogicalDisplayMapper.getDisplayLocked(device2).getPositionLocked()); mLogicalDisplayMapper.getDisplayLocked(device2).getDevicePositionLocked()); } ///////////////// Loading
services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java +32 −3 Original line number Diff line number Diff line Loading @@ -26,12 +26,15 @@ import static org.mockito.Mockito.when; import android.app.PropertyInvalidatedCache; import android.graphics.Point; import android.view.Display; import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import com.android.server.display.layout.Layout; import org.junit.Before; import org.junit.Test; Loading @@ -47,6 +50,7 @@ public class LogicalDisplayTest { private LogicalDisplay mLogicalDisplay; private DisplayDevice mDisplayDevice; private DisplayDeviceRepository mDeviceRepo; private final DisplayDeviceInfo mDisplayDeviceInfo = new DisplayDeviceInfo(); @Before Loading @@ -66,7 +70,7 @@ public class LogicalDisplayTest { // Disable binder caches in this process. PropertyInvalidatedCache.disableForTestMode(); DisplayDeviceRepository repo = new DisplayDeviceRepository( mDeviceRepo = new DisplayDeviceRepository( new DisplayManagerService.SyncRoot(), new PersistentDataStore(new PersistentDataStore.Injector() { @Override Loading @@ -82,8 +86,8 @@ public class LogicalDisplayTest { @Override public void finishWrite(OutputStream os, boolean success) {} })); repo.onDisplayDeviceEvent(mDisplayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED); mLogicalDisplay.updateLocked(repo); mDeviceRepo.onDisplayDeviceEvent(mDisplayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED); mLogicalDisplay.updateLocked(mDeviceRepo); } @Test Loading Loading @@ -137,4 +141,29 @@ public class LogicalDisplayTest { verify(t).setDisplayFlags(any(), eq(SurfaceControl.DISPLAY_RECEIVES_INPUT)); reset(t); } @Test public void testRearDisplaysArePresentationDisplaysThatDestroyContentOnRemoval() { // Assert that the display isn't a presentation display by default, with a default remove // mode assertEquals(0, mLogicalDisplay.getDisplayInfoLocked().flags); assertEquals(Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY, mLogicalDisplay.getDisplayInfoLocked().removeMode); // Update position and test to see that it's been updated to a rear, presentation display // that destroys content on removal mLogicalDisplay.setDevicePositionLocked(Layout.Display.POSITION_REAR); mLogicalDisplay.updateLocked(mDeviceRepo); assertEquals(Display.FLAG_REAR | Display.FLAG_PRESENTATION, mLogicalDisplay.getDisplayInfoLocked().flags); assertEquals(Display.REMOVE_MODE_DESTROY_CONTENT, mLogicalDisplay.getDisplayInfoLocked().removeMode); // And then check the unsetting the position resets both mLogicalDisplay.setDevicePositionLocked(Layout.Display.POSITION_UNKNOWN); mLogicalDisplay.updateLocked(mDeviceRepo); assertEquals(0, mLogicalDisplay.getDisplayInfoLocked().flags); assertEquals(Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY, mLogicalDisplay.getDisplayInfoLocked().removeMode); } }