Merge "Transform displayMetrics if needed" into udc-dev
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 96190c4b..f9aa1bd 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.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 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 @@
* @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 @@
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 0000000..ccb4ebe
--- /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);
+ }
+}