diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 571537c3cc227..462110f5a795f 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; @@ -89,6 +90,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 4a66d3ab2c37c..a87fb8b5c3012 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2515,6 +2515,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 7931cd58d977b..a93b962c33b46 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5433,6 +5433,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()); + } +}