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

Commit 841d7949 authored by Chet Haase's avatar Chet Haase Committed by Android Git Automerger
Browse files

am 87bc53de: Merge "Make notification panel delete-all animation smoother" into ics-mr0

* commit '87bc53de':
  Make notification panel delete-all animation smoother
parents 7a0390b9 87bc53de
Loading
Loading
Loading
Loading
+36 −0
Original line number 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_IMF = 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;

    /**
@@ -274,6 +275,11 @@ public final class ViewRootImpl extends Handler implements ViewParent,
    private Thread mRenderProfiler;
    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)}
     */
@@ -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) {
        Surface surface = mSurface;
        if (surface == null || !surface.isValid()) {
            return;
        }

        if (DEBUG_FPS) {
            trackFPS();
        }

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

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

    private static LinearInterpolator sLinearInterpolator = new LinearInterpolator();

    private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
    private int DEFAULT_ESCAPE_ANIMATION_DURATION = 200; // ms
    private int MAX_ESCAPE_ANIMATION_DURATION = 400; // ms
@@ -199,6 +202,10 @@ public class SwipeHelper {
        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) {
        final View animView = mCallback.getChildContentView(view);
        final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
@@ -221,22 +228,14 @@ public class SwipeHelper {
            duration = DEFAULT_ESCAPE_ANIMATION_DURATION;
        }

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

            public void onAnimationRepeat(Animator animation) {
            }

        anim.addListener(new AnimatorListenerAdapter() {
            public void onAnimationEnd(Animator animation) {
                mCallback.onChildDismissed(view);
            }

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


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

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

                final ArrayList<View> snapshot = new ArrayList<View>(N);
                for (int i=0; i<N; i++) {
                int scrollTop = mScrollView.getScrollY();
                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);
                    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() {
                    @Override
                    public void run() {
                        final int ROW_DELAY = 100;

                        mHandler.postDelayed(new Runnable() {
                            public void run() {
                                animateCollapse(false, 0f);
                            }
                        }, (N-1) * ROW_DELAY);

                        mHandler.postDelayed(new Runnable() {
                        // Decrease the delay for every row we animate to give the sense of
                        // accelerating the swipes
                        final int ROW_DELAY_DECREMENT = 10;
                        int currentDelay = 140;
                        int totalDelay = 0;

                        // Set the shade-animating state to avoid doing other work during
                        // all of these animations. In particular, avoid layout and
                        // redrawing when collapsing the shade.
                        mPile.setViewRemoval(false);

                        mPostCollapseCleanup = new Runnable() {
                            public void run() {
                                try {
                                    mPile.setViewRemoval(true);
                                    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) {
                            final View _v = v;
                            mHandler.post(new Runnable() {
                            mHandler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    mPile.dismissRowAnimated(_v, (int)(ROW_DELAY*0.25f));
                                    mPile.dismissRowAnimated(_v, velocity);
                                }
                            });
                            try {
                                Thread.sleep(ROW_DELAY);
                            } catch (InterruptedException ex) { }
                            }, totalDelay);
                            currentDelay = Math.max(50, currentDelay - ROW_DELAY_DECREMENT);
                            totalDelay += currentDelay;
                        }
                        
                        mPile.setAnimateBounds(true); // reenable layout animation
                        // Delay the collapse animation until after all swipe animations have
                        // 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();
            }
+40 −12
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.policy;

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

    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) {
        this(context, attrs, 0);
    }
@@ -117,7 +119,7 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call

    public void onChildDismissed(View v) {
        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();
        }
    }
@@ -170,7 +172,6 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call
        final View childF = child;

        if (mAnimateBounds) {
            child.setPivotY(0);
            final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f);
            alphaFade.setDuration(APPEAR_ANIM_LEN);
            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) {
        dismissRowAnimated(child, 0);
    }
@@ -199,16 +210,34 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call

    @Override
    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 (mAppearingViews.containsKey(child)) {
                mAppearingViews.remove(child);
            }
            child.setPivotY(0);

            final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f);
            alphaFade.setDuration(DISAPPEAR_ANIM_LEN);
            alphaFade.addListener(new AnimatorListenerAdapter() {
            // Don't fade it out if it already has a low alpha value, but run a non-visual
            // animation which is used by onLayout() to animate shrinking the gap that it left
            // 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
                public void onAnimationEnd(Animator animation) {
                    if (DEBUG) Slog.d(TAG, "actually removing child: " + childF);
@@ -218,9 +247,8 @@ public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Call
                }
            });

            alphaFade.start();

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

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