diff options
5 files changed, 125 insertions, 0 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java index 571537c3cc22..462110f5a795 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; @@ -90,6 +91,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 4a66d3ab2c37..a87fb8b5c301 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -2516,6 +2516,17 @@ public final class DisplayManagerService extends SystemService { } @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) { throw new IllegalArgumentException("listener must not be null"); diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 3a5aa93d205d..0261f388f7cb 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; @@ -98,6 +99,11 @@ final class LogicalDisplay { 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. * @see #isDisplayScalingDisabled() @@ -335,6 +341,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 7931cd58d977..a93b962c33b4 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<DisplayContent.DisplayChildWindowCo return mDisplayPolicy.getSystemUiContext(); } + Point getDisplayPosition() { + return mWmService.mDisplayManagerInternal.getDisplayPosition(getDisplayId()); + } + class RemoteInsetsControlTarget implements InsetsControlTarget { private final IDisplayWindowInsetsController mRemoteInsetsController; diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java new file mode 100644 index 000000000000..301a9fe64d5e --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.graphics.Point; +import android.view.DisplayInfo; +import android.view.Surface; +import android.view.SurfaceControl; + +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; + +public class LogicalDisplayTest { + private static final int DISPLAY_ID = 0; + private static final int LAYER_STACK = 0; + private static final int DISPLAY_WIDTH = 100; + private static final int DISPLAY_HEIGHT = 200; + + private LogicalDisplay mLogicalDisplay; + private DisplayDevice mDisplayDevice; + + @Before + public void setUp() { + // Share classloader to allow package private access. + System.setProperty("dexmaker.share_classloader", "true"); + mDisplayDevice = mock(DisplayDevice.class); + DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo(); + displayDeviceInfo.width = DISPLAY_WIDTH; + displayDeviceInfo.height = DISPLAY_HEIGHT; + displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT; + mLogicalDisplay = new LogicalDisplay(DISPLAY_ID, LAYER_STACK, mDisplayDevice); + when(mDisplayDevice.getDisplayDeviceInfoLocked()).thenReturn(displayDeviceInfo); + + ArrayList<DisplayDevice> 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()); + } +} |