android_view_RenderNodeAnimator.cpp revision f5945a0c8bb868f978d9d0d22043a8b44464a86e
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 28namespace android { 29 30using namespace uirenderer; 31 32static struct { 33 jclass clazz; 34 35 jmethodID callOnFinished; 36} gRenderNodeAnimatorClassInfo; 37 38#ifdef USE_OPENGL_RENDERER 39 40static JNIEnv* getEnv(JavaVM* vm) { 41 JNIEnv* env; 42 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 43 return 0; 44 } 45 return env; 46} 47 48class AnimationListenerBridge : public AnimationListener { 49public: 50 // This holds a strong reference to a Java WeakReference<T> object. This avoids 51 // cyclic-references-of-doom. If you think "I know, just use NewWeakGlobalRef!" 52 // then you end up with basically a PhantomReference, which is totally not 53 // what we want. 54 AnimationListenerBridge(JNIEnv* env, jobject finishListener) { 55 mFinishListener = env->NewGlobalRef(finishListener); 56 env->GetJavaVM(&mJvm); 57 } 58 59 virtual ~AnimationListenerBridge() { 60 if (mFinishListener) { 61 onAnimationFinished(NULL); 62 } 63 } 64 65 virtual void onAnimationFinished(BaseRenderNodeAnimator*) { 66 LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?"); 67 JNIEnv* env = getEnv(mJvm); 68 env->CallStaticVoidMethod( 69 gRenderNodeAnimatorClassInfo.clazz, 70 gRenderNodeAnimatorClassInfo.callOnFinished, 71 mFinishListener); 72 releaseJavaObject(); 73 } 74 75private: 76 void releaseJavaObject() { 77 JNIEnv* env = getEnv(mJvm); 78 env->DeleteGlobalRef(mFinishListener); 79 mFinishListener = NULL; 80 } 81 82 JavaVM* mJvm; 83 jobject mFinishListener; 84}; 85 86static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) { 87 LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderPropertyAnimator::ALPHA, 88 "Invalid property %d", property); 89 return static_cast<RenderPropertyAnimator::RenderProperty>(property); 90} 91 92static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) { 93 LOG_ALWAYS_FATAL_IF(field < 0 94 || field > CanvasPropertyPaintAnimator::ALPHA, 95 "Invalid paint field %d", field); 96 return static_cast<CanvasPropertyPaintAnimator::PaintField>(field); 97} 98 99static jlong createAnimator(JNIEnv* env, jobject clazz, 100 jint propertyRaw, jfloat finalValue) { 101 RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw); 102 BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue); 103 return reinterpret_cast<jlong>( animator ); 104} 105 106static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz, 107 jlong canvasPropertyPtr, jfloat finalValue) { 108 CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr); 109 BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue); 110 return reinterpret_cast<jlong>( animator ); 111} 112 113static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz, 114 jlong canvasPropertyPtr, jint paintFieldRaw, 115 jfloat finalValue) { 116 CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr); 117 CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw); 118 BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator( 119 canvasProperty, paintField, finalValue); 120 return reinterpret_cast<jlong>( animator ); 121} 122 123static jlong createRevealAnimator(JNIEnv* env, jobject clazz, 124 jint centerX, jint centerY, jfloat startRadius, jfloat endRadius) { 125 BaseRenderNodeAnimator* animator = new RevealAnimator(centerX, centerY, startRadius, endRadius); 126 return reinterpret_cast<jlong>( animator ); 127} 128 129static void setStartValue(JNIEnv* env, jobject clazz, jlong animatorPtr, jfloat startValue) { 130 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 131 animator->setStartValue(startValue); 132} 133 134static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong duration) { 135 LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative"); 136 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 137 animator->setDuration(duration); 138} 139 140static jlong getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) { 141 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 142 return static_cast<jlong>(animator->duration()); 143} 144 145static void setStartDelay(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong startDelay) { 146 LOG_ALWAYS_FATAL_IF(startDelay < 0, "Start delay cannot be negative"); 147 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 148 animator->setStartDelay(startDelay); 149} 150 151static jlong getStartDelay(JNIEnv* env, jobject clazz, jlong animatorPtr) { 152 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 153 return static_cast<jlong>(animator->startDelay()); 154} 155 156static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) { 157 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 158 Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); 159 animator->setInterpolator(interpolator); 160} 161 162static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr, jboolean mayRunAsync) { 163 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 164 animator->setAllowRunningAsync(mayRunAsync); 165} 166 167static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) { 168 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 169 if (finishListener) { 170 animator->setListener(new AnimationListenerBridge(env, finishListener)); 171 } 172 animator->start(); 173} 174 175static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) { 176 BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr); 177 animator->end(); 178} 179 180#endif 181 182// ---------------------------------------------------------------------------- 183// JNI Glue 184// ---------------------------------------------------------------------------- 185 186const char* const kClassPathName = "android/view/RenderNodeAnimator"; 187 188static JNINativeMethod gMethods[] = { 189#ifdef USE_OPENGL_RENDERER 190 { "nCreateAnimator", "(IF)J", (void*) createAnimator }, 191 { "nCreateCanvasPropertyFloatAnimator", "(JF)J", (void*) createCanvasPropertyFloatAnimator }, 192 { "nCreateCanvasPropertyPaintAnimator", "(JIF)J", (void*) createCanvasPropertyPaintAnimator }, 193 { "nCreateRevealAnimator", "(IIFF)J", (void*) createRevealAnimator }, 194 { "nSetStartValue", "(JF)V", (void*) setStartValue }, 195 { "nSetDuration", "(JJ)V", (void*) setDuration }, 196 { "nGetDuration", "(J)J", (void*) getDuration }, 197 { "nSetStartDelay", "(JJ)V", (void*) setStartDelay }, 198 { "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, 199 { "nSetAllowRunningAsync", "(JZ)V", (void*) setAllowRunningAsync }, 200 { "nStart", "(JLandroid/view/RenderNodeAnimator;)V", (void*) start }, 201 { "nEnd", "(J)V", (void*) end }, 202#endif 203}; 204 205#define FIND_CLASS(var, className) \ 206 var = env->FindClass(className); \ 207 LOG_FATAL_IF(! var, "Unable to find class " className); 208 209#define GET_STATIC_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 210 var = env->GetStaticMethodID(clazz, methodName, methodDescriptor); \ 211 LOG_FATAL_IF(! var, "Unable to find method " methodName); 212 213int register_android_view_RenderNodeAnimator(JNIEnv* env) { 214 FIND_CLASS(gRenderNodeAnimatorClassInfo.clazz, kClassPathName); 215 gRenderNodeAnimatorClassInfo.clazz = jclass(env->NewGlobalRef(gRenderNodeAnimatorClassInfo.clazz)); 216 217 GET_STATIC_METHOD_ID(gRenderNodeAnimatorClassInfo.callOnFinished, gRenderNodeAnimatorClassInfo.clazz, 218 "callOnFinished", "(Landroid/view/RenderNodeAnimator;)V"); 219 220 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 221} 222 223 224} // namespace android 225