Merge "Make systemui support waterfall"
This commit is contained in:
@@ -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<StatusBar> 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<StatusBar> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Integer, Integer> 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<Integer, Integer> cornerCutoutPadding = StatusBarWindowView.cornerCutoutMargins(
|
||||
cutout, getDisplay());
|
||||
Pair<Integer, Integer> 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,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;
|
||||
@@ -524,6 +525,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,
|
||||
@@ -1739,6 +1742,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 {
|
||||
@@ -5335,7 +5344,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)
|
||||
|
||||
@@ -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<Integer, Integer> 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<Integer, Integer> cornerCutoutMargins) {
|
||||
if (cornerCutoutMargins != null) {
|
||||
setPadding(cornerCutoutMargins.first, 0, cornerCutoutMargins.second, 0);
|
||||
} else {
|
||||
setPadding(0, 0, 0, 0);
|
||||
}
|
||||
private void updatePadding(Pair<Integer, Integer> cornerCutoutMargins) {
|
||||
final int waterfallTop =
|
||||
mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top;
|
||||
Pair<Integer, Integer> 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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Integer, Integer> cornerCutoutMargins = cornerCutoutMargins(mDisplayCutout,
|
||||
getDisplay());
|
||||
updateStatusBarHeight();
|
||||
Pair<Integer, Integer> 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<Integer, Integer> 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<Integer, Integer> 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) {
|
||||
|
||||
@@ -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<Integer, Integer> paddingNeededForCutoutAndRoundedCorner(
|
||||
DisplayCutout cutout, Pair<Integer, Integer> 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<Integer, Integer> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<StatusBar> 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(
|
||||
|
||||
Reference in New Issue
Block a user