1/* 2 * Copyright (C) 2016 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#define LOG_TAG "OpenGLRenderer" 17 18#include "jni.h" 19#include "GraphicsJNI.h" 20#include "core_jni_helpers.h" 21#include "log/log.h" 22 23#include "Animator.h" 24#include "Interpolator.h" 25#include "PropertyValuesAnimatorSet.h" 26#include "PropertyValuesHolder.h" 27#include "VectorDrawable.h" 28 29namespace android { 30using namespace uirenderer; 31using namespace VectorDrawable; 32 33static struct { 34 jclass clazz; 35 jmethodID callOnFinished; 36} gVectorDrawableAnimatorClassInfo; 37 38static JNIEnv* getEnv(JavaVM* vm) { 39 JNIEnv* env; 40 if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) { 41 return 0; 42 } 43 return env; 44} 45 46static AnimationListener* createAnimationListener(JNIEnv* env, jobject finishListener, jint id) { 47 class AnimationListenerBridge : public AnimationListener { 48 public: 49 AnimationListenerBridge(JNIEnv* env, jobject finishListener, jint id) { 50 mFinishListener = env->NewGlobalRef(finishListener); 51 env->GetJavaVM(&mJvm); 52 mId = id; 53 } 54 55 virtual ~AnimationListenerBridge() { 56 if (mFinishListener) { 57 onAnimationFinished(NULL); 58 } 59 } 60 61 virtual void onAnimationFinished(BaseRenderNodeAnimator*) { 62 LOG_ALWAYS_FATAL_IF(!mFinishListener, "Finished listener twice?"); 63 JNIEnv* env = getEnv(mJvm); 64 env->CallStaticVoidMethod( 65 gVectorDrawableAnimatorClassInfo.clazz, 66 gVectorDrawableAnimatorClassInfo.callOnFinished, 67 mFinishListener, mId); 68 releaseJavaObject(); 69 } 70 71 private: 72 void releaseJavaObject() { 73 JNIEnv* env = getEnv(mJvm); 74 env->DeleteGlobalRef(mFinishListener); 75 mFinishListener = NULL; 76 } 77 78 JavaVM* mJvm; 79 jobject mFinishListener; 80 jint mId; 81 }; 82 return new AnimationListenerBridge(env, finishListener, id); 83} 84 85static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr, 86 jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount) { 87 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 88 PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr); 89 Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); 90 set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount); 91} 92 93static jlong createAnimatorSet(JNIEnv*, jobject) { 94 PropertyValuesAnimatorSet* animatorSet = new PropertyValuesAnimatorSet(); 95 return reinterpret_cast<jlong>(animatorSet); 96} 97 98static jlong createGroupPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, 99 jfloat startValue, jfloat endValue) { 100 VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(nativePtr); 101 GroupPropertyValuesHolder* newHolder = new GroupPropertyValuesHolder(group, propertyId, 102 startValue, endValue); 103 return reinterpret_cast<jlong>(newHolder); 104} 105 106static jlong createPathDataPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jlong startValuePtr, 107 jlong endValuePtr) { 108 VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(nativePtr); 109 PathData* startData = reinterpret_cast<PathData*>(startValuePtr); 110 PathData* endData = reinterpret_cast<PathData*>(endValuePtr); 111 PathDataPropertyValuesHolder* newHolder = new PathDataPropertyValuesHolder(path, 112 startData, endData); 113 return reinterpret_cast<jlong>(newHolder); 114} 115 116static jlong createPathColorPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, 117 int startValue, jint endValue) { 118 VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr); 119 FullPathColorPropertyValuesHolder* newHolder = new FullPathColorPropertyValuesHolder(fullPath, 120 propertyId, startValue, endValue); 121 return reinterpret_cast<jlong>(newHolder); 122} 123 124static jlong createPathPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, 125 float startValue, jfloat endValue) { 126 VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr); 127 FullPathPropertyValuesHolder* newHolder = new FullPathPropertyValuesHolder(fullPath, 128 propertyId, startValue, endValue); 129 return reinterpret_cast<jlong>(newHolder); 130} 131 132static jlong createRootAlphaPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jfloat startValue, 133 float endValue) { 134 VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(nativePtr); 135 RootAlphaPropertyValuesHolder* newHolder = new RootAlphaPropertyValuesHolder(tree, 136 startValue, endValue); 137 return reinterpret_cast<jlong>(newHolder); 138} 139static void setPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, 140 jfloatArray srcData, jint length) { 141 142 jfloat* propertyData = env->GetFloatArrayElements(srcData, nullptr); 143 PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr); 144 holder->setPropertyDataSource(propertyData, length); 145 env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT); 146} 147static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { 148 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 149 AnimationListener* listener = createAnimationListener(env, finishListener, id); 150 set->start(listener); 151} 152 153static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { 154 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 155 AnimationListener* listener = createAnimationListener(env, finishListener, id); 156 set->reverse(listener); 157} 158 159static void end(JNIEnv*, jobject, jlong animatorSetPtr) { 160 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 161 set->end(); 162} 163 164static void reset(JNIEnv*, jobject, jlong animatorSetPtr) { 165 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 166 set->reset(); 167} 168 169static const JNINativeMethod gMethods[] = { 170 {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet}, 171 {"nAddAnimator", "(JJJJJI)V", (void*)addAnimator}, 172 {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder}, 173 {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder}, 174 {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder}, 175 {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder}, 176 {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder}, 177 {"nSetPropertyHolderData", "(J[FI)V", (void*)setPropertyHolderData}, 178 {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)start}, 179 {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)reverse}, 180 {"nEnd", "!(J)V", (void*)end}, 181 {"nReset", "!(J)V", (void*)reset}, 182}; 183 184const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT"; 185int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) { 186 gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName); 187 gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env, 188 gVectorDrawableAnimatorClassInfo.clazz); 189 190 gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie( 191 env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished", 192 "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V"); 193 return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable", 194 gMethods, NELEM(gMethods)); 195} 196 197}; // namespace android 198