static jlong createCanvasPropertyFloatAnimator(JNIEnv* env, jobject clazz,
        jlong canvasPropertyPtr, jfloat finalValue) {
    CanvasPropertyPrimitive* canvasProperty = reinterpret_cast<CanvasPropertyPrimitive*>(canvasPropertyPtr);
    BaseRenderNodeAnimator* animator = new CanvasPropertyPrimitiveAnimator(canvasProperty, finalValue);
    animator->setListener(&sLifecycleChecker);
    return reinterpret_cast<jlong>( animator );
}
static jlong createAnimator(JNIEnv* env, jobject clazz,
        jint propertyRaw, jfloat finalValue) {
    RenderPropertyAnimator::RenderProperty property = toRenderProperty(propertyRaw);
    BaseRenderNodeAnimator* animator = new RenderPropertyAnimator(property, finalValue);
    animator->setListener(&sLifecycleChecker);
    return reinterpret_cast<jlong>( animator );
}
static void start(JNIEnv* env, jobject clazz, jlong animatorPtr, jobject finishListener) {
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    if (finishListener) {
        animator->setListener(new AnimationListenerBridge(env, finishListener));
    }
    animator->start();
}
static jlong createCanvasPropertyPaintAnimator(JNIEnv* env, jobject clazz,
        jlong canvasPropertyPtr, jint paintFieldRaw,
        jfloat finalValue) {
    CanvasPropertyPaint* canvasProperty = reinterpret_cast<CanvasPropertyPaint*>(canvasPropertyPtr);
    CanvasPropertyPaintAnimator::PaintField paintField = toPaintField(paintFieldRaw);
    BaseRenderNodeAnimator* animator = new CanvasPropertyPaintAnimator(
            canvasProperty, paintField, finalValue);
    animator->setListener(&sLifecycleChecker);
    return reinterpret_cast<jlong>( animator );
}
static void end(JNIEnv* env, jobject clazz, jlong animatorPtr) {
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    animator->end();
}
static void setAllowRunningAsync(JNIEnv* env, jobject clazz, jlong animatorPtr, jboolean mayRunAsync) {
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    animator->setAllowRunningAsync(mayRunAsync);
}
static void setInterpolator(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong interpolatorPtr) {
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    Interpolator* interpolator = reinterpret_cast<Interpolator*>(interpolatorPtr);
    animator->setInterpolator(interpolator);
}
static void setStartDelay(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong startDelay) {
    LOG_ALWAYS_FATAL_IF(startDelay < 0, "Start delay cannot be negative");
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    animator->setStartDelay(startDelay);
}
static jlong getDuration(JNIEnv* env, jobject clazz, jlong animatorPtr) {
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    return static_cast<jlong>(animator->duration());
}
static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jlong duration) {
    LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    animator->setDuration(duration);
}
static void setStartValue(JNIEnv* env, jobject clazz, jlong animatorPtr, jfloat startValue) {
    BaseRenderNodeAnimator* animator = reinterpret_cast<BaseRenderNodeAnimator*>(animatorPtr);
    animator->setStartValue(startValue);
}
static jlong createRevealAnimator(JNIEnv* env, jobject clazz,
        jint centerX, jint centerY, jfloat startRadius, jfloat endRadius) {
    BaseRenderNodeAnimator* animator = new RevealAnimator(centerX, centerY, startRadius, endRadius);
    animator->setListener(&sLifecycleChecker);
    return reinterpret_cast<jlong>( animator );
}