diff --git a/core/java/android/view/InsetsFlags.java b/core/java/android/view/InsetsFlags.java index a334907c04bc1..3355252c43722 100644 --- a/core/java/android/view/InsetsFlags.java +++ b/core/java/android/view/InsetsFlags.java @@ -21,6 +21,8 @@ import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; @@ -54,7 +56,15 @@ public class InsetsFlags { @ViewDebug.FlagToString( mask = APPEARANCE_LIGHT_NAVIGATION_BARS, equals = APPEARANCE_LIGHT_NAVIGATION_BARS, - name = "LIGHT_NAVIGATION_BARS") + name = "LIGHT_NAVIGATION_BARS"), + @ViewDebug.FlagToString( + mask = APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS, + equals = APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS, + name = "SEMI_TRANSPARENT_STATUS_BARS"), + @ViewDebug.FlagToString( + mask = APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS, + equals = APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS, + name = "SEMI_TRANSPARENT_NAVIGATION_BARS") }) public @Appearance int appearance; diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java index 991ed55180038..227b9f402bba9 100644 --- a/core/java/android/view/WindowInsetsController.java +++ b/core/java/android/view/WindowInsetsController.java @@ -66,6 +66,18 @@ public interface WindowInsetsController { */ int APPEARANCE_LIGHT_NAVIGATION_BARS = 1 << 4; + /** + * Makes status bars semi-transparent with dark background and light foreground. + * @hide + */ + int APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS = 1 << 5; + + /** + * Makes navigation bars semi-transparent with dark background and light foreground. + * @hide + */ + int APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS = 1 << 6; + /** * Determines the appearance of system bars. * @hide @@ -73,7 +85,8 @@ public interface WindowInsetsController { @Retention(RetentionPolicy.SOURCE) @IntDef(flag = true, value = {APPEARANCE_OPAQUE_STATUS_BARS, APPEARANCE_OPAQUE_NAVIGATION_BARS, APPEARANCE_LOW_PROFILE_BARS, APPEARANCE_LIGHT_STATUS_BARS, - APPEARANCE_LIGHT_NAVIGATION_BARS}) + APPEARANCE_LIGHT_NAVIGATION_BARS, APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS, + APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS}) @interface Appearance { } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 34d1f6e1789cb..fcb5da3f8c525 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -28,6 +28,7 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON; @@ -994,6 +995,8 @@ public class NavigationBar implements View.OnAttachStateChangeListener, return MODE_LIGHTS_OUT_TRANSPARENT; } else if ((appearance & APPEARANCE_OPAQUE_NAVIGATION_BARS) != 0) { return MODE_OPAQUE; + } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS) != 0) { + return MODE_SEMI_TRANSPARENT; } else { return MODE_TRANSPARENT; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index d4a2b41573385..14a6d57560339 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -26,6 +26,7 @@ import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS; import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS; +import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS; import static androidx.lifecycle.Lifecycle.State.RESUMED; @@ -2428,6 +2429,8 @@ public class StatusBar extends SystemUI implements DemoMode, return MODE_LIGHTS_OUT_TRANSPARENT; } else if ((appearance & APPEARANCE_OPAQUE_STATUS_BARS) != 0) { return MODE_OPAQUE; + } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS) != 0) { + return MODE_SEMI_TRANSPARENT; } else { return MODE_TRANSPARENT; } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 3bb4c74b7dc06..7e870cf59315a 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1431,14 +1431,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** - * @return {@code true} if bar shown within a given rectangle is allowed to be transparent + * @return {@code true} if bar shown within a given rectangle is allowed to be fully transparent * when the current activity is displayed. */ - boolean isTransparentBarAllowed(Rect rect) { - // TODO(b/175482966): Allow status and navigation bars to be semi-transparent black - // in letterbox mode. - return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect) - || mWmService.isLetterboxActivityCornersRounded(); + boolean isFullyTransparentBarAllowed(Rect rect) { + return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect); } /** diff --git a/services/core/java/com/android/server/wm/BarController.java b/services/core/java/com/android/server/wm/BarController.java index eee27c72e583c..3c8cf4edf7330 100644 --- a/services/core/java/com/android/server/wm/BarController.java +++ b/services/core/java/com/android/server/wm/BarController.java @@ -52,10 +52,19 @@ public class BarController { return !win.isLetterboxedOverlappingWith(getContentFrame(win)); } - boolean isTransparentAllowed(WindowState win) { + /** + * @return {@code true} if bar is allowed to be fully transparent when given window is show. + * + *
Prevents showing a transparent bar over a letterboxed activity which can make
+ * notification icons or navigation buttons unreadable due to contrast between letterbox
+ * background and an activity. For instance, this happens when letterbox background is solid
+ * black while activity is white. To resolve this, only semi-transparent bars are allowed to
+ * be drawn over letterboxed activity.
+ */
+ boolean isFullyTransparentAllowed(WindowState win) {
if (win == null) {
return true;
}
- return win.isTransparentBarAllowed(getContentFrame(win));
+ return win.isFullyTransparentBarAllowed(getContentFrame(win));
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a7db9d624b7e9..f52cb09bc2016 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -42,6 +42,8 @@ import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
@@ -2693,34 +2695,17 @@ public class DisplayPolicy {
private int updateSystemBarsLw(WindowState win, int disableFlags) {
final boolean dockedRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea()
.isRootTaskVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- final boolean freeformRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea()
- .isRootTaskVisible(WINDOWING_MODE_FREEFORM);
final boolean resizing = mDisplayContent.getDockedDividerController().isResizing();
// We need to force system bars when the docked root task is visible, when the freeform
// root task is focused but also when we are resizing for the transitions when docked
// root task visibility changes.
mForceShowSystemBars = dockedRootTaskVisible || win.inFreeformWindowingMode() || resizing;
- final boolean forceOpaqueStatusBar = mForceShowSystemBars && !isKeyguardShowing();
-
- final boolean fullscreenDrawsStatusBarBackground =
- drawsStatusBarBackground(mTopFullscreenOpaqueWindowState);
- final boolean dockedDrawsStatusBarBackground =
- drawsStatusBarBackground(mTopDockedOpaqueWindowState);
- final boolean fullscreenDrawsNavBarBackground =
- drawsNavigationBarBackground(mTopFullscreenOpaqueWindowState);
- final boolean dockedDrawsNavigationBarBackground =
- drawsNavigationBarBackground(mTopDockedOpaqueWindowState);
int appearance = APPEARANCE_OPAQUE_NAVIGATION_BARS | APPEARANCE_OPAQUE_STATUS_BARS;
- if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
- appearance &= ~APPEARANCE_OPAQUE_STATUS_BARS;
- }
-
- appearance = configureNavBarOpacity(appearance, dockedRootTaskVisible,
- freeformRootTaskVisible, resizing, fullscreenDrawsNavBarBackground,
- dockedDrawsNavigationBarBackground);
+ appearance = configureStatusBarOpacity(appearance);
+ appearance = configureNavBarOpacity(appearance, dockedRootTaskVisible, resizing);
final boolean requestHideNavBar = !win.getRequestedVisibility(ITYPE_NAVIGATION_BAR);
final long now = SystemClock.uptimeMillis();
@@ -2755,9 +2740,6 @@ public class DisplayPolicy {
}
private boolean drawsBarBackground(WindowState win, BarController controller) {
- if (!controller.isTransparentAllowed(win)) {
- return false;
- }
if (win == null) {
return true;
}
@@ -2778,15 +2760,40 @@ public class DisplayPolicy {
return drawsBarBackground(win, mNavigationBarController);
}
+ /** @return the current visibility flags with the status bar opacity related flags toggled. */
+ private int configureStatusBarOpacity(int appearance) {
+ final boolean fullscreenDrawsBackground =
+ drawsStatusBarBackground(mTopFullscreenOpaqueWindowState);
+ final boolean dockedDrawsBackground =
+ drawsStatusBarBackground(mTopDockedOpaqueWindowState);
+
+ if (fullscreenDrawsBackground && dockedDrawsBackground) {
+ appearance &= ~APPEARANCE_OPAQUE_STATUS_BARS;
+ }
+
+ if (!mStatusBarController.isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState)
+ || !mStatusBarController.isFullyTransparentAllowed(mTopDockedOpaqueWindowState)) {
+ appearance |= APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
+ }
+
+ return appearance;
+ }
+
/**
* @return the current visibility flags with the nav-bar opacity related flags toggled based
* on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
*/
private int configureNavBarOpacity(int appearance, boolean dockedRootTaskVisible,
- boolean freeformRootTaskVisible, boolean isDockedDividerResizing,
- boolean fullscreenDrawsBackground, boolean dockedDrawsNavigationBarBackground) {
+ boolean isDockedDividerResizing) {
+ final boolean freeformRootTaskVisible = mDisplayContent.getDefaultTaskDisplayArea()
+ .isRootTaskVisible(WINDOWING_MODE_FREEFORM);
+ final boolean fullscreenDrawsBackground =
+ drawsNavigationBarBackground(mTopFullscreenOpaqueWindowState);
+ final boolean dockedDrawsBackground =
+ drawsNavigationBarBackground(mTopDockedOpaqueWindowState);
+
if (mNavBarOpacityMode == NAV_BAR_FORCE_TRANSPARENT) {
- if (fullscreenDrawsBackground && dockedDrawsNavigationBarBackground) {
+ if (fullscreenDrawsBackground && dockedDrawsBackground) {
appearance = clearNavBarOpaqueFlag(appearance);
} else if (dockedRootTaskVisible) {
appearance = setNavBarOpaqueFlag(appearance);
@@ -2811,6 +2818,12 @@ public class DisplayPolicy {
}
}
+ if (!mNavigationBarController.isFullyTransparentAllowed(mTopFullscreenOpaqueWindowState)
+ || !mNavigationBarController.isFullyTransparentAllowed(
+ mTopDockedOpaqueWindowState)) {
+ appearance |= APPEARANCE_SEMI_TRANSPARENT_NAVIGATION_BARS;
+ }
+
return appearance;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 9a7823e35a014..159760491ff1b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3846,11 +3846,11 @@ class WindowState extends WindowContainer