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