Fixing Heads Up Notifications not reacting to action touches in split shade

HUN was not reacting to touches because notification was shifted too low and touch-enabled region was not moving with it. The fix is to not shift notification that much in split shade mode - extra shift was introduced by split shade status bar. Now split shade status bar margin is accounted for in HUN shift calculation.
Also some small cleaning of dead code which I was trying to read :)

Fixes: 201262024
Test: StackScrollAlgorithmTest
Change-Id: I50498c3e038651ff9ee38e9741056933f0c369c8
This commit is contained in:
Michal Brzezinski
2021-10-11 12:55:24 +01:00
parent 635fef18d6
commit e75a1eb617
6 changed files with 76 additions and 67 deletions

View File

@@ -22,7 +22,6 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.view.MotionEvent;
@@ -111,7 +110,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private Interpolator mCurrentAppearInterpolator;
NotificationBackgroundView mBackgroundNormal;
private RectF mAppearAnimationRect = new RectF();
private float mAnimationTranslationY;
private boolean mDrawingAppearAnimation;
private ValueAnimator mAppearAnimator;
@@ -123,13 +121,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private long mLastActionUpTime;
private float mNormalBackgroundVisibilityAmount;
private ValueAnimator.AnimatorUpdateListener mBackgroundVisibilityUpdater
= new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
setNormalBackgroundVisibilityAmount(mBackgroundNormal.getAlpha());
}
};
private FakeShadowView mFakeShadow;
private int mCurrentBackgroundTint;
private int mTargetTint;
@@ -138,11 +129,8 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
private float mOverrideAmount;
private boolean mShadowHidden;
private boolean mIsHeadsUpAnimation;
private int mHeadsUpAddStartLocation;
private float mHeadsUpLocation;
/* In order to track headsup longpress coorindate. */
protected Point mTargetPoint;
private boolean mIsAppearing;
private boolean mDismissed;
private boolean mRefocusOnDismiss;
private AccessibilityManager mAccessibilityManager;
@@ -154,7 +142,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
setClipChildren(false);
setClipToPadding(false);
updateColors();
initDimens();
}
private void updateColors() {
@@ -166,17 +153,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
R.color.notification_ripple_untinted_color);
}
private void initDimens() {
mHeadsUpAddStartLocation = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_start);
}
@Override
public void onDensityOrFontScaleChanged() {
super.onDensityOrFontScaleChanged();
initDimens();
}
/**
* Reload background colors from resources and invalidate views.
*/
@@ -438,7 +414,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
Runnable onFinishedRunnable, AnimatorListenerAdapter animationListener) {
enableAppearDrawing(true);
mIsHeadsUpAnimation = isHeadsUpAnimation;
mHeadsUpLocation = endLocation;
if (mDrawingAppearAnimation) {
startAppearAnimation(false /* isAppearing */, translationDirection,
delay, duration, onFinishedRunnable, animationListener);
@@ -452,7 +427,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
public void performAddAnimation(long delay, long duration, boolean isHeadsUpAppear) {
enableAppearDrawing(true);
mIsHeadsUpAnimation = isHeadsUpAppear;
mHeadsUpLocation = mHeadsUpAddStartLocation;
if (mDrawingAppearAnimation) {
startAppearAnimation(true /* isAppearing */, isHeadsUpAppear ? 0.0f : -1.0f, delay,
duration, null, null);
@@ -474,7 +448,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
mAppearAnimationTranslation = 0;
}
}
mIsAppearing = isAppearing;
float targetValue;
if (isAppearing) {
@@ -782,8 +755,4 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
void onActivated(ActivatableNotificationView view);
void onActivationReset(ActivatableNotificationView view);
}
interface OnDimmedListener {
void onSetDimmed(boolean dimmed);
}
}

View File

@@ -72,7 +72,6 @@ public class AmbientState {
private boolean mPanelFullWidth;
private boolean mPulsing;
private boolean mUnlockHintRunning;
private int mIntrinsicPadding;
private float mHideAmount;
private boolean mAppearing;
private float mPulseHeight = MAX_PULSE_HEIGHT;
@@ -82,6 +81,7 @@ public class AmbientState {
private float mAppearFraction;
private boolean mIsShadeOpening;
private float mOverExpansion;
private int mStackTopMargin;
/** Distance of top of notifications panel from top of screen. */
private float mStackY = 0;
@@ -94,7 +94,6 @@ public class AmbientState {
/** Height of the notifications panel without top padding when expansion completes. */
private float mStackEndHeight;
private float mTransitionToFullShadeAmount;
/**
* @return Height of the notifications panel without top padding when expansion completes.
@@ -493,14 +492,6 @@ public class AmbientState {
return mUnlockHintRunning;
}
public void setIntrinsicPadding(int intrinsicPadding) {
mIntrinsicPadding = intrinsicPadding;
}
public int getIntrinsicPadding() {
return mIntrinsicPadding;
}
/**
* @return whether a view is dozing and not pulsing right now
*/
@@ -577,29 +568,10 @@ public class AmbientState {
mOnPulseHeightChangedListener = onPulseHeightChangedListener;
}
public Runnable getOnPulseHeightChangedListener() {
return mOnPulseHeightChangedListener;
}
public void setTrackedHeadsUpRow(ExpandableNotificationRow row) {
mTrackedHeadsUpRow = row;
}
/**
* Set the amount of pixels we have currently dragged down if we're transitioning to the full
* shade. 0.0f means we're not transitioning yet.
*/
public void setTransitionToFullShadeAmount(float transitionToFullShadeAmount) {
mTransitionToFullShadeAmount = transitionToFullShadeAmount;
}
/**
* get
*/
public float getTransitionToFullShadeAmount() {
return mTransitionToFullShadeAmount;
}
/**
* Returns the currently tracked heads up row, if there is one and it is currently above the
* shelf (still appearing).
@@ -622,4 +594,12 @@ public class AmbientState {
public void setHasAlertEntries(boolean hasAlertEntries) {
mHasAlertEntries = hasAlertEntries;
}
public void setStackTopMargin(int stackTopMargin) {
mStackTopMargin = stackTopMargin;
}
public int getStackTopMargin() {
return mStackTopMargin;
}
}

View File

@@ -4287,7 +4287,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
void setIntrinsicPadding(int intrinsicPadding) {
mIntrinsicPadding = intrinsicPadding;
mAmbientState.setIntrinsicPadding(intrinsicPadding);
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)

View File

@@ -24,6 +24,8 @@ import android.util.MathUtils;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.NotificationShelf;
@@ -54,8 +56,7 @@ public class StackScrollAlgorithm {
private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
private boolean mIsExpanded;
private boolean mClipNotificationScrollToTop;
private int mStatusBarHeight;
private float mHeadsUpInset;
@VisibleForTesting float mHeadsUpInset;
private int mPinnedZTranslationExtra;
private float mNotificationScrimPadding;
@@ -75,9 +76,9 @@ public class StackScrollAlgorithm {
mPaddingBetweenElements = res.getDimensionPixelSize(
R.dimen.notification_divider_height);
mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
mStatusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
mClipNotificationScrollToTop = res.getBoolean(R.bool.config_clipNotificationScrollToTop);
mHeadsUpInset = mStatusBarHeight + res.getDimensionPixelSize(
int statusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
mHeadsUpInset = statusBarHeight + res.getDimensionPixelSize(
R.dimen.heads_up_status_bar_padding);
mPinnedZTranslationExtra = res.getDimensionPixelSize(
R.dimen.heads_up_pinned_elevation);
@@ -562,13 +563,14 @@ public class StackScrollAlgorithm {
// Move the tracked heads up into position during the appear animation, by interpolating
// between the HUN inset (where it will appear as a HUN) and the end position in the shade
float headsUpTranslation = mHeadsUpInset - ambientState.getStackTopMargin();
ExpandableNotificationRow trackedHeadsUpRow = ambientState.getTrackedHeadsUpRow();
if (trackedHeadsUpRow != null) {
ExpandableViewState childState = trackedHeadsUpRow.getViewState();
if (childState != null) {
float endPosition = childState.yTranslation - ambientState.getStackTranslation();
childState.yTranslation = MathUtils.lerp(
mHeadsUpInset, endPosition, ambientState.getAppearFraction());
headsUpTranslation, endPosition, ambientState.getAppearFraction());
}
}
@@ -602,7 +604,7 @@ public class StackScrollAlgorithm {
}
}
if (row.isPinned()) {
childState.yTranslation = Math.max(childState.yTranslation, mHeadsUpInset);
childState.yTranslation = Math.max(childState.yTranslation, headsUpTranslation);
childState.height = Math.max(row.getIntrinsicHeight(), childState.height);
childState.hidden = false;
ExpandableViewState topState =

View File

@@ -1012,6 +1012,7 @@ public class NotificationPanelViewController extends PanelViewController {
constraintSet.setMargin(R.id.notification_stack_scroller, TOP, topMargin);
constraintSet.setMargin(R.id.qs_frame, TOP, topMargin);
constraintSet.applyTo(mNotificationContainerParent);
mAmbientState.setStackTopMargin(topMargin);
mNotificationsQSContainerController.setSplitShadeEnabled(mShouldUseSplitNotificationShade);
updateKeyguardStatusViewAlignment(/* animate= */false);

View File

@@ -0,0 +1,58 @@
package com.android.systemui.statusbar.notification.stack
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mock
import org.mockito.Mockito.`when` as whenever
@SmallTest
class StackScrollAlgorithmTest : SysuiTestCase() {
private val hostView = FrameLayout(context)
private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView)
private val expandableViewState = ExpandableViewState()
private val notificationRow = mock(ExpandableNotificationRow::class.java)
private val ambientState = AmbientState(
context,
SectionProvider { _, _ -> false },
BypassController { false })
@Before
fun setUp() {
whenever(notificationRow.viewState).thenReturn(expandableViewState)
hostView.addView(notificationRow)
}
@Test
fun testUpTranslationSetToDefaultValue() {
whenever(notificationRow.isPinned).thenReturn(true)
whenever(notificationRow.isHeadsUp).thenReturn(true)
stackScrollAlgorithm.resetViewStates(ambientState, 0)
assertThat(expandableViewState.yTranslation).isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
}
@Test
fun testHeadsUpTranslationChangesBasedOnStackMargin() {
whenever(notificationRow.isPinned).thenReturn(true)
whenever(notificationRow.isHeadsUp).thenReturn(true)
val minHeadsUpTranslation = context.resources
.getDimensionPixelSize(R.dimen.notification_side_paddings)
// split shade case with top margin introduced by shade's status bar
ambientState.stackTopMargin = 100
stackScrollAlgorithm.resetViewStates(ambientState, 0)
// top margin presence should decrease heads up translation up to minHeadsUpTranslation
assertThat(expandableViewState.yTranslation).isEqualTo(minHeadsUpTranslation)
}
}