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 29 namespace android { 30 using namespace uirenderer; 31 using namespace VectorDrawable; 32 33 static struct { 34 jclass clazz; 35 jmethodID callOnFinished; 36 } gVectorDrawableAnimatorClassInfo; 37 38 static 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 46 static 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 85 static void addAnimator(JNIEnv*, jobject, jlong animatorSetPtr, jlong propertyHolderPtr, 86 jlong interpolatorPtr, jlong startDelay, jlong duration, jint repeatCount, 87 jint repeatMode) { 88 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 89 PropertyValuesHolder* holder = reinterpret_cast<PropertyValuesHolder*>(propertyHolderPtr); 90 Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr); 91 RepeatMode mode = static_cast<RepeatMode>(repeatMode); 92 set->addPropertyAnimator(holder, interpolator, startDelay, duration, repeatCount, mode); 93 } 94 95 static jlong createAnimatorSet(JNIEnv*, jobject) { 96 PropertyValuesAnimatorSet* animatorSet = new PropertyValuesAnimatorSet(); 97 return reinterpret_cast<jlong>(animatorSet); 98 } 99 100 static void setVectorDrawableTarget(JNIEnv*, jobject,jlong animatorPtr, jlong vectorDrawablePtr) { 101 VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(vectorDrawablePtr); 102 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorPtr); 103 set->setVectorDrawable(tree); 104 } 105 106 static jlong createGroupPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, 107 jfloat startValue, jfloat endValue) { 108 VectorDrawable::Group* group = reinterpret_cast<VectorDrawable::Group*>(nativePtr); 109 GroupPropertyValuesHolder* newHolder = new GroupPropertyValuesHolder(group, propertyId, 110 startValue, endValue); 111 return reinterpret_cast<jlong>(newHolder); 112 } 113 114 static jlong createPathDataPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jlong startValuePtr, 115 jlong endValuePtr) { 116 VectorDrawable::Path* path = reinterpret_cast<VectorDrawable::Path*>(nativePtr); 117 PathData* startData = reinterpret_cast<PathData*>(startValuePtr); 118 PathData* endData = reinterpret_cast<PathData*>(endValuePtr); 119 PathDataPropertyValuesHolder* newHolder = new PathDataPropertyValuesHolder(path, 120 startData, endData); 121 return reinterpret_cast<jlong>(newHolder); 122 } 123 124 static jlong createPathColorPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, 125 int startValue, jint endValue) { 126 VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr); 127 FullPathColorPropertyValuesHolder* newHolder = new FullPathColorPropertyValuesHolder(fullPath, 128 propertyId, startValue, endValue); 129 return reinterpret_cast<jlong>(newHolder); 130 } 131 132 static jlong createPathPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jint propertyId, 133 float startValue, jfloat endValue) { 134 VectorDrawable::FullPath* fullPath = reinterpret_cast<VectorDrawable::FullPath*>(nativePtr); 135 FullPathPropertyValuesHolder* newHolder = new FullPathPropertyValuesHolder(fullPath, 136 propertyId, startValue, endValue); 137 return reinterpret_cast<jlong>(newHolder); 138 } 139 140 static jlong createRootAlphaPropertyHolder(JNIEnv*, jobject, jlong nativePtr, jfloat startValue, 141 float endValue) { 142 VectorDrawable::Tree* tree = reinterpret_cast<VectorDrawable::Tree*>(nativePtr); 143 RootAlphaPropertyValuesHolder* newHolder = new RootAlphaPropertyValuesHolder(tree, 144 startValue, endValue); 145 return reinterpret_cast<jlong>(newHolder); 146 } 147 static void setFloatPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, 148 jfloatArray srcData, jint length) { 149 jfloat* propertyData = env->GetFloatArrayElements(srcData, nullptr); 150 PropertyValuesHolderImpl<float>* holder = 151 reinterpret_cast<PropertyValuesHolderImpl<float>*>(propertyHolderPtr); 152 holder->setPropertyDataSource(propertyData, length); 153 env->ReleaseFloatArrayElements(srcData, propertyData, JNI_ABORT); 154 } 155 156 static void setIntPropertyHolderData(JNIEnv* env, jobject, jlong propertyHolderPtr, 157 jintArray srcData, jint length) { 158 jint* propertyData = env->GetIntArrayElements(srcData, nullptr); 159 PropertyValuesHolderImpl<int>* holder = 160 reinterpret_cast<PropertyValuesHolderImpl<int>*>(propertyHolderPtr); 161 holder->setPropertyDataSource(propertyData, length); 162 env->ReleaseIntArrayElements(srcData, propertyData, JNI_ABORT); 163 } 164 165 static void start(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { 166 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 167 AnimationListener* listener = createAnimationListener(env, finishListener, id); 168 set->start(listener); 169 } 170 171 static void reverse(JNIEnv* env, jobject, jlong animatorSetPtr, jobject finishListener, jint id) { 172 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 173 AnimationListener* listener = createAnimationListener(env, finishListener, id); 174 set->reverse(listener); 175 } 176 177 static void end(JNIEnv*, jobject, jlong animatorSetPtr) { 178 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 179 set->end(); 180 } 181 182 static void reset(JNIEnv*, jobject, jlong animatorSetPtr) { 183 PropertyValuesAnimatorSet* set = reinterpret_cast<PropertyValuesAnimatorSet*>(animatorSetPtr); 184 set->reset(); 185 } 186 187 static const JNINativeMethod gMethods[] = { 188 {"nCreateAnimatorSet", "()J", (void*)createAnimatorSet}, 189 {"nSetVectorDrawableTarget", "(JJ)V", (void*)setVectorDrawableTarget}, 190 {"nAddAnimator", "(JJJJJII)V", (void*)addAnimator}, 191 {"nCreateGroupPropertyHolder", "!(JIFF)J", (void*)createGroupPropertyHolder}, 192 {"nCreatePathDataPropertyHolder", "!(JJJ)J", (void*)createPathDataPropertyHolder}, 193 {"nCreatePathColorPropertyHolder", "!(JIII)J", (void*)createPathColorPropertyHolder}, 194 {"nCreatePathPropertyHolder", "!(JIFF)J", (void*)createPathPropertyHolder}, 195 {"nCreateRootAlphaPropertyHolder", "!(JFF)J", (void*)createRootAlphaPropertyHolder}, 196 {"nSetPropertyHolderData", "(J[FI)V", (void*)setFloatPropertyHolderData}, 197 {"nSetPropertyHolderData", "(J[II)V", (void*)setIntPropertyHolderData}, 198 {"nStart", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)start}, 199 {"nReverse", "(JLandroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V", (void*)reverse}, 200 {"nEnd", "!(J)V", (void*)end}, 201 {"nReset", "!(J)V", (void*)reset}, 202 }; 203 204 const char* const kClassPathName = "android/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT"; 205 int register_android_graphics_drawable_AnimatedVectorDrawable(JNIEnv* env) { 206 gVectorDrawableAnimatorClassInfo.clazz = FindClassOrDie(env, kClassPathName); 207 gVectorDrawableAnimatorClassInfo.clazz = MakeGlobalRefOrDie(env, 208 gVectorDrawableAnimatorClassInfo.clazz); 209 210 gVectorDrawableAnimatorClassInfo.callOnFinished = GetStaticMethodIDOrDie( 211 env, gVectorDrawableAnimatorClassInfo.clazz, "callOnFinished", 212 "(Landroid/graphics/drawable/AnimatedVectorDrawable$VectorDrawableAnimatorRT;I)V"); 213 return RegisterMethodsOrDie(env, "android/graphics/drawable/AnimatedVectorDrawable", 214 gMethods, NELEM(gMethods)); 215 } 216 217 }; // namespace android 218