Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 514a84cf authored by Dave Mankoff's avatar Dave Mankoff
Browse files

Fill in ActivatableNotificationViewController.

This removes calls to Dependency.get() from
ActivatableNotificationView. The controller still isn't
fully fleshed out due to the current structure of the code,
but it is a step in the right direction.

Future CL's will add more controllers for futher subclasses.

Bug: 14724574
Test: atest SystemUITests
Change-Id: If72c1e19af69c41f9c557147e13593b33ba32bce
parent 6cd4ee4c
Loading
Loading
Loading
Loading
+51 −120
Original line number Diff line number Diff line
@@ -29,20 +29,17 @@ import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;

import com.android.systemui.Dependency;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.FakeShadowView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DoubleTapHelper;

/**
 * Base class for both {@link ExpandableNotificationRow} and {@link NotificationShelf}
@@ -94,14 +91,12 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
    private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
            = new PathInterpolator(0, 0, 0.5f, 1);
    private int mTintedRippleColor;
    protected int mNormalRippleColor;
    private final AccessibilityManager mAccessibilityManager;
    private final DoubleTapHelper mDoubleTapHelper;
    private int mNormalRippleColor;
    private Gefingerpoken mTouchHandler;

    private boolean mDimmed;

    protected int mBgTint = NO_COLOR;
    private float mBgAlpha = 1f;
    int mBgTint = NO_COLOR;

    /**
     * Flag to indicate that the notification has been touched once and the second touch will
@@ -116,7 +111,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
    private Interpolator mCurrentAppearInterpolator;
    private Interpolator mCurrentAlphaInterpolator;

    protected NotificationBackgroundView mBackgroundNormal;
    NotificationBackgroundView mBackgroundNormal;
    private NotificationBackgroundView mBackgroundDimmed;
    private ObjectAnimator mBackgroundAnimator;
    private RectF mAppearAnimationRect = new RectF();
@@ -130,7 +125,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
    private boolean mLastInSection;
    private boolean mFirstInSection;
    private boolean mIsBelowSpeedBump;
    private final FalsingManager mFalsingManager;

    private float mNormalBackgroundVisibilityAmount;
    private float mDimmedBackgroundFadeInAmount = -1;
@@ -154,38 +148,24 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
     */
    private boolean mNeedsDimming;
    private int mDimmedAlpha;
    private boolean mBlockNextTouch;
    private boolean mIsHeadsUpAnimation;
    private int mHeadsUpAddStartLocation;
    private float mHeadsUpLocation;
    private boolean mIsAppearing;
    private boolean mDismissed;
    private boolean mRefocusOnDismiss;
    private OnDimmedListener mOnDimmedListener;

    public ActivatableNotificationView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
        mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
        mFalsingManager = Dependency.get(FalsingManager.class);  // TODO: inject into a controller.
        setClipChildren(false);
        setClipToPadding(false);
        updateColors();
        mAccessibilityManager = AccessibilityManager.getInstance(mContext);

        mDoubleTapHelper = new DoubleTapHelper(this, (active) -> {
            if (active) {
                makeActive();
            } else {
                makeInactive(true /* animate */);
            }
        }, super::performClick, this::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
        initDimens();
    }

    public FalsingManager getFalsingManager() {
        return mFalsingManager;
    }

    private void updateColors() {
        mNormalColor = mContext.getColor(R.color.notification_material_background_color);
        mTintedRippleColor = mContext.getColor(
@@ -236,32 +216,15 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        mBackgroundDimmed.setCustomBackground(R.drawable.notification_material_bg_dim);
    }

    private final Runnable mTapTimeoutRunnable = new Runnable() {
        @Override
        public void run() {
            makeInactive(true /* animate */);
        }
    };

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (mNeedsDimming && ev.getActionMasked() == MotionEvent.ACTION_DOWN
                && disallowSingleClick(ev) && !isTouchExplorationEnabled()) {
            if (!mActivated) {
                return true;
            } else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
                mBlockNextTouch = true;
                makeInactive(true /* animate */);
        if (mTouchHandler != null && mTouchHandler.onInterceptTouchEvent(ev)) {
            return true;
        }
        }
        return super.onInterceptTouchEvent(ev);
    }

    private boolean isTouchExplorationEnabled() {
        return mAccessibilityManager.isTouchExplorationEnabled();
    }

    protected boolean disallowSingleClick(MotionEvent ev) {
        return false;
    }
@@ -270,25 +233,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean result;
        if (mBlockNextTouch) {
            mBlockNextTouch = false;
            return false;
        }
        if (mNeedsDimming && !isTouchExplorationEnabled() && isInteractive()) {
            boolean wasActivated = mActivated;
            result = handleTouchEventDimmed(event);
            if (wasActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
                removeCallbacks(mTapTimeoutRunnable);
            }
        } else {
            result = super.onTouchEvent(event);
        }
        return result;
    }

    /**
     * @return whether this view is interactive and can be double tapped
     */
@@ -313,28 +257,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        }
    }

    public void setRippleAllowed(boolean allowed) {
    void setRippleAllowed(boolean allowed) {
        mBackgroundNormal.setPressedAllowed(allowed);
    }

    private boolean handleTouchEventDimmed(MotionEvent event) {
        if (mNeedsDimming && !mDimmed) {
            // We're actually dimmed, but our content isn't dimmable, let's ensure we have a ripple
            super.onTouchEvent(event);
        }
        return mDoubleTapHelper.onTouchEvent(event, getActualHeight());
    }

    @Override
    public boolean performClick() {
        if (!mNeedsDimming || isTouchExplorationEnabled()) {
            return super.performClick();
        }
        return false;
    }

    private void makeActive() {
        mFalsingManager.onNotificationActive();
    void makeActive() {
        startActivateAnimation(false /* reverse */);
        mActivated = true;
        if (mOnActivatedListener != null) {
@@ -388,15 +315,12 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        mBackgroundNormal.animate()
                .alpha(reverse ? 0f : 1f)
                .setInterpolator(alphaInterpolator)
                .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                .setUpdateListener(animation -> {
                    float animatedFraction = animation.getAnimatedFraction();
                    if (reverse) {
                        animatedFraction = 1.0f - animatedFraction;
                    }
                    setNormalBackgroundVisibilityAmount(animatedFraction);
                    }
                })
                .setDuration(ACTIVATE_ANIMATION_LENGTH);
    }
@@ -418,11 +342,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        if (mOnActivatedListener != null) {
            mOnActivatedListener.onActivationReset(this);
        }
        removeCallbacks(mTapTimeoutRunnable);
    }

    public void setDimmed(boolean dimmed, boolean fade) {
        mNeedsDimming = dimmed;
        if (mOnDimmedListener != null) {
            mOnDimmedListener.onSetDimmed(dimmed);
        }
        dimmed &= isDimmable();
        if (mDimmed != dimmed) {
            mDimmed = dimmed;
@@ -439,13 +365,17 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        return true;
    }

    public boolean isDimmed() {
        return mDimmed;
    }

    private void updateOutlineAlpha() {
        float alpha = NotificationStackScrollLayout.BACKGROUND_ALPHA_DIMMED;
        alpha = (alpha + (1.0f - alpha) * mNormalBackgroundVisibilityAmount);
        setOutlineAlpha(alpha);
    }

    public void setNormalBackgroundVisibilityAmount(float normalBackgroundVisibilityAmount) {
    private void setNormalBackgroundVisibilityAmount(float normalBackgroundVisibilityAmount) {
        mNormalBackgroundVisibilityAmount = normalBackgroundVisibilityAmount;
        updateOutlineAlpha();
    }
@@ -473,14 +403,14 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
    /**
     * Sets the tint color of the background
     */
    public void setTintColor(int color) {
    protected void setTintColor(int color) {
        setTintColor(color, false);
    }

    /**
     * Sets the tint color of the background
     */
    public void setTintColor(int color, boolean animated) {
    void setTintColor(int color, boolean animated) {
        if (color != mBgTint) {
            mBgTint = color;
            updateBackgroundTint(animated);
@@ -562,13 +492,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
            mStartTint = mCurrentBackgroundTint;
            mTargetTint = color;
            mBackgroundColorAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
            mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
            mBackgroundColorAnimator.addUpdateListener(animation -> {
                int newColor = NotificationUtils.interpolateColors(mStartTint, mTargetTint,
                        animation.getAnimatedFraction());
                setBackgroundTintColor(newColor);
                }
            });
            mBackgroundColorAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
            mBackgroundColorAnimator.setInterpolator(Interpolators.LINEAR);
@@ -643,11 +570,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
    }

    protected void updateBackgroundAlpha(float transformationAmount) {
        mBgAlpha =  isChildInGroup() && mDimmed ? transformationAmount : 1f;
        float bgAlpha = isChildInGroup() && mDimmed ? transformationAmount : 1f;
        if (mDimmedBackgroundFadeInAmount != -1) {
            mBgAlpha *= mDimmedBackgroundFadeInAmount;
            bgAlpha *= mDimmedBackgroundFadeInAmount;
        }
        mBackgroundDimmed.setAlpha(mBgAlpha);
        mBackgroundDimmed.setAlpha(bgAlpha);
    }

    protected void resetBackgroundAlpha() {
@@ -671,7 +598,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
            mBackgroundDimmed.setVisibility(View.INVISIBLE);
            mBackgroundNormal.setVisibility(View.VISIBLE);
            mBackgroundNormal.setAlpha(1f);
            removeCallbacks(mTapTimeoutRunnable);
            // make in inactive to avoid it sticking around active
            makeInactive(false /* animate */);
        }
@@ -783,14 +709,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        mAppearAnimator.setInterpolator(Interpolators.LINEAR);
        mAppearAnimator.setDuration(
                (long) (duration * Math.abs(mAppearAnimationFraction - targetValue)));
        mAppearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
        mAppearAnimator.addUpdateListener(animation -> {
            mAppearAnimationFraction = (float) animation.getAnimatedValue();
            updateAppearAnimationAlpha();
            updateAppearRect();
            invalidate();
            }
        });
        if (animationListener != null) {
            mAppearAnimator.addListener(animationListener);
@@ -921,7 +844,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
                getCurrentBackgroundRadiusBottom());
    }

    protected void applyBackgroundRoundness(float topRadius, float bottomRadius) {
    private void applyBackgroundRoundness(float topRadius, float bottomRadius) {
        mBackgroundDimmed.setRoundness(topRadius, bottomRadius);
        mBackgroundNormal.setRoundness(topRadius, bottomRadius);
    }
@@ -963,7 +886,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        }
    }

    protected int getRippleColor() {
    private int getRippleColor() {
        if (mBgTint != 0) {
            return mTintedRippleColor;
        } else {
@@ -1010,10 +933,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        mOnActivatedListener = onActivatedListener;
    }

    public boolean hasSameBgColor(ActivatableNotificationView otherView) {
        return calculateBgColor() == otherView.calculateBgColor();
    }

    @Override
    public void setFakeShadowIntensity(float shadowIntensity, float outlineAlpha, int shadowYEnd,
            int outlineTranslation) {
@@ -1071,8 +990,20 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
        return mRefocusOnDismiss || isAccessibilityFocused();
    }

    void setTouchHandler(Gefingerpoken touchHandler) {
        mTouchHandler = touchHandler;
    }

    void setOnDimmedListener(OnDimmedListener onDimmedListener) {
        mOnDimmedListener = onDimmedListener;
    }

    public interface OnActivatedListener {
        void onActivated(ActivatableNotificationView view);
        void onActivationReset(ActivatableNotificationView view);
    }

    interface OnDimmedListener {
        void onSetDimmed(boolean dimmed);
    }
}
+89 −0
Original line number Diff line number Diff line
@@ -16,9 +16,13 @@

package com.android.systemui.statusbar.notification.row;

import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityManager;

import com.android.systemui.Gefingerpoken;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.DoubleTapHelper;

import javax.inject.Inject;

@@ -27,21 +31,106 @@ import javax.inject.Inject;
 */
public class ActivatableNotificationViewController {
    private final ActivatableNotificationView mView;
    private final ExpandableOutlineViewController mExpandableOutlineViewController;
    private final AccessibilityManager mAccessibilityManager;
    private final FalsingManager mFalsingManager;
    private DoubleTapHelper mDoubleTapHelper;
    private boolean mNeedsDimming;

    private TouchHandler mTouchHandler = new TouchHandler();

    @Inject
    public ActivatableNotificationViewController(ActivatableNotificationView view,
            ExpandableOutlineViewController expandableOutlineViewController,
            AccessibilityManager accessibilityManager, FalsingManager falsingManager) {
        mView = view;
        mExpandableOutlineViewController = expandableOutlineViewController;
        mAccessibilityManager = accessibilityManager;
        mFalsingManager = falsingManager;

        mView.setOnActivatedListener(new ActivatableNotificationView.OnActivatedListener() {
            @Override
            public void onActivated(ActivatableNotificationView view) {
                mFalsingManager.onNotificationActive();
            }

            @Override
            public void onActivationReset(ActivatableNotificationView view) {
            }
        });
    }

    /**
     * Initialize the controller, setting up handlers and other behavior.
     */
    public void init() {
        mExpandableOutlineViewController.init();
        mDoubleTapHelper = new DoubleTapHelper(mView, (active) -> {
            if (active) {
                mView.makeActive();
                mFalsingManager.onNotificationActive();
            } else {
                mView.makeInactive(true /* animate */);
            }
        }, mView::performClick, mView::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
        mView.setOnTouchListener(mTouchHandler);
        mView.setTouchHandler(mTouchHandler);
        mView.setOnDimmedListener(dimmed -> {
            mNeedsDimming = dimmed;
            if (dimmed && !mAccessibilityManager.isTouchExplorationEnabled()) {
                mView.setOnClickListener(null);
            } else {
                mView.setOnClickListener((v) -> mView.performClick());
            }
        });
    }

    class TouchHandler implements Gefingerpoken, View.OnTouchListener {
        private boolean mBlockNextTouch;

        @Override
        public boolean onTouch(View v, MotionEvent ev) {
            boolean result;
            if (mBlockNextTouch) {
                mBlockNextTouch = false;
                return true;
            }
            if (mNeedsDimming && !mAccessibilityManager.isTouchExplorationEnabled()
                    && mView.isInteractive()) {
                if (mNeedsDimming && !mView.isDimmed()) {
                    // We're actually dimmed, but our content isn't dimmable,
                    // let's ensure we have a ripple
                    return false;
                }
                result = mDoubleTapHelper.onTouchEvent(ev, mView.getActualHeight());
            } else {
                return false;
            }
            return result;
        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            if (mNeedsDimming && ev.getActionMasked() == MotionEvent.ACTION_DOWN
                    && mView.disallowSingleClick(ev)
                    && !mAccessibilityManager.isTouchExplorationEnabled()) {
                if (!mView.isActivated()) {
                    return true;
                } else if (!mDoubleTapHelper.isWithinDoubleTapSlop(ev)) {
                    mBlockNextTouch = true;
                    mView.makeInactive(true /* animate */);
                    return true;
                }
            }
            return false;
        }

        /**
         * Use {@link #onTouch(View, MotionEvent) instead}.
         */
        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            return false;
        }
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ import com.android.internal.widget.CachingIconView;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
@@ -2188,7 +2189,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
     * @param allowChildExpansion whether a call to this method allows expanding children
     */
    public void setUserExpanded(boolean userExpanded, boolean allowChildExpansion) {
        getFalsingManager().setNotificationExpanded();
        Dependency.get(FalsingManager.class).setNotificationExpanded();
        if (mIsSummaryWithChildren && !shouldShowPublic() && allowChildExpansion
                && !mChildrenContainer.showingAsLowPriority()) {
            final boolean wasExpanded = mGroupManager.isGroupExpanded(mEntry.getSbn());
+41 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification.row;

import javax.inject.Inject;

/**
 * Controller for {@link ExpandableOutlineView}.
 */
public class ExpandableOutlineViewController {
    private final ExpandableOutlineView mView;
    private final ExpandableViewController mExpandableViewController;

    @Inject
    public ExpandableOutlineViewController(ExpandableOutlineView view,
            ExpandableViewController expandableViewController) {
        mView = view;
        mExpandableViewController = expandableViewController;
    }

    /**
     * Initialize the controller.
     */
    public void init() {
        mExpandableViewController.init();
    }
}
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.notification.row;

import javax.inject.Inject;

/**
 * Controller for {@link ExpandableView}.
 */
public class ExpandableViewController {
    private final ExpandableView mView;

    @Inject
    public ExpandableViewController(ExpandableView view) {
        mView = view;
    }

    /**
     * Initialize the controller.
     */
    public void init() {
    }
}
Loading