• 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 #include "ani_emitter.h"
17 
18 #include "event_logger.h"
19 #include "aync_callback_manager.h"
20 #include "interops.h"
21 #include "napi_agent.h"
22 
23 namespace OHOS {
24 namespace AppExecFwk {
25 
26 namespace {
27 DEFINE_EH_HILOG_LABEL("EventsEmitter");
28 }
GetStdString(ani_env * env,ani_string str)29 std::string EventsEmitter::GetStdString(ani_env *env, ani_string str)
30 {
31     std::string result;
32     ani_size sz {};
33     env->String_GetUTF8Size(str, &sz);
34     result.resize(sz + 1);
35     env->String_GetUTF8SubString(str, 0, sz, result.data(), result.size(), &sz);
36     result.resize(sz);
37     return result;
38 }
39 
OnOrOnce(ani_env * env,InnerEvent::EventId eventId,bool once,ani_ref callback,ani_string dataType)40 void EventsEmitter::OnOrOnce(
41     ani_env *env, InnerEvent::EventId eventId, bool once, ani_ref callback, ani_string dataType)
42 {
43     AsyncCallbackManager::GetInstance().InsertCallbackInfo(env, eventId, once, callback, dataType);
44 }
45 
OffEmitterInstances(InnerEvent::EventId eventIdValue)46 void EventsEmitter::OffEmitterInstances(InnerEvent::EventId eventIdValue)
47 {
48     AsyncCallbackManager::GetInstance().DeleteCallbackInfoByEventId(eventIdValue);
49 }
50 
GetSharedSerializeData(ani_env * env)51 std::shared_ptr<SerializeData> EventsEmitter::GetSharedSerializeData(ani_env *env)
52 {
53     auto serializeDataPtr = new (std::nothrow) SerializeData();
54     if (serializeDataPtr == nullptr) {
55         HILOGE("memory allocation failed");
56         return nullptr;
57     }
58     ani_vm* vm = nullptr;
59     auto status = env->GetVM(&vm);
60     if (vm == nullptr) {
61         HILOGE("Get vm failed. status: %{public}d", status);
62         return nullptr;
63     }
64     std::shared_ptr<SerializeData> serializeData(serializeDataPtr, [vm](SerializeData* data) {
65         if (data == nullptr) {
66             return;
67         }
68         if (std::holds_alternative<ani_ref>(data->peerData)) {
69             ani_env *env;
70             ani_status status = ANI_OK;
71             status = vm->GetEnv(ANI_VERSION_1, &env);
72             if (status == ANI_OK) {
73                 status = env->GlobalReference_Delete(std::get<ani_ref>(data->peerData));
74                 delete data;
75                 data = nullptr;
76                 return;
77             }
78             ani_option interopEnabled {"--interop=disable", nullptr};
79             ani_options aniArgs {1, &interopEnabled};
80             status = vm->AttachCurrentThread(&aniArgs, ANI_VERSION_1, &env);
81             if (status != ANI_OK) {
82                 HILOGE("attach thread failed");
83                 delete data;
84                 data = nullptr;
85                 return;
86             }
87             status = env->GlobalReference_Delete(std::get<ani_ref>(data->peerData));
88             vm->DetachCurrentThread();
89         }
90         delete data;
91         data = nullptr;
92     });
93     serializeData->envType = EnvType::ANI;
94     return serializeData;
95 }
96 
EmitWithEventId(ani_env * env,ani_object InnerEvent,ani_object eventData)97 void EventsEmitter::EmitWithEventId(ani_env *env, ani_object InnerEvent, ani_object eventData)
98 {
99     ani_double eventId = 0;
100     ani_status status = ANI_ERROR;
101     if ((status = env->Object_GetPropertyByName_Double(InnerEvent, "eventId", &eventId)) != ANI_OK) {
102         HILOGE("eventId not find");
103         return;
104     }
105     InnerEvent::EventId id = static_cast<uint32_t>(eventId);
106     if (!AsyncCallbackManager::GetInstance().IsExistValidCallback(id)) {
107         HILOGI("Emit has no callback");
108         return;
109     }
110     ani_ref obj;
111     ani_boolean isUndefined = true;
112     status = ANI_ERROR;
113     Priority priority = Priority::LOW;
114     if ((status = env->Object_GetPropertyByName_Ref(InnerEvent, "priority", &obj)) == ANI_OK) {
115         if ((status = env->Reference_IsUndefined(obj, &isUndefined)) == ANI_OK) {
116             if (!isUndefined) {
117                 ani_int res;
118                 env->EnumItem_GetValue_Int(reinterpret_cast<ani_enum_item>(obj), &res);
119                 priority = static_cast<Priority>(res);
120             }
121         }
122     }
123     auto serializeData = EventsEmitter::GetSharedSerializeData(env);
124     if (serializeData == nullptr) {
125         return;
126     }
127     if (!AniSerialize::PeerSerialize(env, eventData, serializeData)) {
128         return;
129     }
130     if (AsyncCallbackManager::GetInstance().IsCrossRuntime(id, EnvType::ANI)) {
131         serializeData->isCrossRuntime = true;
132         if (!AniSerialize::CrossSerialize(env, eventData, serializeData)) {
133             return;
134         }
135     }
136     auto event = InnerEvent::Get(id, serializeData);
137     event->SetIsEnhanced(true);
138     EventHandlerInstance::GetInstance()->SendEvent(event, 0, priority);
139 }
140 
EmitWithEventIdString(ani_env * env,ani_string eventId,ani_object eventData,ani_enum_item enumItem)141 void EventsEmitter::EmitWithEventIdString(
142     ani_env *env, ani_string eventId, ani_object eventData, ani_enum_item enumItem)
143 {
144     InnerEvent::EventId id = GetStdString(env, eventId);
145     if (!AsyncCallbackManager::GetInstance().IsExistValidCallback(id)) {
146         HILOGI("Emit has no callback");
147         return;
148     }
149     Priority priority = Priority::LOW;
150     if (enumItem != nullptr) {
151         ani_int res;
152         env->EnumItem_GetValue_Int(enumItem, &res);
153         priority = static_cast<Priority>(res);
154     }
155     auto serializeData = EventsEmitter::GetSharedSerializeData(env);
156     if (serializeData == nullptr) {
157         return;
158     }
159     if (!AniSerialize::PeerSerialize(env, eventData, serializeData)) {
160         return;
161     }
162     if (AsyncCallbackManager::GetInstance().IsCrossRuntime(id, EnvType::ANI)) {
163         serializeData->isCrossRuntime = true;
164         if (!AniSerialize::CrossSerialize(env, eventData, serializeData)) {
165             return;
166         }
167     }
168     auto event = InnerEvent::Get(id, serializeData);
169     event->SetIsEnhanced(true);
170     EventHandlerInstance::GetInstance()->SendEvent(event, 0, priority);
171 }
172 
GetListenerCount(InnerEvent::EventId eventId)173 ani_double EventsEmitter::GetListenerCount(InnerEvent::EventId eventId)
174 {
175     return AsyncCallbackManager::GetInstance().GetListenerCountByEventId(eventId);
176 }
177 
OnOrOnceSync(ani_env * env,ani_double eventId,ani_boolean once,ani_ref callback,ani_string dataType)178 static void OnOrOnceSync(ani_env *env, ani_double eventId, ani_boolean once, ani_ref callback, ani_string dataType)
179 {
180     InnerEvent::EventId id = static_cast<uint32_t>(eventId);
181     EventsEmitter::OnOrOnce(env, id, once, callback, dataType);
182 }
183 
OnOrOnceStringSync(ani_env * env,ani_string eventId,ani_boolean once,ani_ref callback,ani_string dataType)184 static void OnOrOnceStringSync(
185     ani_env *env, ani_string eventId, ani_boolean once, ani_ref callback, ani_string dataType)
186 {
187     InnerEvent::EventId id = EventsEmitter::GetStdString(env, eventId);
188     EventsEmitter::OnOrOnce(env, id, once, callback, dataType);
189 }
190 
OnOrOnceGenericEventSync(ani_env * env,ani_string eventId,ani_boolean once,ani_ref callback,ani_string dataType)191 static void OnOrOnceGenericEventSync(
192     ani_env *env, ani_string eventId, ani_boolean once, ani_ref callback, ani_string dataType)
193 {
194     InnerEvent::EventId id = EventsEmitter::GetStdString(env, eventId);
195     EventsEmitter::OnOrOnce(env, id, once, callback, dataType);
196 }
197 
OffStringIdSync(ani_env * env,ani_string eventId)198 static void OffStringIdSync(ani_env *env, ani_string eventId)
199 {
200     InnerEvent::EventId id = EventsEmitter::GetStdString(env, eventId);
201     EventsEmitter::OffEmitterInstances(id);
202 }
203 
OffStringSync(ani_env * env,ani_string eventId,ani_ref callback)204 static void OffStringSync(ani_env *env, ani_string eventId, ani_ref callback)
205 {
206     InnerEvent::EventId id = EventsEmitter::GetStdString(env, eventId);
207     AsyncCallbackManager::GetInstance().DeleteCallbackInfo(env, id, callback);
208 }
209 
OffGenericEventSync(ani_env * env,ani_string eventId,ani_ref callback)210 static void OffGenericEventSync(ani_env *env, ani_string eventId, ani_ref callback)
211 {
212     InnerEvent::EventId id = EventsEmitter::GetStdString(env, eventId);
213     AsyncCallbackManager::GetInstance().DeleteCallbackInfo(env, id, callback);
214 }
215 
OffNumberSync(ani_env * env,ani_double eventId)216 static void OffNumberSync(ani_env *env, ani_double eventId)
217 {
218     InnerEvent::EventId id = static_cast<uint32_t>(eventId);
219     EventsEmitter::OffEmitterInstances(id);
220 }
221 
OffNumberCallbackSync(ani_env * env,ani_double eventId,ani_ref callback)222 static void OffNumberCallbackSync(ani_env *env, ani_double eventId, ani_ref callback)
223 {
224     InnerEvent::EventId id = static_cast<uint32_t>(eventId);
225     AsyncCallbackManager::GetInstance().DeleteCallbackInfo(env, id, callback);
226 }
227 
getListenerCountNumber(ani_env * env,ani_double eventId)228 static ani_double getListenerCountNumber(ani_env *env, ani_double eventId)
229 {
230     InnerEvent::EventId id = static_cast<uint32_t>(eventId);
231     return EventsEmitter::GetListenerCount(id);
232 }
233 
getListenerCountString(ani_env * env,ani_string eventId)234 static ani_double getListenerCountString(ani_env *env, ani_string eventId)
235 {
236     InnerEvent::EventId id = EventsEmitter::GetStdString(env, eventId);
237     return EventsEmitter::GetListenerCount(id);
238 }
239 
EmitStringSync(ani_env * env,ani_string eventId)240 static void EmitStringSync(ani_env *env, ani_string eventId)
241 {
242     EventsEmitter::EmitWithEventIdString(env, eventId, nullptr, nullptr);
243 }
244 
EmitStringDataSync(ani_env * env,ani_string eventId,ani_string EventData)245 static void EmitStringDataSync(ani_env *env, ani_string eventId, ani_string EventData)
246 {
247     EventsEmitter::EmitWithEventIdString(env, eventId, EventData, nullptr);
248 }
249 
EmitStringGenericSync(ani_env * env,ani_string eventId,ani_object GenericEventData)250 static void EmitStringGenericSync(ani_env *env, ani_string eventId, ani_object GenericEventData)
251 {
252     EventsEmitter::EmitWithEventIdString(env, eventId, GenericEventData, nullptr);
253 }
254 
EmitInnerEventSync(ani_env * env,ani_object InnerEvent)255 static void EmitInnerEventSync(ani_env *env, ani_object InnerEvent)
256 {
257     EventsEmitter::EmitWithEventId(env, InnerEvent, nullptr);
258 }
259 
EmitInnerEventDataSync(ani_env * env,ani_object InnerEvent,ani_object EventData)260 static void EmitInnerEventDataSync(ani_env *env, ani_object InnerEvent, ani_object EventData)
261 {
262     EventsEmitter::EmitWithEventId(env, InnerEvent, EventData);
263 }
264 
GetPriority(ani_env * env,ani_object options,ani_enum_item & priority)265 static ani_status GetPriority(ani_env *env, ani_object options, ani_enum_item &priority)
266 {
267     ani_ref obj;
268     ani_boolean isUndefined = true;
269     ani_status status = env->Object_GetPropertyByName_Ref(options, "priority", &obj);
270     if (status == ANI_OK) {
271         status = env->Reference_IsUndefined(obj, &isUndefined);
272         if (status == ANI_OK) {
273             if (!isUndefined) {
274                 priority = reinterpret_cast<ani_enum_item>(obj);
275             }
276         }
277     }
278     return status;
279 }
280 
EmitStringOptionsSync(ani_env * env,ani_string eventId,ani_object options)281 static void EmitStringOptionsSync(ani_env *env, ani_string eventId, ani_object options)
282 {
283     ani_enum_item priority = nullptr;
284     GetPriority(env, options, priority);
285     EventsEmitter::EmitWithEventIdString(env, eventId, nullptr, priority);
286 }
287 
EmitStringOptionsGenericSync(ani_env * env,ani_string eventId,ani_object options,ani_object GenericEventData)288 static void EmitStringOptionsGenericSync(ani_env *env,
289     ani_string eventId, ani_object options, ani_object GenericEventData)
290 {
291     ani_enum_item priority = nullptr;
292     GetPriority(env, options, priority);
293     EventsEmitter::EmitWithEventIdString(env, eventId, GenericEventData, priority);
294 }
295 
EmitStringOptionsDataSync(ani_env * env,ani_string eventId,ani_object options,ani_object EventData)296 static void EmitStringOptionsDataSync(ani_env *env,
297     ani_string eventId, ani_object options, ani_object EventData)
298 {
299     ani_enum_item priority = nullptr;
300     GetPriority(env, options, priority);
301     EventsEmitter::EmitWithEventIdString(env, eventId, EventData, priority);
302 }
303 
init(ani_env * env,ani_namespace kitNs)304 ani_status init(ani_env *env, ani_namespace kitNs)
305 {
306     std::array methods = {
307         ani_native_function{"OnOrOnceSync", nullptr, reinterpret_cast<void *>(OnOrOnceSync)},
308         ani_native_function{"OnOrOnceStringSync", nullptr, reinterpret_cast<void *>(OnOrOnceStringSync)},
309         ani_native_function{"OnOrOnceGenericEventSync", nullptr, reinterpret_cast<void *>(OnOrOnceGenericEventSync)},
310         ani_native_function{"OffStringIdSync", nullptr, reinterpret_cast<void *>(OffStringIdSync)},
311         ani_native_function{"OffStringSync", nullptr, reinterpret_cast<void *>(OffStringSync)},
312         ani_native_function{"OffGenericEventSync", nullptr, reinterpret_cast<void *>(OffGenericEventSync)},
313         ani_native_function{"OffNumberSync", "D:V", reinterpret_cast<void *>(OffNumberSync)},
314         ani_native_function{"OffNumberCallbackSync", nullptr, reinterpret_cast<void *>(OffNumberCallbackSync)},
315         ani_native_function{"getListenerCountSync", "D:D", reinterpret_cast<void *>(getListenerCountNumber)},
316         ani_native_function{"getListenerCountStringSync",
317                             "Lstd/core/String;:D", reinterpret_cast<void *>(getListenerCountString)},
318         ani_native_function{"EmitInnerEventSync", "L@ohos/events/emitter/emitter/InnerEvent;:V",
319                             reinterpret_cast<void *>(EmitInnerEventSync)},
320         ani_native_function{"EmitInnerEventDataSync",
321             "L@ohos/events/emitter/emitter/InnerEvent;L@ohos/events/emitter/emitter/EventData;:V",
322             reinterpret_cast<void *>(EmitInnerEventDataSync)},
323         ani_native_function{"EmitStringSync", "Lstd/core/String;:V", reinterpret_cast<void *>(EmitStringSync)},
324         ani_native_function{"EmitStringDataSync",
325             "Lstd/core/String;L@ohos/events/emitter/emitter/EventData;:V",
326             reinterpret_cast<void *>(EmitStringDataSync)},
327         ani_native_function{"EmitStringGenericSync",
328             "Lstd/core/String;L@ohos/events/emitter/emitter/GenericEventData;:V",
329             reinterpret_cast<void *>(EmitStringGenericSync)},
330         ani_native_function{"EmitStringOptionsSync",
331             "Lstd/core/String;L@ohos/events/emitter/emitter/Options;:V",
332             reinterpret_cast<void *>(EmitStringOptionsSync)},
333         ani_native_function{"EmitStringOptionsGenericSync",
334             "Lstd/core/String;L@ohos/events/emitter/emitter/Options;L@ohos/events/emitter/emitter/GenericEventData;:V",
335             reinterpret_cast<void *>(EmitStringOptionsGenericSync)},
336         ani_native_function{"EmitStringOptionsDataSync",
337             "Lstd/core/String;L@ohos/events/emitter/emitter/Options;L@ohos/events/emitter/emitter/EventData;:V",
338             reinterpret_cast<void *>(EmitStringOptionsDataSync)},
339     };
340     AgentInit();
341     return env->Namespace_BindNativeFunctions(kitNs, methods.data(), methods.size());
342 }
343 
344 extern "C" {
ANI_Constructor(ani_vm * vm,uint32_t * result)345 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
346 {
347     HILOGD("ANI_Constructor begin");
348     ani_status status = ANI_ERROR;
349     ani_env *env;
350     if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
351         HILOGE("Unsupported ANI_VERSION_1.");
352         return ANI_ERROR;
353     }
354 
355     ani_namespace kitNs;
356     status = env->FindNamespace("L@ohos/events/emitter/emitter;", &kitNs);
357     if (status != ANI_OK) {
358         HILOGE("Not found ani_namespace L@ohos/events/emitter/emitter");
359         return ANI_INVALID_ARGS;
360     }
361     status = init(env, kitNs);
362     if (status != ANI_OK) {
363         HILOGE("Cannot bind native methods to L@ohos/events/emitter/emitter");
364         return ANI_INVALID_TYPE;
365     }
366 
367     *result = ANI_VERSION_1;
368     return ANI_OK;
369 }
370 }
371 }  // namespace AppExecFwk
372 }  // namespace OHOS