1 /* 2 * Copyright (c) 2024 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 <mutex> 17 #include <unordered_set> 18 #include <map> 19 #include <memory> 20 21 #include "emitter_log.h" 22 #include "inner_event.h" 23 #include "event_handler_impl.h" 24 #include "cj_fn_invoker.h" 25 #include "emitter.h" 26 27 using InnerEvent = OHOS::AppExecFwk::InnerEvent; 28 using Priority = OHOS::AppExecFwk::EventQueue::Priority; 29 30 namespace OHOS::EventsEmitter { 31 const int32_t SUCCESS = 0; 32 33 static std::mutex g_emitterInsMutex; 34 static std::map<InnerEvent::EventId, std::unordered_set<std::shared_ptr<CallbackInfo>>> g_emitterImpls; 35 std::shared_ptr<EventHandlerImpl> eventHandler = EventHandlerImpl::GetEventHandler(); 36 CallbackImpl(std::string name,std::function<void (CEventData)> callback)37 CallbackImpl::CallbackImpl(std::string name, std::function<void(CEventData)> callback) 38 : name(name), callback(callback) 39 {} 40 ~CallbackInfo()41 CallbackInfo::~CallbackInfo() 42 { 43 callbackImpl = nullptr; 44 } 45 IsExistValidCallback(const InnerEvent::EventId & eventId)46 bool IsExistValidCallback(const InnerEvent::EventId &eventId) 47 { 48 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 49 auto subscribe = g_emitterImpls.find(eventId); 50 if (subscribe == g_emitterImpls.end()) { 51 LOGW("emit has no callback"); 52 return false; 53 } 54 return true; 55 } 56 EmitWithEventData(InnerEvent::EventId eventId,uint32_t priority,CEventData data)57 void EmitWithEventData(InnerEvent::EventId eventId, uint32_t priority, CEventData data) 58 { 59 if (!IsExistValidCallback(eventId)) { 60 LOGE("Invalid callback"); 61 return; 62 } 63 std::unique_ptr<CEventData> dataPtr; 64 if (data.size == 0) { 65 dataPtr = std::make_unique<CEventData>(); 66 } else { 67 dataPtr = std::make_unique<CEventData>(data); 68 } 69 auto event = InnerEvent::Get(eventId, dataPtr); 70 eventHandler->SendEvent(event, 0, static_cast<Priority>(priority)); 71 } 72 SearchCallbackInfo(const InnerEvent::EventId & eventId,const std::string & callbackName,bool erase)73 std::shared_ptr<CallbackInfo> SearchCallbackInfo(const InnerEvent::EventId &eventId, 74 const std::string &callbackName, bool erase) 75 { 76 auto subscribe = g_emitterImpls.find(eventId); 77 if (subscribe == g_emitterImpls.end()) { 78 return nullptr; 79 } 80 for (auto callbackInfo : subscribe->second) { 81 if (callbackInfo->callbackImpl->name == callbackName) { 82 LOGD("Callback found.") 83 if (erase) { 84 subscribe->second.erase(callbackInfo); 85 break; 86 } 87 return callbackInfo; 88 } 89 } 90 if (subscribe->second.empty()) { 91 g_emitterImpls.erase(eventId); 92 } else { 93 LOGD("Callback not found."); 94 } 95 return nullptr; 96 } 97 UpdateOnceFlag(std::shared_ptr<CallbackInfo> & callbackInfo,bool once)98 void UpdateOnceFlag(std::shared_ptr<CallbackInfo> &callbackInfo, bool once) 99 { 100 if (!once) { 101 if (callbackInfo->once) { 102 LOGD("On change once to on"); 103 callbackInfo->once = false; 104 } else { 105 LOGD("On already on"); 106 } 107 } else { 108 if (callbackInfo->once) { 109 LOGD("Once already once"); 110 } else { 111 LOGD("Once change on to once"); 112 callbackInfo->once = true; 113 } 114 } 115 } 116 OutPutEventIdLog(const InnerEvent::EventId & eventId)117 void OutPutEventIdLog(const InnerEvent::EventId &eventId) 118 { 119 if (eventId.index() == OHOS::AppExecFwk::TYPE_U32_INDEX) { 120 LOGD("Event id value: %{public}u", std::get<uint32_t>(eventId)); 121 } else { 122 LOGD("Event id value: %{public}s", std::get<std::string>(eventId).c_str()); 123 } 124 } 125 OnOrOnce(InnerEvent::EventId eventId,std::shared_ptr<CallbackImpl> & callbackImpl,bool once)126 int32_t OnOrOnce(InnerEvent::EventId eventId, std::shared_ptr<CallbackImpl> &callbackImpl, bool once) 127 { 128 OutPutEventIdLog(eventId); 129 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 130 auto callbackInfo = SearchCallbackInfo(eventId, callbackImpl->name, false); 131 if (callbackInfo != nullptr) { 132 UpdateOnceFlag(callbackInfo, once); 133 return SUCCESS; 134 } 135 callbackInfo = std::make_shared<CallbackInfo>(); 136 if (!callbackInfo) { 137 LOGE("new callbackInfo failed"); 138 return MEMORY_ERROR; 139 } 140 callbackInfo->callbackImpl = callbackImpl; 141 callbackInfo->once = once; 142 g_emitterImpls[eventId].insert(callbackInfo); 143 return SUCCESS; 144 } 145 On(uint32_t eventId,std::shared_ptr<CallbackImpl> & callback)146 int32_t Emitter::On(uint32_t eventId, std::shared_ptr<CallbackImpl> &callback) 147 { 148 InnerEvent::EventId id = eventId; 149 return OnOrOnce(id, callback, false); 150 } 151 On(char * eventId,std::shared_ptr<CallbackImpl> & callback)152 int32_t Emitter::On(char* eventId, std::shared_ptr<CallbackImpl> &callback) 153 { 154 InnerEvent::EventId id = std::string(eventId); 155 return OnOrOnce(id, callback, false); 156 } 157 Once(uint32_t eventId,std::shared_ptr<CallbackImpl> & callback)158 int32_t Emitter::Once(uint32_t eventId, std::shared_ptr<CallbackImpl> &callback) 159 { 160 InnerEvent::EventId id = eventId; 161 return OnOrOnce(id, callback, true); 162 } 163 Once(char * eventId,std::shared_ptr<CallbackImpl> & callback)164 int32_t Emitter::Once(char* eventId, std::shared_ptr<CallbackImpl> &callback) 165 { 166 InnerEvent::EventId id = std::string(eventId); 167 return OnOrOnce(id, callback, true); 168 } 169 Unsubscribe(InnerEvent::EventId eventId)170 void Unsubscribe(InnerEvent::EventId eventId) 171 { 172 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 173 auto subscribe = g_emitterImpls.find(eventId); 174 if (subscribe != g_emitterImpls.end()) { 175 g_emitterImpls.erase(eventId); 176 } 177 } 178 Unsubscribe(InnerEvent::EventId eventId,std::shared_ptr<CallbackImpl> & callback)179 void Unsubscribe(InnerEvent::EventId eventId, std::shared_ptr<CallbackImpl> &callback) 180 { 181 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 182 (void)SearchCallbackInfo(eventId, callback->name, true); 183 } 184 Off(uint32_t eventId)185 void Emitter::Off(uint32_t eventId) 186 { 187 InnerEvent::EventId id = eventId; 188 Unsubscribe(id); 189 } 190 Off(char * eventId)191 void Emitter::Off(char* eventId) 192 { 193 InnerEvent::EventId id = std::string(eventId); 194 Unsubscribe(id); 195 } 196 Off(uint32_t eventId,std::shared_ptr<CallbackImpl> & callback)197 void Emitter::Off(uint32_t eventId, std::shared_ptr<CallbackImpl> &callback) 198 { 199 InnerEvent::EventId id = eventId; 200 Unsubscribe(id, callback); 201 } 202 Off(char * eventId,std::shared_ptr<CallbackImpl> & callback)203 void Emitter::Off(char* eventId, std::shared_ptr<CallbackImpl> &callback) 204 { 205 InnerEvent::EventId id = std::string(eventId); 206 Unsubscribe(id, callback); 207 } 208 Emit(uint32_t eventId,uint32_t priority,CEventData data)209 void Emitter::Emit(uint32_t eventId, uint32_t priority, CEventData data) 210 { 211 InnerEvent::EventId id = eventId; 212 EmitWithEventData(id, priority, data); 213 } 214 Emit(char * eventId,uint32_t priority,CEventData data)215 void Emitter::Emit(char* eventId, uint32_t priority, CEventData data) 216 { 217 InnerEvent::EventId id = std::string(eventId); 218 EmitWithEventData(id, priority, data); 219 } 220 GetListenerCountByEventId(InnerEvent::EventId eventId)221 uint32_t GetListenerCountByEventId(InnerEvent::EventId eventId) 222 { 223 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 224 auto subscribe = g_emitterImpls.find(eventId); 225 return static_cast<uint32_t>(subscribe->second.size()); 226 } 227 GetListenerCount(uint32_t eventId)228 uint32_t Emitter::GetListenerCount(uint32_t eventId) 229 { 230 InnerEvent::EventId id = eventId; 231 return GetListenerCountByEventId(id); 232 } 233 GetListenerCount(std::string eventId)234 uint32_t Emitter::GetListenerCount(std::string eventId) 235 { 236 InnerEvent::EventId id = eventId; 237 return GetListenerCountByEventId(id); 238 } 239 FreeCEventData(CEventData & eventData)240 void FreeCEventData(CEventData &eventData) 241 { 242 auto params = reinterpret_cast<CParameter *>(eventData.parameters); 243 for (int i = 0; i < eventData.size; i++) { 244 free(params[i].key); 245 free(params[i].value); 246 params[i].key = nullptr; 247 params[i].value = nullptr; 248 } 249 free(params); 250 params = nullptr; 251 } 252 ProcessCallback(const InnerEvent::Pointer & event,std::unordered_set<std::shared_ptr<CallbackInfo>> & callbackInfos)253 void ProcessCallback(const InnerEvent::Pointer& event, 254 std::unordered_set<std::shared_ptr<CallbackInfo>>& callbackInfos) 255 { 256 auto value = event->GetUniqueObject<CEventData>(); 257 CEventData eventData = { .parameters = nullptr, .size = 0}; 258 if (value != nullptr) { 259 eventData = *value; 260 } 261 for (auto callback : callbackInfos) { 262 callback->callbackImpl->callback(eventData); 263 } 264 FreeCEventData(eventData); 265 } 266 GetEventCallbacks(InnerEvent::EventId eventId)267 std::unordered_set<std::shared_ptr<CallbackInfo>> GetEventCallbacks(InnerEvent::EventId eventId) 268 { 269 std::lock_guard<std::mutex> lock(g_emitterInsMutex); 270 std::unordered_set<std::shared_ptr<CallbackInfo>> callbackInfos; 271 auto subscribe = g_emitterImpls.find(eventId); 272 if (subscribe == g_emitterImpls.end()) { 273 LOGW("no callback"); 274 return callbackInfos; 275 } 276 for (auto iter = subscribe->second.begin(); iter != subscribe->second.end();) { 277 callbackInfos.insert(*iter); 278 if ((*iter)->once) { 279 iter = subscribe->second.erase(iter); 280 } else { 281 ++iter; 282 } 283 } 284 if (subscribe->second.empty()) { 285 LOGD("delete the last callback"); 286 g_emitterImpls.erase(eventId); 287 } 288 return callbackInfos; 289 } 290 ProcessEvent(const InnerEvent::Pointer & event)291 void EventHandlerImpl::ProcessEvent(const InnerEvent::Pointer& event) 292 { 293 LOGI("ProcessEvent"); 294 InnerEvent::EventId eventId = event->GetInnerEventIdEx(); 295 OutPutEventIdLog(eventId); 296 auto callbackInfos = GetEventCallbacks(eventId); 297 if (callbackInfos.size() <= 0) { 298 return; 299 } 300 LOGD("size = %{public}zu", callbackInfos.size()); 301 ProcessCallback(event, callbackInfos); 302 } 303 }