android_view_RenderNodeAnimator.cpp revision 389baa395125d5ae5aac3b9d2f98457dde09da26
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "OpenGLRenderer" 18 19#include "jni.h" 20#include "GraphicsJNI.h" 21#include <nativehelper/JNIHelp.h> 22#include <android_runtime/AndroidRuntime.h> 23 24#include <Animator.h> 25#include <Interpolator.h> 26#include <RenderProperties.h> 27 28#include "core_jni_helpers.h" 29 30namespace android { 31 32using namespace uirenderer; 33 34static struct { 35 jclass clazz; 36 37 jmethodID callOnFinished; 38} gRenderNodeAnimatorClassInfo; 39 40#ifdef USE_OPENGL_RENDERER 41 42static JNIEnv* getEnv(JavaVM* vm) { 43 JNIEnv* env; 44 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 45 return 0; 46 } 47 return env; 48} 49 50class AnimationListenerLifecycleChecker : public AnimationListener { 51public: 52 virtual void onAnimationFinished(BaseRenderNodeAnimator* animator) { 53 LOG_ALWAYS_FATAL("Lifecycle failure, nStart(%p) wasn't called", animator); 54 } 55}; 56 57static AnimationListenerLifecycleChecker sLifecycleChecker; 58 59class AnimationListenerBridge : public AnimationListener { 60public: 61 // This holds a strong reference to a Java WeakReference<T> object. This avoids 62 // cyclic-references-of-doom. If you think "I know, just use NewWeakGlobalRef!" 63 // then you end up with basically a PhantomReference, which is totally not 64 // what we want. 65 AnimationListenerBridge(JNIEnv* env, jobject finishListener) { 66 mFinishListener = env->NewGlobalRef(finishListener); 67 env->GetJavaVM(&mJvm); 68 } 69 70 virtual ~AnimationListenerBridge() { 71 if (mFinishListener) { 72 onAnimationFinished(NULL); 73 } 74 } 75 76 virtual void onAnimationFinished(BaseRenderNodeAnimator*) { 77 LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?"); 78 JNIEnv* env = getEnv(mJvm); 79 env->CallStaticVoidMethod( 80 gRenderNodeAnimatorClassInfo.clazz, 81 gRenderNodeAnimatorClassInfo.callOnFinished, 82 mFinishListener); 83 releaseJavaObject(); 84 } 85 86private: 87 void releaseJavaObject() { 88 JNIEnv* env = getEnv(mJvm); 89 env->DeleteGlobalRef(mFinishListener); 90 mFinishListener = NULL; 91 } 92 93 JavaVM* mJvm; 94 jobject mFinishListener; 95}; 96 97static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) { 98 LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderPropertyAnimator::ALPHA, 99 "Invalid property %d", property); 100 return static_cast<RenderPropertyAnimator::RenderProperty>(property); 101} 102 103static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) { 104 LOG_ALWAYS_FATAL_IF(field < 0 105 || field > CanvasPropertyPaintAnimator::ALPHA, 106 "Invalid paint field %d", field); 107 return static_cast<CanvasPropertyPaintAnimator::PaintField>(field); 108} 109 110static jlong createAnimator(JNIEnv* env, jobject clazz, 111 jint propertyRaw, jfloat finalValue) { 112 RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw); 113 BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue); 114 animator->setListener(&sLifecycleChecker); 115 return reinterpret_cast<jlong>( animator ); 116} 117 118static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz, 119 jlong canvasPropertyPtr, jfloat finalValue) { 120 CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr); 121 BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue); 122 animator->setListener(&sLifecycleChecker); 123 return reinterpret_cast<jlong>( animator ); 124} 125 126static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz, 127 jlong canvasPropertyPtr, jint paintFieldRaw, 128 jfloat finalValue) { 129 CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr); 130 CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw); 131 BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator( 132 canvasProperty, paintField, finalValue); 133 animator->setListener(&sLifecycleChecker); 134 return reinterpret_cast<jlong>( animator ); 135} 136 137static jlong createRevealAnimator(JNIEnv* env, jobject clazz, 138 jint centerX, jint centerY, jfloat startRadius, jfloat endRadius) { 139 BaseRenderNodeAnimator* animator = new RevealAnimator(centerX, centerY, startRadius, endRadius); 140 animator->setListener(&sLifecycleChecker); 141 return reinterpret_cast<jlong>( animator ); 142} 143 144static void setStartValue(JNIEnv* env, jobject clazz, jlong animatorPtr, jfloat startValue) { 145 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 146 animator->setStartValue(startValue); 147} 148 149static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong duration) { 150 LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative"); 151 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 152 animator->setDuration(duration); 153} 154 155static jlong getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) { 156 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 157 return static_cast<jlong>(animator->duration()); 158} 159 160static void setStartDelay(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong startDelay) { 161 LOG_ALWAYS_FATAL_IF(startDelay < 0, "Start delay cannot be negative"); 162 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 163 animator->setStartDelay(startDelay); 164} 165 166static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) { 167 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 168 Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); 169 animator->setInterpolator(interpolator); 170} 171 172static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr, jboolean mayRunAsync) { 173 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 174 animator->setAllowRunningAsync(mayRunAsync); 175} 176 177static void setListener(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) { 178 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 179 animator->setListener(new AnimationListenerBridge(env, finishListener)); 180} 181 182static void start(JNIEnv* env, jobject clazz, jlong animatorPtr) { 183 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 184 animator->start(); 185} 186 187static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) { 188 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 189 animator->end(); 190} 191 192#endif 193 194// ---------------------------------------------------------------------------- 195// JNI Glue 196// ---------------------------------------------------------------------------- 197 198const char* const kClassPathName = "android/view/RenderNodeAnimator"; 199 200static JNINativeMethod gMethods[] = { 201#ifdef USE_OPENGL_RENDERER 202 { "nCreateAnimator", "(IF)J", (void*) createAnimator }, 203 { "nCreateCanvasPropertyFloatAnimator", "(JF)J", (void*) createCanvasPropertyFloatAnimator }, 204 { "nCreateCanvasPropertyPaintAnimator", "(JIF)J", (void*) createCanvasPropertyPaintAnimator }, 205 { "nCreateRevealAnimator", "(IIFF)J", (void*) createRevealAnimator }, 206 { "nSetStartValue", "(JF)V", (void*) setStartValue }, 207 { "nSetDuration", "(JJ)V", (void*) setDuration }, 208 { "nGetDuration", "(J)J", (void*) getDuration }, 209 { "nSetStartDelay", "(JJ)V", (void*) setStartDelay }, 210 { "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, 211 { "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync }, 212 { "nSetListener", "(JLandroid/view/RenderNodeAnimator;)V", (void*) setListener}, 213 { "nStart", "(J)V", (void*) start}, 214 { "nEnd", "(J)V", (void*) end }, 215#endif 216}; 217 218int register_android_view_RenderNodeAnimator(JNIEnv* env) { 219#ifdef USE_OPENGL_RENDERER 220 sLifecycleChecker.incStrong(0); 221#endif 222 gRenderNodeAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName); 223 gRenderNodeAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env, 224 gRenderNodeAnimatorClassInfo.clazz); 225 226 gRenderNodeAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie( 227 env, gRenderNodeAnimatorClassInfo.clazz, "callOnFinished", 228 "(Landroid/view/RenderNodeAnimator;)V"); 229 230 return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); 231} 232 233 234} // namespace android 235