diff options
| author | 2021-02-01 12:38:12 +0000 | |
|---|---|---|
| committer | 2021-02-01 12:38:12 +0000 | |
| commit | bc1f09bdb39f186d90428e675d3e12f53e53123d (patch) | |
| tree | 5dbae6fe64cab1c60f80ff123575e306e2f73194 | |
| parent | 283866d88dda61f1496502dad61335c64acd3810 (diff) | |
| parent | 3b9da58ab559ca239fb6941e403b99f689e1fe2d (diff) | |
Merge "Allow status and navigation bars to be semi-transparent in letterbox mode." into sc-dev
9 files changed, 88 insertions, 40 deletions
diff --git a/core/java/android/view/InsetsFlags.java b/core/java/android/view/InsetsFlags.java index a334907c04bc..3355252c4372 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 991ed5518003..227b9f402bba 100644 --- a/core/java/android/view/WindowInsetsController.java +++ b/core/java/android/view/WindowInsetsController.java @@ -67,13 +67,26 @@ 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       */      @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 34d1f6e1789c..fcb5da3f8c52 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 e08224c84813..83651398be43 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; @@ -2430,6 +2431,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 4b4b2b65b8fc..b1da2f0fe888 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 eee27c72e583..3c8cf4edf733 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. +     * +     * <p>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 a7db9d624b7e..f52cb09bc201 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 9a7823e35a01..159760491ff1 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<WindowState> implements WindowManagerP      }      /** -     * @return {@code true} if bar shown within a given frame is allowed to be transparent +     * @return {@code true} if bar shown within a given frame is allowed to be fully transparent       *     when the current window is displayed.       */ -    boolean isTransparentBarAllowed(Rect frame) { -        return mActivityRecord == null || mActivityRecord.isTransparentBarAllowed(frame); +    boolean isFullyTransparentBarAllowed(Rect frame) { +        return mActivityRecord == null || mActivityRecord.isFullyTransparentBarAllowed(frame);      }      public boolean isLetterboxedOverlappingWith(Rect rect) { diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 942e1c91989c..d0d612fc8dda 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -607,7 +607,7 @@ public class SizeCompatTests extends WindowTestsBase {          // The activity doesn't fill the display, so the letterbox of the rotated activity is          // overlapped with the rotated content frame of status bar. Hence the status bar shouldn't          // be transparent. -        assertFalse(statusBarController.isTransparentAllowed(w)); +        assertFalse(statusBarController.isFullyTransparentAllowed(w));          // Make the activity fill the display.          prepareUnresizable(mActivity, 10 /* maxAspect */, SCREEN_ORIENTATION_LANDSCAPE); @@ -617,7 +617,7 @@ public class SizeCompatTests extends WindowTestsBase {          // The letterbox should only cover the notch area, so status bar can be transparent.          assertEquals(new Rect(notchHeight, 0, 0, 0), mActivity.getLetterboxInsets()); -        assertTrue(statusBarController.isTransparentAllowed(w)); +        assertTrue(statusBarController.isFullyTransparentAllowed(w));      }      @Test  |