diff options
| author | 2020-10-20 14:51:22 -0700 | |
|---|---|---|
| committer | 2020-10-23 09:53:50 -0700 | |
| commit | 3b795c7cd74ef5b12e1b349d8f5ccc1310ba4111 (patch) | |
| tree | f7d3bd7a096773adb7ee748f90674f1d98ed1d5c | |
| parent | 19ecd2f473e069fe7c0821439648b801bf69a8d7 (diff) | |
Enable defining system bar side to fit by the side.
Test: Manual + Unit Tests
Bug: 171414476
Bug: 171054589
Bug: 162599873
Change-Id: I948a0907fa76ea16acc91f843f8b5cdbf7126df1
6 files changed, 166 insertions, 6 deletions
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml index 8667ba1cd1a5..b6179edfb063 100644 --- a/packages/CarSystemUI/res/values/config.xml +++ b/packages/CarSystemUI/res/values/config.xml @@ -154,4 +154,13 @@ <!-- The Activity name for the Rear View Camera, if empty, the feature will be disabled. --> <string name="config_rearViewCameraActivity" translatable="false"></string> + + <!-- Whether the Notification Panel should be inset by the top system bar. --> + <bool name="config_notif_panel_inset_by_top_systembar" translatable="false">false</bool> + <!-- Whether the Notification Panel should be inset by the bottom system bar. --> + <bool name="config_notif_panel_inset_by_bottom_systembar" translatable="false">true</bool> + <!-- Whether the Notification Panel should be inset by the left system bar. --> + <bool name="config_notif_panel_inset_by_left_systembar" translatable="false">false</bool> + <!-- Whether the Notification Panel should be inset by the right system bar. --> + <bool name="config_notif_panel_inset_by_right_systembar" translatable="false">false</bool> </resources> diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java index 4b660692cd8f..599e69cb6ab4 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java @@ -49,6 +49,7 @@ import com.android.systemui.R; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.window.OverlayPanelViewController; +import com.android.systemui.car.window.OverlayViewController; import com.android.systemui.car.window.OverlayViewGlobalStateController; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; @@ -84,6 +85,11 @@ public class NotificationPanelViewController extends OverlayPanelViewController private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen; private final NotificationVisibilityLogger mNotificationVisibilityLogger; + private final boolean mFitTopSystemBarInset; + private final boolean mFitBottomSystemBarInset; + private final boolean mFitLeftSystemBarInset; + private final boolean mFitRightSystemBarInset; + private float mInitialBackgroundAlpha; private float mBackgroundAlphaDiff; @@ -164,6 +170,15 @@ public class NotificationPanelViewController extends OverlayPanelViewController mEnableHeadsUpNotificationWhenNotificationShadeOpen = mResources.getBoolean( com.android.car.notification.R.bool .config_enableHeadsUpNotificationWhenNotificationShadeOpen); + + mFitTopSystemBarInset = mResources.getBoolean( + R.bool.config_notif_panel_inset_by_top_systembar); + mFitBottomSystemBarInset = mResources.getBoolean( + R.bool.config_notif_panel_inset_by_bottom_systembar); + mFitLeftSystemBarInset = mResources.getBoolean( + R.bool.config_notif_panel_inset_by_left_systembar); + mFitRightSystemBarInset = mResources.getBoolean( + R.bool.config_notif_panel_inset_by_right_systembar); } // CommandQueue.Callbacks @@ -215,8 +230,26 @@ public class NotificationPanelViewController extends OverlayPanelViewController } @Override - protected int getInsetTypesToFit() { - return WindowInsets.Type.navigationBars(); + protected int getInsetSidesToFit() { + int insetSidesToFit = OverlayViewController.NO_INSET_SIDE; + + if (mFitTopSystemBarInset) { + insetSidesToFit = insetSidesToFit | WindowInsets.Side.TOP; + } + + if (mFitBottomSystemBarInset) { + insetSidesToFit = insetSidesToFit | WindowInsets.Side.BOTTOM; + } + + if (mFitLeftSystemBarInset) { + insetSidesToFit = insetSidesToFit | WindowInsets.Side.LEFT; + } + + if (mFitRightSystemBarInset) { + insetSidesToFit = insetSidesToFit | WindowInsets.Side.RIGHT; + } + + return insetSidesToFit; } @Override diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java index 6c3a6327d90c..b989c421c780 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java @@ -27,6 +27,9 @@ import android.view.WindowInsets; * Owns a {@link View} that is present in SystemUIOverlayWindow. */ public class OverlayViewController { + protected static final int INVALID_INSET_SIDE = -1; + protected static final int NO_INSET_SIDE = 0; + private final int mStubId; private final OverlayViewGlobalStateController mOverlayViewGlobalStateController; @@ -188,4 +191,28 @@ public class OverlayViewController { protected int getInsetTypesToFit() { return statusBars(); } + + /** + * Optionally returns the sides of enabled system bar insets to fit to the sysui overlay window + * when this {@link OverlayViewController} is in the foreground. + * + * For example, if the bottom and left system bars are enabled and this method returns + * WindowInsets.Side.LEFT, then the inset from the bottom system bar will be ignored. + * + * NOTE: By default, this method returns {@link #INVALID_INSET_SIDE}, so insets to fit are + * defined by {@link #getInsetTypesToFit()}, and not by this method, unless it is overridden + * by subclasses. + * + * NOTE: {@link #NO_INSET_SIDE} signifies no insets from any system bars will be honored. Each + * {@link OverlayViewController} can first take this value and add sides of the system bar + * insets to honor to it. + * + * NOTE: If getInsetSidesToFit is overridden to return {@link WindowInsets.Side}, it always + * takes precedence over {@link #getInsetTypesToFit()}. That is, the return value of {@link + * #getInsetTypesToFit()} will be ignored. + */ + @WindowInsets.Side.InsetsSide + protected int getInsetSidesToFit() { + return INVALID_INSET_SIDE; + } } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java index 0da23605a2cf..10f436b5e717 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java @@ -21,6 +21,8 @@ import static android.view.WindowInsets.Type.statusBars; import android.annotation.Nullable; import android.util.Log; +import android.view.WindowInsets; +import android.view.WindowInsets.Side.InsetsSide; import android.view.WindowInsets.Type.InsetsType; import android.view.WindowInsetsController; @@ -119,7 +121,7 @@ public class OverlayViewGlobalStateController { updateInternalsWhenShowingView(viewController); refreshUseStableInsets(); - refreshInsetTypesToFit(); + refreshInsetsToFit(); refreshWindowFocus(); refreshNavigationBarVisibility(); refreshStatusBarVisibility(); @@ -193,7 +195,7 @@ public class OverlayViewGlobalStateController { mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController)); refreshHighestZOrderWhenHidingView(viewController); refreshUseStableInsets(); - refreshInsetTypesToFit(); + refreshInsetsToFit(); refreshWindowFocus(); refreshNavigationBarVisibility(); refreshStatusBarVisibility(); @@ -255,11 +257,25 @@ public class OverlayViewGlobalStateController { mHighestZOrder == null ? false : mHighestZOrder.shouldUseStableInsets()); } - private void refreshInsetTypesToFit() { + /** + * Refreshes the insets to fit (or honor) either by {@link InsetsType} or {@link InsetsSide}. + * + * By default, the insets to fit are defined by the {@link InsetsType}. But if an + * {@link OverlayViewController} overrides {@link OverlayViewController#getInsetSidesToFit()} to + * return an {@link InsetsSide}, then that takes precedence over {@link InsetsType}. + */ + private void refreshInsetsToFit() { if (mZOrderVisibleSortedMap.isEmpty()) { setFitInsetsTypes(statusBars()); } else { - setFitInsetsTypes(mHighestZOrder.getInsetTypesToFit()); + if (mHighestZOrder.getInsetSidesToFit() != OverlayViewController.INVALID_INSET_SIDE) { + // First fit all system bar insets as setFitInsetsSide defines which sides of system + // bar insets to actually honor. + setFitInsetsTypes(WindowInsets.Type.systemBars()); + setFitInsetsSides(mHighestZOrder.getInsetSidesToFit()); + } else { + setFitInsetsTypes(mHighestZOrder.getInsetTypesToFit()); + } } } @@ -272,10 +288,16 @@ public class OverlayViewGlobalStateController { mSystemUIOverlayWindowController.setWindowVisible(visible); } + /** Sets the insets to fit based on the {@link InsetsType} */ private void setFitInsetsTypes(@InsetsType int types) { mSystemUIOverlayWindowController.setFitInsetsTypes(types); } + /** Sets the insets to fit based on the {@link InsetsSide} */ + private void setFitInsetsSides(@InsetsSide int sides) { + mSystemUIOverlayWindowController.setFitInsetsSides(sides); + } + /** * Sets the {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM} flag of the * sysui overlay window. diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java index b22de84eb038..0e73f2520a66 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java @@ -120,6 +120,13 @@ public class SystemUIOverlayWindowController implements updateWindow(); } + /** Sets the sides of system bar insets to fit. Note: This should be rarely used. */ + public void setFitInsetsSides(@WindowInsets.Side.InsetsSide int sides) { + mLpChanged.setFitInsetsSides(sides); + mLpChanged.setFitInsetsIgnoringVisibility(mUsingStableInsets); + updateWindow(); + } + /** Sets the window to the visible state. */ public void setWindowVisible(boolean visible) { mVisible = visible; diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java index 294aa0d3cf9b..9c2931a8ad22 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java @@ -33,6 +33,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; +import android.view.WindowInsets; import android.view.WindowInsetsController; import androidx.test.filters.SmallTest; @@ -887,6 +888,65 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase { verify(mOverlayViewController2, never()).inflate(mBaseLayout); } + @Test + public void showView_setInsetsToFitByType_setsFitInsetsType() { + int insetTypeToFit = WindowInsets.Type.navigationBars(); + setupOverlayViewController1(); + when(mOverlayViewController1.getInsetTypesToFit()).thenReturn(insetTypeToFit); + + mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable); + + verify(mSystemUIOverlayWindowController).setFitInsetsTypes(insetTypeToFit); + } + + @Test + public void refreshInsetsToFit_setInsetsToFitBySide_setsFitInsetsSides() { + int insetSidesToFit = WindowInsets.Side.LEFT; + setupOverlayViewController1(); + when(mOverlayViewController1.getInsetSidesToFit()).thenReturn(insetSidesToFit); + + mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable); + + verify(mSystemUIOverlayWindowController).setFitInsetsSides(insetSidesToFit); + } + + @Test + public void refreshInsetsToFit_setInsetsToFitBySideUsed_firstFitsAllSystemBars() { + int insetSidesToFit = WindowInsets.Side.LEFT; + setupOverlayViewController1(); + when(mOverlayViewController1.getInsetSidesToFit()).thenReturn(insetSidesToFit); + + mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable); + + verify(mSystemUIOverlayWindowController).setFitInsetsTypes(WindowInsets.Type.systemBars()); + } + + @Test + public void refreshInsetsToFit_bothInsetTypeAndSideDefined_insetSideTakesPrecedence() { + int insetTypesToFit = WindowInsets.Type.navigationBars(); + int insetSidesToFit = WindowInsets.Side.LEFT; + setupOverlayViewController1(); + when(mOverlayViewController1.getInsetTypesToFit()).thenReturn(insetTypesToFit); + when(mOverlayViewController1.getInsetSidesToFit()).thenReturn(insetSidesToFit); + + mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable); + + verify(mSystemUIOverlayWindowController).setFitInsetsSides(insetSidesToFit); + } + + @Test + public void refreshInsetsToFit_bothInsetTypeAndSideDefined_insetTypeIgnored() { + int insetTypesToFit = WindowInsets.Type.navigationBars(); + int insetSidesToFit = WindowInsets.Side.LEFT; + setupOverlayViewController1(); + when(mOverlayViewController1.getInsetTypesToFit()).thenReturn(insetTypesToFit); + when(mOverlayViewController1.getInsetSidesToFit()).thenReturn(insetSidesToFit); + + mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable); + + verify(mSystemUIOverlayWindowController, never()).setFitInsetsTypes(insetTypesToFit); + } + private void setupOverlayViewController1() { setupOverlayViewController(mOverlayViewController1, R.id.overlay_view_controller_stub_1, R.id.overlay_view_controller_1); @@ -913,6 +973,8 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase { } when(overlayViewController.getLayout()).thenReturn(layout); when(overlayViewController.isInflated()).thenReturn(true); + when(overlayViewController.getInsetSidesToFit()).thenReturn( + OverlayViewController.INVALID_INSET_SIDE); } private void setOverlayViewControllerAsShowing(OverlayViewController overlayViewController) { |