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}