From 48ec0315a28eb8f33923a5fef9c81642b9410be9 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Fri, 21 Jan 2022 15:59:21 +0800 Subject: [PATCH] Let the dimming window can provide multiple appearance regions A dimming window which extends to status bar area can divide status bar into different appearance regions (up to 3). For example: +---------+-------------+---------+ |/////////| |/////////| <-- Status Bar +---------+-------------+---------+ |/////////| |/////////| |/////////| |/////////| |/////////| |/////////| |/////////| |/////////| |/////////| |/////////| +---------+-------------+---------+ ^ ^ ^ dim layer window dim layer This CL allows non-fullscreen dimming window can specify its appearance, and creates appearance regions in the window bounds, so that status bar can adjust the foreground color in each regions. Before this CL, it would create only one appearance region in the case above, so the status bar icon color might not be displayed properly in some regions. Bug: 208717544 Test: Show a dimming window which extends into status bar area. Change-Id: Ie81ce19e9a504045988c4852795117a15460b709 --- .../com/android/server/wm/DisplayPolicy.java | 102 +++++++++++------- 1 file changed, 65 insertions(+), 37 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 0745b3b6d9719..b4cd7d2076e0e 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -305,10 +305,10 @@ public class DisplayPolicy { private WindowState mRoundedCornerWindow; /** - * Windows to determine the color of status bar. See {@link #mNavBarColorWindowCandidate} for - * the conditions of being candidate window. + * A collection of {@link AppearanceRegion} to indicate that which region of status bar applies + * which appearance. */ - private final ArrayList mStatusBarColorWindows = new ArrayList<>(); + private final ArrayList mStatusBarAppearanceRegionList = new ArrayList<>(); /** * Windows to determine opacity and background of translucent status bar. The window needs to be @@ -323,7 +323,7 @@ public class DisplayPolicy { private InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities(); private AppearanceRegion[] mLastStatusBarAppearanceRegions; - /** The union of checked bounds while fetching {@link #mStatusBarColorWindows}. */ + /** The union of checked bounds while building {@link #mStatusBarAppearanceRegionList}. */ private final Rect mStatusBarColorCheckedBounds = new Rect(); /** The union of checked bounds while fetching {@link #mStatusBarBackgroundWindows}. */ @@ -336,6 +336,7 @@ public class DisplayPolicy { private long mPendingPanicGestureUptime; private static final Rect sTmpRect = new Rect(); + private static final Rect sTmpRect2 = new Rect(); private static final Rect sTmpLastParentFrame = new Rect(); private static final Rect sTmpDisplayCutoutSafe = new Rect(); private static final Rect sTmpDisplayFrame = new Rect(); @@ -1563,7 +1564,7 @@ public class DisplayPolicy { mTopFullscreenOpaqueWindowState = null; mNavBarColorWindowCandidate = null; mNavBarBackgroundWindow = null; - mStatusBarColorWindows.clear(); + mStatusBarAppearanceRegionList.clear(); mStatusBarBackgroundWindows.clear(); mStatusBarColorCheckedBounds.setEmpty(); mStatusBarBackgroundCheckedBounds.setEmpty(); @@ -1643,7 +1644,9 @@ public class DisplayPolicy { mStatusBarBackgroundWindows.add(win); mStatusBarBackgroundCheckedBounds.union(sTmpRect); if (!mStatusBarColorCheckedBounds.contains(sTmpRect)) { - mStatusBarColorWindows.add(win); + mStatusBarAppearanceRegionList.add(new AppearanceRegion( + win.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS, + new Rect(win.getFrame()))); mStatusBarColorCheckedBounds.union(sTmpRect); } } @@ -1663,13 +1666,10 @@ public class DisplayPolicy { } } } else if (win.isDimming()) { - // For dimming window whose host bounds is overlapping with system bars, it can be - // used to determine colors but not opacity of system bars. - if (mStatusBar != null - && sTmpRect.setIntersect(win.getBounds(), mStatusBar.getFrame()) - && !mStatusBarColorCheckedBounds.contains(sTmpRect)) { - mStatusBarColorWindows.add(win); - mStatusBarColorCheckedBounds.union(sTmpRect); + if (mStatusBar != null) { + addStatusBarAppearanceRegionsForDimmingWindow( + win.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS, + mStatusBar.getFrame(), win.getBounds(), win.getFrame()); } if (isOverlappingWithNavBar && mNavBarColorWindowCandidate == null) { mNavBarColorWindowCandidate = win; @@ -1677,6 +1677,48 @@ public class DisplayPolicy { } } + private void addStatusBarAppearanceRegionsForDimmingWindow(int appearance, Rect statusBarFrame, + Rect winBounds, Rect winFrame) { + if (!sTmpRect.setIntersect(winBounds, statusBarFrame)) { + return; + } + if (mStatusBarColorCheckedBounds.contains(sTmpRect)) { + return; + } + if (appearance == 0 || !sTmpRect2.setIntersect(winFrame, statusBarFrame)) { + mStatusBarAppearanceRegionList.add(new AppearanceRegion(0, new Rect(winBounds))); + mStatusBarColorCheckedBounds.union(sTmpRect); + return; + } + // A dimming window can divide status bar into different appearance regions (up to 3). + // +---------+-------------+---------+ + // |/////////| |/////////| <-- Status Bar + // +---------+-------------+---------+ + // |/////////| |/////////| + // |/////////| |/////////| + // |/////////| |/////////| + // |/////////| |/////////| + // |/////////| |/////////| + // +---------+-------------+---------+ + // ^ ^ ^ + // dim layer window dim layer + mStatusBarAppearanceRegionList.add(new AppearanceRegion(appearance, new Rect(winFrame))); + if (!sTmpRect.equals(sTmpRect2)) { + if (sTmpRect.height() == sTmpRect2.height()) { + if (sTmpRect.left != sTmpRect2.left) { + mStatusBarAppearanceRegionList.add(new AppearanceRegion(0, new Rect( + winBounds.left, winBounds.top, sTmpRect2.left, winBounds.bottom))); + } + if (sTmpRect.right != sTmpRect2.right) { + mStatusBarAppearanceRegionList.add(new AppearanceRegion(0, new Rect( + sTmpRect2.right, winBounds.top, winBounds.right, winBounds.bottom))); + } + } + // We don't have vertical status bar yet, so we don't handle the other orientation. + } + mStatusBarColorCheckedBounds.union(sTmpRect); + } + /** * Called following layout of all windows and after policy has been applied * to each window. If in this function you do @@ -2319,14 +2361,9 @@ public class DisplayPolicy { final String focusedApp = win.mAttrs.packageName; final boolean isFullscreen = !win.getRequestedVisibility(ITYPE_STATUS_BAR) || !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR); - final AppearanceRegion[] appearanceRegions = - new AppearanceRegion[mStatusBarColorWindows.size()]; - for (int i = mStatusBarColorWindows.size() - 1; i >= 0; i--) { - final WindowState windowState = mStatusBarColorWindows.get(i); - appearanceRegions[i] = new AppearanceRegion( - getStatusBarAppearance(windowState, windowState), - new Rect(windowState.getFrame())); - } + final AppearanceRegion[] statusBarAppearanceRegions = + new AppearanceRegion[mStatusBarAppearanceRegionList.size()]; + mStatusBarAppearanceRegionList.toArray(statusBarAppearanceRegions); if (mLastDisableFlags != disableFlags) { mLastDisableFlags = disableFlags; final String cause = win.toString(); @@ -2338,7 +2375,7 @@ public class DisplayPolicy { && mRequestedVisibilities.equals(win.getRequestedVisibilities()) && Objects.equals(mFocusedApp, focusedApp) && mLastFocusIsFullscreen == isFullscreen - && Arrays.equals(mLastStatusBarAppearanceRegions, appearanceRegions)) { + && Arrays.equals(mLastStatusBarAppearanceRegions, statusBarAppearanceRegions)) { return; } if (mDisplayContent.isDefaultDisplay && mLastFocusIsFullscreen != isFullscreen @@ -2353,20 +2390,12 @@ public class DisplayPolicy { mRequestedVisibilities = requestedVisibilities; mFocusedApp = focusedApp; mLastFocusIsFullscreen = isFullscreen; - mLastStatusBarAppearanceRegions = appearanceRegions; + mLastStatusBarAppearanceRegions = statusBarAppearanceRegions; callStatusBarSafely(statusBar -> statusBar.onSystemBarAttributesChanged(displayId, - appearance, appearanceRegions, isNavbarColorManagedByIme, behavior, + appearance, statusBarAppearanceRegions, isNavbarColorManagedByIme, behavior, requestedVisibilities, focusedApp)); } - private int getStatusBarAppearance(WindowState opaque, WindowState opaqueOrDimming) { - final boolean onKeyguard = isKeyguardShowing() && !isKeyguardOccluded(); - final WindowState colorWin = onKeyguard ? mNotificationShade : opaqueOrDimming; - return isLightBarAllowed(colorWin, Type.statusBars()) && (colorWin == opaque || onKeyguard) - ? (colorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS) - : 0; - } - private void callStatusBarSafely(Consumer consumer) { mHandler.post(() -> { StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); @@ -2760,11 +2789,10 @@ public class DisplayPolicy { pw.print(prefix); pw.print("mNavBarBackgroundWindow="); pw.println(mNavBarBackgroundWindow); } - if (!mStatusBarColorWindows.isEmpty()) { - pw.print(prefix); pw.println("mStatusBarColorWindows="); - for (int i = mStatusBarColorWindows.size() - 1; i >= 0; i--) { - final WindowState win = mStatusBarColorWindows.get(i); - pw.print(prefixInner); pw.println(win); + if (mLastStatusBarAppearanceRegions != null) { + pw.print(prefix); pw.println("mLastStatusBarAppearanceRegions="); + for (int i = mLastStatusBarAppearanceRegions.length - 1; i >= 0; i--) { + pw.print(prefixInner); pw.println(mLastStatusBarAppearanceRegions[i]); } } if (!mStatusBarBackgroundWindows.isEmpty()) {