diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 2 | ||||
-rw-r--r-- | core/java/android/view/RenderNode.java | 21 | ||||
-rw-r--r-- | core/java/android/view/RenderNodeAnimator.java | 44 | ||||
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 20 | ||||
-rw-r--r-- | core/java/android/view/View.java | 9 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 21 | ||||
-rw-r--r-- | core/java/android/widget/Editor.java | 2 | ||||
-rw-r--r-- | core/jni/android_view_RenderNode.cpp | 7 | ||||
-rw-r--r-- | core/jni/android_view_RenderNodeAnimator.cpp | 53 | ||||
-rw-r--r-- | core/jni/android_view_ThreadedRenderer.cpp | 87 |
10 files changed, 194 insertions, 72 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index de90899..edb3798 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -485,4 +485,6 @@ public abstract class HardwareRenderer { * Called by {@link ViewRootImpl} when a new performTraverals is scheduled. */ abstract void notifyFramePending(); + + abstract void registerAnimatingRenderNode(RenderNode animator); } diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index 099f153..9dc9766 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -167,10 +167,13 @@ public class RenderNode { public static final int STATUS_DREW = 0x4; private boolean mValid; - private final long mNativeRenderNode; + // Do not access directly unless you are ThreadedRenderer + final long mNativeRenderNode; + private final View mOwningView; - private RenderNode(String name) { + private RenderNode(String name, View owningView) { mNativeRenderNode = nCreate(name); + mOwningView = owningView; } /** @@ -178,6 +181,7 @@ public class RenderNode { */ private RenderNode(long nativePtr) { mNativeRenderNode = nativePtr; + mOwningView = null; } /** @@ -188,8 +192,8 @@ public class RenderNode { * * @return A new RenderNode. */ - public static RenderNode create(String name) { - return new RenderNode(name); + public static RenderNode create(String name, @Nullable View owningView) { + return new RenderNode(name, owningView); } /** @@ -805,7 +809,15 @@ public class RenderNode { /////////////////////////////////////////////////////////////////////////// public void addAnimator(RenderNodeAnimator animator) { + if (mOwningView == null || mOwningView.mAttachInfo == null) { + throw new IllegalStateException("Cannot start this animator on a detached view!"); + } nAddAnimator(mNativeRenderNode, animator.getNativeAnimator()); + mOwningView.mAttachInfo.mViewRootImpl.registerAnimatingRenderNode(this); + } + + public void endAllAnimators() { + nEndAllAnimators(mNativeRenderNode); } /////////////////////////////////////////////////////////////////////////// @@ -891,6 +903,7 @@ public class RenderNode { /////////////////////////////////////////////////////////////////////////// private static native void nAddAnimator(long renderNode, long animatorPtr); + private static native void nEndAllAnimators(long renderNode); /////////////////////////////////////////////////////////////////////////// // Finalization diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java index 9433237..413ea04 100644 --- a/core/java/android/view/RenderNodeAnimator.java +++ b/core/java/android/view/RenderNodeAnimator.java @@ -19,7 +19,6 @@ package android.view; import android.animation.Animator; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; -import android.animation.Animator.AnimatorListener; import android.graphics.Canvas; import android.graphics.CanvasProperty; import android.graphics.Paint; @@ -30,7 +29,6 @@ import com.android.internal.view.animation.FallbackLUTInterpolator; import com.android.internal.view.animation.HasNativeInterpolator; import com.android.internal.view.animation.NativeInterpolatorFactory; -import java.lang.ref.WeakReference; import java.util.ArrayList; /** @@ -111,13 +109,11 @@ public class RenderNodeAnimator extends Animator { mRenderProperty = property; mFinalValue = finalValue; mUiThreadHandlesDelay = true; - init(nCreateAnimator(new WeakReference<RenderNodeAnimator>(this), - property, finalValue)); + init(nCreateAnimator(property, finalValue)); } public RenderNodeAnimator(CanvasProperty<Float> property, float finalValue) { init(nCreateCanvasPropertyFloatAnimator( - new WeakReference<RenderNodeAnimator>(this), property.getNativeContainer(), finalValue)); mUiThreadHandlesDelay = false; } @@ -132,14 +128,12 @@ public class RenderNodeAnimator extends Animator { */ public RenderNodeAnimator(CanvasProperty<Paint> property, int paintField, float finalValue) { init(nCreateCanvasPropertyPaintAnimator( - new WeakReference<RenderNodeAnimator>(this), property.getNativeContainer(), paintField, finalValue)); mUiThreadHandlesDelay = false; } public RenderNodeAnimator(int x, int y, float startRadius, float endRadius) { - init(nCreateRevealAnimator(new WeakReference<RenderNodeAnimator>(this), - x, y, startRadius, endRadius)); + init(nCreateRevealAnimator(x, y, startRadius, endRadius)); mUiThreadHandlesDelay = true; } @@ -192,7 +186,7 @@ public class RenderNodeAnimator extends Animator { } private void doStart() { - nStart(mNativePtr.get()); + nStart(mNativePtr.get(), this); // Alpha is a special snowflake that has the canonical value stored // in mTransformationInfo instead of in RenderNode, so we need to update @@ -248,24 +242,21 @@ public class RenderNodeAnimator extends Animator { public void setTarget(View view) { mViewTarget = view; - mTarget = view.mRenderNode; - mTarget.addAnimator(this); + setTarget(mViewTarget.mRenderNode); } public void setTarget(Canvas canvas) { if (!(canvas instanceof GLES20RecordingCanvas)) { throw new IllegalArgumentException("Not a GLES20RecordingCanvas"); } - final GLES20RecordingCanvas recordingCanvas = (GLES20RecordingCanvas) canvas; setTarget(recordingCanvas.mNode); } - public void setTarget(RenderNode node) { + private void setTarget(RenderNode node) { if (mTarget != null) { throw new IllegalStateException("Target already set!"); } - mViewTarget = null; mTarget = node; mTarget.addAnimator(this); } @@ -335,6 +326,12 @@ public class RenderNodeAnimator extends Animator { for (int i = 0; i < numListeners; i++) { listeners.get(i).onAnimationEnd(this); } + + // Release the native object, as it has a global reference to us. This + // breaks the cyclic reference chain, and allows this object to be + // GC'd + mNativePtr.release(); + mNativePtr = null; } @SuppressWarnings("unchecked") @@ -427,11 +424,8 @@ public class RenderNodeAnimator extends Animator { } // Called by native - private static void callOnFinished(WeakReference<RenderNodeAnimator> weakThis) { - RenderNodeAnimator animator = weakThis.get(); - if (animator != null) { - animator.onFinished(); - } + private static void callOnFinished(RenderNodeAnimator animator) { + animator.onFinished(); } @Override @@ -439,22 +433,20 @@ public class RenderNodeAnimator extends Animator { throw new IllegalStateException("Cannot clone this animator"); } - private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis, - int property, float finalValue); - private static native long nCreateCanvasPropertyFloatAnimator(WeakReference<RenderNodeAnimator> weakThis, + private static native long nCreateAnimator(int property, float finalValue); + private static native long nCreateCanvasPropertyFloatAnimator( long canvasProperty, float finalValue); - private static native long nCreateCanvasPropertyPaintAnimator(WeakReference<RenderNodeAnimator> weakThis, + private static native long nCreateCanvasPropertyPaintAnimator( long canvasProperty, int paintField, float finalValue); - private static native long nCreateRevealAnimator(WeakReference<RenderNodeAnimator> weakThis, + private static native long nCreateRevealAnimator( int x, int y, float startRadius, float endRadius); private static native void nSetStartValue(long nativePtr, float startValue); private static native void nSetDuration(long nativePtr, long duration); private static native long nGetDuration(long nativePtr); private static native void nSetStartDelay(long nativePtr, long startDelay); - private static native long nGetStartDelay(long nativePtr); private static native void nSetInterpolator(long animPtr, long interpolatorPtr); - private static native void nStart(long animPtr); + private static native void nStart(long animPtr, RenderNodeAnimator finishListener); private static native void nEnd(long animPtr); } diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 50341fc..faade96 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -314,6 +314,20 @@ public class ThreadedRenderer extends HardwareRenderer { attachInfo.mIgnoreDirtyState = false; + // register animating rendernodes which started animating prior to renderer + // creation, which is typical for animators started prior to first draw + if (attachInfo.mPendingAnimatingRenderNodes != null) { + final int count = attachInfo.mPendingAnimatingRenderNodes.size(); + for (int i = 0; i < count; i++) { + registerAnimatingRenderNode( + attachInfo.mPendingAnimatingRenderNodes.get(i)); + } + attachInfo.mPendingAnimatingRenderNodes.clear(); + // We don't need this anymore as subsequent calls to + // ViewRootImpl#attachRenderNodeAnimator will go directly to us. + attachInfo.mPendingAnimatingRenderNodes = null; + } + int syncResult = nSyncAndDrawFrame(mNativeProxy, frameTimeNanos, recordDuration, view.getResources().getDisplayMetrics().density); if ((syncResult & SYNC_INVALIDATE_REQUIRED) != 0) { @@ -372,6 +386,11 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override + void registerAnimatingRenderNode(RenderNode animator) { + nRegisterAnimatingRenderNode(mRootNode.mNativeRenderNode, animator.mNativeRenderNode); + } + + @Override protected void finalize() throws Throwable { try { nDeleteProxy(mNativeProxy); @@ -468,6 +487,7 @@ public class ThreadedRenderer extends HardwareRenderer { private static native int nSyncAndDrawFrame(long nativeProxy, long frameTimeNanos, long recordDuration, float density); private static native void nDestroyCanvasAndSurface(long nativeProxy); + private static native void nRegisterAnimatingRenderNode(long rootRenderNode, long animatingNode); private static native void nInvokeFunctor(long functor, boolean waitForCompletion); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6f58582..9e1dbe0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3565,7 +3565,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS); mUserPaddingStart = UNDEFINED_PADDING; mUserPaddingEnd = UNDEFINED_PADDING; - mRenderNode = RenderNode.create(getClass().getName()); + mRenderNode = RenderNode.create(getClass().getName(), this); if (!sCompatibilityDone && context != null) { final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; @@ -4161,7 +4161,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, */ View() { mResources = null; - mRenderNode = RenderNode.create(getClass().getName()); + mRenderNode = RenderNode.create(getClass().getName(), this); } private static SparseArray<String> getAttributeMap() { @@ -15180,9 +15180,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @param renderNode Existing RenderNode, or {@code null} * @return A valid display list for the specified drawable */ - private static RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) { + private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) { if (renderNode == null) { - renderNode = RenderNode.create(drawable.getClass().getName()); + renderNode = RenderNode.create(drawable.getClass().getName(), this); } final Rect bounds = drawable.getBounds(); @@ -19908,6 +19908,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, boolean mHardwareAccelerated; boolean mHardwareAccelerationRequested; HardwareRenderer mHardwareRenderer; + List<RenderNode> mPendingAnimatingRenderNodes; /** * The state of the display to which the window is attached, as reported diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index bb469a3..80dbbf5 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -671,6 +671,17 @@ public final class ViewRootImpl implements ViewParent, ThreadedRenderer.invokeFunctor(functor, waitForCompletion); } + public void registerAnimatingRenderNode(RenderNode animator) { + if (mAttachInfo.mHardwareRenderer != null) { + mAttachInfo.mHardwareRenderer.registerAnimatingRenderNode(animator); + } else { + if (mAttachInfo.mPendingAnimatingRenderNodes == null) { + mAttachInfo.mPendingAnimatingRenderNodes = new ArrayList<RenderNode>(); + } + mAttachInfo.mPendingAnimatingRenderNodes.add(animator); + } + } + private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) { mAttachInfo.mHardwareAccelerated = false; mAttachInfo.mHardwareAccelerationRequested = false; @@ -2329,6 +2340,16 @@ public final class ViewRootImpl implements ViewParent, Trace.traceEnd(Trace.TRACE_TAG_VIEW); } + // For whatever reason we didn't create a HardwareRenderer, end any + // hardware animations that are now dangling + if (mAttachInfo.mPendingAnimatingRenderNodes != null) { + final int count = mAttachInfo.mPendingAnimatingRenderNodes.size(); + for (int i = 0; i < count; i++) { + mAttachInfo.mPendingAnimatingRenderNodes.get(i).endAllAnimators(); + } + mAttachInfo.mPendingAnimatingRenderNodes.clear(); + } + if (mReportNextDraw) { mReportNextDraw = false; if (mAttachInfo.mHardwareRenderer != null) { diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 29c8298..46b225d 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -147,7 +147,7 @@ public class Editor { boolean isDirty; public TextDisplayList(String name) { isDirty = true; - displayList = RenderNode.create(name); + displayList = RenderNode.create(name, null); } boolean needsRecord() { return isDirty || !displayList.isValid(); } } diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index 1e9d722..1296831 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -455,6 +455,12 @@ static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz, renderNode->addAnimator(animator); } +static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz, + jlong renderNodePtr) { + RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); + renderNode->animators().endAllAnimators(); +} + #endif // USE_OPENGL_RENDERER // ---------------------------------------------------------------------------- @@ -534,6 +540,7 @@ static JNINativeMethod gMethods[] = { { "nGetPivotY", "(J)F", (void*) android_view_RenderNode_getPivotY }, { "nAddAnimator", "(JJ)V", (void*) android_view_RenderNode_addAnimator }, + { "nEndAllAnimators", "(J)V", (void*) android_view_RenderNode_endAllAnimators }, #endif }; diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp index 767534f..85c2a09 100644 --- a/core/jni/android_view_RenderNodeAnimator.cpp +++ b/core/jni/android_view_RenderNodeAnimator.cpp @@ -51,28 +51,36 @@ public: // cyclic-references-of-doom. If you think "I know, just use NewWeakGlobalRef!" // then you end up with basically a PhantomReference, which is totally not // what we want. - AnimationListenerBridge(JNIEnv* env, jobject weakThis) { - mWeakThis = env->NewGlobalRef(weakThis); + AnimationListenerBridge(JNIEnv* env, jobject finishListener) { + mFinishListener = env->NewGlobalRef(finishListener); env->GetJavaVM(&mJvm); } virtual ~AnimationListenerBridge() { - JNIEnv* env = getEnv(mJvm); - env->DeleteGlobalRef(mWeakThis); - mWeakThis = NULL; + if (mFinishListener) { + onAnimationFinished(NULL); + } } virtual void onAnimationFinished(BaseRenderNodeAnimator*) { + LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?"); JNIEnv* env = getEnv(mJvm); env->CallStaticVoidMethod( gRenderNodeAnimatorClassInfo.clazz, gRenderNodeAnimatorClassInfo.callOnFinished, - mWeakThis); + mFinishListener); + releaseJavaObject(); } private: + void releaseJavaObject() { + JNIEnv* env = getEnv(mJvm); + env->DeleteGlobalRef(mFinishListener); + mFinishListener = NULL; + } + JavaVM* mJvm; - jobject mWeakThis; + jobject mFinishListener; }; static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) { @@ -88,38 +96,33 @@ static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) { return static_cast<CanvasPropertyPaintAnimator::PaintField>(field); } -static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis, +static jlong createAnimator(JNIEnv* env, jobject clazz, jint propertyRaw, jfloat finalValue) { RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw); - BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue); - animator->setListener(new AnimationListenerBridge(env, weakThis)); return reinterpret_cast<jlong>( animator ); } static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz, - jobject weakThis, jlong canvasPropertyPtr, jfloat finalValue) { + jlong canvasPropertyPtr, jfloat finalValue) { CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr); BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue); - animator->setListener(new AnimationListenerBridge(env, weakThis)); return reinterpret_cast<jlong>( animator ); } static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz, - jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw, + jlong canvasPropertyPtr, jint paintFieldRaw, jfloat finalValue) { CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr); CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw); BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator( canvasProperty, paintField, finalValue); - animator->setListener(new AnimationListenerBridge(env, weakThis)); return reinterpret_cast<jlong>( animator ); } -static jlong createRevealAnimator(JNIEnv* env, jobject clazz, jobject weakThis, +static jlong createRevealAnimator(JNIEnv* env, jobject clazz, jint centerX, jint centerY, jfloat startRadius, jfloat endRadius) { BaseRenderNodeAnimator* animator = new RevealAnimator(centerX, centerY, startRadius, endRadius); - animator->setListener(new AnimationListenerBridge(env, weakThis)); return reinterpret_cast<jlong>( animator ); } @@ -156,8 +159,11 @@ static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong animator->setInterpolator(interpolator); } -static void start(JNIEnv* env, jobject clazz, jlong animatorPtr) { +static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) { BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); + if (finishListener) { + animator->setListener(new AnimationListenerBridge(env, finishListener)); + } animator->start(); } @@ -176,17 +182,16 @@ const char* const kClassPathName = "android/view/RenderNodeAnimator"; static JNINativeMethod gMethods[] = { #ifdef USE_OPENGL_RENDERER - { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IF)J", (void*) createAnimator }, - { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JF)J", (void*) createCanvasPropertyFloatAnimator }, - { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyPaintAnimator }, - { "nCreateRevealAnimator", "(Ljava/lang/ref/WeakReference;IIFF)J", (void*) createRevealAnimator }, + { "nCreateAnimator", "(IF)J", (void*) createAnimator }, + { "nCreateCanvasPropertyFloatAnimator", "(JF)J", (void*) createCanvasPropertyFloatAnimator }, + { "nCreateCanvasPropertyPaintAnimator", "(JIF)J", (void*) createCanvasPropertyPaintAnimator }, + { "nCreateRevealAnimator", "(IIFF)J", (void*) createRevealAnimator }, { "nSetStartValue", "(JF)V", (void*) setStartValue }, { "nSetDuration", "(JJ)V", (void*) setDuration }, { "nGetDuration", "(J)J", (void*) getDuration }, { "nSetStartDelay", "(JJ)V", (void*) setStartDelay }, - { "nGetStartDelay", "(J)J", (void*) getStartDelay }, { "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, - { "nStart", "(J)V", (void*) start }, + { "nStart", "(JLandroid/view/RenderNodeAnimator;)V", (void*) start }, { "nEnd", "(J)V", (void*) end }, #endif }; @@ -204,7 +209,7 @@ int register_android_view_RenderNodeAnimator(JNIEnv* env) { gRenderNodeAnimatorClassInfo.clazz = jclass(env->NewGlobalRef(gRenderNodeAnimatorClassInfo.clazz)); GET_STATIC_METHOD_ID(gRenderNodeAnimatorClassInfo.callOnFinished, gRenderNodeAnimatorClassInfo.clazz, - "callOnFinished", "(Ljava/lang/ref/WeakReference;)V"); + "callOnFinished", "(Landroid/view/RenderNodeAnimator;)V"); return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); } diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 4e3419a..99babac 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -33,6 +33,8 @@ #include "android_view_GraphicBuffer.h" #include <Animator.h> +#include <AnimationContext.h> +#include <IContextFactory.h> #include <RenderNode.h> #include <renderthread/CanvasContext.h> #include <renderthread/RenderProxy.h> @@ -103,7 +105,7 @@ private: std::string mMessage; }; -class RootRenderNode : public RenderNode, AnimationHook, ErrorHandler { +class RootRenderNode : public RenderNode, ErrorHandler { public: RootRenderNode(JNIEnv* env) : RenderNode() { mLooper = Looper::getForThread(); @@ -114,34 +116,84 @@ public: virtual ~RootRenderNode() {} - virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) { - OnFinishedEvent event(animator, listener); - mOnFinishedEvents.push_back(event); - } - virtual void onError(const std::string& message) { mLooper->sendMessage(new RenderingException(mVm, message), 0); } virtual void prepareTree(TreeInfo& info) { - info.animationHook = this; info.errorHandler = this; RenderNode::prepareTree(info); - info.animationHook = NULL; info.errorHandler = NULL; + } + + void sendMessage(const sp<MessageHandler>& handler) { + mLooper->sendMessage(handler, 0); + } + + void attachAnimatingNode(RenderNode* animatingNode) { + mPendingAnimatingRenderNodes.push_back(animatingNode); + } + + void doAttachAnimatingNodes(AnimationContext* context) { + for (size_t i = 0; i < mPendingAnimatingRenderNodes.size(); i++) { + RenderNode* node = mPendingAnimatingRenderNodes[i].get(); + context->addAnimatingRenderNode(*node); + } + mPendingAnimatingRenderNodes.clear(); + } + +private: + sp<Looper> mLooper; + JavaVM* mVm; + std::vector< sp<RenderNode> > mPendingAnimatingRenderNodes; +}; + +class AnimationContextBridge : public AnimationContext { +public: + AnimationContextBridge(renderthread::TimeLord& clock, RootRenderNode* rootNode) + : AnimationContext(clock), mRootNode(rootNode) { + } + + virtual ~AnimationContextBridge() {} + // Marks the start of a frame, which will update the frame time and move all + // next frame animations into the current frame + virtual void startFrame() { + mRootNode->doAttachAnimatingNodes(this); + AnimationContext::startFrame(); + } + + // Runs any animations still left in mCurrentFrameAnimations + virtual void runRemainingAnimations(TreeInfo& info) { + AnimationContext::runRemainingAnimations(info); // post all the finished stuff if (mOnFinishedEvents.size()) { sp<InvokeAnimationListeners> message = new InvokeAnimationListeners(mOnFinishedEvents); - mLooper->sendMessage(message, 0); + mRootNode->sendMessage(message); } } + virtual void callOnFinished(BaseRenderNodeAnimator* animator, AnimationListener* listener) { + OnFinishedEvent event(animator, listener); + mOnFinishedEvents.push_back(event); + } + private: - sp<Looper> mLooper; + sp<RootRenderNode> mRootNode; std::vector<OnFinishedEvent> mOnFinishedEvents; - JavaVM* mVm; +}; + +class ContextFactoryImpl : public IContextFactory { +public: + ContextFactoryImpl(RootRenderNode* rootNode) : mRootNode(rootNode) {} + + virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) { + return new AnimationContextBridge(clock, mRootNode); + } + +private: + RootRenderNode* mRootNode; }; static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz, @@ -168,8 +220,9 @@ static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, job static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz, jboolean translucent, jlong rootRenderNodePtr) { - RenderNode* rootRenderNode = reinterpret_cast<RenderNode*>(rootRenderNodePtr); - return (jlong) new RenderProxy(translucent, rootRenderNode); + RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootRenderNodePtr); + ContextFactoryImpl factory(rootRenderNode); + return (jlong) new RenderProxy(translucent, rootRenderNode, &factory); } static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz, @@ -244,6 +297,13 @@ static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, j proxy->destroyCanvasAndSurface(); } +static void android_view_ThreadedRenderer_registerAnimatingRenderNode(JNIEnv* env, jobject clazz, + jlong rootNodePtr, jlong animatingNodePtr) { + RootRenderNode* rootRenderNode = reinterpret_cast<RootRenderNode*>(rootNodePtr); + RenderNode* animatingNode = reinterpret_cast<RenderNode*>(animatingNodePtr); + rootRenderNode->attachAnimatingNode(animatingNode); +} + static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz, jlong functorPtr, jboolean waitForCompletion) { Functor* functor = reinterpret_cast<Functor*>(functorPtr); @@ -371,6 +431,7 @@ static JNINativeMethod gMethods[] = { { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface }, + { "nRegisterAnimatingRenderNode", "(JJ)V", (void*) android_view_ThreadedRenderer_registerAnimatingRenderNode }, { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer }, { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, |