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