diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index ea2b9e79d99c8..1c42db9a3f8d6 100644 --- a/core/java/android/hardware/display/DisplayManagerInternal.java +++ b/core/java/android/hardware/display/DisplayManagerInternal.java @@ -17,6 +17,7 @@ package android.hardware.display; import android.annotation.Nullable; +import android.graphics.Point; import android.hardware.SensorManager; import android.os.Handler; import android.os.PowerManager; @@ -80,6 +81,16 @@ public abstract class DisplayManagerInternal { */ public abstract DisplayInfo getDisplayInfo(int displayId); + /** + * Returns the position of the display's projection. + * + * @param displayId The logical display id. + * @return The x, y coordinates of the display, or null if the display does not exist. The + * return object must be treated as immutable. + */ + @Nullable + public abstract Point getDisplayPosition(int displayId); + /** * Registers a display transaction listener to provide the client a chance to * update its surfaces within the same transaction as any display layout updates. diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index a23205124f74f..677555659186f 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2482,6 +2482,17 @@ public final class DisplayManagerService extends SystemService { return getDisplayInfoInternal(displayId, Process.myUid()); } + @Override + public Point getDisplayPosition(int displayId) { + synchronized (mSyncRoot) { + LogicalDisplay display = mLogicalDisplays.get(displayId); + if (display != null) { + return display.getDisplayPosition(); + } + return null; + } + } + @Override public void registerDisplayTransactionListener(DisplayTransactionListener listener) { if (listener == null) { diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 3a5aa93d205dc..0261f388f7cbe 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -16,6 +16,7 @@ package com.android.server.display; +import android.graphics.Point; import android.graphics.Rect; import android.hardware.display.DisplayManagerInternal; import android.view.Display; @@ -97,6 +98,11 @@ final class LogicalDisplay { private int mDisplayOffsetX; private int mDisplayOffsetY; + /** + * The position of the display projection sent to SurfaceFlinger + */ + private final Point mDisplayPosition = new Point(); + /** * {@code true} if display scaling is disabled, or {@code false} if the default scaling mode * is used. @@ -334,6 +340,16 @@ final class LogicalDisplay { } } + /** + * Returns the position of the display's projection. + * + * @return The x, y coordinates of the display. The return object must be treated as immutable. + */ + Point getDisplayPosition() { + // Allocate a new object to avoid a data race. + return new Point(mDisplayPosition); + } + /** * Applies the layer stack and transformation to the given display device * so that it shows the contents of this logical display. @@ -445,6 +461,8 @@ final class LogicalDisplay { } else { // Surface.ROTATION_270 mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX); } + + mDisplayPosition.set(mTempDisplayRect.left, mTempDisplayRect.top); device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 236a62b7a05d3..2a336f93229e2 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -6824,6 +6824,10 @@ class DisplayContent extends WindowContainer displayDevices = new ArrayList<>(); + displayDevices.add(mDisplayDevice); + mLogicalDisplay.updateLocked(displayDevices); + } + + @Test + public void testGetDisplayPosition() { + Point expectedPosition = new Point(); + + SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class); + mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false); + assertEquals(expectedPosition, mLogicalDisplay.getDisplayPosition()); + + expectedPosition.set(20, 40); + mLogicalDisplay.setDisplayOffsetsLocked(20, 40); + mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false); + assertEquals(expectedPosition, mLogicalDisplay.getDisplayPosition()); + + expectedPosition.set(40, -20); + DisplayInfo displayInfo = new DisplayInfo(); + displayInfo.logicalWidth = DISPLAY_HEIGHT; + displayInfo.logicalHeight = DISPLAY_WIDTH; + displayInfo.rotation = Surface.ROTATION_90; + mLogicalDisplay.setDisplayInfoOverrideFromWindowManagerLocked(displayInfo); + mLogicalDisplay.configureDisplayLocked(t, mDisplayDevice, false); + assertEquals(expectedPosition, mLogicalDisplay.getDisplayPosition()); + } +}