From 38ccd25cc3664bd6166a34ad88b7049ca5b9c98e Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Thu, 7 Mar 2013 13:15:10 +0100 Subject: Improve All Apps --> Workspace performance Fix bug where HW layers were not enabled for that transition Bug: 8323765 --- src/com/android/launcher2/Workspace.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index 20bcca7ee..cb9ac55f5 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -1700,7 +1700,6 @@ public class Workspace extends SmoothPagedView } } } - buildPageHardwareLayers(); anim.setStartDelay(delay); } @@ -1720,6 +1719,7 @@ public class Workspace extends SmoothPagedView @Override public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) { mIsSwitchingState = true; + updateChildrenLayersEnabled(false); cancelScrollingIndicatorAnimations(); } -- cgit v1.2.3 From 045d613fdddbabaa4433664d2980487b6a01d5fc Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Wed, 3 Apr 2013 16:25:02 -0700 Subject: Fix crash in draw listener Bug: 8528246 Change-Id: Ie3600bed58dc393fcf71f735213a32b51551b52d --- src/com/android/launcher2/Launcher.java | 11 +++++++++-- src/com/android/launcher2/LauncherAnimUtils.java | 14 +++++++++++--- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index 9e651c60c..56a854c00 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -1272,15 +1272,22 @@ public final class Launcher extends Activity // layers on all the workspace pages, so that transitioning to Launcher from other // apps is nice and speedy. observer.addOnDrawListener(new ViewTreeObserver.OnDrawListener() { + private boolean mStarted = false; public void onDraw() { + if (mStarted) return; + mStarted = true; // We delay the layer building a bit in order to give // other message processing a time to run. In particular // this avoids a delay in hiding the IME if it was // currently shown, because doing that may involve // some communication back with the app. mWorkspace.postDelayed(mBuildLayersRunnable, 500); - - observer.removeOnDrawListener(this); + final ViewTreeObserver.OnDrawListener listener = this; + mWorkspace.post(new Runnable() { + public void run() { + mWorkspace.getViewTreeObserver().removeOnDrawListener(listener); + } + }); return; } }); diff --git a/src/com/android/launcher2/LauncherAnimUtils.java b/src/com/android/launcher2/LauncherAnimUtils.java index 5055d3505..a89cb4654 100644 --- a/src/com/android/launcher2/LauncherAnimUtils.java +++ b/src/com/android/launcher2/LauncherAnimUtils.java @@ -52,15 +52,23 @@ public class LauncherAnimUtils { // Helper method. Assumes a draw is pending, and that if the animation's duration is 0 // it should be cancelled public static void startAnimationAfterNextDraw(final Animator animator, final View view) { - final ViewTreeObserver observer = view.getViewTreeObserver(); - observer.addOnDrawListener(new ViewTreeObserver.OnDrawListener() { + view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() { + private boolean mStarted = false; public void onDraw() { + if (mStarted) return; + mStarted = true; // Use this as a signal that the animation was cancelled if (animator.getDuration() == 0) { return; } animator.start(); - view.getViewTreeObserver().removeOnDrawListener(this); + + final ViewTreeObserver.OnDrawListener listener = this; + view.post(new Runnable() { + public void run() { + view.getViewTreeObserver().removeOnDrawListener(listener); + } + }); } }); } -- cgit v1.2.3 From 32b59c122c130364881311bc57c76b805d296fd1 Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Mon, 8 Apr 2013 18:28:15 -0700 Subject: Fix bug where folder open animation gets finished early Also, sync FirstFrameAnimatorHelper with changes made in Recents Bug: 8530231 Change-Id: Ibf1a43f67d91df89a2338f0f0c0fb52ee5496e57 --- .../launcher2/FirstFrameAnimatorHelper.java | 52 ++++++++++++++++------ .../launcher2/LauncherViewPropertyAnimator.java | 16 ++++--- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/com/android/launcher2/FirstFrameAnimatorHelper.java b/src/com/android/launcher2/FirstFrameAnimatorHelper.java index 2351dd074..8eac7cd2c 100644 --- a/src/com/android/launcher2/FirstFrameAnimatorHelper.java +++ b/src/com/android/launcher2/FirstFrameAnimatorHelper.java @@ -16,20 +16,24 @@ package com.android.launcher2; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.animation.Animator.AnimatorListener; import android.util.Log; import android.view.ViewTreeObserver; import android.view.View; +import android.view.ViewPropertyAnimator; /* * This is a helper class that listens to updates from the corresponding animation. * For the first two frames, it adjusts the current play time of the animation to * prevent jank at the beginning of the animation */ -public class FirstFrameAnimatorHelper implements ValueAnimator.AnimatorUpdateListener { +public class FirstFrameAnimatorHelper extends AnimatorListenerAdapter + implements ValueAnimator.AnimatorUpdateListener { private static final boolean DEBUG = false; - private static final int MAX_FIRST_FRAME_DELAY = 200; + private static final int MAX_DELAY = 1000; private static final int IDEAL_FRAME_DURATION = 16; private View mTarget; private long mStartFrame; @@ -45,43 +49,65 @@ public class FirstFrameAnimatorHelper implements ValueAnimator.AnimatorUpdateLis animator.addUpdateListener(this); } + public FirstFrameAnimatorHelper(ViewPropertyAnimator vpa, View target) { + mTarget = target; + vpa.setListener(this); + } + + // only used for ViewPropertyAnimators + public void onAnimationStart(Animator animation) { + final ValueAnimator va = (ValueAnimator) animation; + va.addUpdateListener(FirstFrameAnimatorHelper.this); + onAnimationUpdate(va); + } + public static void initializeDrawListener(View view) { + if (sGlobalDrawListener != null) { + view.getViewTreeObserver().removeOnDrawListener(sGlobalDrawListener); + } sGlobalDrawListener = new ViewTreeObserver.OnDrawListener() { private long mTime = System.currentTimeMillis(); public void onDraw() { sGlobalFrameCounter++; - long newTime = System.currentTimeMillis(); if (DEBUG) { + long newTime = System.currentTimeMillis(); Log.d("FirstFrameAnimatorHelper", "TICK " + (newTime - mTime)); + mTime = newTime; } - mTime = newTime; } }; view.getViewTreeObserver().addOnDrawListener(sGlobalDrawListener); } public void onAnimationUpdate(final ValueAnimator animation) { + final long currentTime = System.currentTimeMillis(); if (mStartTime == -1) { mStartFrame = sGlobalFrameCounter; - mStartTime = System.currentTimeMillis(); + mStartTime = currentTime; } - if (!mHandlingOnAnimationUpdate) { + if (!mHandlingOnAnimationUpdate && + // If the current play time exceeds the duration, the animation + // will get finished, even if we call setCurrentPlayTime -- therefore + // don't adjust the animation in that case + animation.getCurrentPlayTime() < animation.getDuration()) { mHandlingOnAnimationUpdate = true; long frameNum = sGlobalFrameCounter - mStartFrame; - // If we haven't drawn our first frame, reset the time to t = 0 - // (give up after 200ms of waiting though - might happen, for example, if we are no - // longer in the foreground and no frames are being rendered ever) - if (frameNum == 0 && System.currentTimeMillis() < mStartTime + MAX_FIRST_FRAME_DELAY) { - mTarget.getRootView().invalidate(); // make sure we'll do a draw + // (give up after MAX_DELAY ms of waiting though - might happen, for example, if we + // are no longer in the foreground and no frames are being rendered ever) + if (frameNum == 0 && currentTime < mStartTime + MAX_DELAY) { + // The first frame on animations doesn't always trigger an invalidate... + // force an invalidate here to make sure the animation continues to advance + mTarget.getRootView().invalidate(); animation.setCurrentPlayTime(0); // For the second frame, if the first frame took more than 16ms, // adjust the start time and pretend it took only 16ms anyway. This // prevents a large jump in the animation due to an expensive first frame - } else if (frameNum == 1 && !mAdjustedSecondFrameTime && - System.currentTimeMillis() > mStartTime + 16) { + } else if (frameNum == 1 && currentTime < mStartTime + MAX_DELAY && + !mAdjustedSecondFrameTime && + currentTime > mStartTime + IDEAL_FRAME_DURATION) { animation.setCurrentPlayTime(IDEAL_FRAME_DURATION); mAdjustedSecondFrameTime = true; } else { diff --git a/src/com/android/launcher2/LauncherViewPropertyAnimator.java b/src/com/android/launcher2/LauncherViewPropertyAnimator.java index 274ff80b3..83b745eb5 100644 --- a/src/com/android/launcher2/LauncherViewPropertyAnimator.java +++ b/src/com/android/launcher2/LauncherViewPropertyAnimator.java @@ -53,6 +53,7 @@ public class LauncherViewPropertyAnimator extends Animator implements AnimatorLi TimeInterpolator mInterpolator; ArrayList mListeners; boolean mRunning = false; + FirstFrameAnimatorHelper mFirstFrameHelper; public LauncherViewPropertyAnimator(View target) { mTarget = target; @@ -124,12 +125,10 @@ public class LauncherViewPropertyAnimator extends Animator implements AnimatorLi @Override public void onAnimationStart(Animator animation) { - // This is the first time we get a handle to the internal ValueAnimator - // used by the ViewPropertyAnimator. - // FirstFrameAnimatorHelper hooks itself up to the updates on the animator, - // and then adjusts the play time to keep the first two frames jank-free - new FirstFrameAnimatorHelper((ValueAnimator) animation, mTarget) - .onAnimationUpdate((ValueAnimator) animation); + // This is the first time we get a handle to the internal ValueAnimator + // used by the ViewPropertyAnimator. + mFirstFrameHelper.onAnimationStart(animation); + for (int i = 0; i < mListeners.size(); i++) { Animator.AnimatorListener listener = mListeners.get(i); listener.onAnimationStart(this); @@ -193,6 +192,11 @@ public class LauncherViewPropertyAnimator extends Animator implements AnimatorLi @Override public void start() { mViewPropertyAnimator = mTarget.animate(); + + // FirstFrameAnimatorHelper hooks itself up to the updates on the animator, + // and then adjusts the play time to keep the first two frames jank-free + mFirstFrameHelper = new FirstFrameAnimatorHelper(mViewPropertyAnimator, mTarget); + if (mPropertiesToSet.contains(Properties.TRANSLATION_X)) { mViewPropertyAnimator.translationX(mTranslationX); } -- cgit v1.2.3 From 10f0f145ae5d822f34f84d7489c5f8008bb416ae Mon Sep 17 00:00:00 2001 From: Michael Jurka Date: Thu, 11 Apr 2013 11:36:41 -0700 Subject: Fix NPE Bug: 8596760 Change-Id: I401aa0f9a1b8b1c167b502f6aad11cb0f98b7c33 --- src/com/android/launcher2/Launcher.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index 2c0f6b05d..b2c36ee07 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -1293,7 +1293,11 @@ public final class Launcher extends Activity final ViewTreeObserver.OnDrawListener listener = this; mWorkspace.post(new Runnable() { public void run() { - mWorkspace.getViewTreeObserver().removeOnDrawListener(listener); + if (mWorkspace != null && + mWorkspace.getViewTreeObserver() != null) { + mWorkspace.getViewTreeObserver(). + removeOnDrawListener(listener); + } } }); return; -- cgit v1.2.3