Move rotate utility to DisplayCutout

This was only in WMDisplayCutout, but it really is generic and we
plan to support rotating cutouts in the client.

Bug: 202201326
Test: DisplayContentTests DisplayCutoutTest
Change-Id: I75dc5e2296d096680e7660c98faf88b5cb1726e8
This commit is contained in:
Evan Rosky
2022-01-20 20:13:49 -08:00
parent d80c67c952
commit 3c12e168a3
6 changed files with 192 additions and 316 deletions

View File

@@ -53,6 +53,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
@@ -369,6 +370,33 @@ public final class DisplayCutout {
true);
}
/**
* Creates a DisplayCutout instance.
*
* <p>Note that this is only useful for tests. For production code, developers should always
* use a {@link DisplayCutout} obtained from the system.</p>
*
* @param safeInsets the insets from each edge which avoid the display cutout as returned by
* {@link #getSafeInsetTop()} etc.
* @param boundLeft the left bounding rect of the display cutout in pixels. If null is passed,
* it's treated as an empty rectangle (0,0)-(0,0).
* @param boundTop the top bounding rect of the display cutout in pixels. If null is passed,
* it's treated as an empty rectangle (0,0)-(0,0).
* @param boundRight the right bounding rect of the display cutout in pixels. If null is
* passed, it's treated as an empty rectangle (0,0)-(0,0).
* @param boundBottom the bottom bounding rect of the display cutout in pixels. If null is
* passed, it's treated as an empty rectangle (0,0)-(0,0).
* @param waterfallInsets the insets for the curved areas in waterfall display.
* @param info the cutout path parser info.
* @hide
*/
public DisplayCutout(@NonNull Insets safeInsets, @Nullable Rect boundLeft,
@Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom,
@NonNull Insets waterfallInsets, @Nullable CutoutPathParserInfo info) {
this(safeInsets.toRect(), waterfallInsets, boundLeft, boundTop, boundRight, boundBottom,
info, true);
}
/**
* Creates a DisplayCutout instance.
*
@@ -1097,6 +1125,85 @@ public final class DisplayCutout {
res.getDimensionPixelSize(R.dimen.waterfall_display_bottom_edge_size));
}
/**
* @return a copy of this cutout that has been rotated for a display in toRotation.
* @hide
*/
public DisplayCutout getRotated(int startWidth, int startHeight,
int fromRotation, int toRotation) {
if (this == DisplayCutout.NO_CUTOUT) {
return DisplayCutout.NO_CUTOUT;
}
final int rotation = RotationUtils.deltaRotation(fromRotation, toRotation);
if (rotation == ROTATION_0) {
return this;
}
final Insets waterfallInsets = RotationUtils.rotateInsets(getWaterfallInsets(), rotation);
// returns a copy
final Rect[] newBounds = getBoundingRectsAll();
final Rect displayBounds = new Rect(0, 0, startWidth, startHeight);
for (int i = 0; i < newBounds.length; ++i) {
if (newBounds[i].isEmpty()) continue;
RotationUtils.rotateBounds(newBounds[i], displayBounds, rotation);
}
Collections.rotate(Arrays.asList(newBounds), -rotation);
final CutoutPathParserInfo info = getCutoutPathParserInfo();
final CutoutPathParserInfo newInfo = new CutoutPathParserInfo(
info.getDisplayWidth(), info.getDisplayHeight(), info.getDensity(),
info.getCutoutSpec(), toRotation, info.getScale());
final boolean swapAspect = (rotation % 2) != 0;
final int endWidth = swapAspect ? startHeight : startWidth;
final int endHeight = swapAspect ? startWidth : startHeight;
final DisplayCutout tmp =
DisplayCutout.constructDisplayCutout(newBounds, waterfallInsets, newInfo);
final Rect safeInsets = DisplayCutout.computeSafeInsets(endWidth, endHeight, tmp);
return tmp.replaceSafeInsets(safeInsets);
}
/**
* Compute the insets derived from a cutout. This is usually used to populate the safe-insets
* of the cutout via {@link #replaceSafeInsets}.
* @hide
*/
public static Rect computeSafeInsets(int displayW, int displayH, DisplayCutout cutout) {
if (displayW == displayH) {
throw new UnsupportedOperationException("not implemented: display=" + displayW + "x"
+ displayH + " cutout=" + cutout);
}
int leftInset = Math.max(cutout.getWaterfallInsets().left, findCutoutInsetForSide(
displayW, displayH, cutout.getBoundingRectLeft(), Gravity.LEFT));
int topInset = Math.max(cutout.getWaterfallInsets().top, findCutoutInsetForSide(
displayW, displayH, cutout.getBoundingRectTop(), Gravity.TOP));
int rightInset = Math.max(cutout.getWaterfallInsets().right, findCutoutInsetForSide(
displayW, displayH, cutout.getBoundingRectRight(), Gravity.RIGHT));
int bottomInset = Math.max(cutout.getWaterfallInsets().bottom, findCutoutInsetForSide(
displayW, displayH, cutout.getBoundingRectBottom(), Gravity.BOTTOM));
return new Rect(leftInset, topInset, rightInset, bottomInset);
}
private static int findCutoutInsetForSide(int displayW, int displayH, Rect boundingRect,
int gravity) {
if (boundingRect.isEmpty()) {
return 0;
}
int inset = 0;
switch (gravity) {
case Gravity.TOP:
return Math.max(inset, boundingRect.bottom);
case Gravity.BOTTOM:
return Math.max(inset, displayH - boundingRect.top);
case Gravity.LEFT:
return Math.max(inset, boundingRect.right);
case Gravity.RIGHT:
return Math.max(inset, displayW - boundingRect.left);
default:
throw new IllegalArgumentException("unknown gravity: " + gravity);
}
}
/**
* Helper class for passing {@link DisplayCutout} through binder.
*

View File

@@ -19,6 +19,10 @@ package android.view;
import static android.view.DisplayCutout.NO_CUTOUT;
import static android.view.DisplayCutout.extractBoundsFromList;
import static android.view.DisplayCutout.fromSpec;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.not;
@@ -497,6 +501,74 @@ public class DisplayCutoutTest {
new ParcelableWrapper(mCutoutNumbers));
}
@Test
public void testGetRotatedBounds_top_rot0() {
int displayW = 500, displayH = 1000;
DisplayCutout expected = new DisplayCutout(Insets.of(20, 100, 20, 0),
ZERO_RECT, new Rect(50, 0, 75, 100), ZERO_RECT, ZERO_RECT,
Insets.of(20, 0, 20, 0));
DisplayCutout cutout = new DisplayCutout(Insets.of(20, 100, 20, 0),
ZERO_RECT, new Rect(50, 0, 75, 100), ZERO_RECT, ZERO_RECT,
Insets.of(20, 0, 20, 0));
DisplayCutout rotated = cutout.getRotated(displayW, displayH, ROTATION_0, ROTATION_0);
assertEquals(expected, rotated);
}
@Test
public void testGetRotatedBounds_top_rot90() {
int displayW = 500, displayH = 1000;
DisplayCutout expected = new DisplayCutout(Insets.of(100, 20, 0, 20),
new Rect(0, displayW - 75, 100, displayW - 50), ZERO_RECT, ZERO_RECT, ZERO_RECT,
Insets.of(0, 20, 0, 20), createParserInfo(ROTATION_90));
DisplayCutout cutout = new DisplayCutout(Insets.of(20, 100, 20, 0),
ZERO_RECT, new Rect(50, 0, 75, 100), ZERO_RECT, ZERO_RECT,
Insets.of(20, 0, 20, 0));
DisplayCutout rotated = cutout.getRotated(displayW, displayH, ROTATION_0, ROTATION_90);
assertEquals(expected, rotated);
}
@Test
public void testGetRotatedBounds_top_rot180() {
int displayW = 500, displayH = 1000;
DisplayCutout expected = new DisplayCutout(Insets.of(20, 0, 20, 100),
ZERO_RECT, ZERO_RECT, ZERO_RECT,
new Rect(displayW - 75, displayH - 100, displayW - 50, displayH - 0),
Insets.of(20, 0, 20, 0), createParserInfo(ROTATION_180));
DisplayCutout cutout = new DisplayCutout(Insets.of(20, 100, 20, 0),
ZERO_RECT, new Rect(50, 0, 75, 100), ZERO_RECT, ZERO_RECT,
Insets.of(20, 0, 20, 0));
DisplayCutout rotated = cutout.getRotated(displayW, displayH, ROTATION_0, ROTATION_180);
assertEquals(expected, rotated);
}
@Test
public void testGetRotatedBounds_top_rot270() {
int displayW = 500, displayH = 1000;
DisplayCutout expected = new DisplayCutout(Insets.of(0, 20, 100, 20),
ZERO_RECT, ZERO_RECT, new Rect(displayH - 100, 50, displayH - 0, 75), ZERO_RECT,
Insets.of(0, 20, 0, 20), createParserInfo(ROTATION_270));
DisplayCutout cutout = new DisplayCutout(Insets.of(20, 100, 20, 0),
ZERO_RECT, new Rect(50, 0, 75, 100), ZERO_RECT, ZERO_RECT,
Insets.of(20, 0, 20, 0));
DisplayCutout rotated = cutout.getRotated(displayW, displayH, ROTATION_0, ROTATION_270);
assertEquals(expected, rotated);
}
@Test
public void testGetRotatedBounds_top_rot90to180() {
int displayW = 500, displayH = 1000;
DisplayCutout expected = new DisplayCutout(Insets.of(20, 0, 20, 100),
ZERO_RECT, ZERO_RECT, ZERO_RECT,
new Rect(displayW - 75, displayH - 100, displayW - 50, displayH - 0),
Insets.of(20, 0, 20, 0), createParserInfo(ROTATION_180));
DisplayCutout cutout = new DisplayCutout(Insets.of(100, 20, 0, 20),
new Rect(0, displayW - 75, 100, displayW - 50), ZERO_RECT, ZERO_RECT, ZERO_RECT,
Insets.of(0, 20, 0, 20));
// starting from 90, so the start displayW/H are swapped:
DisplayCutout rotated = cutout.getRotated(displayH, displayW, ROTATION_90, ROTATION_180);
assertEquals(expected, rotated);
}
private static DisplayCutout createCutoutTop() {
return createCutoutWithInsets(0, 100, 0, 0);
}
@@ -533,4 +605,11 @@ public class DisplayCutoutTest {
ZERO_RECT,
waterfallInsets);
}
private static DisplayCutout.CutoutPathParserInfo createParserInfo(
@Surface.Rotation int rotation) {
return new DisplayCutout.CutoutPathParserInfo(
0 /* displayWidth */, 0 /* displayHeight */, 0f /* density */, "" /* cutoutSpec */,
rotation, 0f /* scale */);
}
}

View File

@@ -191,13 +191,13 @@ import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.IntArray;
import android.util.RotationUtils;
import android.util.Size;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayCutout.CutoutPathParserInfo;
import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.IDisplayWindowInsetsController;
@@ -238,7 +238,6 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.internal.util.function.pooled.PooledPredicate;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.utils.DisplayRotationUtil;
import com.android.server.wm.utils.RotationCache;
import com.android.server.wm.utils.WmDisplayCutout;
@@ -578,8 +577,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
/** Caches the value whether told display manager that we have content. */
private boolean mLastHasContent;
private static DisplayRotationUtil sRotationUtil = new DisplayRotationUtil();
/**
* The input method window for this display.
*/
@@ -2082,20 +2079,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return WmDisplayCutout.computeSafeInsets(
cutout, displayWidth, displayHeight);
}
final Insets waterfallInsets =
RotationUtils.rotateInsets(cutout.getWaterfallInsets(), rotation);
final DisplayCutout rotatedCutout =
cutout.getRotated(displayWidth, displayHeight, ROTATION_0, rotation);
final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
final Rect[] newBounds = sRotationUtil.getRotatedBounds(
cutout.getBoundingRectsAll(),
rotation, displayWidth, displayHeight);
final CutoutPathParserInfo info = cutout.getCutoutPathParserInfo();
final CutoutPathParserInfo newInfo = new CutoutPathParserInfo(
info.getDisplayWidth(), info.getDisplayHeight(), info.getDensity(),
info.getCutoutSpec(), rotation, info.getScale());
return WmDisplayCutout.computeSafeInsets(
DisplayCutout.constructDisplayCutout(newBounds, waterfallInsets, newInfo),
return new WmDisplayCutout(rotatedCutout, new Size(
rotated ? displayHeight : displayWidth,
rotated ? displayWidth : displayHeight);
rotated ? displayWidth : displayHeight));
}
private WmDisplayCutout calculateDisplayCutoutForRotationUncached(

View File

@@ -1,96 +0,0 @@
/*
* Copyright (C) 2018 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 com.android.server.wm.utils;
import static android.view.DisplayCutout.BOUNDS_POSITION_LENGTH;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import com.android.internal.annotations.VisibleForTesting;
/**
* Utility to compute bounds after rotating the screen.
*/
public class DisplayRotationUtil {
private final Matrix mTmpMatrix = new Matrix();
private static int getRotationToBoundsOffset(int rotation) {
switch (rotation) {
case ROTATION_0:
return 0;
case ROTATION_90:
return -1;
case ROTATION_180:
return 2;
case ROTATION_270:
return 1;
default:
// should not happen
return 0;
}
}
@VisibleForTesting
static int getBoundIndexFromRotation(int i, int rotation) {
return Math.floorMod(i + getRotationToBoundsOffset(rotation),
BOUNDS_POSITION_LENGTH);
}
/**
* Compute bounds after rotating the screen.
*
* @param bounds Bounds before the rotation. The array must contain exactly 4 non-null elements.
* @param rotation rotation constant defined in android.view.Surface.
* @param initialDisplayWidth width of the display before the rotation.
* @param initialDisplayHeight height of the display before the rotation.
* @return Bounds after the rotation.
*
* @hide
*/
public Rect[] getRotatedBounds(
Rect[] bounds, int rotation, int initialDisplayWidth, int initialDisplayHeight) {
if (bounds.length != BOUNDS_POSITION_LENGTH) {
throw new IllegalArgumentException(
"bounds must have exactly 4 elements: bounds=" + bounds);
}
if (rotation == ROTATION_0) {
return bounds;
}
transformPhysicalToLogicalCoordinates(rotation, initialDisplayWidth, initialDisplayHeight,
mTmpMatrix);
Rect[] newBounds = new Rect[BOUNDS_POSITION_LENGTH];
for (int i = 0; i < bounds.length; i++) {
final Rect rect = bounds[i];
if (!rect.isEmpty()) {
final RectF rectF = new RectF(rect);
mTmpMatrix.mapRect(rectF);
rectF.round(rect);
}
newBounds[getBoundIndexFromRotation(i, rotation)] = rect;
}
return newBounds;
}
}

View File

@@ -19,7 +19,6 @@ package com.android.server.wm.utils;
import android.graphics.Rect;
import android.util.Size;
import android.view.DisplayCutout;
import android.view.Gravity;
import java.util.Objects;
@@ -52,7 +51,7 @@ public class WmDisplayCutout {
return NO_CUTOUT;
}
final Size displaySize = new Size(displayWidth, displayHeight);
final Rect safeInsets = computeSafeInsets(displaySize, inner);
final Rect safeInsets = DisplayCutout.computeSafeInsets(displayWidth, displayHeight, inner);
return new WmDisplayCutout(inner.replaceSafeInsets(safeInsets), displaySize);
}
@@ -66,45 +65,6 @@ public class WmDisplayCutout {
return computeSafeInsets(mInner, width, height);
}
private static Rect computeSafeInsets(Size displaySize, DisplayCutout cutout) {
if (displaySize.getWidth() == displaySize.getHeight()) {
throw new UnsupportedOperationException("not implemented: display=" + displaySize +
" cutout=" + cutout);
}
int leftInset = Math.max(cutout.getWaterfallInsets().left,
findCutoutInsetForSide(displaySize, cutout.getBoundingRectLeft(), Gravity.LEFT));
int topInset = Math.max(cutout.getWaterfallInsets().top,
findCutoutInsetForSide(displaySize, cutout.getBoundingRectTop(), Gravity.TOP));
int rightInset = Math.max(cutout.getWaterfallInsets().right,
findCutoutInsetForSide(displaySize, cutout.getBoundingRectRight(), Gravity.RIGHT));
int bottomInset = Math.max(cutout.getWaterfallInsets().bottom,
findCutoutInsetForSide(displaySize, cutout.getBoundingRectBottom(),
Gravity.BOTTOM));
return new Rect(leftInset, topInset, rightInset, bottomInset);
}
private static int findCutoutInsetForSide(Size display, Rect boundingRect, int gravity) {
if (boundingRect.isEmpty()) {
return 0;
}
int inset = 0;
switch (gravity) {
case Gravity.TOP:
return Math.max(inset, boundingRect.bottom);
case Gravity.BOTTOM:
return Math.max(inset, display.getHeight() - boundingRect.top);
case Gravity.LEFT:
return Math.max(inset, boundingRect.right);
case Gravity.RIGHT:
return Math.max(inset, display.getWidth() - boundingRect.left);
default:
throw new IllegalArgumentException("unknown gravity: " + gravity);
}
}
public DisplayCutout getDisplayCutout() {
return mInner;
}

View File

@@ -1,163 +0,0 @@
/*
* Copyright (C) 2018 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 com.android.server.wm.utils;
import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static com.android.server.wm.utils.DisplayRotationUtil.getBoundIndexFromRotation;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import org.junit.Test;
/**
* Tests for {@link DisplayRotationUtil}
*
* Build/Install/Run:
* atest WmTests:DisplayRotationUtilTest
*/
@SmallTest
@Presubmit
public class DisplayRotationUtilTest {
private static final Rect ZERO_RECT = new Rect();
@Test
public void testGetBoundIndexFromRotation_rot0() {
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_LEFT, ROTATION_0),
equalTo(BOUNDS_POSITION_LEFT));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_TOP, ROTATION_0),
equalTo(BOUNDS_POSITION_TOP));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_RIGHT, ROTATION_0),
equalTo(BOUNDS_POSITION_RIGHT));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_BOTTOM, ROTATION_0),
equalTo(BOUNDS_POSITION_BOTTOM));
}
@Test
public void testGetBoundIndexFromRotation_rot90() {
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_LEFT, ROTATION_90),
equalTo(BOUNDS_POSITION_BOTTOM));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_TOP, ROTATION_90),
equalTo(BOUNDS_POSITION_LEFT));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_RIGHT, ROTATION_90),
equalTo(BOUNDS_POSITION_TOP));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_BOTTOM, ROTATION_90),
equalTo(BOUNDS_POSITION_RIGHT));
}
@Test
public void testGetBoundIndexFromRotation_rot180() {
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_LEFT, ROTATION_180),
equalTo(BOUNDS_POSITION_RIGHT));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_TOP, ROTATION_180),
equalTo(BOUNDS_POSITION_BOTTOM));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_RIGHT, ROTATION_180),
equalTo(BOUNDS_POSITION_LEFT));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_BOTTOM, ROTATION_180),
equalTo(BOUNDS_POSITION_TOP));
}
@Test
public void testGetBoundIndexFromRotation_rot270() {
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_LEFT, ROTATION_270),
equalTo(BOUNDS_POSITION_TOP));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_TOP, ROTATION_270),
equalTo(BOUNDS_POSITION_RIGHT));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_RIGHT, ROTATION_270),
equalTo(BOUNDS_POSITION_BOTTOM));
assertThat(getBoundIndexFromRotation(BOUNDS_POSITION_BOTTOM, ROTATION_270),
equalTo(BOUNDS_POSITION_LEFT));
}
@Test
public void testGetRotatedBounds_top_rot0() {
DisplayRotationUtil util = new DisplayRotationUtil();
Rect[] bounds = new Rect[] {ZERO_RECT, new Rect(50, 0, 150, 10), ZERO_RECT, ZERO_RECT};
assertThat(util.getRotatedBounds(bounds, ROTATION_0, 200, 300),
equalTo(bounds));
}
@Test
public void testGetRotatedBounds_top_rot90() {
DisplayRotationUtil util = new DisplayRotationUtil();
Rect[] bounds = new Rect[] {ZERO_RECT, new Rect(50, 0, 150, 10), ZERO_RECT, ZERO_RECT};
assertThat(util.getRotatedBounds(bounds, ROTATION_90, 200, 300),
equalTo(new Rect[] {new Rect(0, 50, 10, 150), ZERO_RECT, ZERO_RECT, ZERO_RECT}));
}
@Test
public void testGetRotatedBounds_top_rot180() {
DisplayRotationUtil util = new DisplayRotationUtil();
Rect[] bounds = new Rect[] {ZERO_RECT, new Rect(50, 0, 150, 10), ZERO_RECT, ZERO_RECT};
assertThat(util.getRotatedBounds(bounds, ROTATION_180, 200, 300),
equalTo(new Rect[] {ZERO_RECT, ZERO_RECT, ZERO_RECT, new Rect(50, 290, 150, 300)}));
}
@Test
public void testGetRotatedBounds_top_rot270() {
DisplayRotationUtil util = new DisplayRotationUtil();
Rect[] bounds = new Rect[] {ZERO_RECT, new Rect(50, 0, 150, 10), ZERO_RECT, ZERO_RECT};
assertThat(util.getRotatedBounds(bounds, ROTATION_270, 200, 300),
equalTo(new Rect[] {ZERO_RECT, ZERO_RECT, new Rect(290, 50, 300, 150), ZERO_RECT}));
}
@Test
public void testGetRotatedBounds_left_rot0() {
DisplayRotationUtil util = new DisplayRotationUtil();
Rect[] bounds = new Rect[] {new Rect(0, 50, 10, 150), ZERO_RECT, ZERO_RECT, ZERO_RECT};
assertThat(util.getRotatedBounds(bounds, ROTATION_0, 300, 200),
equalTo(bounds));
}
@Test
public void testGetRotatedBounds_left_rot90() {
DisplayRotationUtil util = new DisplayRotationUtil();
Rect[] bounds = new Rect[] {new Rect(0, 50, 10, 150), ZERO_RECT, ZERO_RECT, ZERO_RECT};
assertThat(util.getRotatedBounds(bounds, ROTATION_90, 300, 200),
equalTo(new Rect[] {ZERO_RECT, ZERO_RECT, ZERO_RECT, new Rect(50, 290, 150, 300)}));
}
@Test
public void testGetRotatedBounds_left_rot180() {
DisplayRotationUtil util = new DisplayRotationUtil();
Rect[] bounds = new Rect[] {new Rect(0, 50, 10, 150), ZERO_RECT, ZERO_RECT, ZERO_RECT};
assertThat(util.getRotatedBounds(bounds, ROTATION_180, 300, 200),
equalTo(new Rect[] {ZERO_RECT, ZERO_RECT, new Rect(290, 50, 300, 150), ZERO_RECT}));
}
@Test
public void testGetRotatedBounds_left_rot270() {
DisplayRotationUtil util = new DisplayRotationUtil();
Rect[] bounds = new Rect[] {new Rect(0, 50, 10, 150), ZERO_RECT, ZERO_RECT, ZERO_RECT};
assertThat(util.getRotatedBounds(bounds, ROTATION_270, 300, 200),
equalTo(new Rect[] {ZERO_RECT, new Rect(50, 0, 150, 10), ZERO_RECT, ZERO_RECT}));
}
}