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

Commit 87bc53de authored by Chet Haase's avatar Chet Haase Committed by Android (Google) Code Review
Browse files

Merge "Make notification panel delete-all animation smoother" into ics-mr0

parents 07848843 2f2022af
Loading
Loading
Loading
Loading
+36 −0
Original line number Original line Diff line number Diff line
@@ -108,6 +108,7 @@ public final class ViewRootImpl extends Handler implements ViewParent,
    private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV;
    private static final boolean DEBUG_TRACKBALL = false || LOCAL_LOGV;
    private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
    private static final boolean DEBUG_IMF = false || LOCAL_LOGV;
    private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV;
    private static final boolean DEBUG_CONFIGURATION = false || LOCAL_LOGV;
    private static final boolean DEBUG_FPS = false;
    private static final boolean WATCH_POINTER = false;
    private static final boolean WATCH_POINTER = false;


    /**
    /**
@@ -274,6 +275,11 @@ public final class ViewRootImpl extends Handler implements ViewParent,
    private Thread mRenderProfiler;
    private Thread mRenderProfiler;
    private volatile boolean mRenderProfilingEnabled;
    private volatile boolean mRenderProfilingEnabled;


    // Variables to track frames per second, enabled via DEBUG_FPS flag
    private long mFpsStartTime = -1;
    private long mFpsPrevTime = -1;
    private int mFpsNumFrames;

    /**
    /**
     * see {@link #playSoundEffect(int)}
     * see {@link #playSoundEffect(int)}
     */
     */
@@ -1766,12 +1772,42 @@ public final class ViewRootImpl extends Handler implements ViewParent,
        }
        }
    }
    }


    /**
     * Called from draw() when DEBUG_FPS is enabled
     */
    private void trackFPS() {
        // Tracks frames per second drawn. First value in a series of draws may be bogus
        // because it down not account for the intervening idle time
        long nowTime = System.currentTimeMillis();
        if (mFpsStartTime < 0) {
            mFpsStartTime = mFpsPrevTime = nowTime;
            mFpsNumFrames = 0;
        } else {
            ++mFpsNumFrames;
            String thisHash = Integer.toHexString(System.identityHashCode(this));
            long frameTime = nowTime - mFpsPrevTime;
            long totalTime = nowTime - mFpsStartTime;
            Log.v(TAG, "0x" + thisHash + "\tFrame time:\t" + frameTime);
            mFpsPrevTime = nowTime;
            if (totalTime > 1000) {
                float fps = (float) mFpsNumFrames * 1000 / totalTime;
                Log.v(TAG, "0x" + thisHash + "\tFPS:\t" + fps);
                mFpsStartTime = nowTime;
                mFpsNumFrames = 0;
            }
        }
    }

    private void draw(boolean fullRedrawNeeded) {
    private void draw(boolean fullRedrawNeeded) {
        Surface surface = mSurface;
        Surface surface = mSurface;
        if (surface == null || !surface.isValid()) {
        if (surface == null || !surface.isValid()) {
            return;
            return;
        }
        }


        if (DEBUG_FPS) {
            trackFPS();
        }

        if (!sFirstDrawComplete) {
        if (!sFirstDrawComplete) {
            synchronized (sFirstDrawHandlers) {
            synchronized (sFirstDrawHandlers) {
                sFirstDrawComplete = true;
                sFirstDrawComplete = true;
+11 −12
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui;
package com.android.systemui;


import android.animation.Animator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ObjectAnimator;
import android.animation.Animator.AnimatorListener;
import android.animation.Animator.AnimatorListener;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator;
@@ -40,6 +41,8 @@ public class SwipeHelper {
    public static final int X = 0;
    public static final int X = 0;
    public static final int Y = 1;
    public static final int Y = 1;


    private static LinearInterpolator sLinearInterpolator = new LinearInterpolator();

    private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
    private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
    private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
    private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
    private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
    private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
@@ -199,6 +202,10 @@ public class SwipeHelper {
        return mDragging;
        return mDragging;
    }
    }


    /**
     * @param view The view to be dismissed
     * @param velocity The desired pixels/second speed at which the view should move
     */
    public void dismissChild(final View view, float velocity) {
    public void dismissChild(final View view, float velocity) {
        final View animView = mCallback.getChildContentView(view);
        final View animView = mCallback.getChildContentView(view);
        final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
        final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
@@ -221,22 +228,14 @@ public class SwipeHelper {
            duration = DEFAULT_ESCAPE_ANIMATION_DURATION;
            duration = DEFAULT_ESCAPE_ANIMATION_DURATION;
        }
        }


        animView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        ObjectAnimator anim = createTranslationAnimation(animView, newPos);
        ObjectAnimator anim = createTranslationAnimation(animView, newPos);
        anim.setInterpolator(new LinearInterpolator());
        anim.setInterpolator(sLinearInterpolator);
        anim.setDuration(duration);
        anim.setDuration(duration);
        anim.addListener(new AnimatorListener() {
        anim.addListener(new AnimatorListenerAdapter() {
            public void onAnimationStart(Animator animation) {
            }

            public void onAnimationRepeat(Animator animation) {
            }

            public void onAnimationEnd(Animator animation) {
            public void onAnimationEnd(Animator animation) {
                mCallback.onChildDismissed(view);
                mCallback.onChildDismissed(view);
            }
                animView.setLayerType(View.LAYER_TYPE_NONE, null);

            public void onAnimationCancel(Animator animation) {
                mCallback.onChildDismissed(view);
            }
            }
        });
        });
        anim.addUpdateListener(new AnimatorUpdateListener() {
        anim.addUpdateListener(new AnimatorUpdateListener() {
+50 −27
Original line number Original line Diff line number Diff line
@@ -50,7 +50,6 @@ import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.VelocityTracker;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
@@ -213,6 +212,8 @@ public class PhoneStatusBar extends StatusBar {
    boolean mAnimatingReveal = false;
    boolean mAnimatingReveal = false;
    int mViewDelta;
    int mViewDelta;
    int[] mAbsPos = new int[2];
    int[] mAbsPos = new int[2];
    Runnable mPostCollapseCleanup = null;



    // for disabling the status bar
    // for disabling the status bar
    int mDisabled = 0;
    int mDisabled = 0;
@@ -1238,6 +1239,10 @@ public class PhoneStatusBar extends StatusBar {
            return;
            return;
        }
        }
        mExpanded = false;
        mExpanded = false;
        if (mPostCollapseCleanup != null) {
            mPostCollapseCleanup.run();
            mPostCollapseCleanup = null;
        }
    }
    }


    void doAnimation() {
    void doAnimation() {
@@ -2066,49 +2071,67 @@ public class PhoneStatusBar extends StatusBar {
        }
        }
        public void onClick(View v) {
        public void onClick(View v) {
            synchronized (mNotificationData) {
            synchronized (mNotificationData) {
                // let's also queue up 400ms worth of animated dismissals
                // animate-swipe all dismissable notifications, then animate the shade closed
                final int N = mini(5, mPile.getChildCount());
                int numChildren = mPile.getChildCount();


                final ArrayList<View> snapshot = new ArrayList<View>(N);
                int scrollTop = mScrollView.getScrollY();
                for (int i=0; i<N; i++) {
                int scrollBottom = scrollTop + mScrollView.getHeight();
                final ArrayList<View> snapshot = new ArrayList<View>(numChildren);
                for (int i=0; i<numChildren; i++) {
                    final View child = mPile.getChildAt(i);
                    final View child = mPile.getChildAt(i);
                    if (mPile.canChildBeDismissed(child)) snapshot.add(child);
                    if (mPile.canChildBeDismissed(child) && child.getBottom() > scrollTop &&
                            child.getTop() < scrollBottom) {
                        snapshot.add(child);
                    }
                    }
                }
                final int N = snapshot.size();
                new Thread(new Runnable() {
                new Thread(new Runnable() {
                    @Override
                    @Override
                    public void run() {
                    public void run() {
                        final int ROW_DELAY = 100;
                        // Decrease the delay for every row we animate to give the sense of

                        // accelerating the swipes
                        mHandler.postDelayed(new Runnable() {
                        final int ROW_DELAY_DECREMENT = 10;
                            public void run() {
                        int currentDelay = 140;
                                animateCollapse(false, 0f);
                        int totalDelay = 0;
                            }

                        }, (N-1) * ROW_DELAY);
                        // Set the shade-animating state to avoid doing other work during

                        // all of these animations. In particular, avoid layout and
                        mHandler.postDelayed(new Runnable() {
                        // redrawing when collapsing the shade.
                        mPile.setViewRemoval(false);

                        mPostCollapseCleanup = new Runnable() {
                            public void run() {
                            public void run() {
                                try {
                                try {
                                    mPile.setViewRemoval(true);
                                    mBarService.onClearAllNotifications();
                                    mBarService.onClearAllNotifications();
                                } catch (RemoteException ex) { }
                                } catch (Exception ex) { }
                            }
                            }
                        }, N * ROW_DELAY + 500);
                        };

                        mPile.setAnimateBounds(false); // temporarily disable some re-layouts


                        View sampleView = snapshot.get(0);
                        int width = sampleView.getWidth();
                        final int velocity = (int)(width * 8); // 1000/8 = 125 ms duration
                        for (View v : snapshot) {
                        for (View v : snapshot) {
                            final View _v = v;
                            final View _v = v;
                            mHandler.post(new Runnable() {
                            mHandler.postDelayed(new Runnable() {
                                @Override
                                @Override
                                public void run() {
                                public void run() {
                                    mPile.dismissRowAnimated(_v, (int)(ROW_DELAY*0.25f));
                                    mPile.dismissRowAnimated(_v, velocity);
                                }
                                }
                            });
                            }, totalDelay);
                            try {
                            currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT);
                                Thread.sleep(ROW_DELAY);
                            totalDelay += currentDelay;
                            } catch (InterruptedException ex) { }
                        }
                        }
                        
                        // Delay the collapse animation until after all swipe animations have
                        mPile.setAnimateBounds(true); // reenable layout animation
                        // finished. Provide some buffer because there may be some extra delay
                        // before actually starting each swipe animation. Ideally, we'd
                        // synchronize the end of those animations with the start of the collaps
                        // exactly.
                        mHandler.postDelayed(new Runnable() {
                            public void run() {
                                animateCollapse(false);
                            }
                        }, totalDelay + 225);
                    }
                    }
                }).start();
                }).start();
            }
            }
+40 −12
Original line number Original line Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.policy;


import android.animation.Animator;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.Context;
@@ -29,7 +28,6 @@ import android.util.AttributeSet;
import android.util.Log;
import android.util.Log;
import android.util.Slog;
import android.util.Slog;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewGroup;
@@ -59,6 +57,10 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call


    private SwipeHelper mSwipeHelper;
    private SwipeHelper mSwipeHelper;


    // Flag set during notification removal animation to avoid causing too much work until
    // animation is done
    boolean mRemoveViews = true;

    public NotificationRowLayout(Context context, AttributeSet attrs) {
    public NotificationRowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        this(context, attrs, 0);
    }
    }
@@ -117,7 +119,7 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call


    public void onChildDismissed(View v) {
    public void onChildDismissed(View v) {
        final View veto = v.findViewById(R.id.veto);
        final View veto = v.findViewById(R.id.veto);
        if (veto != null && veto.getVisibility() != View.GONE) {
        if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
            veto.performClick();
            veto.performClick();
        }
        }
    }
    }
@@ -170,7 +172,6 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call
        final View childF = child;
        final View childF = child;


        if (mAnimateBounds) {
        if (mAnimateBounds) {
            child.setPivotY(0);
            final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f);
            final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f);
            alphaFade.setDuration(APPEAR_ANIM_LEN);
            alphaFade.setDuration(APPEAR_ANIM_LEN);
            alphaFade.addListener(new AnimatorListenerAdapter() {
            alphaFade.addListener(new AnimatorListenerAdapter() {
@@ -189,6 +190,16 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call
        }
        }
    }
    }


    /**
     * Sets a flag to tell us whether to actually remove views. Removal is delayed by setting this
     * to false during some animations to smooth out performance. Callers should restore the
     * flag to true after the animation is done, and then they should make sure that the views
     * get removed properly.
     */
    public void setViewRemoval(boolean removeViews) {
        mRemoveViews = removeViews;
    }

    public void dismissRowAnimated(View child) {
    public void dismissRowAnimated(View child) {
        dismissRowAnimated(child, 0);
        dismissRowAnimated(child, 0);
    }
    }
@@ -199,16 +210,34 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call


    @Override
    @Override
    public void removeView(View child) {
    public void removeView(View child) {
        final View childF = child;
        if (!mRemoveViews) {
            // This flag is cleared during an animation that removes all notifications. There
            // should be a call to remove all notifications when the animation is done, at which
            // time the view will be removed.
            return;
        }
        if (mAnimateBounds) {
        if (mAnimateBounds) {
            if (mAppearingViews.containsKey(child)) {
            if (mAppearingViews.containsKey(child)) {
                mAppearingViews.remove(child);
                mAppearingViews.remove(child);
            }
            }
            child.setPivotY(0);


            final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f);
            // Don't fade it out if it already has a low alpha value, but run a non-visual
            alphaFade.setDuration(DISAPPEAR_ANIM_LEN);
            // animation which is used by onLayout() to animate shrinking the gap that it left
            alphaFade.addListener(new AnimatorListenerAdapter() {
            // in the list
            ValueAnimator anim;
            float currentAlpha = child.getAlpha();
            if (currentAlpha > .1) {
                anim = ObjectAnimator.ofFloat(child, "alpha", currentAlpha, 0);
            } else {
                if (currentAlpha > 0) {
                    // Just make it go away - no need to render it anymore
                    child.setAlpha(0);
                }
                anim = ValueAnimator.ofFloat(0, 1);
            }
            anim.setDuration(DISAPPEAR_ANIM_LEN);
            final View childF = child;
            anim.addListener(new AnimatorListenerAdapter() {
                @Override
                @Override
                public void onAnimationEnd(Animator animation) {
                public void onAnimationEnd(Animator animation) {
                    if (DEBUG) Slog.d(TAG, "actually removing child: " + childF);
                    if (DEBUG) Slog.d(TAG, "actually removing child: " + childF);
@@ -218,9 +247,8 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call
                }
                }
            });
            });


            alphaFade.start();
            anim.start();

            mDisappearingViews.put(child, anim);
            mDisappearingViews.put(child, alphaFade);


            requestLayout(); // start the container animation
            requestLayout(); // start the container animation
        } else {
        } else {