diff options
author | John Reck <jreck@google.com> | 2014-05-19 10:28:35 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2014-05-19 15:28:05 -0700 |
commit | 918988c1ce5af002d41c7ac37f3fa490558b0c90 (patch) | |
tree | 86f781960d7997eb0e34f21a0895815cfb240d19 | |
parent | 3a9f0175ba77498d821a75f710a523a2b83f7c17 (diff) | |
download | frameworks_base-918988c1ce5af002d41c7ac37f3fa490558b0c90.zip frameworks_base-918988c1ce5af002d41c7ac37f3fa490558b0c90.tar.gz frameworks_base-918988c1ce5af002d41c7ac37f3fa490558b0c90.tar.bz2 |
Baby steps
Run ViewPropertyAnimators with no listeners on the RenderThread
Change-Id: I7ff5300db96c7f4b59b09e3fff8a0df173f132dd
-rw-r--r-- | core/java/android/view/RenderNodeAnimator.java | 10 | ||||
-rw-r--r-- | core/java/android/view/ViewPropertyAnimator.java | 29 | ||||
-rw-r--r-- | core/java/android/view/ViewPropertyAnimatorRT.java | 118 | ||||
-rw-r--r-- | core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java | 11 | ||||
-rw-r--r-- | tests/RenderThreadTest/Android.mk | 2 | ||||
-rw-r--r-- | tests/RenderThreadTest/AndroidManifest.xml | 4 |
6 files changed, 165 insertions, 9 deletions
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index c1a4fee..e918119 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -48,6 +48,8 @@ public final class RenderNodeAnimator extends Animator { public static final int Y = 9; public static final int Z = 10; public static final int ALPHA = 11; + // The last value in the enum, used for array size initialization + public static final int LAST_VALUE = ALPHA; // Keep in sync with enum PaintFields in Animator.h public static final int PAINT_STROKE_WIDTH = 0; @@ -86,7 +88,7 @@ public final class RenderNodeAnimator extends Animator { private boolean mStarted = false; private boolean mFinished = false; - public int mapViewPropertyToRenderProperty(int viewProperty) { + public static int mapViewPropertyToRenderProperty(int viewProperty) { return sViewPropertyAnimatorMap.get(viewProperty); } @@ -125,11 +127,15 @@ public final class RenderNodeAnimator extends Animator { } } + static boolean isNativeInterpolator(TimeInterpolator interpolator) { + return interpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class); + } + private void applyInterpolator() { if (mInterpolator == null) return; long ni; - if (mInterpolator.getClass().isAnnotationPresent(HasNativeInterpolator.class)) { + if (isNativeInterpolator(mInterpolator)) { ni = ((NativeInterpolatorFactory)mInterpolator).createNativeInterpolator(); } else { long duration = nGetDuration(mNativePtr.get()); diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index 11d2622..3104862 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -19,6 +19,7 @@ package android.view; import android.animation.Animator; import android.animation.ValueAnimator; import android.animation.TimeInterpolator; +import android.os.Build; import java.util.ArrayList; import java.util.HashMap; @@ -109,6 +110,11 @@ public class ViewPropertyAnimator { private ValueAnimator mTempValueAnimator; /** + * A RenderThread-driven backend that may intercept startAnimation + */ + private ViewPropertyAnimatorRT mRTBackend; + + /** * This listener is the mechanism by which the underlying Animator causes changes to the * properties currently being animated, as well as the cleanup after an animation is * complete. @@ -227,7 +233,7 @@ public class ViewPropertyAnimator { * values are used to calculate the animated value for a given animation fraction * during the animation. */ - private static class NameValuesHolder { + static class NameValuesHolder { int mNameConstant; float mFromValue; float mDeltaValue; @@ -247,6 +253,9 @@ public class ViewPropertyAnimator { ViewPropertyAnimator(View view) { mView = view; view.ensureTransformationInfo(); + if (view.getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) { + mRTBackend = new ViewPropertyAnimatorRT(view); + } } /** @@ -371,6 +380,10 @@ public class ViewPropertyAnimator { return this; } + Animator.AnimatorListener getListener() { + return mListener; + } + /** * Sets a listener for update events in the underlying ValueAnimator that runs * the property animations. Note that the underlying animator is animating between @@ -390,6 +403,10 @@ public class ViewPropertyAnimator { return this; } + ValueAnimator.AnimatorUpdateListener getUpdateListener() { + return mUpdateListener; + } + /** * Starts the currently pending property animations immediately. Calling <code>start()</code> * is optional because all animations start automatically at the next opportunity. However, @@ -825,12 +842,22 @@ public class ViewPropertyAnimator { return this; } + boolean hasActions() { + return mPendingSetupAction != null + || mPendingCleanupAction != null + || mPendingOnStartAction != null + || mPendingOnEndAction != null; + } + /** * Starts the underlying Animator for a set of properties. We use a single animator that * simply runs from 0 to 1, and then use that fractional value to set each property * value accordingly. */ private void startAnimation() { + if (mRTBackend != null && mRTBackend.startAnimation(this)) { + return; + } mView.setHasTransientState(true); ValueAnimator animator = ValueAnimator.ofFloat(1.0f); ArrayList<NameValuesHolder> nameValueList = diff --git a/core/java/android/view/ViewPropertyAnimatorRT.java b/core/java/android/view/ViewPropertyAnimatorRT.java new file mode 100644 index 0000000..709efdb --- /dev/null +++ b/core/java/android/view/ViewPropertyAnimatorRT.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2014 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 android.view; + +import android.animation.TimeInterpolator; +import android.view.ViewPropertyAnimator.NameValuesHolder; + +import com.android.internal.view.animation.FallbackLUTInterpolator; + +import java.util.ArrayList; + + +/** + * This is a RenderThread driven backend for ViewPropertyAnimator. + */ +class ViewPropertyAnimatorRT { + + private final View mView; + + private RenderNodeAnimator mAnimators[] = new RenderNodeAnimator[RenderNodeAnimator.LAST_VALUE + 1]; + + ViewPropertyAnimatorRT(View view) { + mView = view; + } + + /** + * @return true if ViewPropertyAnimatorRT handled the animation, + * false if ViewPropertyAnimator needs to handle it + */ + public boolean startAnimation(ViewPropertyAnimator parent) { + cancelAnimators(parent.mPendingAnimations); + if (!canHandleAnimator(parent)) { + return false; + } + doStartAnimation(parent); + return true; + } + + private void doStartAnimation(ViewPropertyAnimator parent) { + int size = parent.mPendingAnimations.size(); + + long startDelay = parent.getStartDelay(); + long duration = parent.getDuration(); + TimeInterpolator interpolator = parent.getInterpolator(); + if (!RenderNodeAnimator.isNativeInterpolator(interpolator)) { + interpolator = new FallbackLUTInterpolator(interpolator, duration); + } + for (int i = 0; i < size; i++) { + NameValuesHolder holder = parent.mPendingAnimations.get(i); + int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant); + + RenderNodeAnimator animator = new RenderNodeAnimator(property, holder.mFromValue + holder.mDeltaValue); + animator.setStartDelay(startDelay); + animator.setDuration(duration); + animator.setInterpolator(interpolator); + animator.setTarget(mView); + animator.start(); + } + + parent.mPendingAnimations.clear(); + } + + private boolean canHandleAnimator(ViewPropertyAnimator parent) { + // TODO: Can we eliminate this entirely? + // If RenderNode.animatorProperties() can be toggled to point at staging + // instead then RNA can be used as the animators for software as well + // as the updateListener fallback paths. If this can be toggled + // at the top level somehow, combined with requiresUiRedraw, we could + // ensure that RT does not self-animate, allowing for safe driving of + // the animators from the UI thread using the same mechanisms + // ViewPropertyAnimator does, just with everything sitting on a single + // animator subsystem instead of multiple. + + if (parent.getUpdateListener() != null) { + return false; + } + if (parent.getListener() != null) { + // TODO support + return false; + } + if (!mView.isHardwareAccelerated()) { + // TODO handle this maybe? + return false; + } + if (parent.hasActions()) { + return false; + } + // Here goes nothing... + return true; + } + + private void cancelAnimators(ArrayList<NameValuesHolder> mPendingAnimations) { + int size = mPendingAnimations.size(); + for (int i = 0; i < size; i++) { + NameValuesHolder holder = mPendingAnimations.get(i); + int property = RenderNodeAnimator.mapViewPropertyToRenderProperty(holder.mNameConstant); + if (mAnimators[property] != null) { + mAnimators[property].cancel(); + mAnimators[property] = null; + } + } + } + +} diff --git a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java index 1feb943..06838c9 100644 --- a/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java +++ b/core/java/com/android/internal/view/animation/FallbackLUTInterpolator.java @@ -24,10 +24,13 @@ import android.view.Choreographer; * Interpolator that builds a lookup table to use. This is a fallback for * building a native interpolator from a TimeInterpolator that is not marked * with {@link HasNativeInterpolator} + * + * This implements TimeInterpolator to allow for easier interop with Animators */ @HasNativeInterpolator -public class FallbackLUTInterpolator implements NativeInterpolatorFactory { +public class FallbackLUTInterpolator implements NativeInterpolatorFactory, TimeInterpolator { + private TimeInterpolator mSourceInterpolator; private final float mLut[]; /** @@ -35,6 +38,7 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory { * interpolator creation */ public FallbackLUTInterpolator(TimeInterpolator interpolator, long duration) { + mSourceInterpolator = interpolator; mLut = createLUT(interpolator, duration); } @@ -63,4 +67,9 @@ public class FallbackLUTInterpolator implements NativeInterpolatorFactory { float[] lut = createLUT(interpolator, duration); return NativeInterpolatorFactoryHelper.createLutInterpolator(lut); } + + @Override + public float getInterpolation(float input) { + return mSourceInterpolator.getInterpolation(input); + } } diff --git a/tests/RenderThreadTest/Android.mk b/tests/RenderThreadTest/Android.mk index bdcba2e..e07e943 100644 --- a/tests/RenderThreadTest/Android.mk +++ b/tests/RenderThreadTest/Android.mk @@ -1,7 +1,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_MODULE_TAGS := optional +LOCAL_MODULE_TAGS := tests # Only compile source java files in this apk. LOCAL_SRC_FILES := $(call all-java-files-under, src) diff --git a/tests/RenderThreadTest/AndroidManifest.xml b/tests/RenderThreadTest/AndroidManifest.xml index c76cfce..a7f4f6e 100644 --- a/tests/RenderThreadTest/AndroidManifest.xml +++ b/tests/RenderThreadTest/AndroidManifest.xml @@ -4,10 +4,6 @@ android:versionCode="1" android:versionName="1.0" > - <uses-sdk - android:minSdkVersion="18" - android:targetSdkVersion="18" /> - <application android:allowBackup="true" android:icon="@drawable/ic_launcher" |