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

Commit 2a5e452f authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Animate notifs depending on touch when exiting doze mode

When exiting doze mode during pulsing and the reason for the wakeup
is a touch event, we calculate the delay of the animations to animate
the notification from black/white to color depending on the point
where the touch happened to wake up the screen.

Bug: 18146441
Change-Id: Ica76b235d629acfc2b09b5f56027c688502f89d8
parent fb6121e0
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
@@ -267,6 +268,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    private UnlockMethodCache mUnlockMethodCache;
    private DozeServiceHost mDozeServiceHost;
    private boolean mScreenOnComingFromTouch;
    private PointF mScreenOnTouchLocation;

    int mPixelFormat;
    Object mQueueLock = new Object();
@@ -3705,7 +3707,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        }
        boolean animate = !mDozing && mDozeScrimController.isPulsing();
        mNotificationPanel.setDozing(mDozing, animate);
        mStackScroller.setDark(mDozing, animate);
        mStackScroller.setDark(mDozing, animate, mScreenOnTouchLocation);
        mScrimController.setDozing(mDozing);
        mDozeScrimController.setDozing(mDozing, animate);
    }
@@ -3961,6 +3963,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
    public void onScreenTurnedOff() {
        mScreenOnFromKeyguard = false;
        mScreenOnComingFromTouch = false;
        mScreenOnTouchLocation = null;
        mStackScroller.setAnimationsEnabled(false);
        updateVisibleToUser();
    }
@@ -4083,16 +4086,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
        return !mNotificationData.getActiveNotifications().isEmpty();
    }

    public void wakeUpIfDozing(long time, boolean fromTouch) {
    public void wakeUpIfDozing(long time, MotionEvent event) {
        if (mDozing && mDozeScrimController.isPulsing()) {
            PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
            pm.wakeUp(time);
            if (fromTouch) {
            mScreenOnComingFromTouch = true;
            mScreenOnTouchLocation = new PointF(event.getX(), event.getY());
            mNotificationPanel.setTouchDisabled(false);
        }
    }
    }

    private final class ShadeUpdates {
        private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
+1 −1
Original line number Diff line number Diff line
@@ -173,7 +173,7 @@ public class StatusBarWindowView extends FrameLayout {
            intercept = mDragDownHelper.onInterceptTouchEvent(ev);
            // wake up on a touch down event, if dozing
            if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
                mService.wakeUpIfDozing(ev.getEventTime(), true);
                mService.wakeUpIfDozing(ev.getEventTime(), ev);
            }
        }
        if (!intercept) {
+7 −2
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ public class AnimationFilter {
    boolean hasDelays;
    boolean hasGoToFullShadeEvent;
    boolean hasDarkEvent;
    int darkAnimationOriginIndex;

    public AnimationFilter animateAlpha() {
        animateAlpha = true;
@@ -94,14 +95,16 @@ public class AnimationFilter {
        reset();
        int size = events.size();
        for (int i = 0; i < size; i++) {
            NotificationStackScrollLayout.AnimationEvent ev = events.get(i);
            combineFilter(events.get(i).filter);
            if (events.get(i).animationType ==
            if (ev.animationType ==
                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_GO_TO_FULL_SHADE) {
                hasGoToFullShadeEvent = true;
            }
            if (events.get(i).animationType ==
            if (ev.animationType ==
                    NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_DARK) {
                hasDarkEvent = true;
                darkAnimationOriginIndex = ev.darkAnimationOriginIndex;
            }
        }
    }
@@ -132,5 +135,7 @@ public class AnimationFilter {
        hasDelays = false;
        hasGoToFullShadeEvent = false;
        hasDarkEvent = false;
        darkAnimationOriginIndex =
                NotificationStackScrollLayout.AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
    }
}
+75 −7
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@

package com.android.systemui.statusbar.stack;

import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -149,6 +151,7 @@ public class NotificationStackScrollLayout extends ViewGroup
    private boolean mDimmedNeedsAnimation;
    private boolean mHideSensitiveNeedsAnimation;
    private boolean mDarkNeedsAnimation;
    private int mDarkAnimationOriginIndex;
    private boolean mActivateNeedsAnimation;
    private boolean mGoToFullShadeNeedsAnimation;
    private boolean mIsExpanded = true;
@@ -210,6 +213,7 @@ public class NotificationStackScrollLayout extends ViewGroup
        }
    };
    private PhoneStatusBar mPhoneStatusBar;
    private int[] mTempInt2 = new int[2];

    public NotificationStackScrollLayout(Context context) {
        this(context, null);
@@ -587,10 +591,38 @@ public class NotificationStackScrollLayout extends ViewGroup
        return getChildAtPosition(ev.getX(), ev.getY());
    }

    public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) {
        getLocationOnScreen(mTempInt2);
        float localTouchY = touchY - mTempInt2[1];

        ExpandableView closestChild = null;
        float minDist = Float.MAX_VALUE;

        // find the view closest to the location, accounting for GONE views
        final int count = getChildCount();
        for (int childIdx = 0; childIdx < count; childIdx++) {
            ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
            if (slidingChild.getVisibility() == GONE
                    || slidingChild instanceof StackScrollerDecorView
                    || slidingChild == mSpeedBumpView) {
                continue;
            }
            float childTop = slidingChild.getTranslationY();
            float top = childTop + slidingChild.getClipTopAmount();
            float bottom = childTop + slidingChild.getActualHeight();

            float dist = Math.min(Math.abs(top - localTouchY), Math.abs(bottom - localTouchY));
            if (dist < minDist) {
                closestChild = slidingChild;
                minDist = dist;
            }
        }
        return closestChild;
    }

    public ExpandableView getChildAtRawPosition(float touchX, float touchY) {
        int[] location = new int[2];
        getLocationOnScreen(location);
        return getChildAtPosition(touchX - location[0], touchY - location[1]);
        getLocationOnScreen(mTempInt2);
        return getChildAtPosition(touchX - mTempInt2[0], touchY - mTempInt2[1]);
    }

    public ExpandableView getChildAtPosition(float touchX, float touchY) {
@@ -1818,8 +1850,9 @@ public class NotificationStackScrollLayout extends ViewGroup

    private void generateDarkEvent() {
        if (mDarkNeedsAnimation) {
            mAnimationEvents.add(
                    new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_DARK));
            AnimationEvent ev = new AnimationEvent(null, AnimationEvent.ANIMATION_TYPE_DARK);
            ev.darkAnimationOriginIndex = mDarkAnimationOriginIndex;
            mAnimationEvents.add(ev);
        }
        mDarkNeedsAnimation = false;
    }
@@ -2182,15 +2215,46 @@ public class NotificationStackScrollLayout extends ViewGroup
    /**
     * See {@link AmbientState#setDark}.
     */
    public void setDark(boolean dark, boolean animate) {
    public void setDark(boolean dark, boolean animate, @Nullable PointF touchWakeUpScreenLocation) {
        mAmbientState.setDark(dark);
        if (animate && mAnimationsEnabled) {
            mDarkNeedsAnimation = true;
            mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation);
            mNeedsAnimation =  true;
        }
        requestChildrenUpdate();
    }

    private int findDarkAnimationOriginIndex(@Nullable PointF screenLocation) {
        if (screenLocation == null || screenLocation.y < mTopPadding + mTopPaddingOverflow) {
            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
        }
        if (screenLocation.y > getBottomMostNotificationBottom()) {
            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_BELOW;
        }
        View child = getClosestChildAtRawPosition(screenLocation.x, screenLocation.y);
        if (child != null) {
            return getNotGoneIndex(child);
        } else {
            return AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE;
        }
    }

    private int getNotGoneIndex(View child) {
        int count = getChildCount();
        int notGoneIndex = 0;
        for (int i = 0; i < count; i++) {
            View v = getChildAt(i);
            if (child == v) {
                return notGoneIndex;
            }
            if (v.getVisibility() != View.GONE) {
                notGoneIndex++;
            }
        }
        return -1;
    }

    public void setDismissView(DismissView dismissView) {
        mDismissView = dismissView;
        addView(mDismissView);
@@ -2556,12 +2620,16 @@ public class NotificationStackScrollLayout extends ViewGroup
        static final int ANIMATION_TYPE_VIEW_RESIZE = 12;
        static final int ANIMATION_TYPE_EVERYTHING = 13;

        static final int DARK_ANIMATION_ORIGIN_INDEX_ABOVE = -1;
        static final int DARK_ANIMATION_ORIGIN_INDEX_BELOW = -2;

        final long eventStartTime;
        final View changingView;
        final int animationType;
        final AnimationFilter filter;
        final long length;
        View viewAfterChangingView;
        int darkAnimationOriginIndex;

        AnimationEvent(View view, int type) {
            this(view, type, LENGTHS[type]);
+11 −1
Original line number Diff line number Diff line
@@ -315,7 +315,17 @@ public class StackStateAnimator {
    }

    private long calculateDelayDark(StackScrollState.ViewState viewState) {
        return viewState.notGoneIndex * ANIMATION_DELAY_PER_ELEMENT_DARK;
        int referenceIndex;
        if (mAnimationFilter.darkAnimationOriginIndex ==
                NotificationStackScrollLayout.AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_ABOVE) {
            referenceIndex = 0;
        } else if (mAnimationFilter.darkAnimationOriginIndex ==
                NotificationStackScrollLayout.AnimationEvent.DARK_ANIMATION_ORIGIN_INDEX_BELOW) {
            referenceIndex = mHostLayout.getNotGoneChildCount() - 1;
        } else {
            referenceIndex = mAnimationFilter.darkAnimationOriginIndex;
        }
        return Math.abs(referenceIndex - viewState.notGoneIndex) * ANIMATION_DELAY_PER_ELEMENT_DARK;
    }

    private long calculateDelayGoToFullShade(StackScrollState.ViewState viewState) {