• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef INTERFACES_KITS_JS_SRC_COMMON_ANI_HELPER_ANI_HELPER_H
17 #define INTERFACES_KITS_JS_SRC_COMMON_ANI_HELPER_ANI_HELPER_H
18 
19 #include <optional>
20 #include <string>
21 #include <tuple>
22 
23 #include <ani.h>
24 
25 #include "ani_signature.h"
26 #include "event_handler.h"
27 #include "event_runner.h"
28 #include "file_utils.h"
29 #include "filemgmt_libhilog.h"
30 #include "type_converter.h"
31 
32 namespace OHOS::FileManagement::ModuleFileIO::ANI {
33 using namespace std;
34 using namespace OHOS::FileManagement::ModuleFileIO::ANI::AniSignature;
35 
36 class AniHelper {
37 public:
38     template <typename T>
SetFieldValue(ani_env * env,const ani_class & cls,ani_object & obj,const char * fieldName,const T & value)39     static ani_status SetFieldValue(
40         ani_env *env, const ani_class &cls, ani_object &obj, const char *fieldName, const T &value)
41     {
42         ani_field field;
43         auto status = env->Class_FindField(cls, fieldName, &field);
44         if (status != ANI_OK) {
45             return status;
46         }
47 
48         if constexpr (is_same_v<T, int> || is_same_v<T, int32_t> || is_same_v<T, ani_int>) {
49             status = env->Object_SetField_Int(obj, field, value);
50         } else if constexpr (is_same_v<T, int64_t> || is_same_v<T, ani_long>) {
51             status = env->Object_SetField_Long(obj, field, value);
52         } else if constexpr (is_same_v<T, double> || is_same_v<T, ani_double>) {
53             status = env->Object_SetField_Double(obj, field, value);
54         } else if constexpr (is_same_v<T, bool> || is_same_v<T, ani_boolean>) {
55             status = env->Object_SetField_Boolean(obj, field, value);
56         } else if constexpr (is_same_v<T, string> || is_same_v<T, const char *>) {
57             auto [succ, aniStr] = TypeConverter::ToAniString(env, value);
58             if (!succ) {
59                 return ANI_ERROR;
60             }
61             status = env->Object_SetField_Ref(obj, field, move(aniStr));
62         } else if constexpr (is_base_of_v<ani_ref, T>) {
63             status = env->Object_SetField_Ref(obj, field, value);
64         } else {
65             return ANI_INVALID_TYPE;
66         }
67         return status;
68     }
69 
70     template <typename T>
SetPropertyValue(ani_env * env,const ani_class & cls,ani_object & obj,const string & property,const T & value)71     static ani_status SetPropertyValue(
72         ani_env *env, const ani_class &cls, ani_object &obj, const string &property, const T &value)
73     {
74         ani_method method;
75         string setter = "<set>" + property;
76         auto status = env->Class_FindMethod(cls, setter.c_str(), nullptr, &method);
77         if (status != ANI_OK) {
78             return status;
79         }
80 
81         if constexpr (is_same_v<T, string> || is_same_v<T, const char *>) {
82             auto [succ, aniStr] = TypeConverter::ToAniString(env, value);
83             if (!succ) {
84                 return ANI_ERROR;
85             }
86             status = env->Object_CallMethod_Void(obj, method, move(aniStr));
87         } else if constexpr (is_base_of_v<ani_ref, T> || is_same_v<T, int> || is_same_v<T, int32_t> ||
88                              is_same_v<T, ani_int> || is_same_v<T, int64_t> || is_same_v<T, ani_long> ||
89                              is_same_v<T, double> || is_same_v<T, ani_double> || is_same_v<T, bool> ||
90                              is_same_v<T, ani_boolean>) {
91             status = env->Object_CallMethod_Void(obj, method, value);
92         } else {
93             return ANI_INVALID_TYPE;
94         }
95         return status;
96     }
97 
ParseInt64Option(ani_env * env,ani_object obj,const string & tag)98     static tuple<bool, optional<int64_t>> ParseInt64Option(ani_env *env, ani_object obj, const string &tag)
99     {
100         ani_boolean isUndefined = true;
101         ani_ref property;
102         ani_status status = ANI_ERROR;
103         status = env->Object_GetPropertyByName_Ref(obj, tag.c_str(), &property);
104         if (status != ANI_OK) {
105             return { false, nullopt };
106         }
107         env->Reference_IsUndefined(property, &isUndefined);
108         if (isUndefined) {
109             return { true, nullopt };
110         }
111         static const string longValueSig = Builder::BuildSignatureDescriptor({}, BasicTypes::longType);
112         ani_long value;
113         status = env->Object_CallMethodByName_Long(
114             static_cast<ani_object>(property), BasicTypesConverter::toLong.c_str(), longValueSig.c_str(), &value);
115         if (status != ANI_OK) {
116             return { false, nullopt };
117         }
118         auto result = make_optional<int64_t>(static_cast<int64_t>(value));
119         return { true, move(result) };
120     }
121 
ParseEncoding(ani_env * env,ani_object obj)122     static tuple<bool, optional<string>> ParseEncoding(ani_env *env, ani_object obj)
123     {
124         ani_boolean isUndefined;
125         ani_ref property;
126         if (ANI_OK != env->Object_GetPropertyByName_Ref(obj, "encoding", &property)) {
127             return { false, nullopt };
128         }
129         env->Reference_IsUndefined(property, &isUndefined);
130         if (isUndefined) {
131             return { true, nullopt };
132         }
133         auto [succ, encoding] = TypeConverter::ToUTF8String(env, (ani_string)property);
134         if (!succ) {
135             return { false, nullopt };
136         }
137         return { true, make_optional<string>(move(encoding)) };
138     }
139 
GetThreadEnvStorage()140     static ani_env *&GetThreadEnvStorage()
141     {
142         static thread_local ani_env *env { nullptr };
143         return env;
144     }
145 
GetThreadEnv(ani_vm * vm)146     static ani_env *GetThreadEnv(ani_vm *vm)
147     {
148         auto &env = GetThreadEnvStorage();
149         if (env != nullptr) {
150             return env;
151         }
152 
153         ani_options aniArgs { 0, nullptr };
154         auto status = vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env);
155         if (status != ANI_OK) {
156             status = vm->GetEnv(ANI_VERSION_1, &env);
157             if (status != ANI_OK) {
158                 HILOGE("vm GetEnv, err: %{public}d", status);
159                 return nullptr;
160             }
161         }
162         return env;
163     }
164 
DetachThreadEnv(ani_vm * vm)165     static void DetachThreadEnv(ani_vm *vm)
166     {
167         if (vm && GetThreadEnvStorage()) {
168             auto status = vm->DetachCurrentThread();
169             if (status != ANI_OK) {
170                 HILOGE("Detach thread env from vm failed! status: %{public}d", status);
171                 return;
172             }
173             GetThreadEnvStorage() = nullptr;
174         }
175     }
176 
SendEventToMainThread(const function<void ()> & func)177     static bool SendEventToMainThread(const function<void()> &func)
178     {
179         if (func == nullptr) {
180             HILOGE("func is nullptr!");
181             return false;
182         }
183 
184         auto &mainHandler = GetMainHandler();
185         if (!mainHandler) {
186             HILOGE("mainHandler is not initialized!");
187             return false;
188         }
189         bool succ = mainHandler->PostTask(func, "", 0, OHOS::AppExecFwk::EventQueue::Priority::HIGH, {});
190         if (!succ) {
191             HILOGE("Failed to post task to main thread.");
192             return false;
193         }
194         return true;
195     }
196 
197 private:
GetMainHandler()198     static std::shared_ptr<OHOS::AppExecFwk::EventHandler> &GetMainHandler()
199     {
200         static std::shared_ptr<OHOS::AppExecFwk::EventHandler> mainHandler =
201             []() -> std::shared_ptr<OHOS::AppExecFwk::EventHandler> {
202             auto runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner();
203             if (runner) {
204                 return CreateSharedPtr<OHOS::AppExecFwk::EventHandler>(runner);
205             } else {
206                 HILOGE("Get main event runner failed when initializing mainHandler!");
207                 return nullptr;
208             }
209         }();
210 
211         return mainHandler;
212     }
213 };
214 
215 } // namespace OHOS::FileManagement::ModuleFileIO::ANI
216 #endif // INTERFACES_KITS_JS_SRC_COMMON_ANI_HELPER_ANI_HELPER_H