Letterboxing: ensure bar contrast
Ensures that any bars that draw over a letterbox draw their own
background such that they always have contrast.
This fixes an issue, where if a light status / navigation bar app was
letterboxed, the bar would still draw dark icons over the now black
letterbox, making the icons unreadable.
To do so, splits the letterbox into a layout and an apply surface
changes phase.
Change-Id: Ia8afa3386d75d9a72434d701b867c3ebc35cc36f
Fixes: 72696928
Test: Open a letterboxed app with a white navigation bar, verify it is visible
Test: ApiDemos > App > Activity > Max Aspect Ratio > 1:1, verify navbar is visible
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 1f71b8f..c15893b 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -24,7 +24,6 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.SurfaceControl.HIDDEN;
import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
@@ -712,7 +711,7 @@
if (destroyedSomething) {
final DisplayContent dc = getDisplayContent();
dc.assignWindowLayers(true /*setLayoutNeeded*/);
- updateLetterbox(null);
+ updateLetterboxSurface(null);
}
}
@@ -979,7 +978,7 @@
void removeChild(WindowState child) {
super.removeChild(child);
checkKeyguardFlagsChanged();
- updateLetterbox(child);
+ updateLetterboxSurface(child);
}
private boolean waitingForReplacement() {
@@ -1470,7 +1469,7 @@
return isInterestingAndDrawn;
}
- void updateLetterbox(WindowState winHint) {
+ void layoutLetterbox(WindowState winHint) {
final WindowState w = findMainWindow();
if (w != winHint && winHint != null && w != null) {
return;
@@ -1481,19 +1480,20 @@
if (mLetterbox == null) {
mLetterbox = new Letterbox(() -> makeChildSurface(null));
}
- mLetterbox.setDimensions(mPendingTransaction, getParent().getBounds(), w.mFrame);
+ mLetterbox.layout(getParent().getBounds(), w.mFrame);
} else if (mLetterbox != null) {
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- // Make sure we have a transaction here, in case we're called outside of a transaction.
- // This does not use mPendingTransaction, because SurfaceAnimator uses a
- // global transaction in onAnimationEnd.
- SurfaceControl.openTransaction();
- try {
- mLetterbox.hide(t);
- } finally {
- SurfaceControl.mergeToGlobalTransaction(t);
- SurfaceControl.closeTransaction();
- }
+ mLetterbox.hide();
+ }
+ }
+
+ void updateLetterboxSurface(WindowState winHint) {
+ final WindowState w = findMainWindow();
+ if (w != winHint && winHint != null && w != null) {
+ return;
+ }
+ layoutLetterbox(winHint);
+ if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
+ mLetterbox.applySurfaceChanges(mPendingTransaction);
}
}
@@ -2156,4 +2156,12 @@
return new Rect();
}
}
+
+ /**
+ * @eturn true if there is a letterbox and any part of that letterbox overlaps with
+ * the given {@code rect}.
+ */
+ boolean isLetterboxOverlappingWith(Rect rect) {
+ return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
+ }
}