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