android_view_RenderNodeAnimator.cpp revision 315c329544d7c593d1072b071cbb92d9afe74021
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 weakThis) { 55 mWeakThis = env->NewGlobalRef(weakThis); 56 env->GetJavaVM(&mJvm); 57 } 58 59 virtual ~AnimationListenerBridge() { 60 JNIEnv* env = getEnv(mJvm); 61 env->DeleteGlobalRef(mWeakThis); 62 mWeakThis = NULL; 63 } 64 65 virtual void onAnimationFinished(BaseAnimator*) { 66 JNIEnv* env = getEnv(mJvm); 67 env->CallStaticVoidMethod( 68 gRenderNodeAnimatorClassInfo.clazz, 69 gRenderNodeAnimatorClassInfo.callOnFinished, 70 mWeakThis); 71 } 72 73private: 74 JavaVM* mJvm; 75 jobject mWeakThis; 76}; 77 78static inline RenderPropertyAnimator::RenderProperty toRenderProperty(jint property) { 79 LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderPropertyAnimator::ALPHA, 80 "Invalid property %d", property); 81 return static_cast<RenderPropertyAnimator::RenderProperty>(property); 82} 83 84static inline RenderPropertyAnimator::DeltaValueType toDeltaType(jint deltaType) { 85 LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA 86 && deltaType != RenderPropertyAnimator::ABSOLUTE, 87 "Invalid delta type %d", deltaType); 88 return static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType); 89} 90 91static inline CanvasPropertyPaintAnimator::PaintField toPaintField(jint field) { 92 LOG_ALWAYS_FATAL_IF(field < 0 93 || field > CanvasPropertyPaintAnimator::ALPHA, 94 "Invalid paint field %d", field); 95 return static_cast<CanvasPropertyPaintAnimator::PaintField>(field); 96} 97 98static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis, 99 jint propertyRaw, jint deltaTypeRaw, jfloat deltaValue) { 100 RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw); 101 RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw); 102 103 BaseAnimator* animator = new RenderPropertyAnimator(property, deltaType, deltaValue); 104 animator->setListener(new AnimationListenerBridge(env, weakThis)); 105 return reinterpret_cast<jlong>( animator ); 106} 107 108static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz, 109 jobject weakThis, jlong canvasPropertyPtr, jint deltaTypeRaw, jfloat deltaValue) { 110 RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw); 111 CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr); 112 BaseAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, deltaType, deltaValue); 113 animator->setListener(new AnimationListenerBridge(env, weakThis)); 114 return reinterpret_cast<jlong>( animator ); 115} 116 117static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz, 118 jobject weakThis, jlong canvasPropertyPtr, jint paintFieldRaw, 119 jint deltaTypeRaw, jfloat deltaValue) { 120 RenderPropertyAnimator::DeltaValueType deltaType = toDeltaType(deltaTypeRaw); 121 CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr); 122 CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw); 123 BaseAnimator* animator = new CanvasPropertyPaintAnimator( 124 canvasProperty, paintField, deltaType, deltaValue); 125 animator->setListener(new AnimationListenerBridge(env, weakThis)); 126 return reinterpret_cast<jlong>( animator ); 127} 128 129static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) { 130 LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative"); 131 BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr); 132 animator->setDuration(duration); 133} 134 135static jint getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) { 136 BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr); 137 return static_cast<jint>(animator->duration()); 138} 139 140static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) { 141 BaseAnimator* animator = reinterpret_cast<BaseAnimator*>(animatorPtr); 142 Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); 143 animator->setInterpolator(interpolator); 144} 145 146#endif 147 148// ---------------------------------------------------------------------------- 149// JNI Glue 150// ---------------------------------------------------------------------------- 151 152const char* const kClassPathName = "android/view/RenderNodeAnimator"; 153 154static JNINativeMethod gMethods[] = { 155#ifdef USE_OPENGL_RENDERER 156 { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator }, 157 { "nCreateCanvasPropertyFloatAnimator", "(Ljava/lang/ref/WeakReference;JIF)J", (void*) createCanvasPropertyFloatAnimator }, 158 { "nCreateCanvasPropertyPaintAnimator", "(Ljava/lang/ref/WeakReference;JIIF)J", (void*) createCanvasPropertyPaintAnimator }, 159 { "nSetDuration", "(JI)V", (void*) setDuration }, 160 { "nGetDuration", "(J)I", (void*) getDuration }, 161 { "nSetInterpolator", "(JJ)V", (void*) setInterpolator }, 162#endif 163}; 164 165#define FIND_CLASS(var, className) \ 166 var = env->FindClass(className); \ 167 LOG_FATAL_IF(! var, "Unable to find class " className); 168 169#define GET_STATIC_METHOD_ID(var, clazz, methodName, methodDescriptor) \ 170 var = env->GetStaticMethodID(clazz, methodName, methodDescriptor); \ 171 LOG_FATAL_IF(! var, "Unable to find method " methodName); 172 173int register_android_view_RenderNodeAnimator(JNIEnv* env) { 174 FIND_CLASS(gRenderNodeAnimatorClassInfo.clazz, kClassPathName); 175 gRenderNodeAnimatorClassInfo.clazz = jclass(env->NewGlobalRef(gRenderNodeAnimatorClassInfo.clazz)); 176 177 GET_STATIC_METHOD_ID(gRenderNodeAnimatorClassInfo.callOnFinished, gRenderNodeAnimatorClassInfo.clazz, 178 "callOnFinished", "(Ljava/lang/ref/WeakReference;)V"); 179 180 return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)); 181} 182 183 184} // namespace android 185