Enable expanding of status bar just below the notch
Test: Expand status bar with cutout emulation enabled
Bug: 79435224
Change-Id: I427f382578f4dc2abe347973323bb455cb67594d
Merged-In: I427f382578f4dc2abe347973323bb455cb67594d
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f00957a..3b58b72 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1012,4 +1012,7 @@
<!-- How much into a DisplayCutout's bounds we can go, on each side -->
<dimen name="display_cutout_margin_consumption">0px</dimen>
+ <!-- How much we expand the touchable region of the status bar below the notch to catch touches
+ that just start below the notch. -->
+ <dimen name="display_cutout_touchable_region_size">12dp</dimen>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index efaf557..6d5e938 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -560,31 +560,34 @@
resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0));
}
- public static void boundsFromDirection(DisplayCutout displayCutout, int gravity, Rect out) {
+ public static void boundsFromDirection(DisplayCutout displayCutout, int gravity,
+ Rect out) {
+ Region bounds = boundsFromDirection(displayCutout, gravity);
+ out.set(bounds.getBounds());
+ bounds.recycle();
+ }
+
+ public static Region boundsFromDirection(DisplayCutout displayCutout, int gravity) {
Region bounds = displayCutout.getBounds();
switch (gravity) {
case Gravity.TOP:
bounds.op(0, 0, Integer.MAX_VALUE, displayCutout.getSafeInsetTop(),
Region.Op.INTERSECT);
- out.set(bounds.getBounds());
break;
case Gravity.LEFT:
bounds.op(0, 0, displayCutout.getSafeInsetLeft(), Integer.MAX_VALUE,
Region.Op.INTERSECT);
- out.set(bounds.getBounds());
break;
case Gravity.BOTTOM:
bounds.op(0, displayCutout.getSafeInsetTop() + 1, Integer.MAX_VALUE,
Integer.MAX_VALUE, Region.Op.INTERSECT);
- out.set(bounds.getBounds());
break;
case Gravity.RIGHT:
bounds.op(displayCutout.getSafeInsetLeft() + 1, 0, Integer.MAX_VALUE,
Integer.MAX_VALUE, Region.Op.INTERSECT);
- out.set(bounds.getBounds());
break;
}
- bounds.recycle();
+ return bounds;
}
private void localBounds(Rect out) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index fa0a774..0aad438 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -21,15 +21,22 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.graphics.Region.Op;
import android.support.v4.util.ArraySet;
import android.util.Log;
import android.util.Pools;
+import android.view.DisplayCutout;
+import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.InternalInsetsInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.ScreenDecorations;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.StatusBarState;
@@ -41,6 +48,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashSet;
+import java.util.List;
import java.util.Stack;
/**
@@ -60,6 +68,7 @@
private int mStatusBarHeight;
private int mHeadsUpInset;
+ private int mDisplayCutoutTouchableRegionSize;
private boolean mTrackingHeadsUp;
private HashSet<String> mSwipedOutKeys = new HashSet<>();
private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>();
@@ -120,6 +129,8 @@
com.android.internal.R.dimen.status_bar_height);
mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize(
R.dimen.heads_up_status_bar_padding);
+ mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize(
+ R.dimen.display_cutout_touchable_region_size);
}
@Override
@@ -128,6 +139,11 @@
initResources();
}
+ @Override
+ public void onOverlayChanged() {
+ initResources();
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////////
// Public methods:
@@ -301,12 +317,32 @@
info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height);
- } else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) {
- info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
- info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
+ } else {
+ setCollapsedTouchableInsets(info);
}
}
+ private void setCollapsedTouchableInsets(ViewTreeObserver.InternalInsetsInfo info) {
+ info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+ info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
+ updateRegionForNotch(info.touchableRegion);
+ }
+
+ private void updateRegionForNotch(Region region) {
+ DisplayCutout cutout = mStatusBarWindowView.getRootWindowInsets().getDisplayCutout();
+ if (cutout == null) {
+ return;
+ }
+
+ // Expand touchable region such that we also catch touches that just start below the notch
+ // area.
+ Region bounds = ScreenDecorations.DisplayCutoutView.boundsFromDirection(
+ cutout, Gravity.TOP);
+ bounds.translate(0, mDisplayCutoutTouchableRegionSize);
+ region.op(bounds, Op.UNION);
+ bounds.recycle();
+ }
+
@Override
public void onConfigChanged(Configuration newConfig) {
Resources resources = mContext.getResources();
@@ -403,7 +439,8 @@
private void updateTouchableRegionListener() {
boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway
- || mWaitingOnCollapseWhenGoingAway;
+ || mWaitingOnCollapseWhenGoingAway
+ || mStatusBarWindowView.getRootWindowInsets().getDisplayCutout() != null;
if (shouldObserve == mIsObserving) {
return;
}
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 a79a41b..0390f60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -94,6 +94,12 @@
private boolean mExpandAnimationRunning;
private boolean mExpandAnimationPending;
+ /**
+ * If set to true, the current gesture started below the notch and we need to dispatch touch
+ * events manually as it's outside of the regular view bounds.
+ */
+ private boolean mExpandingBelowNotch;
+
public StatusBarWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
setMotionEventSplittingEnabled(false);
@@ -258,7 +264,16 @@
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
+ boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP;
boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL;
+
+ // Reset manual touch dispatch state here but make sure the UP/CANCEL event still gets
+ // delivered.
+ boolean expandingBelowNotch = mExpandingBelowNotch;
+ if (isUp || isCancel) {
+ mExpandingBelowNotch = false;
+ }
+
if (!isCancel && mService.shouldIgnoreTouch()) {
return false;
}
@@ -291,6 +306,17 @@
mService.mDozeScrimController.extendPulse();
}
+ // In case we start outside of the view bounds (below the status bar), we need to dispatch
+ // the touch manually as the view system can't accomodate for touches outside of the
+ // regular view bounds.
+ if (isDown && ev.getY() >= mBottom) {
+ mExpandingBelowNotch = true;
+ expandingBelowNotch = true;
+ }
+ if (expandingBelowNotch) {
+ return mNotificationPanel.dispatchTouchEvent(ev);
+ }
+
return super.dispatchTouchEvent(ev);
}