summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/policy/BarController.java19
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java49
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java8
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java40
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java7
-rw-r--r--services/core/java/com/android/server/wm/Letterbox.java108
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java5
7 files changed, 161 insertions, 75 deletions
diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java
index c906705ae5a9..cf88bd5364a7 100644
--- a/services/core/java/com/android/server/policy/BarController.java
+++ b/services/core/java/com/android/server/policy/BarController.java
@@ -20,6 +20,7 @@ import static com.android.server.wm.proto.BarControllerProto.STATE;
import static com.android.server.wm.proto.BarControllerProto.TRANSIENT_STATE;
import android.app.StatusBarManager;
+import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
@@ -68,6 +69,7 @@ public class BarController {
private boolean mShowTransparent;
private boolean mSetUnHideFlagWhenNextTransparent;
private boolean mNoAnimationOnNextShow;
+ private final Rect mContentFrame = new Rect();
private OnBarVisibilityChangedListener mVisibilityChangeListener;
@@ -87,6 +89,15 @@ public class BarController {
mWin = win;
}
+ /**
+ * Sets the frame within which the bar will display its content.
+ *
+ * This is used to determine if letterboxes interfere with the display of such content.
+ */
+ public void setContentFrame(Rect frame) {
+ mContentFrame.set(frame);
+ }
+
public void setShowTransparent(boolean transparent) {
if (transparent != mShowTransparent) {
mShowTransparent = transparent;
@@ -135,7 +146,8 @@ public class BarController {
} else {
vis &= ~mTranslucentFlag;
}
- if ((fl & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
+ if ((fl & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+ && isTransparentAllowed(win)) {
vis |= mTransparentFlag;
} else {
vis &= ~mTransparentFlag;
@@ -148,6 +160,10 @@ public class BarController {
return vis;
}
+ boolean isTransparentAllowed(WindowState win) {
+ return win == null || !win.isLetterboxedOverlappingWith(mContentFrame);
+ }
+
public boolean setBarShowingLw(final boolean show) {
if (mWin == null) return false;
if (show && mTransientBarState == TRANSIENT_BAR_HIDING) {
@@ -328,6 +344,7 @@ public class BarController {
pw.println(StatusBarManager.windowStateToString(mState));
pw.print(prefix); pw.print(" "); pw.print("mTransientBar"); pw.print('=');
pw.println(transientBarStateToString(mTransientBarState));
+ pw.print(prefix); pw.print(" mContentFrame="); pw.println(mContentFrame);
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3cd79e1642dc..3cdb130d5efe 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4705,6 +4705,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
displayFrames.mStable.top = displayFrames.mUnrestricted.top
+ mStatusBarHeightForRotation[displayFrames.mRotation];
+ // Tell the bar controller where the collapsed status bar content is
+ mTmpRect.set(mStatusBar.getContentFrameLw());
+ mTmpRect.intersect(displayFrames.mDisplayCutoutSafe);
+ mTmpRect.top = mStatusBar.getContentFrameLw().top; // Ignore top display cutout inset
+ mTmpRect.bottom = displayFrames.mStable.top; // Use collapsed status bar size
+ mStatusBarController.setContentFrame(mTmpRect);
+
boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
boolean statusBarTranslucent = (sysui
& (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
@@ -4838,6 +4845,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe, mTmpNavigationFrame, dcf,
mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe,
displayFrames.mDisplayCutout);
+ mNavigationBarController.setContentFrame(mNavigationBar.getContentFrameLw());
+
if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
return mNavigationBarController.checkHiddenLw();
}
@@ -8025,11 +8034,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// If the top fullscreen-or-dimming window is also the top fullscreen, respect
// its light flag.
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- if (!statusColorWin.isLetterboxedForDisplayCutoutLw()) {
- // Only allow white status bar if the window was not letterboxed.
- vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
- & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- }
+ vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
+ & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else if (statusColorWin != null && statusColorWin.isDimming()) {
// Otherwise if it's dimming, clear the light flag.
vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
@@ -8097,15 +8103,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return vis;
}
- private boolean drawsSystemBarBackground(WindowState win) {
- return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
- }
-
- private boolean forcesDrawStatusBarBackground(WindowState win) {
- return win == null || (win.getAttrs().privateFlags
- & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
- }
-
private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
final boolean dockedStackVisible =
mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
@@ -8129,13 +8126,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mTopDockedOpaqueWindowState, 0, 0);
final boolean fullscreenDrawsStatusBarBackground =
- (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
- && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
- || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
+ drawsStatusBarBackground(vis, mTopFullscreenOpaqueWindowState);
final boolean dockedDrawsStatusBarBackground =
- (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
- && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
- || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
+ drawsStatusBarBackground(dockedVis, mTopDockedOpaqueWindowState);
// prevent status bar interaction from clearing certain flags
int type = win.getAttrs().type;
@@ -8238,6 +8231,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return vis;
}
+ private boolean drawsStatusBarBackground(int vis, WindowState win) {
+ if (!mStatusBarController.isTransparentAllowed(win)) {
+ return false;
+ }
+ if (win == null) {
+ return true;
+ }
+
+ final boolean drawsSystemBars =
+ (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+ final boolean forceDrawsSystemBars =
+ (win.getAttrs().privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+
+ return forceDrawsSystemBars || drawsSystemBars && (vis & View.STATUS_BAR_TRANSLUCENT) == 0;
+ }
+
/**
* @return the current visibility flags with the nav-bar opacity related flags toggled based
* on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index b0d5e1a8c62a..990421653c1d 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -447,6 +447,14 @@ 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/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 88cb54d126c1..d2ddf551fc8d 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_BEHIND;
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 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
if (destroyedSomething) {
final DisplayContent dc = getDisplayContent();
dc.assignWindowLayers(true /*setLayoutNeeded*/);
- updateLetterbox(null);
+ updateLetterboxSurface(null);
}
}
@@ -979,7 +978,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
void removeChild(WindowState child) {
super.removeChild(child);
checkKeyguardFlagsChanged();
- updateLetterbox(child);
+ updateLetterboxSurface(child);
}
private boolean waitingForReplacement() {
@@ -1470,7 +1469,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
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 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
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);
}
}
@@ -2163,4 +2163,12 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
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);
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 59babcfe0371..c35c05dc7212 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -80,7 +80,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -558,6 +557,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
w.updateLastInsetValues();
}
+ if (w.mAppToken != null) {
+ w.mAppToken.layoutLetterbox(w);
+ }
+
if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
+ " mContainingFrame=" + w.mContainingFrame
+ " mDisplayFrame=" + w.mDisplayFrame);
@@ -697,7 +700,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
final AppWindowToken atoken = w.mAppToken;
if (atoken != null) {
- atoken.updateLetterbox(w);
+ atoken.updateLetterboxSurface(w);
final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
mTmpUpdateAllDrawn.add(atoken);
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index 0f9735dc23d4..4eb021cd55dc 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -49,24 +49,26 @@ public class Letterbox {
}
/**
- * Sets the dimensions of the the letterbox, such that the area between the outer and inner
+ * Lays out the letterbox, such that the area between the outer and inner
* frames will be covered by black color surfaces.
*
- * @param t a transaction in which to set the dimensions
+ * The caller must use {@link #applySurfaceChanges} to apply the new layout to the surface.
+ *
* @param outer the outer frame of the letterbox (this frame will be black, except the area
* that intersects with the {code inner} frame).
* @param inner the inner frame of the letterbox (this frame will be clear)
*/
- public void setDimensions(SurfaceControl.Transaction t, Rect outer, Rect inner) {
+ public void layout(Rect outer, Rect inner) {
mOuter.set(outer);
mInner.set(inner);
- mTop.setRect(t, outer.left, outer.top, inner.right, inner.top);
- mLeft.setRect(t, outer.left, inner.top, inner.left, outer.bottom);
- mBottom.setRect(t, inner.left, inner.bottom, outer.right, outer.bottom);
- mRight.setRect(t, inner.right, outer.top, outer.right, inner.bottom);
+ mTop.layout(outer.left, outer.top, inner.right, inner.top);
+ mLeft.layout(outer.left, inner.top, inner.left, outer.bottom);
+ mBottom.layout(inner.left, inner.bottom, outer.right, outer.bottom);
+ mRight.layout(inner.right, outer.top, outer.right, inner.bottom);
}
+
/**
* Gets the insets between the outer and inner rects.
*/
@@ -79,12 +81,20 @@ public class Letterbox {
}
/**
+ * Returns true if any part of the letterbox overlaps with the given {@code rect}.
+ */
+ public boolean isOverlappingWith(Rect rect) {
+ return mTop.isOverlappingWith(rect) || mLeft.isOverlappingWith(rect)
+ || mBottom.isOverlappingWith(rect) || mRight.isOverlappingWith(rect);
+ }
+
+ /**
* Hides the letterbox.
*
- * @param t a transaction in which to hide the letterbox
+ * The caller must use {@link #applySurfaceChanges} to apply the new layout to the surface.
*/
- public void hide(SurfaceControl.Transaction t) {
- setDimensions(t, EMPTY_RECT, EMPTY_RECT);
+ public void hide() {
+ layout(EMPTY_RECT, EMPTY_RECT);
}
/**
@@ -100,43 +110,40 @@ public class Letterbox {
mRight.destroy();
}
+ /** Returns whether a call to {@link #applySurfaceChanges} would change the surface. */
+ public boolean needsApplySurfaceChanges() {
+ return mTop.needsApplySurfaceChanges()
+ || mLeft.needsApplySurfaceChanges()
+ || mBottom.needsApplySurfaceChanges()
+ || mRight.needsApplySurfaceChanges();
+ }
+
+ public void applySurfaceChanges(SurfaceControl.Transaction t) {
+ mTop.applySurfaceChanges(t);
+ mLeft.applySurfaceChanges(t);
+ mBottom.applySurfaceChanges(t);
+ mRight.applySurfaceChanges(t);
+ }
+
private class LetterboxSurface {
private final String mType;
private SurfaceControl mSurface;
- private int mLastLeft = 0;
- private int mLastTop = 0;
- private int mLastRight = 0;
- private int mLastBottom = 0;
+ private final Rect mSurfaceFrame = new Rect();
+ private final Rect mLayoutFrame = new Rect();
public LetterboxSurface(String type) {
mType = type;
}
- public void setRect(SurfaceControl.Transaction t,
- int left, int top, int right, int bottom) {
- if (mLastLeft == left && mLastTop == top
- && mLastRight == right && mLastBottom == bottom) {
+ public void layout(int left, int top, int right, int bottom) {
+ if (mLayoutFrame.left == left && mLayoutFrame.top == top
+ && mLayoutFrame.right == right && mLayoutFrame.bottom == bottom) {
// Nothing changed.
return;
}
-
- if (left < right && top < bottom) {
- if (mSurface == null) {
- createSurface();
- }
- t.setPosition(mSurface, left, top);
- t.setSize(mSurface, right - left, bottom - top);
- t.show(mSurface);
- } else if (mSurface != null) {
- t.hide(mSurface);
- }
-
- mLastLeft = left;
- mLastTop = top;
- mLastRight = right;
- mLastBottom = bottom;
+ mLayoutFrame.set(left, top, right, bottom);
}
private void createSurface() {
@@ -154,11 +161,40 @@ public class Letterbox {
}
public int getWidth() {
- return Math.max(0, mLastRight - mLastLeft);
+ return Math.max(0, mLayoutFrame.width());
}
public int getHeight() {
- return Math.max(0, mLastBottom - mLastTop);
+ return Math.max(0, mLayoutFrame.height());
+ }
+
+ public boolean isOverlappingWith(Rect rect) {
+ if (getWidth() <= 0 || getHeight() <= 0) {
+ return false;
+ }
+ return Rect.intersects(rect, mLayoutFrame);
+ }
+
+ public void applySurfaceChanges(SurfaceControl.Transaction t) {
+ if (mSurfaceFrame.equals(mLayoutFrame)) {
+ // Nothing changed.
+ return;
+ }
+ mSurfaceFrame.set(mLayoutFrame);
+ if (!mSurfaceFrame.isEmpty()) {
+ if (mSurface == null) {
+ createSurface();
+ }
+ t.setPosition(mSurface, mSurfaceFrame.left, mSurfaceFrame.top);
+ t.setSize(mSurface, mSurfaceFrame.width(), mSurfaceFrame.height());
+ t.show(mSurface);
+ } else if (mSurface != null) {
+ t.hide(mSurface);
+ }
+ }
+
+ public boolean needsApplySurfaceChanges() {
+ return !mSurfaceFrame.equals(mLayoutFrame);
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 91cd4bb545a1..591289723a00 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3074,6 +3074,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return (fl & FLAG_FULLSCREEN) != 0 || (sysui & (SYSTEM_UI_FLAG_FULLSCREEN)) != 0;
}
+ @Override
+ public boolean isLetterboxedOverlappingWith(Rect rect) {
+ return mAppToken != null && mAppToken.isLetterboxOverlappingWith(rect);
+ }
+
boolean isDragResizeChanged() {
return mDragResizing != computeDragResizing();
}