* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <ani_signature_builder.h>
#include "ani_utils.h"
#include "movingphotoview_ani.h"
namespace OHOS::Ace {
namespace {
static constexpr int32_t US_CONVERT = 1000;
}
std::unique_ptr<NG::MovingPhotoModelNG> NG::MovingPhotoModelNG::instance_ = nullptr;
std::mutex NG::MovingPhotoModelNG::mutex_;
ani_long MovingPhotoAni::CreateMovingPhotoNode([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object,
ani_int peerId, ani_int flags)
{
auto node = NG::MovingPhotoModelNG::CreateMovingPhotoNode(peerId, u"");
node->IncRefCount();
auto ptr = Ace::AceType::RawPtr(node);
return reinterpret_cast<ani_long>(ptr);
}
ani_long MovingPhotoAni::CreateMovingPhotoController([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object)
{
auto controller = Ace::AceType::MakeRefPtr<NG::MovingPhotoController>();
controller->IncRefCount();
return reinterpret_cast<ani_long>(Ace::AceType::RawPtr(controller));
}
NG::MovingPhotoController* MovingPhotoAni::GetMovingPhotoController(ani_env* env, ani_ref ref)
{
auto object = static_cast<ani_object>(ref);
if (AniUtils::GetIsUndefinedObject(env, object)) {
return nullptr;
}
ani_ref peerOptRef;
if (ANI_OK != env->Object_GetFieldByName_Ref(static_cast<ani_object>(object), "peer", &peerOptRef)) {
return nullptr;
}
ani_long ptr;
if (ANI_OK != env->Object_GetFieldByName_Long(static_cast<ani_object>(peerOptRef), "ptr", &ptr)) {
return nullptr;
}
return reinterpret_cast<NG::MovingPhotoController*>(ptr);
}
void MovingPhotoAni::DestroyPeerImpl(NG::MovingPhotoController* peer)
{
if (peer) {
peer->DecRefCount();
}
}
ani_long MovingPhotoAni::GetFinalizer([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object)
{
return reinterpret_cast<ani_long>(&DestroyPeerImpl);
}
void MovingPhotoAni::SetMuted([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetMuted(movingPhotoNode, false);
return;
}
std::optional<bool> mutedOpt;
if (!AniUtils::ParseOptionalBool(env, options, mutedOpt)) {
NG::MovingPhotoModelNG::SetMuted(movingPhotoNode, false);
return;
}
bool mutedValue = false;
if (mutedOpt) {
mutedValue = mutedOpt.value();
}
NG::MovingPhotoModelNG::SetMuted(movingPhotoNode, mutedValue);
}
void MovingPhotoAni::SetObjectFit([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetObjectFit(movingPhotoNode, ImageFit::COVER);
return;
}
ani_int fitNum {};
if (ANI_OK != env->Object_GetPropertyByName_Int(options, "value", &fitNum)) {
NG::MovingPhotoModelNG::SetObjectFit(movingPhotoNode, ImageFit::COVER);
return;
}
ImageFit imageFit = ImageFit::COVER;
imageFit = static_cast<ImageFit>(static_cast<int32_t>(fitNum));
NG::MovingPhotoModelNG::SetObjectFit(movingPhotoNode, imageFit);
}
void MovingPhotoAni::SetOnComplete([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetOnComplete(movingPhotoNode, nullptr);
return;
}
auto asyncEvent = std::make_shared<AniAsyncEvent>(env, options);
CHECK_NULL_VOID(asyncEvent);
auto onComplete = [asyncEvent]() {
asyncEvent->Call(0, nullptr);
};
NG::MovingPhotoModelNG::SetOnComplete(movingPhotoNode, std::move(onComplete));
}
void MovingPhotoAni::SetOnStart([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetOnStart(movingPhotoNode, nullptr);
return;
}
auto asyncEvent = std::make_shared<AniAsyncEvent>(env, options);
CHECK_NULL_VOID(asyncEvent);
auto onStart = [asyncEvent]() {
asyncEvent->Call(0, nullptr);
};
NG::MovingPhotoModelNG::SetOnStart(movingPhotoNode, std::move(onStart));
}
void MovingPhotoAni::SetOnStop([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetOnStop(movingPhotoNode, nullptr);
return;
}
auto asyncEvent = std::make_shared<AniAsyncEvent>(env, options);
CHECK_NULL_VOID(asyncEvent);
auto onStop = [asyncEvent]() {
asyncEvent->Call(0, nullptr);
};
NG::MovingPhotoModelNG::SetOnStop(movingPhotoNode, std::move(onStop));
}
void MovingPhotoAni::SetOnPause([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetOnPause(movingPhotoNode, nullptr);
return;
}
auto asyncEvent = std::make_shared<AniAsyncEvent>(env, options);
CHECK_NULL_VOID(asyncEvent);
auto onPause = [asyncEvent]() {
asyncEvent->Call(0, nullptr);
};
NG::MovingPhotoModelNG::SetOnPause(movingPhotoNode, std::move(onPause));
}
void MovingPhotoAni::SetOnFinish([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetOnFinish(movingPhotoNode, nullptr);
return;
}
auto asyncEvent = std::make_shared<AniAsyncEvent>(env, options);
CHECK_NULL_VOID(asyncEvent);
auto onFinish = [asyncEvent]() {
asyncEvent->Call(0, nullptr);
};
NG::MovingPhotoModelNG::SetOnFinish(movingPhotoNode, std::move(onFinish));
}
void MovingPhotoAni::SetOnError([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetOnError(movingPhotoNode, nullptr);
return;
}
auto asyncEvent = std::make_shared<AniAsyncEvent>(env, options);
CHECK_NULL_VOID(asyncEvent);
auto onError = [asyncEvent]() {
asyncEvent->Call(0, nullptr);
};
NG::MovingPhotoModelNG::SetOnError(movingPhotoNode, std::move(onError));
}
void MovingPhotoAni::SetOnPrepared([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::SetOnPrepared(movingPhotoNode, nullptr);
return;
}
auto asyncEvent = std::make_shared<AniAsyncEvent>(env, options);
CHECK_NULL_VOID(asyncEvent);
auto onPrepared = [asyncEvent]() {
asyncEvent->Call(0, nullptr);
};
NG::MovingPhotoModelNG::SetOnPrepared(movingPhotoNode, std::move(onPrepared));
}
void MovingPhotoAni::SetAutoPlayPeriod([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object,
ani_long nodeptr, ani_double startTimeAni, ani_double endTimeAni)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
double startTime = static_cast<double>(startTimeAni);
double endTime = static_cast<double>(endTimeAni);
NG::MovingPhotoModelNG::AutoPlayPeriod(movingPhotoNode, static_cast<int64_t>(startTime * US_CONVERT),
static_cast<int64_t>(endTime * US_CONVERT));
}
void MovingPhotoAni::SetAutoPlay([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::AutoPlay(movingPhotoNode, false);
return;
}
ani_boolean isAutoPlayAni {};
bool isAutoPlay = false;
if (ANI_OK == env->Object_GetPropertyByName_Boolean(options, "value", &isAutoPlayAni)) {
isAutoPlay = static_cast<bool>(isAutoPlayAni);
}
NG::MovingPhotoModelNG::AutoPlay(movingPhotoNode, isAutoPlay);
}
void MovingPhotoAni::SetRepeatPlay([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::RepeatPlay(movingPhotoNode, false);
return;
}
ani_boolean isRepeatPlayAni {};
bool isRepeatPlay = false;
if (ANI_OK == env->Object_GetPropertyByName_Boolean(options, "value", &isRepeatPlayAni)) {
isRepeatPlay = static_cast<bool>(isRepeatPlayAni);
}
NG::MovingPhotoModelNG::RepeatPlay(movingPhotoNode, isRepeatPlay);
}
void MovingPhotoAni::SetEnableAnalyzer([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object,
ani_long nodeptr, ani_object options)
{
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
if (AniUtils::GetIsUndefinedObject(env, options)) {
NG::MovingPhotoModelNG::EnableAnalyzer(movingPhotoNode, false);
return;
}
ani_boolean enabledAni {};
bool enabled = false;
if (ANI_OK == env->Object_GetPropertyByName_Boolean(options, "value", &enabledAni)) {
enabled = static_cast<bool>(enabledAni);
}
NG::MovingPhotoModelNG::EnableAnalyzer(movingPhotoNode, enabled);
}
void MovingPhotoAni::StartPlayback([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
controller->StartPlayback();
}
void MovingPhotoAni::StopPlayback([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
controller->StopPlayback();
}
void MovingPhotoAni::PausePlayback([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
controller->Pause();
}
void MovingPhotoAni::Reset([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
controller->Reset();
}
void MovingPhotoAni::Restart([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
controller->Restart();
}
void MovingPhotoAni::RefreshMovingPhoto([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object,
ani_long nodeptr)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
controller->RefreshMovingPhoto();
}
void MovingPhotoAni::EnableTransition([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object,
ani_long nodeptr, ani_boolean options)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
controller->EnableTransition(static_cast<bool>(options));
}
void MovingPhotoAni::SetPlaybackPeriod([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object,
ani_long nodeptr, ani_double startTimeAni, ani_double endTimeAni)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
double startTime = static_cast<double>(startTimeAni);
double endTime = static_cast<double>(endTimeAni);
controller->SetPlaybackPeriod(static_cast<int64_t>(startTime * US_CONVERT),
static_cast<int64_t>(endTime * US_CONVERT));
}
void MovingPhotoAni::EnableAutoPlay([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object, ani_long nodeptr,
ani_boolean options)
{
NG::MovingPhotoController* controller = reinterpret_cast<NG::MovingPhotoController*>(nodeptr);
controller->EnableAutoPlay(static_cast<bool>(options));
}
void MovingPhotoAni::SetMovingPhotoViewOptions([[maybe_unused]] ani_env *env, [[maybe_unused]] ani_class object,
ani_long nodeptr, ani_object options)
{
if (AniUtils::GetIsUndefinedObject(env, options)) {
return;
}
auto movingPhotoNode = reinterpret_cast<NG::MovingPhotoNode *>(nodeptr);
CHECK_NULL_VOID(movingPhotoNode);
ani_ref movingPhotoRef;
if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "movingPhoto", &movingPhotoRef)) {
return;
}
ani_object movingPhotoObj = static_cast<ani_object>(movingPhotoRef);
if (AniUtils::GetIsUndefinedObject(env, movingPhotoObj)) {
return;
}
SetMovingPhotoUri(env, movingPhotoNode, movingPhotoObj);
ani_ref objRef;
if (ANI_OK == env->Object_GetPropertyByName_Ref(options, "controller", &objRef)) {
auto controller = Ace::Referenced::Claim(GetMovingPhotoController(env, objRef));
NG::MovingPhotoModelNG::SetMovingPhotoController(movingPhotoNode, controller);
}
ani_ref imageAIOptionsRef;
if (ANI_OK == env->Object_GetPropertyByName_Ref(options, "imageAIOptions", &imageAIOptionsRef)) {
NG::MovingPhotoModelNG::SetImageAIOptions(movingPhotoNode, reinterpret_cast<void*>(imageAIOptionsRef));
}
NG::MovingPhotoModelNG::SetMovingPhotoFormat(movingPhotoNode, ParsePixelMapFormat(env, options));
NG::MovingPhotoModelNG::SetDynamicRangeMode(movingPhotoNode, ParseDynamicRangeMode(env, options));
ani_ref playWithMaskRef;
bool playWithMaskValue = false;
if (ANI_OK == env->Object_GetPropertyByName_Ref(options, "playWithMask", &playWithMaskRef)) {
std::optional<bool> playWithMaskOpt;
if (AniUtils::ParseOptionalBool(env, static_cast<ani_object>(playWithMaskRef), playWithMaskOpt)) {
if (playWithMaskOpt) {
playWithMaskValue = playWithMaskOpt.value();
}
}
}
NG::MovingPhotoModelNG::SetWaterMask(movingPhotoNode, playWithMaskValue);
}
void MovingPhotoAni::SetMovingPhotoUri(ani_env *env, NG::MovingPhotoNode* movingPhotoNode, ani_object obj)
{
ani_ref fn_ref;
if (ANI_OK != env->Object_CallMethodByName_Ref(obj, "getUri", ":X{C{std.core.Null}C{std.core.String}}", &fn_ref)) {
return;
}
ani_class stringClass {};
ani_object ani_obj = static_cast<ani_object>(fn_ref);
env->FindClass("std.core.String", &stringClass);
ani_boolean isString = ANI_FALSE;
env->Object_InstanceOf(ani_obj, stringClass, &isString);
if (isString) {
std::string imageUriStr = AniUtils::AniStringToStdString(env, static_cast<ani_string>(fn_ref));
NG::MovingPhotoModelNG::SetImageSrc(movingPhotoNode, imageUriStr);
}
}
MovingPhotoFormat MovingPhotoAni::ParsePixelMapFormat(ani_env *env, ani_object options)
{
ani_ref format_ref;
auto format = MovingPhotoFormat::UNKNOWN;
if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "movingPhotoFormat", &format_ref)) {
return format;
}
if (AniUtils::GetIsUndefinedObject(env, format_ref)) {
return format;
}
if (AniUtils::GetIsEnum(env, format_ref, OHOS::Ace::ANI_MOVINGPHOTO_PIXELMAPFORMAT)) {
ani_int formatAni;
if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(format_ref), &formatAni)) {
return format;
}
int32_t formatNum;
if (ANI_OK != AniUtils::GetInt32(env, formatAni, formatNum)) {
return format;
}
return static_cast<MovingPhotoFormat>(formatNum);
}
return format;
}
DynamicRangeMode MovingPhotoAni::ParseDynamicRangeMode(ani_env *env, ani_object options)
{
ani_ref dynamic_ref;
auto dynamicRangeMode = DynamicRangeMode::HIGH;
if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "dynamicRangeMode", &dynamic_ref)) {
return dynamicRangeMode;
}
if (AniUtils::GetIsUndefinedObject(env, dynamic_ref)) {
return dynamicRangeMode;
}
if (AniUtils::GetIsEnum(env, dynamic_ref, OHOS::Ace::ANI_MOVINGPHOTO_DYNAMICRANGEMODE)) {
ani_int dynamicAni;
if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(dynamic_ref), &dynamicAni)) {
return dynamicRangeMode;
}
int32_t dynamicRangeModeNum;
if (ANI_OK != AniUtils::GetInt32(env, dynamicAni, dynamicRangeModeNum)) {
return dynamicRangeMode;
}
return static_cast<DynamicRangeMode>(dynamicRangeModeNum);
}
return dynamicRangeMode;
}
}
ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
{
ani_env *env;
ani_status isVersionOk = vm->GetEnv(ANI_VERSION_1, &env);
if (ANI_OK != isVersionOk) {
return isVersionOk;
}
ani_class cls;
ani_status isOk = env->FindClass(OHOS::Ace::ANI_MOVINGPHOTO_NATIVE, &cls);
if (ANI_OK != isOk) {
return isOk;
}
std::array methods = {
ani_native_function{"createMovingPhoto", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::CreateMovingPhotoNode)},
ani_native_function{"setMovingPhotoViewOptions", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetMovingPhotoViewOptions)},
ani_native_function{"muted", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetMuted)},
ani_native_function{"objectFit", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetObjectFit)},
ani_native_function{"autoPlayPeriod", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetAutoPlayPeriod)},
ani_native_function{"autoPlay", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetAutoPlay)},
ani_native_function{"repeatPlay", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetRepeatPlay)},
ani_native_function{"enableAnalyzer", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetEnableAnalyzer)},
ani_native_function{"onComplete", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetOnComplete)},
ani_native_function{"onStart", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetOnStart)},
ani_native_function{"onStop", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetOnStop)},
ani_native_function{"onPause", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetOnPause)},
ani_native_function{"onFinish", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetOnFinish)},
ani_native_function{"onError", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetOnError)},
ani_native_function{"onPrepared", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetOnPrepared)},
ani_native_function{"createMovingPhotoController", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::CreateMovingPhotoController)},
ani_native_function{"getFinalizer", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::GetFinalizer)},
ani_native_function{"startPlayback", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::StartPlayback)},
ani_native_function{"stopPlayback", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::StopPlayback)},
ani_native_function{"refreshMovingPhoto", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::RefreshMovingPhoto)},
ani_native_function{"pausePlayback", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::PausePlayback)},
ani_native_function{"reset", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::Reset)},
ani_native_function{"restart", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::Restart)},
ani_native_function{"enableTransition", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::EnableTransition)},
ani_native_function{"setPlaybackPeriod", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::SetPlaybackPeriod)},
ani_native_function{"enableAutoPlay", nullptr,
reinterpret_cast<void *>(OHOS::Ace::MovingPhotoAni::EnableAutoPlay)},
};
if (ANI_OK != env->Class_BindStaticNativeMethods(cls, methods.data(), methods.size())) {
return ANI_INVALID_TYPE;
};
*result = ANI_VERSION_1;
return ANI_OK;
}