diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2018-08-22 03:14:04 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2018-08-22 03:14:04 +0000 |
commit | a99c657655fab3cbdf2b35e2cebdc001990ae684 (patch) | |
tree | 91a2e7d70e80485e8cff87f280f5d6616083dc37 | |
parent | 44b2fa6114b64125eea887a48c699069b7957eea (diff) | |
parent | 2c9fd5fbbb43541ce4291c07bf61bdbe5dc70252 (diff) | |
download | base-a99c657655fab3cbdf2b35e2cebdc001990ae684.tar.gz |
Snap for 4969136 from 2c9fd5fbbb43541ce4291c07bf61bdbe5dc70252 to pi-qpr1-release
Change-Id: I348dc5200bd75dc04d6af22983e9c0bf2643dcd6
18 files changed, 200 insertions, 33 deletions
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 496bc9ff5383..5f80d31651a8 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -325,6 +325,7 @@ public final class DisplayCutout { * * @hide */ + @VisibleForTesting public static DisplayCutout fromBoundingRect(int left, int top, int right, int bottom) { Region r = Region.obtain(); r.set(left, top, right, bottom); @@ -422,8 +423,11 @@ public final class DisplayCutout { m.postTranslate(offsetX, 0); p.transform(m); - addToRegion(p, r); + final Rect tmpRect = new Rect(); + toRectAndAddToRegion(p, r, tmpRect); + final int topInset = tmpRect.bottom; + final int bottomInset; if (bottomSpec != null) { final Path bottomPath; try { @@ -436,10 +440,17 @@ public final class DisplayCutout { m.postTranslate(0, displayHeight); bottomPath.transform(m); p.addPath(bottomPath); - addToRegion(bottomPath, r); + toRectAndAddToRegion(bottomPath, r, tmpRect); + bottomInset = displayHeight - tmpRect.top; + } else { + bottomInset = 0; } - final Pair<Path, DisplayCutout> result = new Pair<>(p, fromBounds(r)); + // Reuse tmpRect as the inset rect we store into the DisplayCutout instance. + tmpRect.set(0, topInset, 0, bottomInset); + final DisplayCutout cutout = new DisplayCutout(tmpRect, r, false /* copyArguments */); + + final Pair<Path, DisplayCutout> result = new Pair<>(p, cutout); synchronized (CACHE_LOCK) { sCachedSpec = spec; sCachedDisplayWidth = displayWidth; @@ -450,12 +461,11 @@ public final class DisplayCutout { return result; } - private static void addToRegion(Path p, Region r) { + private static void toRectAndAddToRegion(Path p, Region inoutRegion, Rect inoutRect) { final RectF rectF = new RectF(); - final Rect rect = new Rect(); p.computeBounds(rectF, false /* unused */); - rectF.round(rect); - r.op(rect, Op.UNION); + rectF.round(inoutRect); + inoutRegion.op(inoutRect, Op.UNION); } private static Region boundingRectsToRegion(List<Rect> rects) { diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index fb7cd3d974f5..9d6aee102c02 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2984,6 +2984,10 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">false</bool> + <!-- If true, and there is a cutout on the main built in display, the cutout will be masked + by shrinking the display such that it does not overlap the cutout area. --> + <bool name="config_maskMainBuiltInDisplayCutout">false</bool> + <!-- Ultrasound support for Mic/speaker path --> <!-- Whether the default microphone audio source supports near-ultrasound frequencies (range of 18 - 21 kHz). --> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 471170bbe93b..73cb59e84644 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -61,6 +61,15 @@ <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. --> <dimen name="status_bar_edge_ignore">5dp</dimen> + <!-- Default radius of the software rounded corners. --> + <dimen name="rounded_corner_radius">0dp</dimen> + <!-- Radius of the software rounded corners at the top of the display in its natural + orientation. If zero, the value of rounded_corner_radius is used. --> + <dimen name="rounded_corner_radius_top">0dp</dimen> + <!-- Radius of the software rounded corners at the bottom of the display in its natural + orientation. If zero, the value of rounded_corner_radius is used. --> + <dimen name="rounded_corner_radius_bottom">0dp</dimen> + <!-- Width of the window of the divider bar used to resize docked stacks. --> <dimen name="docked_stack_divider_thickness">48dp</dimen> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index cf624acfc675..cd9d0c4f57f9 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3408,6 +3408,8 @@ <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" /> <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" /> + <java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" /> + <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" /> <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" /> </resources> diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java index 6ee74cb9a742..fe45fe7d3aaf 100644 --- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java +++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java @@ -19,6 +19,7 @@ package android.view; import static android.view.DisplayCutout.NO_CUTOUT; import static android.view.DisplayCutout.fromSpec; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertEquals; @@ -220,6 +221,19 @@ public class DisplayCutoutTest { } @Test + public void fromSpec_setsSafeInsets_top() { + DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z", 200, 400, 2f); + assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 0))); + } + + @Test + public void fromSpec_setsSafeInsets_top_and_bottom() { + DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z" + + "@bottom M -50,0 v -10,0 h 100 v 20 z", 200, 400, 2f); + assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 10))); + } + + @Test public void parcel_unparcel_nocutout() { Parcel p = Parcel.obtain(); diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 3c84e5a91026..7d90e02d0f2f 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -939,9 +939,9 @@ <dimen name="bottom_padding">48dp</dimen> <dimen name="edge_margin">8dp</dimen> - <dimen name="rounded_corner_radius">0dp</dimen> - <dimen name="rounded_corner_radius_top">0dp</dimen> - <dimen name="rounded_corner_radius_bottom">0dp</dimen> + <dimen name="rounded_corner_radius">@*android:dimen/rounded_corner_radius</dimen> + <dimen name="rounded_corner_radius_top">@*android:dimen/rounded_corner_radius_top</dimen> + <dimen name="rounded_corner_radius_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen> <dimen name="rounded_corner_content_padding">0dp</dimen> <dimen name="nav_content_padding">0dp</dimen> <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen> diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index 71cf9b52a2db..9ced14d16ae3 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -89,9 +89,9 @@ public class ScreenDecorations extends SystemUI implements Tunable { private DisplayManager mDisplayManager; private DisplayManager.DisplayListener mDisplayListener; - private int mRoundedDefault; - private int mRoundedDefaultTop; - private int mRoundedDefaultBottom; + @VisibleForTesting protected int mRoundedDefault; + @VisibleForTesting protected int mRoundedDefaultTop; + @VisibleForTesting protected int mRoundedDefaultBottom; private View mOverlay; private View mBottomOverlay; private float mDensity; @@ -119,12 +119,7 @@ public class ScreenDecorations extends SystemUI implements Tunable { private void startOnScreenDecorationsThread() { mRotation = RotationUtils.getExactRotation(mContext); mWindowManager = mContext.getSystemService(WindowManager.class); - mRoundedDefault = mContext.getResources().getDimensionPixelSize( - R.dimen.rounded_corner_radius); - mRoundedDefaultTop = mContext.getResources().getDimensionPixelSize( - R.dimen.rounded_corner_radius_top); - mRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize( - R.dimen.rounded_corner_radius_bottom); + updateRoundedCornerRadii(); if (hasRoundedCorners() || shouldDrawCutout()) { setupDecorations(); } @@ -249,6 +244,7 @@ public class ScreenDecorations extends SystemUI implements Tunable { int oldRotation = mRotation; mPendingRotationChange = false; updateOrientation(); + updateRoundedCornerRadii(); if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation); if (shouldDrawCutout() && mOverlay == null) { setupDecorations(); @@ -281,6 +277,26 @@ public class ScreenDecorations extends SystemUI implements Tunable { } } + private void updateRoundedCornerRadii() { + final int newRoundedDefault = mContext.getResources().getDimensionPixelSize( + R.dimen.rounded_corner_radius); + final int newRoundedDefaultTop = mContext.getResources().getDimensionPixelSize( + R.dimen.rounded_corner_radius_top); + final int newRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize( + R.dimen.rounded_corner_radius_bottom); + + final boolean roundedCornersChanged = mRoundedDefault != newRoundedDefault + || mRoundedDefaultBottom != newRoundedDefaultBottom + || mRoundedDefaultTop != newRoundedDefaultTop; + + if (roundedCornersChanged) { + mRoundedDefault = newRoundedDefault; + mRoundedDefaultTop = newRoundedDefaultTop; + mRoundedDefaultBottom = newRoundedDefaultBottom; + onTuningChanged(SIZE, null); + } + } + private void updateViews() { View topLeft = mOverlay.findViewById(R.id.left); View topRight = mOverlay.findViewById(R.id.right); diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index 644c0b347bde..cc969177ab2e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -21,6 +21,7 @@ import static com.android.systemui.tuner.TunablePadding.FLAG_START; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -226,4 +227,17 @@ public class ScreenDecorationsTest extends SysuiTestCase { verify(padding).destroy(); } + @Test + public void testUpdateRoundedCorners() { + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false); + mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 20); + + mScreenDecorations.start(); + assertEquals(mScreenDecorations.mRoundedDefault, 20); + + mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 5); + mScreenDecorations.onConfigurationChanged(null); + assertEquals(mScreenDecorations.mRoundedDefault, 5); + } } diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml index 754ba722d081..b08924b8adb6 100644 --- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml @@ -16,7 +16,7 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay">Corner display cutout</string> + <string name="display_cutout_emulation_overlay">Corner cutout</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml index 68c2dcbbe3f6..0a106fa0c08f 100644 --- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml @@ -16,7 +16,7 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay">Double display cutout</string> + <string name="display_cutout_emulation_overlay">Double cutout</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml index 49896773ac55..0bf83306f875 100644 --- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml @@ -18,7 +18,7 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay">Narrow display cutout</string> + <string name="display_cutout_emulation_overlay">Narrow cutout</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml index 6dcbbd923601..bcc7c9756a6e 100644 --- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml @@ -16,7 +16,7 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay">Tall display cutout</string> + <string name="display_cutout_emulation_overlay">Tall cutout</string> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml index f4b9f7ea7c37..0fcbdebbd345 100644 --- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml @@ -16,7 +16,7 @@ --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay">Wide display cutout</string> + <string name="display_cutout_emulation_overlay">Wide cutout</string> </resources> diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java index 349e1c8b713e..512e85192d36 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java +++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java @@ -104,6 +104,12 @@ final class DisplayDeviceInfo { public static final int FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 10; /** + * Flag: The display cutout of this display is masked. + * @hide + */ + public static final int FLAG_MASK_DISPLAY_CUTOUT = 1 << 11; + + /** * Touch attachment: Display does not receive touch. */ public static final int TOUCH_NONE = 0; @@ -453,6 +459,9 @@ final class DisplayDeviceInfo { if ((flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { msg.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD"); } + if ((flags & FLAG_MASK_DISPLAY_CUTOUT) != 0) { + msg.append(", FLAG_MASK_DISPLAY_CUTOUT"); + } return msg.toString(); } } diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 21ae048e1d75..16d82df4dd5b 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -402,6 +402,10 @@ final class LocalDisplayAdapter extends DisplayAdapter { && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) { mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND; } + if (res.getBoolean( + com.android.internal.R.bool.config_maskMainBuiltInDisplayCutout)) { + mInfo.flags |= DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT; + } mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res, mInfo.width, mInfo.height); mInfo.type = Display.TYPE_BUILT_IN; diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index 23ee56b24b19..373de63c0ec9 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -23,6 +23,8 @@ import android.view.DisplayInfo; import android.view.Surface; import android.view.SurfaceControl; +import com.android.server.wm.utils.InsetUtils; + import java.io.PrintWriter; import java.util.Arrays; import java.util.List; @@ -251,14 +253,18 @@ final class LogicalDisplay { if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; } + Rect maskingInsets = getMaskingInsets(deviceInfo); + int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right; + int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom; + mBaseDisplayInfo.type = deviceInfo.type; mBaseDisplayInfo.address = deviceInfo.address; mBaseDisplayInfo.name = deviceInfo.name; mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId; - mBaseDisplayInfo.appWidth = deviceInfo.width; - mBaseDisplayInfo.appHeight = deviceInfo.height; - mBaseDisplayInfo.logicalWidth = deviceInfo.width; - mBaseDisplayInfo.logicalHeight = deviceInfo.height; + mBaseDisplayInfo.appWidth = maskedWidth; + mBaseDisplayInfo.appHeight = maskedHeight; + mBaseDisplayInfo.logicalWidth = maskedWidth; + mBaseDisplayInfo.logicalHeight = maskedHeight; mBaseDisplayInfo.rotation = Surface.ROTATION_0; mBaseDisplayInfo.modeId = deviceInfo.modeId; mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId; @@ -275,13 +281,15 @@ final class LogicalDisplay { mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos; mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos; mBaseDisplayInfo.state = deviceInfo.state; - mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width; - mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height; - mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width; - mBaseDisplayInfo.largestNominalAppHeight = deviceInfo.height; + mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth; + mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight; + mBaseDisplayInfo.largestNominalAppWidth = maskedWidth; + mBaseDisplayInfo.largestNominalAppHeight = maskedHeight; mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid; mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName; - mBaseDisplayInfo.displayCutout = deviceInfo.displayCutout; + boolean maskCutout = + (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0; + mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout; mPrimaryDisplayDeviceInfo = deviceInfo; mInfo = null; @@ -289,6 +297,18 @@ final class LogicalDisplay { } /** + * Returns insets in ROTATION_0 for areas that are masked. + */ + private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) { + boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0; + if (maskCutout && deviceInfo.displayCutout != null) { + return deviceInfo.displayCutout.getSafeInsets(); + } else { + return new Rect(); + } + } + + /** * Applies the layer stack and transformation to the given display device * so that it shows the contents of this logical display. * @@ -349,6 +369,12 @@ final class LogicalDisplay { int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width; int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height; + Rect maskingInsets = getMaskingInsets(displayDeviceInfo); + InsetUtils.rotateInsets(maskingInsets, orientation); + // Don't consider the masked area as available when calculating the scaling below. + physWidth -= maskingInsets.left + maskingInsets.right; + physHeight -= maskingInsets.top + maskingInsets.bottom; + // Determine whether the width or height is more constrained to be scaled. // physWidth / displayInfo.logicalWidth => letter box // or physHeight / displayInfo.logicalHeight => pillar box @@ -375,6 +401,9 @@ final class LogicalDisplay { mTempDisplayRect.set(displayRectLeft, displayRectTop, displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight); + // Now add back the offset for the masked area. + mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top); + mTempDisplayRect.left += mDisplayOffsetX; mTempDisplayRect.right += mDisplayOffsetX; mTempDisplayRect.top += mDisplayOffsetY; diff --git a/services/core/java/com/android/server/wm/utils/InsetUtils.java b/services/core/java/com/android/server/wm/utils/InsetUtils.java index b4a998add374..c8600dd151d2 100644 --- a/services/core/java/com/android/server/wm/utils/InsetUtils.java +++ b/services/core/java/com/android/server/wm/utils/InsetUtils.java @@ -17,6 +17,7 @@ package com.android.server.wm.utils; import android.graphics.Rect; +import android.view.Surface; /** * Utility methods to handle insets represented as rects. @@ -27,6 +28,32 @@ public class InsetUtils { } /** + * Transforms insets given in one rotation into insets in a different rotation. + * + * @param inOutInsets the insets to transform, is set to the transformed insets + * @param rotationDelta the delta between the new and old rotation. + * Must be one of Surface.ROTATION_0/90/180/270. + */ + public static void rotateInsets(Rect inOutInsets, int rotationDelta) { + final Rect r = inOutInsets; + switch (rotationDelta) { + case Surface.ROTATION_0: + return; + case Surface.ROTATION_90: + r.set(r.top, r.right, r.bottom, r.left); + break; + case Surface.ROTATION_180: + r.set(r.right, r.bottom, r.left, r.top); + break; + case Surface.ROTATION_270: + r.set(r.bottom, r.left, r.top, r.right); + break; + default: + throw new IllegalArgumentException("Unknown rotation: " + rotationDelta); + } + } + + /** * Adds {@code insetsToAdd} to {@code inOutInsets}. */ public static void addInsets(Rect inOutInsets, Rect insetsToAdd) { diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java index d0f0fe315bcf..08bcc3d751f2 100644 --- a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java @@ -16,6 +16,11 @@ package com.android.server.wm.utils; +import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90; +import static android.view.Surface.ROTATION_0; +import static android.view.Surface.ROTATION_180; +import static android.view.Surface.ROTATION_270; + import static junit.framework.Assert.assertEquals; import android.graphics.Rect; @@ -39,5 +44,29 @@ public class InsetUtilsTest { InsetUtils.addInsets(rect1, rect2); assertEquals(new Rect(60, 80, 100, 120), rect1); } + + @Test + public void rotate() { + final Rect original = new Rect(1, 2, 3, 4); + + assertEquals("rot0", original, rotateCopy(original, ROTATION_0)); + + final Rect rot90 = rotateCopy(original, ROTATION_90); + assertEquals("rot90", new Rect(2, 3, 4, 1), rot90); + + final Rect rot180 = rotateCopy(original, ROTATION_180); + assertEquals("rot180", new Rect(3, 4, 1, 2), rot180); + assertEquals("rot90(rot90)=rot180", rotateCopy(rot90, ROTATION_90), rot180); + + final Rect rot270 = rotateCopy(original, ROTATION_270); + assertEquals("rot270", new Rect(4, 1, 2, 3), rot270); + assertEquals("rot90(rot180)=rot270", rotateCopy(rot180, ROTATION_90), rot270); + } + + private static Rect rotateCopy(Rect insets, int rotationDelta) { + final Rect copy = new Rect(insets); + InsetUtils.rotateInsets(copy, rotationDelta); + return copy; + } } |