diff options
Diffstat (limited to 'libs')
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); + } +} |