summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kevin Chyn <kchyn@google.com> 2023-06-12 21:40:36 +0000
committer Kevin Chyn <kchyn@google.com> 2023-06-14 19:01:14 +0000
commit32f5bd101a4606867bca7dc027e3af2f913f0a80 (patch)
treeb10d34ef6a5dc158b353bf50b3052f32b6cae0ac
parentb3ea50636a8c0429f67b64aec383d0da06889a1a (diff)
Transform displayMetrics if needed
Display#getRotation returns ROTATION_0 for displays that are not active. Display#getRealMetrics relies on rotation to flip width/height when the display is rotated. This results in incorrect metrics being reported from getRearDisplayMetrics() when the rear display is off and the device is rotated. This CL adjusts the rear display metrics so that they are reflective of the actual device rotation. Bug: 281952366 Test: atest WindowAreaComponentImplTests Test: Run CTS tests starting in different initial orientations Change-Id: I0b60039217f706b7829550d21c4f883778ca1f6d
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java56
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java96
2 files changed, 146 insertions, 6 deletions
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index 96190c4bc00a..f9aa1bd98e38 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -28,6 +28,7 @@ import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.Display;
import android.view.DisplayAddress;
+import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -36,6 +37,7 @@ import androidx.window.extensions.core.util.function.Consumer;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import java.util.Objects;
@@ -229,27 +231,41 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
* @since {@link WindowExtensions#VENDOR_API_LEVEL_3}
*/
@Override
+ @NonNull
public DisplayMetrics getRearDisplayMetrics() {
- DisplayMetrics metrics = null;
+ DisplayMetrics rearDisplayMetrics = null;
// DISPLAY_CATEGORY_REAR displays are only available when you are in the concurrent
// display state, so we have to look through all displays to match the address
- Display[] displays = mDisplayManager.getDisplays(
+ final Display[] displays = mDisplayManager.getDisplays(
DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED);
+ final Display defaultDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+
for (int i = 0; i < displays.length; i++) {
DisplayAddress.Physical address =
(DisplayAddress.Physical) displays[i].getAddress();
if (mRearDisplayAddress == address.getPhysicalDisplayId()) {
- metrics = new DisplayMetrics();
- displays[i].getRealMetrics(metrics);
+ rearDisplayMetrics = new DisplayMetrics();
+ final Display rearDisplay = displays[i];
+
+ // We must always retrieve the metrics for the rear display regardless of if it is
+ // the default display or not.
+ rearDisplay.getRealMetrics(rearDisplayMetrics);
+
+ // TODO(b/287170025): This should be something like if (!rearDisplay.isEnabled)
+ // instead. Currently when the rear display is disabled, its state is STATE_OFF.
+ if (rearDisplay.getDisplayId() != Display.DEFAULT_DISPLAY) {
+ rotateRearDisplayMetricsIfNeeded(defaultDisplay.getRotation(),
+ rearDisplay.getRotation(), rearDisplayMetrics);
+ }
break;
}
}
synchronized (mLock) {
// Update the rear display metrics with our latest value if one was received
- if (metrics != null) {
- mRearDisplayMetrics = metrics;
+ if (rearDisplayMetrics != null) {
+ mRearDisplayMetrics = rearDisplayMetrics;
}
return Objects.requireNonNullElseGet(mRearDisplayMetrics, DisplayMetrics::new);
@@ -540,6 +556,34 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
return mLastReportedRearDisplayPresentationStatus;
}
+ @VisibleForTesting
+ static void rotateRearDisplayMetricsIfNeeded(
+ @Surface.Rotation int defaultDisplayRotation,
+ @Surface.Rotation int rearDisplayRotation,
+ @NonNull DisplayMetrics inOutMetrics) {
+ // If the rear display has a non-zero rotation, it means the backing DisplayContent /
+ // DisplayRotation is fresh.
+ if (rearDisplayRotation != Surface.ROTATION_0) {
+ return;
+ }
+
+ // If the default display is 0 or 180, the rear display must also be 0 or 180.
+ if (defaultDisplayRotation == Surface.ROTATION_0
+ || defaultDisplayRotation == Surface.ROTATION_180) {
+ return;
+ }
+
+ final int heightPixels = inOutMetrics.heightPixels;
+ final int widthPixels = inOutMetrics.widthPixels;
+ inOutMetrics.widthPixels = heightPixels;
+ inOutMetrics.heightPixels = widthPixels;
+
+ final int noncompatHeightPixels = inOutMetrics.noncompatHeightPixels;
+ final int noncompatWidthPixels = inOutMetrics.noncompatWidthPixels;
+ inOutMetrics.noncompatWidthPixels = noncompatHeightPixels;
+ inOutMetrics.noncompatHeightPixels = noncompatWidthPixels;
+ }
+
/**
* Callback for the {@link DeviceStateRequest} to be notified of when the request has been
* activated or cancelled. This callback provides information to the client library
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java
new file mode 100644
index 000000000000..ccb4ebe9199e
--- /dev/null
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2023 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 androidx.window.extensions.area;
+
+import static org.junit.Assert.assertEquals;
+
+import android.platform.test.annotations.Presubmit;
+import android.util.DisplayMetrics;
+import android.view.Surface;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WindowAreaComponentImplTests {
+
+ private final DisplayMetrics mTestDisplayMetrics = new DisplayMetrics();
+
+ @Before
+ public void setup() {
+ mTestDisplayMetrics.widthPixels = 1;
+ mTestDisplayMetrics.heightPixels = 2;
+ mTestDisplayMetrics.noncompatWidthPixels = 3;
+ mTestDisplayMetrics.noncompatHeightPixels = 4;
+ }
+
+ /**
+ * Cases where the rear display metrics does not need to be transformed.
+ */
+ @Test
+ public void testRotateRearDisplayMetrics_noTransformNeeded() {
+ final DisplayMetrics originalMetrics = new DisplayMetrics();
+ originalMetrics.setTo(mTestDisplayMetrics);
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_0, Surface.ROTATION_0, mTestDisplayMetrics);
+ assertEquals(originalMetrics, mTestDisplayMetrics);
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_180, Surface.ROTATION_180, mTestDisplayMetrics);
+ assertEquals(originalMetrics, mTestDisplayMetrics);
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_0, Surface.ROTATION_180, mTestDisplayMetrics);
+ assertEquals(originalMetrics, mTestDisplayMetrics);
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_180, Surface.ROTATION_0, mTestDisplayMetrics);
+ assertEquals(originalMetrics, mTestDisplayMetrics);
+ }
+
+ /**
+ * Cases where the rear display metrics need to be transformed.
+ */
+ @Test
+ public void testRotateRearDisplayMetrics_transformNeeded() {
+ DisplayMetrics originalMetrics = new DisplayMetrics();
+ originalMetrics.setTo(mTestDisplayMetrics);
+
+ DisplayMetrics expectedMetrics = new DisplayMetrics();
+ expectedMetrics.setTo(mTestDisplayMetrics);
+ expectedMetrics.widthPixels = mTestDisplayMetrics.heightPixels;
+ expectedMetrics.heightPixels = mTestDisplayMetrics.widthPixels;
+ expectedMetrics.noncompatWidthPixels = mTestDisplayMetrics.noncompatHeightPixels;
+ expectedMetrics.noncompatHeightPixels = mTestDisplayMetrics.noncompatWidthPixels;
+
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_90, Surface.ROTATION_0, mTestDisplayMetrics);
+ assertEquals(expectedMetrics, mTestDisplayMetrics);
+
+ mTestDisplayMetrics.setTo(originalMetrics);
+ WindowAreaComponentImpl.rotateRearDisplayMetricsIfNeeded(
+ Surface.ROTATION_270, Surface.ROTATION_0, mTestDisplayMetrics);
+ assertEquals(expectedMetrics, mTestDisplayMetrics);
+ }
+}