From bd6d0ad8acf8ab169ad8f9f028abaa3f873e968b Mon Sep 17 00:00:00 2001 From: shawnlin Date: Wed, 29 Jan 2020 18:38:49 +0800 Subject: [PATCH] Make systemui support waterfall - Status bar content should be always below waterfall. We have to minus status bar height with waterfall inset top to get the correct content height and set the top padding/margin to waterfall inset top. - Update paddings/margins for waterfall insets in below 3 places, which also move setup rouned corner padding from ScreenDecorations to these 3 places. 1. PhoneStatusBar 2. QuickStatusBarHeader 3. KeyguardStatusBarView - Adjust notification minimum expand height for waterfall in NotificationStackScrollLayout. Bug: 146876976 Test: manual-select waterfall cutout overlay in develop option and check the status bar. Test: atest SystemUITests Change-Id: Ib489e0ac69433635c3be990b5f8e56a3704b4a09 --- .../android/systemui/ScreenDecorations.java | 94 ++----------- .../systemui/qs/QuickStatusBarHeader.java | 31 +++-- .../stack/NotificationStackScrollLayout.java | 13 +- .../phone/KeyguardStatusBarView.java | 44 ++++--- .../phone/NotificationShadeWindowView.java | 33 ++--- .../statusbar/phone/PhoneStatusBarView.java | 65 +++------ .../statusbar/phone/StatusBarWindowView.java | 124 ++++++++++++++++++ .../systemui/ScreenDecorationsTest.java | 67 +--------- 8 files changed, 225 insertions(+), 246 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index e66b9f21bd8c9..a2ae59e9d0273 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -22,12 +22,8 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; -import static com.android.systemui.tuner.TunablePadding.FLAG_END; -import static com.android.systemui.tuner.TunablePadding.FLAG_START; - import android.annotation.Dimension; import android.app.ActivityManager; -import android.app.Fragment; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -69,13 +65,7 @@ import com.android.internal.util.Preconditions; import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.fragments.FragmentHostManager; -import com.android.systemui.fragments.FragmentHostManager.FragmentListener; -import com.android.systemui.plugins.qs.QS; import com.android.systemui.qs.SecureSetting; -import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment; -import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.tuner.TunablePadding; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; import com.android.systemui.util.leak.RotationUtils; @@ -86,8 +76,6 @@ import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; -import dagger.Lazy; - /** * An overlay that draws screen decorations in software (e.g for rounded corners or display cutout) * for antialiasing and emulation purposes. @@ -102,7 +90,6 @@ public class ScreenDecorations extends SystemUI implements Tunable { private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS = SystemProperties.getBoolean("debug.screenshot_rounded_corners", false); private static final boolean VERBOSE = false; - private final Lazy mStatusBarLazy; private DisplayManager mDisplayManager; private final BroadcastDispatcher mBroadcastDispatcher; @@ -146,12 +133,10 @@ public class ScreenDecorations extends SystemUI implements Tunable { @Inject public ScreenDecorations(Context context, - Lazy statusBarLazy, @Main Handler handler, BroadcastDispatcher broadcastDispatcher, TunerService tunerService) { super(context); - mStatusBarLazy = statusBarLazy; mMainHandler = handler; mBroadcastDispatcher = broadcastDispatcher; mTunerService = tunerService; @@ -161,7 +146,6 @@ public class ScreenDecorations extends SystemUI implements Tunable { public void start() { mHandler = startHandlerThread(); mHandler.post(this::startOnScreenDecorationsThread); - setupStatusBarPaddingIfNeeded(); } @VisibleForTesting @@ -440,42 +424,6 @@ public class ScreenDecorations extends SystemUI implements Tunable { com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout); } - - private void setupStatusBarPaddingIfNeeded() { - // TODO: This should be moved to a more appropriate place, as it is not related to the - // screen decorations overlay. - int padding = mContext.getResources().getDimensionPixelSize( - R.dimen.rounded_corner_content_padding); - if (padding != 0) { - setupStatusBarPadding(padding); - } - - } - - private void setupStatusBarPadding(int padding) { - // Add some padding to all the content near the edge of the screen. - StatusBar statusBar = mStatusBarLazy.get(); - final View notificationShadeWindowView = statusBar.getNotificationShadeWindowView(); - if (notificationShadeWindowView != null) { - TunablePadding.addTunablePadding( - notificationShadeWindowView.findViewById(R.id.keyguard_header), - PADDING, padding, FLAG_END); - - final FragmentHostManager fragmentHostManager = - FragmentHostManager.get(notificationShadeWindowView); - fragmentHostManager.addTagListener(QS.TAG, - new TunablePaddingTagListener(padding, R.id.header)); - } - - final View statusBarWindow = statusBar.getStatusBarWindow(); - if (statusBarWindow != null) { - final FragmentHostManager fragmentHostManager = - FragmentHostManager.get(statusBarWindow); - fragmentHostManager.addTagListener(CollapsedStatusBarFragment.TAG, - new TunablePaddingTagListener(padding, R.id.status_bar)); - } - } - @VisibleForTesting WindowManager.LayoutParams getWindowLayoutParams() { final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( @@ -566,32 +514,6 @@ public class ScreenDecorations extends SystemUI implements Tunable { view.setLayoutParams(params); } - @VisibleForTesting - static class TunablePaddingTagListener implements FragmentListener { - - private final int mPadding; - private final int mId; - private TunablePadding mTunablePadding; - - public TunablePaddingTagListener(int padding, int id) { - mPadding = padding; - mId = id; - } - - @Override - public void onFragmentViewCreated(String tag, Fragment fragment) { - if (mTunablePadding != null) { - mTunablePadding.destroy(); - } - View view = fragment.getView(); - if (mId != 0) { - view = view.findViewById(mId); - } - mTunablePadding = TunablePadding.addTunablePadding(view, PADDING, mPadding, - FLAG_START | FLAG_END); - } - } - public static class DisplayCutoutView extends View implements DisplayManager.DisplayListener, RegionInterceptableView { @@ -763,11 +685,11 @@ public class ScreenDecorations extends SystemUI implements Tunable { return false; } if (mStart) { - return displayCutout.getSafeInsetLeft() > 0 - || displayCutout.getSafeInsetTop() > 0; + return !displayCutout.getBoundingRectLeft().isEmpty() + || !displayCutout.getBoundingRectTop().isEmpty(); } else { - return displayCutout.getSafeInsetRight() > 0 - || displayCutout.getSafeInsetBottom() > 0; + return !displayCutout.getBoundingRectRight().isEmpty() + || !displayCutout.getBoundingRectBottom().isEmpty(); } } @@ -809,15 +731,15 @@ public class ScreenDecorations extends SystemUI implements Tunable { private int getGravity(DisplayCutout displayCutout) { if (mStart) { - if (displayCutout.getSafeInsetLeft() > 0) { + if (!displayCutout.getBoundingRectLeft().isEmpty()) { return Gravity.LEFT; - } else if (displayCutout.getSafeInsetTop() > 0) { + } else if (!displayCutout.getBoundingRectTop().isEmpty()) { return Gravity.TOP; } } else { - if (displayCutout.getSafeInsetRight() > 0) { + if (!displayCutout.getBoundingRectRight().isEmpty()) { return Gravity.RIGHT; - } else if (displayCutout.getSafeInsetBottom() > 0) { + } else if (!displayCutout.getBoundingRectBottom().isEmpty()) { return Gravity.BOTTOM; } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java index d4af1548af41b..8cd70cf63b8ed 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java @@ -61,9 +61,9 @@ import com.android.systemui.plugins.DarkIconDispatcher; import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver; import com.android.systemui.qs.QSDetail.Callback; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager; +import com.android.systemui.statusbar.phone.StatusBarWindowView; import com.android.systemui.statusbar.phone.StatusIconContainer; import com.android.systemui.statusbar.policy.Clock; import com.android.systemui.statusbar.policy.DateView; @@ -146,6 +146,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements } }; private boolean mHasTopCutout = false; + private int mRoundedCornerPadding = 0; @Inject public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs, @@ -325,6 +326,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements Resources resources = mContext.getResources(); updateMinimumHeight(); + mRoundedCornerPadding = resources.getDimensionPixelSize( + R.dimen.rounded_corner_content_padding); + // Update height for a few views, especially due to landscape mode restricting space. mHeaderTextContainerView.getLayoutParams().height = resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height); @@ -432,16 +436,23 @@ public class QuickStatusBarHeader extends RelativeLayout implements @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { DisplayCutout cutout = insets.getDisplayCutout(); - Pair padding = PhoneStatusBarView.cornerCutoutMargins( - cutout, getDisplay()); - if (padding == null) { - mSystemIconsView.setPaddingRelative( - getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0, - getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0); - } else { - mSystemIconsView.setPadding(padding.first, 0, padding.second, 0); - } + // Handle padding of QuickStatusBarHeader + Pair cornerCutoutPadding = StatusBarWindowView.cornerCutoutMargins( + cutout, getDisplay()); + Pair padding = + StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner( + cutout, cornerCutoutPadding, mRoundedCornerPadding); + setPadding(padding.first, 0, padding.second, getPaddingBottom()); + + // Handle padding of SystemIconsView + final int waterfallTopInset = cutout == null ? 0 : cutout.getWaterfallInsets().top; + mSystemIconsView.setPaddingRelative( + getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), + waterfallTopInset, + getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), + 0); + return super.onApplyWindowInsets(insets); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 4b9976cc20975..7cc2b156a2b5c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -57,6 +57,7 @@ import android.util.Log; import android.util.MathUtils; import android.util.Pair; import android.view.ContextThemeWrapper; +import android.view.DisplayCutout; import android.view.InputDevice; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -513,6 +514,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private float mLastSentExpandedHeight; private boolean mWillExpand; + private int mWaterfallTopInset; + @Inject public NotificationStackScrollLayout( @Named(VIEW_CONTEXT) Context context, @@ -1714,6 +1717,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd public WindowInsets onApplyWindowInsets(WindowInsets insets) { mBottomInset = insets.getSystemWindowInsetBottom(); + mWaterfallTopInset = 0; + final DisplayCutout cutout = insets.getDisplayCutout(); + if (cutout != null) { + mWaterfallTopInset = cutout.getWaterfallInsets().top; + } + if (ANCHOR_SCROLLING) { // TODO } else { @@ -5310,7 +5319,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd @ShadeViewRefactor(RefactorComponent.COORDINATOR) public int getMinExpansionHeight() { - return mShelf.getIntrinsicHeight() - (mShelf.getIntrinsicHeight() - mStatusBarHeight) / 2; + return mShelf.getIntrinsicHeight() + - (mShelf.getIntrinsicHeight() - mStatusBarHeight + mWaterfallTopInset) / 2 + + mWaterfallTopInset; } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index b24942ab22b31..b46ca401ae059 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -102,6 +102,9 @@ public class KeyguardStatusBarView extends RelativeLayout */ private int mCutoutSideNudge = 0; + private DisplayCutout mDisplayCutout; + private int mRoundedCornerPadding = 0; + public KeyguardStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); } @@ -159,9 +162,15 @@ public class KeyguardStatusBarView extends RelativeLayout getResources().getDimensionPixelSize(R.dimen.keyguard_carrier_text_margin)); mCarrierLabel.setLayoutParams(lp); - lp = (MarginLayoutParams) getLayoutParams(); + updateKeyguardStatusBarHeight(); + } + + private void updateKeyguardStatusBarHeight() { + final int waterfallTop = + mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top; + MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); lp.height = getResources().getDimensionPixelSize( - R.dimen.status_bar_header_height_keyguard); + R.dimen.status_bar_header_height_keyguard) + waterfallTop; setLayoutParams(lp); } @@ -175,6 +184,8 @@ public class KeyguardStatusBarView extends RelativeLayout R.dimen.display_cutout_margin_consumption); mShowPercentAvailable = getContext().getResources().getBoolean( com.android.internal.R.bool.config_battery_percentage_setting_available); + mRoundedCornerPadding = res.getDimensionPixelSize( + R.dimen.rounded_corner_content_padding); } private void updateVisibilities() { @@ -225,23 +236,26 @@ public class KeyguardStatusBarView extends RelativeLayout } private boolean updateLayoutConsideringCutout() { - DisplayCutout dc = getRootWindowInsets().getDisplayCutout(); + mDisplayCutout = getRootWindowInsets().getDisplayCutout(); + updateKeyguardStatusBarHeight(); + Pair cornerCutoutMargins = - PhoneStatusBarView.cornerCutoutMargins(dc, getDisplay()); - updateCornerCutoutPadding(cornerCutoutMargins); - if (dc == null || cornerCutoutMargins != null) { + StatusBarWindowView.cornerCutoutMargins(mDisplayCutout, getDisplay()); + updatePadding(cornerCutoutMargins); + if (mDisplayCutout == null || cornerCutoutMargins != null) { return updateLayoutParamsNoCutout(); } else { - return updateLayoutParamsForCutout(dc); + return updateLayoutParamsForCutout(); } } - private void updateCornerCutoutPadding(Pair cornerCutoutMargins) { - if (cornerCutoutMargins != null) { - setPadding(cornerCutoutMargins.first, 0, cornerCutoutMargins.second, 0); - } else { - setPadding(0, 0, 0, 0); - } + private void updatePadding(Pair cornerCutoutMargins) { + final int waterfallTop = + mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top; + Pair padding = + StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner( + mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding); + setPadding(padding.first, waterfallTop, padding.second, 0); } private boolean updateLayoutParamsNoCutout() { @@ -268,7 +282,7 @@ public class KeyguardStatusBarView extends RelativeLayout return true; } - private boolean updateLayoutParamsForCutout(DisplayCutout dc) { + private boolean updateLayoutParamsForCutout() { if (mLayoutState == LAYOUT_CUTOUT) { return false; } @@ -279,7 +293,7 @@ public class KeyguardStatusBarView extends RelativeLayout } Rect bounds = new Rect(); - boundsFromDirection(dc, Gravity.TOP, bounds); + boundsFromDirection(mDisplayCutout, Gravity.TOP, bounds); mCutoutSpace.setVisibility(View.VISIBLE); RelativeLayout.LayoutParams lp = (LayoutParams) mCutoutSpace.getLayoutParams(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java index 7650a3ab3a4ea..bc80a1a5137d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowView.java @@ -88,33 +88,11 @@ public class NotificationShadeWindowView extends FrameLayout { boolean paddingChanged = insets.top != getPaddingTop() || insets.bottom != getPaddingBottom(); - int rightCutout = 0; - int leftCutout = 0; - DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout(); - if (displayCutout != null) { - leftCutout = displayCutout.getSafeInsetLeft(); - rightCutout = displayCutout.getSafeInsetRight(); - } - - int targetLeft = Math.max(insets.left, leftCutout); - int targetRight = Math.max(insets.right, rightCutout); - - // Super-special right inset handling, because scrims and backdrop need to ignore it. - if (targetRight != mRightInset || targetLeft != mLeftInset) { - mRightInset = targetRight; - mLeftInset = targetLeft; - applyMargins(); - } // Drop top inset, and pass through bottom inset. if (paddingChanged) { setPadding(0, 0, 0, 0); } } else { - if (mRightInset != 0 || mLeftInset != 0) { - mRightInset = 0; - mLeftInset = 0; - applyMargins(); - } boolean changed = getPaddingLeft() != 0 || getPaddingRight() != 0 || getPaddingTop() != 0 @@ -123,6 +101,17 @@ public class NotificationShadeWindowView extends FrameLayout { setPadding(0, 0, 0, 0); } } + + mLeftInset = 0; + mRightInset = 0; + DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout(); + if (displayCutout != null) { + mLeftInset = displayCutout.getSafeInsetLeft(); + mRightInset = displayCutout.getSafeInsetRight(); + } + mLeftInset = Math.max(insets.left, mLeftInset); + mRightInset = Math.max(insets.right, mRightInset); + applyMargins(); return windowInsets; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index f3b0a79f95189..156a7e5636e0e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -23,12 +23,10 @@ import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFro import android.annotation.Nullable; import android.content.Context; import android.content.res.Configuration; -import android.graphics.Point; import android.graphics.Rect; import android.util.AttributeSet; import android.util.EventLog; import android.util.Pair; -import android.view.Display; import android.view.DisplayCutout; import android.view.Gravity; import android.view.MotionEvent; @@ -36,7 +34,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; import android.view.accessibility.AccessibilityEvent; -import android.widget.FrameLayout; import android.widget.LinearLayout; import com.android.systemui.Dependency; @@ -84,6 +81,8 @@ public class PhoneStatusBarView extends PanelBar { private int mCutoutSideNudge = 0; private boolean mHeadsUpVisible; + private int mRoundedCornerPadding = 0; + public PhoneStatusBarView(Context context, AttributeSet attrs) { super(context, attrs); @@ -294,15 +293,25 @@ public class PhoneStatusBarView extends PanelBar { public void updateResources() { mCutoutSideNudge = getResources().getDimensionPixelSize( R.dimen.display_cutout_margin_consumption); + mRoundedCornerPadding = getResources().getDimensionPixelSize( + R.dimen.rounded_corner_content_padding); + updateStatusBarHeight(); + } + + private void updateStatusBarHeight() { + final int waterfallTopInset = + mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top; ViewGroup.LayoutParams layoutParams = getLayoutParams(); - layoutParams.height = getResources().getDimensionPixelSize(R.dimen.status_bar_height); + layoutParams.height = + getResources().getDimensionPixelSize(R.dimen.status_bar_height) - waterfallTopInset; setLayoutParams(layoutParams); } private void updateLayoutForCutout() { - Pair cornerCutoutMargins = cornerCutoutMargins(mDisplayCutout, - getDisplay()); + updateStatusBarHeight(); + Pair cornerCutoutMargins = + StatusBarWindowView.cornerCutoutMargins(mDisplayCutout, getDisplay()); updateCutoutLocation(cornerCutoutMargins); updateSafeInsets(cornerCutoutMargins); } @@ -337,47 +346,11 @@ public class PhoneStatusBarView extends PanelBar { // Depending on our rotation, we may have to work around a cutout in the middle of the view, // or letterboxing from the right or left sides. - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); - if (mDisplayCutout == null || mDisplayCutout.isEmpty() - || mLastOrientation != ORIENTATION_PORTRAIT || cornerCutoutMargins == null) { - lp.leftMargin = 0; - lp.rightMargin = 0; - return; - } + Pair padding = + StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner( + mDisplayCutout, cornerCutoutMargins, mRoundedCornerPadding); - lp.leftMargin = Math.max(lp.leftMargin, cornerCutoutMargins.first); - lp.rightMargin = Math.max(lp.rightMargin, cornerCutoutMargins.second); - - // If we're already inset enough (e.g. on the status bar side), we can have 0 margin - WindowInsets insets = getRootWindowInsets(); - int leftInset = insets.getSystemWindowInsetLeft(); - int rightInset = insets.getSystemWindowInsetRight(); - if (lp.leftMargin <= leftInset) { - lp.leftMargin = 0; - } - if (lp.rightMargin <= rightInset) { - lp.rightMargin = 0; - } - } - - public static Pair cornerCutoutMargins(DisplayCutout cutout, - Display display) { - if (cutout == null) { - return null; - } - Point size = new Point(); - display.getRealSize(size); - - Rect bounds = new Rect(); - boundsFromDirection(cutout, Gravity.TOP, bounds); - - if (bounds.left <= 0) { - return new Pair<>(bounds.right, 0); - } - if (bounds.right >= size.x) { - return new Pair<>(0, size.x - bounds.left); - } - return null; + setPadding(padding.first, getPaddingTop(), padding.second, getPaddingBottom()); } public void setHeadsUpVisible(boolean headsUpVisible) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index da5df6a72961c..22bf513272f4c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -16,8 +16,21 @@ package com.android.systemui.statusbar.phone; +import static android.view.WindowInsets.Type.systemBars; + +import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection; + import android.content.Context; +import android.graphics.Insets; +import android.graphics.Point; +import android.graphics.Rect; import android.util.AttributeSet; +import android.util.Pair; +import android.view.Display; +import android.view.DisplayCutout; +import android.view.Gravity; +import android.view.View; +import android.view.WindowInsets; import android.widget.FrameLayout; /** @@ -28,7 +41,118 @@ public class StatusBarWindowView extends FrameLayout { public static final String TAG = "PhoneStatusBarWindowView"; public static final boolean DEBUG = StatusBar.DEBUG; + private int mLeftInset = 0; + private int mRightInset = 0; + private int mTopInset = 0; + public StatusBarWindowView(Context context, AttributeSet attrs) { super(context, attrs); } + + @Override + public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) { + final Insets insets = windowInsets.getInsetsIgnoringVisibility(systemBars()); + mLeftInset = 0; + mRightInset = 0; + mTopInset = 0; + DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout(); + if (displayCutout != null) { + mTopInset = displayCutout.getWaterfallInsets().top; + mLeftInset = displayCutout.getSafeInsetLeft(); + mRightInset = displayCutout.getSafeInsetRight(); + } + mLeftInset = Math.max(insets.left, mLeftInset); + mRightInset = Math.max(insets.right, mRightInset); + applyMargins(); + return windowInsets; + } + + private void applyMargins() { + final int count = getChildCount(); + for (int i = 0; i < count; i++) { + View child = getChildAt(i); + if (child.getLayoutParams() instanceof LayoutParams) { + LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset + || lp.topMargin != mTopInset) { + lp.rightMargin = mRightInset; + lp.leftMargin = mLeftInset; + lp.topMargin = mTopInset; + child.requestLayout(); + } + } + } + } + + /** + * Compute the padding needed for status bar related views, e.g., PhoneStatusBar, + * QuickStatusBarHeader and KeyguardStatusBarView). + * + * @param cutout + * @param cornerCutoutPadding + * @param roundedCornerContentPadding + * @return + */ + public static Pair paddingNeededForCutoutAndRoundedCorner( + DisplayCutout cutout, Pair cornerCutoutPadding, + int roundedCornerContentPadding) { + if (cutout == null) { + return new Pair<>(roundedCornerContentPadding, roundedCornerContentPadding); + } + + // compute the padding needed for corner cutout. + final int leftMargin = cutout.getSafeInsetLeft(); + final int rightMargin = cutout.getSafeInsetRight(); + int leftCornerCutoutPadding = 0; + int rightCornerCutoutPadding = 0; + if (cornerCutoutPadding != null) { + if (cornerCutoutPadding.first > leftMargin) { + leftCornerCutoutPadding = cornerCutoutPadding.first - leftMargin; + } + if (cornerCutoutPadding.second > rightMargin) { + rightCornerCutoutPadding = cornerCutoutPadding.second - rightMargin; + } + } + + // compute the padding needed for rounded corner + int leftRoundedCornerPadding = 0; + int rightRoundedCornerPadding = 0; + if (roundedCornerContentPadding > leftMargin) { + leftRoundedCornerPadding = roundedCornerContentPadding - leftMargin; + } + if (roundedCornerContentPadding > rightMargin) { + rightRoundedCornerPadding = roundedCornerContentPadding - rightMargin; + } + + return new Pair<>( + Math.max(leftCornerCutoutPadding, leftRoundedCornerPadding), + Math.max(rightCornerCutoutPadding, rightRoundedCornerPadding)); + } + + /** + * Compute the corner cutout margins + * + * @param cutout + * @param display + * @return + */ + public static Pair cornerCutoutMargins(DisplayCutout cutout, + Display display) { + if (cutout == null) { + return null; + } + Point size = new Point(); + display.getRealSize(size); + + Rect bounds = new Rect(); + boundsFromDirection(cutout, Gravity.TOP, bounds); + + if (bounds.left <= 0) { + return new Pair<>(bounds.right, 0); + } + if (bounds.right >= size.x) { + return new Pair<>(0, size.x - bounds.left); + } + return null; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java index 5706bee3f60dc..79188ce1b5c9f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java @@ -17,25 +17,18 @@ package com.android.systemui; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY; import static com.android.systemui.ScreenDecorations.rectsToRegion; -import static com.android.systemui.tuner.TunablePadding.FLAG_END; -import static com.android.systemui.tuner.TunablePadding.FLAG_START; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.Fragment; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Handler; @@ -43,21 +36,12 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.Display; -import android.view.View; import android.view.WindowManager; import androidx.test.filters.SmallTest; import com.android.systemui.R.dimen; -import com.android.systemui.ScreenDecorations.TunablePaddingTagListener; import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.fragments.FragmentHostManager; -import com.android.systemui.fragments.FragmentService; -import com.android.systemui.statusbar.phone.NotificationShadeWindowView; -import com.android.systemui.statusbar.phone.StatusBar; -import com.android.systemui.statusbar.phone.StatusBarWindowView; -import com.android.systemui.tuner.TunablePadding; -import com.android.systemui.tuner.TunablePadding.TunablePaddingService; import com.android.systemui.tuner.TunerService; import org.junit.Before; @@ -68,8 +52,6 @@ import org.mockito.MockitoAnnotations; import java.util.Collections; -import dagger.Lazy; - @RunWithLooper @RunWith(AndroidTestingRunner.class) @SmallTest @@ -77,19 +59,12 @@ public class ScreenDecorationsTest extends SysuiTestCase { private TestableLooper mTestableLooper; private ScreenDecorations mScreenDecorations; - @Mock private StatusBar mStatusBar; private WindowManager mWindowManager; - private FragmentService mFragmentService; - private FragmentHostManager mFragmentHostManager; - private NotificationShadeWindowView mView; - private StatusBarWindowView mStatusBarWindowView; - private TunablePaddingService mTunablePaddingService; private Handler mMainHandler; @Mock private TunerService mTunerService; @Mock private BroadcastDispatcher mBroadcastDispatcher; - @Mock private Lazy mStatusBarLazy; @Before public void setup() { @@ -97,25 +72,14 @@ public class ScreenDecorationsTest extends SysuiTestCase { mTestableLooper = TestableLooper.get(this); mMainHandler = new Handler(mTestableLooper.getLooper()); - mTunablePaddingService = mDependency.injectMockDependency(TunablePaddingService.class); - mFragmentService = mDependency.injectMockDependency(FragmentService.class); mWindowManager = mock(WindowManager.class); - mView = spy(new NotificationShadeWindowView(mContext, null)); - mStatusBarWindowView = spy(new StatusBarWindowView(mContext, null)); - when(mStatusBarLazy.get()).thenReturn(mStatusBar); - when(mStatusBar.getNotificationShadeWindowView()).thenReturn(mView); - when(mStatusBar.getStatusBarWindow()).thenReturn(mStatusBarWindowView); Display display = mContext.getSystemService(WindowManager.class).getDefaultDisplay(); when(mWindowManager.getDefaultDisplay()).thenReturn(display); mContext.addMockSystemService(WindowManager.class, mWindowManager); - mFragmentHostManager = mock(FragmentHostManager.class); - when(mFragmentService.getFragmentHostManager(any())).thenReturn(mFragmentHostManager); - - - mScreenDecorations = new ScreenDecorations(mContext, mStatusBarLazy, mMainHandler, + mScreenDecorations = new ScreenDecorations(mContext, mMainHandler, mBroadcastDispatcher, mTunerService) { @Override public void start() { @@ -159,8 +123,6 @@ public class ScreenDecorationsTest extends SysuiTestCase { mScreenDecorations.start(); // No views added. verify(mWindowManager, never()).addView(any(), any()); - // No Fragments watched. - verify(mFragmentHostManager, never()).addTagListener(any(), any()); // No Tuners tuned. verify(mTunerService, never()).addTunable(any(), any()); } @@ -178,12 +140,8 @@ public class ScreenDecorationsTest extends SysuiTestCase { // Add 2 windows for rounded corners (top and bottom). verify(mWindowManager, times(2)).addView(any(), any()); - // Add 2 tag listeners for each of the fragments that are needed. - verify(mFragmentHostManager, times(2)).addTagListener(any(), any()); // One tunable. verify(mTunerService, times(1)).addTunable(any(), any()); - // One TunablePadding. - verify(mTunablePaddingService, times(1)).add(any(), anyString(), anyInt(), anyInt()); } @Test @@ -226,29 +184,6 @@ public class ScreenDecorationsTest extends SysuiTestCase { is(PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY)); } - @Test - public void testPaddingTagListener() { - TunablePaddingTagListener tagListener = new TunablePaddingTagListener(14, 5); - View v = mock(View.class); - View child = mock(View.class); - Fragment f = mock(Fragment.class); - TunablePadding padding = mock(TunablePadding.class); - - when(mTunablePaddingService.add(any(), anyString(), anyInt(), anyInt())) - .thenReturn(padding); - when(f.getView()).thenReturn(v); - when(v.findViewById(5)).thenReturn(child); - - // Trigger callback and verify we get a TunablePadding created. - tagListener.onFragmentViewCreated(null, f); - verify(mTunablePaddingService).add(eq(child), eq(ScreenDecorations.PADDING), eq(14), - eq(FLAG_START | FLAG_END)); - - // Call again and verify destroy is called. - tagListener.onFragmentViewCreated(null, f); - verify(padding).destroy(); - } - @Test public void testUpdateRoundedCorners() { mContext.getOrCreateTestableResources().addOverride(