Allow bar to be transparent if letterbox contains bar
When top window request fullscreen and device contain a real cutout and the layoutInDisplayCutout is default or never, a letterbox will be created for this activity, which cause BarController#isTransparentAllowed return false so the status bar cannot be transparent, the bar will shows a black background during hidding animation. For a better animating effect, allow the bar to be transparent if the letterbox is fully covered the bar. Also modify the layout area of each letterbox surface, so it can be more convenient to do geometric check when multiple cutout existing. Bug: 152273579 Test: manualy verify no black background shows on status bar when opening fullscreen app. Test: atest DisplayPolicyTests LetterboxTest Change-Id: I1f458394a8c6a2ac53a461b6819a026090d62898
This commit is contained in:
@@ -395,14 +395,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the window has a letterbox and any part of that letterbox overlaps with
|
||||
* the given {@code rect}.
|
||||
*/
|
||||
default boolean isLetterboxedOverlappingWith(Rect rect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @return the current windowing mode of this window. */
|
||||
int getWindowingMode();
|
||||
|
||||
|
||||
@@ -1414,11 +1414,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
|
||||
* the given {@code rect}.
|
||||
* @see Letterbox#notIntersectsOrFullyContains(Rect)
|
||||
*/
|
||||
boolean isLetterboxOverlappingWith(Rect rect) {
|
||||
return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
|
||||
boolean letterboxNotIntersectsOrFullyContains(Rect rect) {
|
||||
return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect);
|
||||
}
|
||||
|
||||
static class Token extends IApplicationToken.Stub {
|
||||
|
||||
@@ -168,7 +168,7 @@ public class BarController {
|
||||
}
|
||||
|
||||
boolean isTransparentAllowed(WindowState win) {
|
||||
return win == null || !win.isLetterboxedOverlappingWith(mContentFrame);
|
||||
return win == null || win.letterboxNotIntersectsOrFullyContains(mContentFrame);
|
||||
}
|
||||
|
||||
boolean setBarShowingLw(final boolean show) {
|
||||
|
||||
@@ -77,10 +77,10 @@ public class Letterbox {
|
||||
mOuter.set(outer);
|
||||
mInner.set(inner);
|
||||
|
||||
mTop.layout(outer.left, outer.top, inner.right, inner.top, surfaceOrigin);
|
||||
mLeft.layout(outer.left, inner.top, inner.left, outer.bottom, surfaceOrigin);
|
||||
mBottom.layout(inner.left, inner.bottom, outer.right, outer.bottom, surfaceOrigin);
|
||||
mRight.layout(inner.right, outer.top, outer.right, inner.bottom, surfaceOrigin);
|
||||
mTop.layout(outer.left, outer.top, outer.right, inner.top, surfaceOrigin);
|
||||
mLeft.layout(outer.left, outer.top, inner.left, outer.bottom, surfaceOrigin);
|
||||
mBottom.layout(outer.left, inner.bottom, outer.right, outer.bottom, surfaceOrigin);
|
||||
mRight.layout(inner.right, outer.top, outer.right, outer.bottom, surfaceOrigin);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,17 +101,29 @@ public class Letterbox {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any part of the letterbox overlaps with the given {@code rect}.
|
||||
* 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.
|
||||
*/
|
||||
public boolean isOverlappingWith(Rect rect) {
|
||||
boolean notIntersectsOrFullyContains(Rect rect) {
|
||||
int emptyCount = 0;
|
||||
int noOverlappingCount = 0;
|
||||
for (LetterboxSurface surface : mSurfaces) {
|
||||
if (surface.isOverlappingWith(rect)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return (emptyCount + noOverlappingCount) == mSurfaces.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the letterbox.
|
||||
*
|
||||
@@ -282,17 +294,6 @@ public class Letterbox {
|
||||
return Math.max(0, mLayoutFrameGlobal.height());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the given {@code rect} overlaps with this letterbox piece.
|
||||
* @param rect the area to check for overlap in global coordinates
|
||||
*/
|
||||
public boolean isOverlappingWith(Rect rect) {
|
||||
if (mLayoutFrameGlobal.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return Rect.intersects(rect, mLayoutFrameGlobal);
|
||||
}
|
||||
|
||||
public void applySurfaceChanges(SurfaceControl.Transaction t) {
|
||||
if (mSurfaceFrameRelative.equals(mLayoutFrameRelative)) {
|
||||
// Nothing changed.
|
||||
|
||||
@@ -3660,9 +3660,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
return mActivityRecord.getBounds().equals(mTmpRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLetterboxedOverlappingWith(Rect rect) {
|
||||
return mActivityRecord != null && mActivityRecord.isLetterboxOverlappingWith(rect);
|
||||
/**
|
||||
* @see Letterbox#notIntersectsOrFullyContains(Rect)
|
||||
*/
|
||||
boolean letterboxNotIntersectsOrFullyContains(Rect rect) {
|
||||
return mActivityRecord == null
|
||||
|| mActivityRecord.letterboxNotIntersectsOrFullyContains(rect);
|
||||
}
|
||||
|
||||
boolean isDragResizeChanged() {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
@@ -53,10 +54,102 @@ public class LetterboxTest {
|
||||
mTransaction = spy(StubTransaction.class);
|
||||
}
|
||||
|
||||
private static final int TOP_BAR = 0x1;
|
||||
private static final int BOTTOM_BAR = 0x2;
|
||||
private static final int LEFT_BAR = 0x4;
|
||||
private static final int RIGHT_BAR = 0x8;
|
||||
|
||||
@Test
|
||||
public void testOverlappingWith_usesGlobalCoordinates() {
|
||||
mLetterbox.layout(new Rect(0, 0, 10, 50), new Rect(0, 2, 10, 45), new Point(1000, 2000));
|
||||
assertTrue(mLetterbox.isOverlappingWith(new Rect(0, 0, 1, 1)));
|
||||
public void testNotIntersectsOrFullyContains_usesGlobalCoordinates() {
|
||||
final Rect outer = new Rect(0, 0, 10, 50);
|
||||
final Point surfaceOrig = new Point(1000, 2000);
|
||||
|
||||
final Rect topBar = new Rect(0, 0, 10, 2);
|
||||
final Rect bottomBar = new Rect(0, 45, 10, 50);
|
||||
final Rect leftBar = new Rect(0, 0, 2, 50);
|
||||
final Rect rightBar = new Rect(8, 0, 10, 50);
|
||||
|
||||
final LetterboxLayoutVerifier verifier =
|
||||
new LetterboxLayoutVerifier(outer, surfaceOrig, mLetterbox);
|
||||
verifier.setBarRect(topBar, bottomBar, leftBar, rightBar);
|
||||
|
||||
// top
|
||||
verifier.setInner(0, 2, 10, 50).verifyPositions(TOP_BAR | BOTTOM_BAR, BOTTOM_BAR);
|
||||
// bottom
|
||||
verifier.setInner(0, 0, 10, 45).verifyPositions(TOP_BAR | BOTTOM_BAR, TOP_BAR);
|
||||
// left
|
||||
verifier.setInner(2, 0, 10, 50).verifyPositions(LEFT_BAR | RIGHT_BAR, RIGHT_BAR);
|
||||
// right
|
||||
verifier.setInner(0, 0, 8, 50).verifyPositions(LEFT_BAR | RIGHT_BAR, LEFT_BAR);
|
||||
// top + bottom
|
||||
verifier.setInner(0, 2, 10, 45).verifyPositions(TOP_BAR | BOTTOM_BAR, 0);
|
||||
// left + right
|
||||
verifier.setInner(2, 0, 8, 50).verifyPositions(LEFT_BAR | RIGHT_BAR, 0);
|
||||
// top + left
|
||||
verifier.setInner(2, 2, 10, 50).verifyPositions(TOP_BAR | LEFT_BAR, 0);
|
||||
// top + left + right
|
||||
verifier.setInner(2, 2, 8, 50).verifyPositions(TOP_BAR | LEFT_BAR | RIGHT_BAR, 0);
|
||||
// left + right + bottom
|
||||
verifier.setInner(2, 0, 8, 45).verifyPositions(LEFT_BAR | RIGHT_BAR | BOTTOM_BAR, 0);
|
||||
// all
|
||||
verifier.setInner(2, 2, 8, 45)
|
||||
.verifyPositions(TOP_BAR | BOTTOM_BAR | LEFT_BAR | RIGHT_BAR, 0);
|
||||
}
|
||||
|
||||
private static class LetterboxLayoutVerifier {
|
||||
final Rect mOuter;
|
||||
final Rect mInner = new Rect();
|
||||
final Point mSurfaceOrig;
|
||||
final Letterbox mLetterbox;
|
||||
final Rect mTempRect = new Rect();
|
||||
|
||||
final Rect mTop = new Rect();
|
||||
final Rect mBottom = new Rect();
|
||||
final Rect mLeft = new Rect();
|
||||
final Rect mRight = new Rect();
|
||||
|
||||
LetterboxLayoutVerifier(Rect outer, Point surfaceOrig, Letterbox letterbox) {
|
||||
mOuter = new Rect(outer);
|
||||
mSurfaceOrig = new Point(surfaceOrig);
|
||||
mLetterbox = letterbox;
|
||||
}
|
||||
|
||||
LetterboxLayoutVerifier setInner(int left, int top, int right, int bottom) {
|
||||
mInner.set(left, top, right, bottom);
|
||||
mLetterbox.layout(mOuter, mInner, mSurfaceOrig);
|
||||
return this;
|
||||
}
|
||||
|
||||
void setBarRect(Rect top, Rect bottom, Rect left, Rect right) {
|
||||
mTop.set(top);
|
||||
mBottom.set(bottom);
|
||||
mLeft.set(left);
|
||||
mRight.set(right);
|
||||
}
|
||||
|
||||
void verifyPositions(int allowedPos, int noOverlapPos) {
|
||||
assertEquals(mLetterbox.notIntersectsOrFullyContains(mTop),
|
||||
(allowedPos & TOP_BAR) != 0);
|
||||
assertEquals(mLetterbox.notIntersectsOrFullyContains(mBottom),
|
||||
(allowedPos & BOTTOM_BAR) != 0);
|
||||
assertEquals(mLetterbox.notIntersectsOrFullyContains(mLeft),
|
||||
(allowedPos & LEFT_BAR) != 0);
|
||||
assertEquals(mLetterbox.notIntersectsOrFullyContains(mRight),
|
||||
(allowedPos & RIGHT_BAR) != 0);
|
||||
|
||||
mTempRect.set(mTop.left, mTop.top, mTop.right, mTop.bottom + 1);
|
||||
assertEquals(mLetterbox.notIntersectsOrFullyContains(mTempRect),
|
||||
(noOverlapPos & TOP_BAR) != 0);
|
||||
mTempRect.set(mLeft.left, mLeft.top, mLeft.right + 1, mLeft.bottom);
|
||||
assertEquals(mLetterbox.notIntersectsOrFullyContains(mTempRect),
|
||||
(noOverlapPos & LEFT_BAR) != 0);
|
||||
mTempRect.set(mRight.left - 1, mRight.top, mRight.right, mRight.bottom);
|
||||
assertEquals(mLetterbox.notIntersectsOrFullyContains(mTempRect),
|
||||
(noOverlapPos & RIGHT_BAR) != 0);
|
||||
mTempRect.set(mBottom.left, mBottom.top - 1, mBottom.right, mBottom.bottom);
|
||||
assertEquals(mLetterbox.notIntersectsOrFullyContains(mTempRect),
|
||||
(noOverlapPos & BOTTOM_BAR) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user