Loading services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java +31 −11 Original line number Diff line number Diff line Loading @@ -480,6 +480,15 @@ class AppCompatLetterboxPolicy { private final Point mLetterboxPosition = new Point(); private boolean mRunning; // The model needs to store the bounds for the multiple surfaces which will be // created in Shell anyway. private final Rect mLeftBounds = new Rect(); private final Rect mTopBounds = new Rect(); private final Rect mRightBounds = new Rect(); private final Rect mBottomBounds = new Rect(); private final Rect[] mSurfacesBounds = new Rect[]{mLeftBounds, mTopBounds, mRightBounds, mBottomBounds}; @Override public void layoutLetterboxIfNeeded(@NonNull WindowState w) { mRunning = true; Loading @@ -488,6 +497,7 @@ class AppCompatLetterboxPolicy { calculateLetterboxInnerBounds(mActivityRecord, w, mInnerBounds); mActivityRecord.mAppCompatController.getReachabilityPolicy() .setLetterboxInnerBoundsSupplier(() -> mInnerBounds); updateSurfacesBounds(); } @Override Loading Loading @@ -528,10 +538,10 @@ class AppCompatLetterboxPolicy { public Rect getLetterboxInsets() { if (isRunning()) { return new Rect( Math.max(0, mInnerBounds.left - mOuterBounds.left), Math.max(0, mOuterBounds.top - mInnerBounds.top), Math.max(0, mOuterBounds.right - mInnerBounds.right), Math.max(0, mInnerBounds.bottom - mOuterBounds.bottom) Math.max(0, mLeftBounds.width()), Math.max(0, mTopBounds.height()), Math.max(0, mRightBounds.width()), Math.max(0, mBottomBounds.height()) ); } return new Rect(); Loading Loading @@ -570,15 +580,25 @@ class AppCompatLetterboxPolicy { start(winHint); } /** * @return {@code true} if bar shown within a given rectangle is allowed to be fully * transparent when the current activity is displayed. */ @Override public boolean isFullyTransparentBarAllowed(@NonNull Rect rect) { // TODO(b/374921442) Handle Transparent Activities Letterboxing in Shell. // At the moment Shell handles letterbox with a single surface. This would make // notIntersectsOrFullyContains() to return false in the existing Letterbox // implementation. // Note: Previous implementation is // !isRunning() || mLetterbox.notIntersectsOrFullyContains(rect); return !isRunning(); return !isRunning() || AppCompatLetterboxUtils.fullyContainsOrNotIntersects(rect, mSurfacesBounds); } private void updateSurfacesBounds() { mTopBounds.set(mOuterBounds.left, mOuterBounds.top, mOuterBounds.right, mInnerBounds.top); mLeftBounds.set(mOuterBounds.left, mOuterBounds.top, mInnerBounds.left, mOuterBounds.bottom); mRightBounds.set(mInnerBounds.right, mOuterBounds.top, mOuterBounds.right, mOuterBounds.bottom); mBottomBounds.set(mOuterBounds.left, mInnerBounds.bottom, mOuterBounds.right, mOuterBounds.bottom); } } } services/core/java/com/android/server/wm/AppCompatLetterboxUtils.java +27 −0 Original line number Diff line number Diff line Loading @@ -99,4 +99,31 @@ class AppCompatLetterboxUtils { outInnerBounds.set( transparentPolicy.isRunning() ? activity.getBounds() : window.getFrame()); } /** * Returns {@code true} if the letterbox does not overlap with the bar, or the letterbox can * fully cover the window frame. * * @param rect The area of the window frame. * @param boundsToCheck A Collection of bounds to check. */ static boolean fullyContainsOrNotIntersects(@NonNull Rect rect, @NonNull Rect[] boundsToCheck) { // TODO(b/409293223): Make this algorithm simpler and more efficient. int emptyCount = 0; int noOverlappingCount = 0; for (Rect bounds : boundsToCheck) { if (bounds.isEmpty()) { // empty letterbox emptyCount++; } else if (!Rect.intersects(bounds, rect)) { // no overlapping noOverlappingCount++; } else if (bounds.contains(rect)) { // overlapping and covered return true; } } return (emptyCount + noOverlappingCount) == boundsToCheck.length; } } services/core/java/com/android/server/wm/Letterbox.java +5 −16 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ public class Letterbox { // for overlaping an app window and letterbox surfaces. private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow"); private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom }; private final Rect[] mTmpSurfacesRect = new Rect[4]; @NonNull private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy; Loading Loading @@ -138,23 +139,11 @@ public class Letterbox { * * @param rect The area of the window frame. */ boolean notIntersectsOrFullyContains(Rect rect) { int emptyCount = 0; int noOverlappingCount = 0; for (LetterboxSurface surface : mSurfaces) { final Rect surfaceRect = surface.mLayoutFrameGlobal; if (surfaceRect.isEmpty()) { // empty letterbox emptyCount++; } else if (!Rect.intersects(surfaceRect, rect)) { // no overlapping noOverlappingCount++; } else if (surfaceRect.contains(rect)) { // overlapping and covered return true; } boolean notIntersectsOrFullyContains(@NonNull Rect rect) { for (int i = 0; i < mTmpSurfacesRect.length; i++) { mTmpSurfacesRect[i] = mSurfaces[i].mLayoutFrameGlobal; } return (emptyCount + noOverlappingCount) == mSurfaces.length; return AppCompatLetterboxUtils.fullyContainsOrNotIntersects(rect, mTmpSurfacesRect); } /** Loading services/tests/wmtests/src/com/android/server/wm/AppCompatLetterboxUtilsTest.java +139 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxInnerBounds; import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxOuterBounds; import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxPosition; import static com.android.server.wm.AppCompatLetterboxUtils.fullyContainsOrNotIntersects; import static org.mockito.Mockito.mock; Loading Loading @@ -143,6 +144,123 @@ public class AppCompatLetterboxUtilsTest extends WindowTestsBase { }); } @Test public void testNoBoundsToCheck() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testEmptyBoundsToCheck() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(30, 30, 40, 40)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testContainsEmptyRect() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect()); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_NoIntersection() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_FullyContains() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(-5, -5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_PartiallyIntersects() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(5, 5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ false); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsNoIntersection() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(-20, -20, -10, -10)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsWithOneContaining() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(-5, -5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsWithOneIntersecting() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(5, 5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ false); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsWithEmptyAndNoIntersection() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(), new Rect(10, 10, 20, 20)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsWithEmptyAndContaining() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(), new Rect(-5, -5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_EmptyRectToCheck() { runTestScenario((robot) -> { robot.setWindowFrameArea(new Rect()); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(-5, -5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_EmptyRectToCheckAndEmptyBounds() { runTestScenario((robot) -> { robot.setWindowFrameArea(new Rect()); robot.setBoundsToCheck(new Rect()); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } /** * Runs a test scenario providing a Robot. */ Loading @@ -157,6 +275,10 @@ public class AppCompatLetterboxUtilsTest extends WindowTestsBase { private final Rect mInnerBound = new Rect(); private final Rect mOuterBound = new Rect(); private final Rect mWindowFrameArea = new Rect(); private Rect[] mBoundsToCheck; @NonNull private final WindowState mWindowState; Loading Loading @@ -188,6 +310,18 @@ public class AppCompatLetterboxUtilsTest extends WindowTestsBase { doReturn(frame).when(mWindowState).getFrame(); } void setWindowFrameArea(int left, int top, int right, int bottom) { mWindowFrameArea.set(left, top, right, bottom); } void setWindowFrameArea(@NonNull Rect windowFrameArea) { mWindowFrameArea.set(windowFrameArea); } void setBoundsToCheck(@NonNull Rect... boundsToCheck) { mBoundsToCheck = boundsToCheck; } void getLetterboxPosition() { calculateLetterboxPosition(activity().top(), mPosition); } Loading Loading @@ -235,5 +369,10 @@ public class AppCompatLetterboxUtilsTest extends WindowTestsBase { Assert.assertEquals(mInnerBound, activity().top().getBounds()); } void checkFullyContainsOrNotIntersects(boolean expected) { Assert.assertEquals(expected, fullyContainsOrNotIntersects(mWindowFrameArea, mBoundsToCheck)); } } } Loading
services/core/java/com/android/server/wm/AppCompatLetterboxPolicy.java +31 −11 Original line number Diff line number Diff line Loading @@ -480,6 +480,15 @@ class AppCompatLetterboxPolicy { private final Point mLetterboxPosition = new Point(); private boolean mRunning; // The model needs to store the bounds for the multiple surfaces which will be // created in Shell anyway. private final Rect mLeftBounds = new Rect(); private final Rect mTopBounds = new Rect(); private final Rect mRightBounds = new Rect(); private final Rect mBottomBounds = new Rect(); private final Rect[] mSurfacesBounds = new Rect[]{mLeftBounds, mTopBounds, mRightBounds, mBottomBounds}; @Override public void layoutLetterboxIfNeeded(@NonNull WindowState w) { mRunning = true; Loading @@ -488,6 +497,7 @@ class AppCompatLetterboxPolicy { calculateLetterboxInnerBounds(mActivityRecord, w, mInnerBounds); mActivityRecord.mAppCompatController.getReachabilityPolicy() .setLetterboxInnerBoundsSupplier(() -> mInnerBounds); updateSurfacesBounds(); } @Override Loading Loading @@ -528,10 +538,10 @@ class AppCompatLetterboxPolicy { public Rect getLetterboxInsets() { if (isRunning()) { return new Rect( Math.max(0, mInnerBounds.left - mOuterBounds.left), Math.max(0, mOuterBounds.top - mInnerBounds.top), Math.max(0, mOuterBounds.right - mInnerBounds.right), Math.max(0, mInnerBounds.bottom - mOuterBounds.bottom) Math.max(0, mLeftBounds.width()), Math.max(0, mTopBounds.height()), Math.max(0, mRightBounds.width()), Math.max(0, mBottomBounds.height()) ); } return new Rect(); Loading Loading @@ -570,15 +580,25 @@ class AppCompatLetterboxPolicy { start(winHint); } /** * @return {@code true} if bar shown within a given rectangle is allowed to be fully * transparent when the current activity is displayed. */ @Override public boolean isFullyTransparentBarAllowed(@NonNull Rect rect) { // TODO(b/374921442) Handle Transparent Activities Letterboxing in Shell. // At the moment Shell handles letterbox with a single surface. This would make // notIntersectsOrFullyContains() to return false in the existing Letterbox // implementation. // Note: Previous implementation is // !isRunning() || mLetterbox.notIntersectsOrFullyContains(rect); return !isRunning(); return !isRunning() || AppCompatLetterboxUtils.fullyContainsOrNotIntersects(rect, mSurfacesBounds); } private void updateSurfacesBounds() { mTopBounds.set(mOuterBounds.left, mOuterBounds.top, mOuterBounds.right, mInnerBounds.top); mLeftBounds.set(mOuterBounds.left, mOuterBounds.top, mInnerBounds.left, mOuterBounds.bottom); mRightBounds.set(mInnerBounds.right, mOuterBounds.top, mOuterBounds.right, mOuterBounds.bottom); mBottomBounds.set(mOuterBounds.left, mInnerBounds.bottom, mOuterBounds.right, mOuterBounds.bottom); } } }
services/core/java/com/android/server/wm/AppCompatLetterboxUtils.java +27 −0 Original line number Diff line number Diff line Loading @@ -99,4 +99,31 @@ class AppCompatLetterboxUtils { outInnerBounds.set( transparentPolicy.isRunning() ? activity.getBounds() : window.getFrame()); } /** * Returns {@code true} if the letterbox does not overlap with the bar, or the letterbox can * fully cover the window frame. * * @param rect The area of the window frame. * @param boundsToCheck A Collection of bounds to check. */ static boolean fullyContainsOrNotIntersects(@NonNull Rect rect, @NonNull Rect[] boundsToCheck) { // TODO(b/409293223): Make this algorithm simpler and more efficient. int emptyCount = 0; int noOverlappingCount = 0; for (Rect bounds : boundsToCheck) { if (bounds.isEmpty()) { // empty letterbox emptyCount++; } else if (!Rect.intersects(bounds, rect)) { // no overlapping noOverlappingCount++; } else if (bounds.contains(rect)) { // overlapping and covered return true; } } return (emptyCount + noOverlappingCount) == boundsToCheck.length; } }
services/core/java/com/android/server/wm/Letterbox.java +5 −16 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ public class Letterbox { // for overlaping an app window and letterbox surfaces. private final LetterboxSurface mFullWindowSurface = new LetterboxSurface("fullWindow"); private final LetterboxSurface[] mSurfaces = { mLeft, mTop, mRight, mBottom }; private final Rect[] mTmpSurfacesRect = new Rect[4]; @NonNull private final AppCompatReachabilityPolicy mAppCompatReachabilityPolicy; Loading Loading @@ -138,23 +139,11 @@ public class Letterbox { * * @param rect The area of the window frame. */ boolean notIntersectsOrFullyContains(Rect rect) { int emptyCount = 0; int noOverlappingCount = 0; for (LetterboxSurface surface : mSurfaces) { final Rect surfaceRect = surface.mLayoutFrameGlobal; if (surfaceRect.isEmpty()) { // empty letterbox emptyCount++; } else if (!Rect.intersects(surfaceRect, rect)) { // no overlapping noOverlappingCount++; } else if (surfaceRect.contains(rect)) { // overlapping and covered return true; } boolean notIntersectsOrFullyContains(@NonNull Rect rect) { for (int i = 0; i < mTmpSurfacesRect.length; i++) { mTmpSurfacesRect[i] = mSurfaces[i].mLayoutFrameGlobal; } return (emptyCount + noOverlappingCount) == mSurfaces.length; return AppCompatLetterboxUtils.fullyContainsOrNotIntersects(rect, mTmpSurfacesRect); } /** Loading
services/tests/wmtests/src/com/android/server/wm/AppCompatLetterboxUtilsTest.java +139 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxInnerBounds; import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxOuterBounds; import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxPosition; import static com.android.server.wm.AppCompatLetterboxUtils.fullyContainsOrNotIntersects; import static org.mockito.Mockito.mock; Loading Loading @@ -143,6 +144,123 @@ public class AppCompatLetterboxUtilsTest extends WindowTestsBase { }); } @Test public void testNoBoundsToCheck() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testEmptyBoundsToCheck() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(30, 30, 40, 40)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testContainsEmptyRect() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect()); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_NoIntersection() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_FullyContains() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(-5, -5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_PartiallyIntersects() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(5, 5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ false); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsNoIntersection() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(-20, -20, -10, -10)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsWithOneContaining() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(-5, -5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsWithOneIntersecting() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(5, 5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ false); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsWithEmptyAndNoIntersection() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(), new Rect(10, 10, 20, 20)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_MultipleBoundsWithEmptyAndContaining() { runTestScenario((robot) -> { robot.setWindowFrameArea(/* left */ 0, /* top */ 0, /* right */ 10, /* bottom */ 10); robot.setBoundsToCheck(new Rect(), new Rect(-5, -5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_EmptyRectToCheck() { runTestScenario((robot) -> { robot.setWindowFrameArea(new Rect()); robot.setBoundsToCheck(new Rect(10, 10, 20, 20), new Rect(-5, -5, 15, 15)); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } @Test public void testCheckFullyContainsOrNotIntersects_EmptyRectToCheckAndEmptyBounds() { runTestScenario((robot) -> { robot.setWindowFrameArea(new Rect()); robot.setBoundsToCheck(new Rect()); robot.checkFullyContainsOrNotIntersects(/* expected */ true); }); } /** * Runs a test scenario providing a Robot. */ Loading @@ -157,6 +275,10 @@ public class AppCompatLetterboxUtilsTest extends WindowTestsBase { private final Rect mInnerBound = new Rect(); private final Rect mOuterBound = new Rect(); private final Rect mWindowFrameArea = new Rect(); private Rect[] mBoundsToCheck; @NonNull private final WindowState mWindowState; Loading Loading @@ -188,6 +310,18 @@ public class AppCompatLetterboxUtilsTest extends WindowTestsBase { doReturn(frame).when(mWindowState).getFrame(); } void setWindowFrameArea(int left, int top, int right, int bottom) { mWindowFrameArea.set(left, top, right, bottom); } void setWindowFrameArea(@NonNull Rect windowFrameArea) { mWindowFrameArea.set(windowFrameArea); } void setBoundsToCheck(@NonNull Rect... boundsToCheck) { mBoundsToCheck = boundsToCheck; } void getLetterboxPosition() { calculateLetterboxPosition(activity().top(), mPosition); } Loading Loading @@ -235,5 +369,10 @@ public class AppCompatLetterboxUtilsTest extends WindowTestsBase { Assert.assertEquals(mInnerBound, activity().top().getBounds()); } void checkFullyContainsOrNotIntersects(boolean expected) { Assert.assertEquals(expected, fullyContainsOrNotIntersects(mWindowFrameArea, mBoundsToCheck)); } } }