summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java7
-rw-r--r--services/core/java/com/android/server/wm/BarController.java17
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java33
-rw-r--r--services/core/java/com/android/server/wm/Letterbox.java33
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java99
7 files changed, 176 insertions, 30 deletions
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 8868a6c2e6d8..b3e162d473db 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -396,14 +396,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();
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 40e558c09965..3e9377ed0664 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1395,6 +1395,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
+ * @see Letterbox#notIntersectsOrFullyContains(Rect)
+ */
+ boolean letterboxNotIntersectsOrFullyContains(Rect rect) {
+ return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect);
+ }
+
+ /**
* @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
* the given {@code rect}.
*/
diff --git a/services/core/java/com/android/server/wm/BarController.java b/services/core/java/com/android/server/wm/BarController.java
index 123fb6c9d8e3..c1447553ba31 100644
--- a/services/core/java/com/android/server/wm/BarController.java
+++ b/services/core/java/com/android/server/wm/BarController.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static com.android.server.wm.BarControllerProto.STATE;
import static com.android.server.wm.BarControllerProto.TRANSIENT_STATE;
+import android.annotation.NonNull;
import android.app.StatusBarManager;
import android.graphics.Rect;
import android.os.Handler;
@@ -169,13 +170,23 @@ public class BarController {
return vis;
}
+ private Rect getContentFrame(@NonNull WindowState win) {
+ final Rect rotatedContentFrame = win.mToken.getFixedRotationBarContentFrame(mWindowType);
+ return rotatedContentFrame != null ? rotatedContentFrame : mContentFrame;
+ }
+
+ boolean isLightAppearanceAllowed(WindowState win) {
+ if (win == null) {
+ return true;
+ }
+ return !win.isLetterboxedOverlappingWith(getContentFrame(win));
+ }
+
boolean isTransparentAllowed(WindowState win) {
if (win == null) {
return true;
}
- final Rect rotatedContentFrame = win.mToken.getFixedRotationBarContentFrame(mWindowType);
- final Rect contentFrame = rotatedContentFrame != null ? rotatedContentFrame : mContentFrame;
- return !win.isLetterboxedOverlappingWith(contentFrame);
+ return win.letterboxNotIntersectsOrFullyContains(getContentFrame(win));
}
boolean setBarShowingLw(final boolean show) {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 68051ab59599..605d0b2cc127 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -3437,17 +3437,22 @@ public class DisplayPolicy {
WindowState opaqueOrDimming) {
final boolean onKeyguard = isKeyguardShowing() && !isKeyguardOccluded();
final WindowState statusColorWin = onKeyguard ? mNotificationShade : opaqueOrDimming;
- if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
- // If the top fullscreen-or-dimming window is also the top fullscreen, respect
- // its light flag.
- appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
- final int legacyAppearance = InsetsFlags.getAppearance(
- PolicyControl.getSystemUiVisibility(statusColorWin, null));
- appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance)
- & APPEARANCE_LIGHT_STATUS_BARS;
- } else if (statusColorWin != null && statusColorWin.isDimming()) {
- // Otherwise if it's dimming, clear the light flag.
- appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
+ if (statusColorWin != null) {
+ if (statusColorWin == opaque || onKeyguard) {
+ // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+ // its light flag.
+ appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
+ final int legacyAppearance = InsetsFlags.getAppearance(
+ PolicyControl.getSystemUiVisibility(statusColorWin, null));
+ appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance)
+ & APPEARANCE_LIGHT_STATUS_BARS;
+ } else if (statusColorWin.isDimming()) {
+ // Otherwise if it's dimming, clear the light flag.
+ appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
+ }
+ if (!mStatusBarController.isLightAppearanceAllowed(statusColorWin)) {
+ appearance &= ~APPEARANCE_LIGHT_STATUS_BARS;
+ }
}
return appearance;
}
@@ -3512,8 +3517,7 @@ public class DisplayPolicy {
return vis;
}
- @VisibleForTesting
- static int updateLightNavigationBarAppearanceLw(int appearance, WindowState opaque,
+ private int updateLightNavigationBarAppearanceLw(int appearance, WindowState opaque,
WindowState opaqueOrDimming, WindowState imeWindow, WindowState navColorWin) {
if (navColorWin != null) {
@@ -3526,6 +3530,9 @@ public class DisplayPolicy {
// Clear the light flag for dimming window.
appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
}
+ if (!mNavigationBarController.isLightAppearanceAllowed(navColorWin)) {
+ appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
+ }
}
return appearance;
}
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index a685886da032..28dcbcdf3cc7 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -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,6 +101,31 @@ public class Letterbox {
}
/**
+ * 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.
+ */
+ 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;
+ }
+ }
+ return (emptyCount + noOverlappingCount) == mSurfaces.length;
+ }
+
+ /**
* Returns true if any part of the letterbox overlaps with the given {@code rect}.
*/
public boolean isOverlappingWith(Rect rect) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 26bcf3b285ec..1f2a8f052a3e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3797,7 +3797,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mActivityRecord.getBounds().equals(mTmpRect);
}
- @Override
+ /**
+ * @see Letterbox#notIntersectsOrFullyContains(Rect)
+ */
+ boolean letterboxNotIntersectsOrFullyContains(Rect rect) {
+ return mActivityRecord == null
+ || mActivityRecord.letterboxNotIntersectsOrFullyContains(rect);
+ }
+
public boolean isLetterboxedOverlappingWith(Rect rect) {
return mActivityRecord != null && mActivityRecord.isLetterboxOverlappingWith(rect);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index bf84aecdb6a0..2f3004bf6832 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -16,8 +16,8 @@
package com.android.server.wm;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
@@ -60,6 +60,103 @@ public class LetterboxTest {
assertTrue(mLetterbox.isOverlappingWith(new Rect(0, 0, 1, 1)));
}
+ 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 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
public void testSurfaceOrigin_applied() {
mLetterbox.layout(new Rect(0, 0, 10, 10), new Rect(0, 1, 10, 10), new Point(1000, 2000));