1100ae2f9Sopenharmony_ci/*
2100ae2f9Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
3100ae2f9Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4100ae2f9Sopenharmony_ci * you may not use this file except in compliance with the License.
5100ae2f9Sopenharmony_ci * You may obtain a copy of the License at
6100ae2f9Sopenharmony_ci *
7100ae2f9Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8100ae2f9Sopenharmony_ci *
9100ae2f9Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10100ae2f9Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11100ae2f9Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12100ae2f9Sopenharmony_ci * See the License for the specific language governing permissions and
13100ae2f9Sopenharmony_ci * limitations under the License.
14100ae2f9Sopenharmony_ci */
15100ae2f9Sopenharmony_ci
16100ae2f9Sopenharmony_ci#include <mutex>
17100ae2f9Sopenharmony_ci#include <unordered_set>
18100ae2f9Sopenharmony_ci#include <map>
19100ae2f9Sopenharmony_ci#include <memory>
20100ae2f9Sopenharmony_ci
21100ae2f9Sopenharmony_ci#include "emitter_log.h"
22100ae2f9Sopenharmony_ci#include "inner_event.h"
23100ae2f9Sopenharmony_ci#include "event_handler_impl.h"
24100ae2f9Sopenharmony_ci#include "cj_fn_invoker.h"
25100ae2f9Sopenharmony_ci#include "emitter.h"
26100ae2f9Sopenharmony_ci
27100ae2f9Sopenharmony_ciusing InnerEvent = OHOS::AppExecFwk::InnerEvent;
28100ae2f9Sopenharmony_ciusing Priority = OHOS::AppExecFwk::EventQueue::Priority;
29100ae2f9Sopenharmony_ci
30100ae2f9Sopenharmony_cinamespace OHOS::EventsEmitter {
31100ae2f9Sopenharmony_ci    const int32_t SUCCESS = 0;
32100ae2f9Sopenharmony_ci    struct EventDataWorker {
33100ae2f9Sopenharmony_ci        CEventData data;
34100ae2f9Sopenharmony_ci        InnerEvent::EventId eventId;
35100ae2f9Sopenharmony_ci        CallbackInfo* callbackInfo;
36100ae2f9Sopenharmony_ci    };
37100ae2f9Sopenharmony_ci
38100ae2f9Sopenharmony_ci    static std::mutex g_emitterInsMutex;
39100ae2f9Sopenharmony_ci    static std::map<InnerEvent::EventId, std::unordered_set<CallbackInfo *>> g_emitterImpls;
40100ae2f9Sopenharmony_ci    std::shared_ptr<EventHandlerImpl> eventHandler = EventHandlerImpl::GetEventHandler();
41100ae2f9Sopenharmony_ci
42100ae2f9Sopenharmony_ci    CallbackImpl::CallbackImpl(std::string name, std::function<void(CEventData)> callback)
43100ae2f9Sopenharmony_ci        : name(name), callback(callback)
44100ae2f9Sopenharmony_ci    {}
45100ae2f9Sopenharmony_ci
46100ae2f9Sopenharmony_ci    CallbackInfo::~CallbackInfo()
47100ae2f9Sopenharmony_ci    {
48100ae2f9Sopenharmony_ci        callbackImpl = nullptr;
49100ae2f9Sopenharmony_ci    }
50100ae2f9Sopenharmony_ci
51100ae2f9Sopenharmony_ci    bool IsExistValidCallback(const InnerEvent::EventId &eventId)
52100ae2f9Sopenharmony_ci    {
53100ae2f9Sopenharmony_ci        std::lock_guard<std::mutex> lock(g_emitterInsMutex);
54100ae2f9Sopenharmony_ci        auto subscribe = g_emitterImpls.find(eventId);
55100ae2f9Sopenharmony_ci        if (subscribe == g_emitterImpls.end()) {
56100ae2f9Sopenharmony_ci            LOGW("emit has no callback");
57100ae2f9Sopenharmony_ci            return false;
58100ae2f9Sopenharmony_ci        }
59100ae2f9Sopenharmony_ci        for (auto callbackInfo : subscribe->second) {
60100ae2f9Sopenharmony_ci            if (!callbackInfo->isDeleted) {
61100ae2f9Sopenharmony_ci                return true;
62100ae2f9Sopenharmony_ci            }
63100ae2f9Sopenharmony_ci        }
64100ae2f9Sopenharmony_ci        return false;
65100ae2f9Sopenharmony_ci    }
66100ae2f9Sopenharmony_ci
67100ae2f9Sopenharmony_ci    void EmitWithEventData(InnerEvent::EventId eventId, uint32_t priority, CEventData data)
68100ae2f9Sopenharmony_ci    {
69100ae2f9Sopenharmony_ci        if (!IsExistValidCallback(eventId)) {
70100ae2f9Sopenharmony_ci            LOGE("Invalid callback");
71100ae2f9Sopenharmony_ci            return;
72100ae2f9Sopenharmony_ci        }
73100ae2f9Sopenharmony_ci        std::unique_ptr<CEventData> dataPtr;
74100ae2f9Sopenharmony_ci        if (data.size == 0) {
75100ae2f9Sopenharmony_ci            dataPtr = std::make_unique<CEventData>();
76100ae2f9Sopenharmony_ci        } else {
77100ae2f9Sopenharmony_ci            dataPtr = std::make_unique<CEventData>(data);
78100ae2f9Sopenharmony_ci        }
79100ae2f9Sopenharmony_ci        auto event = InnerEvent::Get(eventId, dataPtr);
80100ae2f9Sopenharmony_ci        eventHandler->SendEvent(event, 0, static_cast<Priority>(priority));
81100ae2f9Sopenharmony_ci    }
82100ae2f9Sopenharmony_ci
83100ae2f9Sopenharmony_ci    CallbackInfo *SearchCallbackInfo(const InnerEvent::EventId &eventIdValue, const std::string &callbackName)
84100ae2f9Sopenharmony_ci    {
85100ae2f9Sopenharmony_ci        auto subscribe = g_emitterImpls.find(eventIdValue);
86100ae2f9Sopenharmony_ci        if (subscribe == g_emitterImpls.end()) {
87100ae2f9Sopenharmony_ci            return nullptr;
88100ae2f9Sopenharmony_ci        }
89100ae2f9Sopenharmony_ci        for (auto callbackInfo : subscribe->second) {
90100ae2f9Sopenharmony_ci            if (callbackInfo->isDeleted) {
91100ae2f9Sopenharmony_ci                continue;
92100ae2f9Sopenharmony_ci            }
93100ae2f9Sopenharmony_ci            if (callbackInfo->callbackImpl->name == callbackName) {
94100ae2f9Sopenharmony_ci                LOGD("Callback found.")
95100ae2f9Sopenharmony_ci                return callbackInfo;
96100ae2f9Sopenharmony_ci            }
97100ae2f9Sopenharmony_ci        }
98100ae2f9Sopenharmony_ci        LOGD("Callback not found.")
99100ae2f9Sopenharmony_ci        return nullptr;
100100ae2f9Sopenharmony_ci    }
101100ae2f9Sopenharmony_ci
102100ae2f9Sopenharmony_ci    void UpdateOnceFlag(CallbackInfo *callbackInfo, bool once)
103100ae2f9Sopenharmony_ci    {
104100ae2f9Sopenharmony_ci        if (!once) {
105100ae2f9Sopenharmony_ci            if (callbackInfo->once) {
106100ae2f9Sopenharmony_ci                LOGD("On change once to on");
107100ae2f9Sopenharmony_ci                callbackInfo->once = false;
108100ae2f9Sopenharmony_ci            } else {
109100ae2f9Sopenharmony_ci                LOGD("On already on");
110100ae2f9Sopenharmony_ci            }
111100ae2f9Sopenharmony_ci        } else {
112100ae2f9Sopenharmony_ci            if (callbackInfo->once) {
113100ae2f9Sopenharmony_ci                LOGD("Once already once");
114100ae2f9Sopenharmony_ci            } else {
115100ae2f9Sopenharmony_ci                LOGD("Once change on to once");
116100ae2f9Sopenharmony_ci                callbackInfo->once = true;
117100ae2f9Sopenharmony_ci            }
118100ae2f9Sopenharmony_ci        }
119100ae2f9Sopenharmony_ci    }
120100ae2f9Sopenharmony_ci
121100ae2f9Sopenharmony_ci    void OutPutEventIdLog(const InnerEvent::EventId &eventId)
122100ae2f9Sopenharmony_ci    {
123100ae2f9Sopenharmony_ci        if (eventId.index() == OHOS::AppExecFwk::TYPE_U32_INDEX) {
124100ae2f9Sopenharmony_ci            LOGD("Event id value: %{public}u", std::get<uint32_t>(eventId));
125100ae2f9Sopenharmony_ci        } else {
126100ae2f9Sopenharmony_ci            LOGD("Event id value: %{public}s", std::get<std::string>(eventId).c_str());
127100ae2f9Sopenharmony_ci        }
128100ae2f9Sopenharmony_ci    }
129100ae2f9Sopenharmony_ci
130100ae2f9Sopenharmony_ci    int32_t OnOrOnce(InnerEvent::EventId eventId, CallbackImpl **callbackImpl, bool once)
131100ae2f9Sopenharmony_ci    {
132100ae2f9Sopenharmony_ci        OutPutEventIdLog(eventId);
133100ae2f9Sopenharmony_ci        std::lock_guard<std::mutex> lock(g_emitterInsMutex);
134100ae2f9Sopenharmony_ci        auto callback = *callbackImpl;
135100ae2f9Sopenharmony_ci        auto callbackInfo = SearchCallbackInfo(eventId, callback->name);
136100ae2f9Sopenharmony_ci        if (callbackInfo != nullptr) {
137100ae2f9Sopenharmony_ci            UpdateOnceFlag(callbackInfo, once);
138100ae2f9Sopenharmony_ci            delete callback;
139100ae2f9Sopenharmony_ci            *callbackImpl = nullptr;
140100ae2f9Sopenharmony_ci            return SUCCESS;
141100ae2f9Sopenharmony_ci        }
142100ae2f9Sopenharmony_ci        callbackInfo = new (std::nothrow) CallbackInfo();
143100ae2f9Sopenharmony_ci        if (!callbackInfo) {
144100ae2f9Sopenharmony_ci            LOGE("new callbackInfo failed");
145100ae2f9Sopenharmony_ci            delete callback;
146100ae2f9Sopenharmony_ci            *callbackImpl = nullptr;
147100ae2f9Sopenharmony_ci            return MEMORY_ERROR;
148100ae2f9Sopenharmony_ci        }
149100ae2f9Sopenharmony_ci        callbackInfo->callbackImpl = callback;
150100ae2f9Sopenharmony_ci        callbackInfo->once = once;
151100ae2f9Sopenharmony_ci        g_emitterImpls[eventId].insert(callbackInfo);
152100ae2f9Sopenharmony_ci        return SUCCESS;
153100ae2f9Sopenharmony_ci    }
154100ae2f9Sopenharmony_ci
155100ae2f9Sopenharmony_ci    int32_t Emitter::On(uint32_t eventId, CallbackImpl *callback)
156100ae2f9Sopenharmony_ci    {
157100ae2f9Sopenharmony_ci        InnerEvent::EventId id = eventId;
158100ae2f9Sopenharmony_ci        return OnOrOnce(id, &callback, false);
159100ae2f9Sopenharmony_ci    }
160100ae2f9Sopenharmony_ci
161100ae2f9Sopenharmony_ci    int32_t Emitter::On(char* eventId, CallbackImpl *callback)
162100ae2f9Sopenharmony_ci    {
163100ae2f9Sopenharmony_ci        InnerEvent::EventId id = std::string(eventId);
164100ae2f9Sopenharmony_ci        return OnOrOnce(id, &callback, false);
165100ae2f9Sopenharmony_ci    }
166100ae2f9Sopenharmony_ci
167100ae2f9Sopenharmony_ci    int32_t Emitter::Once(uint32_t eventId, CallbackImpl *callback)
168100ae2f9Sopenharmony_ci    {
169100ae2f9Sopenharmony_ci        InnerEvent::EventId id = eventId;
170100ae2f9Sopenharmony_ci        return OnOrOnce(id, &callback, true);
171100ae2f9Sopenharmony_ci    }
172100ae2f9Sopenharmony_ci
173100ae2f9Sopenharmony_ci    int32_t Emitter::Once(char* eventId, CallbackImpl *callback)
174100ae2f9Sopenharmony_ci    {
175100ae2f9Sopenharmony_ci        InnerEvent::EventId id = std::string(eventId);
176100ae2f9Sopenharmony_ci        return OnOrOnce(id, &callback, true);
177100ae2f9Sopenharmony_ci    }
178100ae2f9Sopenharmony_ci
179100ae2f9Sopenharmony_ci    void Unsubscribe(InnerEvent::EventId eventId)
180100ae2f9Sopenharmony_ci    {
181100ae2f9Sopenharmony_ci        std::lock_guard<std::mutex> lock(g_emitterInsMutex);
182100ae2f9Sopenharmony_ci        auto subscribe = g_emitterImpls.find(eventId);
183100ae2f9Sopenharmony_ci        if (subscribe != g_emitterImpls.end()) {
184100ae2f9Sopenharmony_ci            for (auto callbackInfo : subscribe->second) {
185100ae2f9Sopenharmony_ci                callbackInfo->isDeleted = true;
186100ae2f9Sopenharmony_ci            }
187100ae2f9Sopenharmony_ci        }
188100ae2f9Sopenharmony_ci    }
189100ae2f9Sopenharmony_ci
190100ae2f9Sopenharmony_ci    void Unsubscribe(InnerEvent::EventId eventId, CallbackImpl *callback)
191100ae2f9Sopenharmony_ci    {
192100ae2f9Sopenharmony_ci        std::lock_guard<std::mutex> lock(g_emitterInsMutex);
193100ae2f9Sopenharmony_ci        auto callbackInfo = SearchCallbackInfo(eventId, callback->name);
194100ae2f9Sopenharmony_ci        if (callbackInfo != nullptr) {
195100ae2f9Sopenharmony_ci            callbackInfo->isDeleted = true;
196100ae2f9Sopenharmony_ci        }
197100ae2f9Sopenharmony_ci    }
198100ae2f9Sopenharmony_ci
199100ae2f9Sopenharmony_ci    void Emitter::Off(uint32_t eventId)
200100ae2f9Sopenharmony_ci    {
201100ae2f9Sopenharmony_ci        InnerEvent::EventId id = eventId;
202100ae2f9Sopenharmony_ci        Unsubscribe(id);
203100ae2f9Sopenharmony_ci    }
204100ae2f9Sopenharmony_ci
205100ae2f9Sopenharmony_ci    void Emitter::Off(char* eventId)
206100ae2f9Sopenharmony_ci    {
207100ae2f9Sopenharmony_ci        InnerEvent::EventId id = std::string(eventId);
208100ae2f9Sopenharmony_ci        Unsubscribe(id);
209100ae2f9Sopenharmony_ci    }
210100ae2f9Sopenharmony_ci
211100ae2f9Sopenharmony_ci    void Emitter::Off(uint32_t eventId, CallbackImpl *callback)
212100ae2f9Sopenharmony_ci    {
213100ae2f9Sopenharmony_ci        InnerEvent::EventId id = eventId;
214100ae2f9Sopenharmony_ci        Unsubscribe(id, callback);
215100ae2f9Sopenharmony_ci    }
216100ae2f9Sopenharmony_ci
217100ae2f9Sopenharmony_ci    void Emitter::Off(char* eventId, CallbackImpl *callback)
218100ae2f9Sopenharmony_ci    {
219100ae2f9Sopenharmony_ci        InnerEvent::EventId id = std::string(eventId);
220100ae2f9Sopenharmony_ci        Unsubscribe(id, callback);
221100ae2f9Sopenharmony_ci    }
222100ae2f9Sopenharmony_ci
223100ae2f9Sopenharmony_ci    void Emitter::Emit(uint32_t eventId, uint32_t priority, CEventData data)
224100ae2f9Sopenharmony_ci    {
225100ae2f9Sopenharmony_ci        InnerEvent::EventId id = eventId;
226100ae2f9Sopenharmony_ci        EmitWithEventData(id, priority, data);
227100ae2f9Sopenharmony_ci    }
228100ae2f9Sopenharmony_ci
229100ae2f9Sopenharmony_ci    void Emitter::Emit(char* eventId, uint32_t priority, CEventData data)
230100ae2f9Sopenharmony_ci    {
231100ae2f9Sopenharmony_ci        InnerEvent::EventId id = std::string(eventId);
232100ae2f9Sopenharmony_ci        EmitWithEventData(id, priority, data);
233100ae2f9Sopenharmony_ci    }
234100ae2f9Sopenharmony_ci
235100ae2f9Sopenharmony_ci    uint32_t GetListenerCountByEventId(InnerEvent::EventId eventId)
236100ae2f9Sopenharmony_ci    {
237100ae2f9Sopenharmony_ci        uint32_t count = 0;
238100ae2f9Sopenharmony_ci        std::lock_guard<std::mutex> lock(g_emitterInsMutex);
239100ae2f9Sopenharmony_ci        auto subscribe = g_emitterImpls.find(eventId);
240100ae2f9Sopenharmony_ci        if (subscribe != g_emitterImpls.end()) {
241100ae2f9Sopenharmony_ci            for (auto callbackInfo : subscribe->second) {
242100ae2f9Sopenharmony_ci                if (!callbackInfo->isDeleted) {
243100ae2f9Sopenharmony_ci                    ++count;
244100ae2f9Sopenharmony_ci                }
245100ae2f9Sopenharmony_ci            }
246100ae2f9Sopenharmony_ci        }
247100ae2f9Sopenharmony_ci        return count;
248100ae2f9Sopenharmony_ci    }
249100ae2f9Sopenharmony_ci
250100ae2f9Sopenharmony_ci    uint32_t Emitter::GetListenerCount(uint32_t eventId)
251100ae2f9Sopenharmony_ci    {
252100ae2f9Sopenharmony_ci        InnerEvent::EventId id = eventId;
253100ae2f9Sopenharmony_ci        return GetListenerCountByEventId(id);
254100ae2f9Sopenharmony_ci    }
255100ae2f9Sopenharmony_ci
256100ae2f9Sopenharmony_ci    uint32_t Emitter::GetListenerCount(std::string eventId)
257100ae2f9Sopenharmony_ci    {
258100ae2f9Sopenharmony_ci        InnerEvent::EventId id = eventId;
259100ae2f9Sopenharmony_ci        return GetListenerCountByEventId(id);
260100ae2f9Sopenharmony_ci    }
261100ae2f9Sopenharmony_ci
262100ae2f9Sopenharmony_ci    void FreeCEventData(CEventData &eventData)
263100ae2f9Sopenharmony_ci    {
264100ae2f9Sopenharmony_ci        auto params = reinterpret_cast<CParameter *>(eventData.parameters);
265100ae2f9Sopenharmony_ci        for (int i = 0; i < eventData.size; i++) {
266100ae2f9Sopenharmony_ci            free(params[i].key);
267100ae2f9Sopenharmony_ci            free(params[i].value);
268100ae2f9Sopenharmony_ci            params[i].key = nullptr;
269100ae2f9Sopenharmony_ci            params[i].value = nullptr;
270100ae2f9Sopenharmony_ci        }
271100ae2f9Sopenharmony_ci        free(params);
272100ae2f9Sopenharmony_ci        params = nullptr;
273100ae2f9Sopenharmony_ci    }
274100ae2f9Sopenharmony_ci
275100ae2f9Sopenharmony_ci    void ProcessCallback(const InnerEvent::Pointer& event, std::unordered_set<CallbackInfo *>& callbackInfos)
276100ae2f9Sopenharmony_ci    {
277100ae2f9Sopenharmony_ci        auto value = event->GetUniqueObject<CEventData>();
278100ae2f9Sopenharmony_ci        CEventData eventData = { .parameters = nullptr, .size = 0};
279100ae2f9Sopenharmony_ci        if (value != nullptr) {
280100ae2f9Sopenharmony_ci            eventData = *value;
281100ae2f9Sopenharmony_ci        }
282100ae2f9Sopenharmony_ci        for (auto iter = callbackInfos.begin(); iter != callbackInfos.end();) {
283100ae2f9Sopenharmony_ci            CallbackInfo* callbackInfo = *iter;
284100ae2f9Sopenharmony_ci            if (callbackInfo->once || callbackInfo->isDeleted) {
285100ae2f9Sopenharmony_ci                LOGI("once callback or isDeleted callback");
286100ae2f9Sopenharmony_ci                iter = callbackInfos.erase(iter);
287100ae2f9Sopenharmony_ci                if (callbackInfo->processed) {
288100ae2f9Sopenharmony_ci                    delete callbackInfo->callbackImpl;
289100ae2f9Sopenharmony_ci                    delete callbackInfo;
290100ae2f9Sopenharmony_ci                    callbackInfo = nullptr;
291100ae2f9Sopenharmony_ci                    continue;
292100ae2f9Sopenharmony_ci                }
293100ae2f9Sopenharmony_ci            } else {
294100ae2f9Sopenharmony_ci                ++iter;
295100ae2f9Sopenharmony_ci            }
296100ae2f9Sopenharmony_ci            if (!callbackInfo->isDeleted) {
297100ae2f9Sopenharmony_ci                callbackInfo->callbackImpl->callback(eventData);
298100ae2f9Sopenharmony_ci            } else {
299100ae2f9Sopenharmony_ci                LOGD("callback is deleted.");
300100ae2f9Sopenharmony_ci            }
301100ae2f9Sopenharmony_ci            callbackInfo->processed = true;
302100ae2f9Sopenharmony_ci        }
303100ae2f9Sopenharmony_ci        FreeCEventData(eventData);
304100ae2f9Sopenharmony_ci    }
305100ae2f9Sopenharmony_ci
306100ae2f9Sopenharmony_ci    void EventHandlerImpl::ProcessEvent(const InnerEvent::Pointer& event)
307100ae2f9Sopenharmony_ci    {
308100ae2f9Sopenharmony_ci        LOGI("ProcessEvent");
309100ae2f9Sopenharmony_ci        InnerEvent::EventId eventId = event->GetInnerEventIdEx();
310100ae2f9Sopenharmony_ci        OutPutEventIdLog(eventId);
311100ae2f9Sopenharmony_ci        std::unordered_set<CallbackInfo *> callbackInfos;
312100ae2f9Sopenharmony_ci        {
313100ae2f9Sopenharmony_ci            std::lock_guard<std::mutex> lock(g_emitterInsMutex);
314100ae2f9Sopenharmony_ci            auto subscribe = g_emitterImpls.find(eventId);
315100ae2f9Sopenharmony_ci            if (subscribe == g_emitterImpls.end()) {
316100ae2f9Sopenharmony_ci                LOGW("ProcessEvent has no callback");
317100ae2f9Sopenharmony_ci                return;
318100ae2f9Sopenharmony_ci            }
319100ae2f9Sopenharmony_ci            callbackInfos = subscribe->second;
320100ae2f9Sopenharmony_ci        }
321100ae2f9Sopenharmony_ci        LOGD("size = %{public}zu", callbackInfos.size());
322100ae2f9Sopenharmony_ci        ProcessCallback(event, callbackInfos);
323100ae2f9Sopenharmony_ci        if (callbackInfos.empty()) {
324100ae2f9Sopenharmony_ci            g_emitterImpls.erase(eventId);
325100ae2f9Sopenharmony_ci            LOGD("ProcessEvent delete the last callback");
326100ae2f9Sopenharmony_ci        } else {
327100ae2f9Sopenharmony_ci            std::lock_guard<std::mutex> lock(g_emitterInsMutex);
328100ae2f9Sopenharmony_ci            auto subscribe = g_emitterImpls.find(eventId);
329100ae2f9Sopenharmony_ci            subscribe->second = callbackInfos;
330100ae2f9Sopenharmony_ci        }
331100ae2f9Sopenharmony_ci    }
332100ae2f9Sopenharmony_ci}