Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java +50 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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 Loading libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * 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); } } Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java +50 −6 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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 Loading
libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/area/WindowAreaComponentImplTests.java 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * 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); } }