Loading packages/SystemUI/res/values/dimens.xml +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1012,4 +1012,7 @@ <!-- How much into a DisplayCutout's bounds we can go, on each side --> <!-- How much into a DisplayCutout's bounds we can go, on each side --> <dimen name="display_cutout_margin_consumption">0px</dimen> <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> </resources> packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +9 −6 Original line number Original line Diff line number Diff line Loading @@ -582,31 +582,34 @@ public class ScreenDecorations extends SystemUI implements Tunable { resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)); 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(); Region bounds = displayCutout.getBounds(); switch (gravity) { switch (gravity) { case Gravity.TOP: case Gravity.TOP: bounds.op(0, 0, Integer.MAX_VALUE, displayCutout.getSafeInsetTop(), bounds.op(0, 0, Integer.MAX_VALUE, displayCutout.getSafeInsetTop(), Region.Op.INTERSECT); Region.Op.INTERSECT); out.set(bounds.getBounds()); break; break; case Gravity.LEFT: case Gravity.LEFT: bounds.op(0, 0, displayCutout.getSafeInsetLeft(), Integer.MAX_VALUE, bounds.op(0, 0, displayCutout.getSafeInsetLeft(), Integer.MAX_VALUE, Region.Op.INTERSECT); Region.Op.INTERSECT); out.set(bounds.getBounds()); break; break; case Gravity.BOTTOM: case Gravity.BOTTOM: bounds.op(0, displayCutout.getSafeInsetTop() + 1, Integer.MAX_VALUE, bounds.op(0, displayCutout.getSafeInsetTop() + 1, Integer.MAX_VALUE, Integer.MAX_VALUE, Region.Op.INTERSECT); Integer.MAX_VALUE, Region.Op.INTERSECT); out.set(bounds.getBounds()); break; break; case Gravity.RIGHT: case Gravity.RIGHT: bounds.op(displayCutout.getSafeInsetLeft() + 1, 0, Integer.MAX_VALUE, bounds.op(displayCutout.getSafeInsetLeft() + 1, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, Region.Op.INTERSECT); Integer.MAX_VALUE, Region.Op.INTERSECT); out.set(bounds.getBounds()); break; break; } } bounds.recycle(); return bounds; } } private void localBounds(Rect out) { private void localBounds(Rect out) { Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +41 −4 Original line number Original line Diff line number Diff line Loading @@ -22,14 +22,21 @@ import android.content.Context; import android.content.res.Configuration; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources; import androidx.collection.ArraySet; import androidx.collection.ArraySet; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Region.Op; import android.util.Log; import android.util.Log; import android.util.Pools; import android.util.Pools; import android.view.DisplayCutout; import android.view.Gravity; import android.view.View; import android.view.View; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.InternalInsetsInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.ScreenDecorations; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarState; Loading @@ -41,6 +48,7 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.HashSet; import java.util.HashSet; import java.util.List; import java.util.Stack; import java.util.Stack; /** /** Loading @@ -60,6 +68,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, private int mStatusBarHeight; private int mStatusBarHeight; private int mHeadsUpInset; private int mHeadsUpInset; private int mDisplayCutoutTouchableRegionSize; private boolean mTrackingHeadsUp; private boolean mTrackingHeadsUp; private HashSet<String> mSwipedOutKeys = new HashSet<>(); private HashSet<String> mSwipedOutKeys = new HashSet<>(); private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>(); private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>(); Loading Loading @@ -120,6 +129,8 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, com.android.internal.R.dimen.status_bar_height); com.android.internal.R.dimen.status_bar_height); mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize( mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize( R.dimen.heads_up_status_bar_padding); R.dimen.heads_up_status_bar_padding); mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize( R.dimen.display_cutout_touchable_region_size); } } @Override @Override Loading @@ -128,6 +139,11 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, initResources(); initResources(); } } @Override public void onOverlayChanged() { initResources(); } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// // Public methods: // Public methods: Loading Loading @@ -301,10 +317,30 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height); info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height); } else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) { } else { setCollapsedTouchableInsets(info); } } private void setCollapsedTouchableInsets(ViewTreeObserver.InternalInsetsInfo info) { info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight); 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 @Override Loading Loading @@ -403,7 +439,8 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, private void updateTouchableRegionListener() { private void updateTouchableRegionListener() { boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway; || mWaitingOnCollapseWhenGoingAway || mStatusBarWindowView.getRootWindowInsets().getDisplayCutout() != null; if (shouldObserve == mIsObserving) { if (shouldObserve == mIsObserving) { return; return; } } Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +26 −0 Original line number Original line Diff line number Diff line Loading @@ -94,6 +94,12 @@ public class StatusBarWindowView extends FrameLayout { private boolean mExpandAnimationRunning; private boolean mExpandAnimationRunning; private boolean mExpandAnimationPending; 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) { public StatusBarWindowView(Context context, AttributeSet attrs) { super(context, attrs); super(context, attrs); setMotionEventSplittingEnabled(false); setMotionEventSplittingEnabled(false); Loading Loading @@ -258,7 +264,16 @@ public class StatusBarWindowView extends FrameLayout { @Override @Override public boolean dispatchTouchEvent(MotionEvent ev) { public boolean dispatchTouchEvent(MotionEvent ev) { boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN; boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN; boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP; boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL; 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()) { if (!isCancel && mService.shouldIgnoreTouch()) { return false; return false; } } Loading Loading @@ -291,6 +306,17 @@ public class StatusBarWindowView extends FrameLayout { mService.mDozeScrimController.extendPulse(); 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); return super.dispatchTouchEvent(ev); } } Loading Loading
packages/SystemUI/res/values/dimens.xml +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1012,4 +1012,7 @@ <!-- How much into a DisplayCutout's bounds we can go, on each side --> <!-- How much into a DisplayCutout's bounds we can go, on each side --> <dimen name="display_cutout_margin_consumption">0px</dimen> <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> </resources>
packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +9 −6 Original line number Original line Diff line number Diff line Loading @@ -582,31 +582,34 @@ public class ScreenDecorations extends SystemUI implements Tunable { resolveSizeAndState(mBoundingRect.height(), heightMeasureSpec, 0)); 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(); Region bounds = displayCutout.getBounds(); switch (gravity) { switch (gravity) { case Gravity.TOP: case Gravity.TOP: bounds.op(0, 0, Integer.MAX_VALUE, displayCutout.getSafeInsetTop(), bounds.op(0, 0, Integer.MAX_VALUE, displayCutout.getSafeInsetTop(), Region.Op.INTERSECT); Region.Op.INTERSECT); out.set(bounds.getBounds()); break; break; case Gravity.LEFT: case Gravity.LEFT: bounds.op(0, 0, displayCutout.getSafeInsetLeft(), Integer.MAX_VALUE, bounds.op(0, 0, displayCutout.getSafeInsetLeft(), Integer.MAX_VALUE, Region.Op.INTERSECT); Region.Op.INTERSECT); out.set(bounds.getBounds()); break; break; case Gravity.BOTTOM: case Gravity.BOTTOM: bounds.op(0, displayCutout.getSafeInsetTop() + 1, Integer.MAX_VALUE, bounds.op(0, displayCutout.getSafeInsetTop() + 1, Integer.MAX_VALUE, Integer.MAX_VALUE, Region.Op.INTERSECT); Integer.MAX_VALUE, Region.Op.INTERSECT); out.set(bounds.getBounds()); break; break; case Gravity.RIGHT: case Gravity.RIGHT: bounds.op(displayCutout.getSafeInsetLeft() + 1, 0, Integer.MAX_VALUE, bounds.op(displayCutout.getSafeInsetLeft() + 1, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, Region.Op.INTERSECT); Integer.MAX_VALUE, Region.Op.INTERSECT); out.set(bounds.getBounds()); break; break; } } bounds.recycle(); return bounds; } } private void localBounds(Rect out) { private void localBounds(Rect out) { Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java +41 −4 Original line number Original line Diff line number Diff line Loading @@ -22,14 +22,21 @@ import android.content.Context; import android.content.res.Configuration; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources; import androidx.collection.ArraySet; import androidx.collection.ArraySet; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Region.Op; import android.util.Log; import android.util.Log; import android.util.Pools; import android.util.Pools; import android.view.DisplayCutout; import android.view.Gravity; import android.view.View; import android.view.View; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.InternalInsetsInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.ScreenDecorations; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.NotificationData; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.StatusBarState; Loading @@ -41,6 +48,7 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import java.io.FileDescriptor; import java.io.FileDescriptor; import java.io.PrintWriter; import java.io.PrintWriter; import java.util.HashSet; import java.util.HashSet; import java.util.List; import java.util.Stack; import java.util.Stack; /** /** Loading @@ -60,6 +68,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, private int mStatusBarHeight; private int mStatusBarHeight; private int mHeadsUpInset; private int mHeadsUpInset; private int mDisplayCutoutTouchableRegionSize; private boolean mTrackingHeadsUp; private boolean mTrackingHeadsUp; private HashSet<String> mSwipedOutKeys = new HashSet<>(); private HashSet<String> mSwipedOutKeys = new HashSet<>(); private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>(); private HashSet<NotificationData.Entry> mEntriesToRemoveAfterExpand = new HashSet<>(); Loading Loading @@ -120,6 +129,8 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, com.android.internal.R.dimen.status_bar_height); com.android.internal.R.dimen.status_bar_height); mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize( mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize( R.dimen.heads_up_status_bar_padding); R.dimen.heads_up_status_bar_padding); mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize( R.dimen.display_cutout_touchable_region_size); } } @Override @Override Loading @@ -128,6 +139,11 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, initResources(); initResources(); } } @Override public void onOverlayChanged() { initResources(); } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// // Public methods: // Public methods: Loading Loading @@ -301,10 +317,30 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height); info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height); } else if (mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway) { } else { setCollapsedTouchableInsets(info); } } private void setCollapsedTouchableInsets(ViewTreeObserver.InternalInsetsInfo info) { info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION); info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight); 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 @Override Loading Loading @@ -403,7 +439,8 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable, private void updateTouchableRegionListener() { private void updateTouchableRegionListener() { boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway boolean shouldObserve = hasPinnedHeadsUp() || mHeadsUpGoingAway || mWaitingOnCollapseWhenGoingAway; || mWaitingOnCollapseWhenGoingAway || mStatusBarWindowView.getRootWindowInsets().getDisplayCutout() != null; if (shouldObserve == mIsObserving) { if (shouldObserve == mIsObserving) { return; return; } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +26 −0 Original line number Original line Diff line number Diff line Loading @@ -94,6 +94,12 @@ public class StatusBarWindowView extends FrameLayout { private boolean mExpandAnimationRunning; private boolean mExpandAnimationRunning; private boolean mExpandAnimationPending; 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) { public StatusBarWindowView(Context context, AttributeSet attrs) { super(context, attrs); super(context, attrs); setMotionEventSplittingEnabled(false); setMotionEventSplittingEnabled(false); Loading Loading @@ -258,7 +264,16 @@ public class StatusBarWindowView extends FrameLayout { @Override @Override public boolean dispatchTouchEvent(MotionEvent ev) { public boolean dispatchTouchEvent(MotionEvent ev) { boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN; boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN; boolean isUp = ev.getActionMasked() == MotionEvent.ACTION_UP; boolean isCancel = ev.getActionMasked() == MotionEvent.ACTION_CANCEL; 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()) { if (!isCancel && mService.shouldIgnoreTouch()) { return false; return false; } } Loading Loading @@ -291,6 +306,17 @@ public class StatusBarWindowView extends FrameLayout { mService.mDozeScrimController.extendPulse(); 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); return super.dispatchTouchEvent(ev); } } Loading