1 /*
2 * Copyright (c) 2023-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 "event_handler_wrap.h"
17
18 #include <cinttypes>
19 #include <chrono>
20 #include <mutex>
21 #include "cpp/mutex.h"
22
23 #include "hilog_tag_wrapper.h"
24
25 namespace OHOS {
26 namespace AAFwk {
27 namespace {
28 constexpr int64_t EVENT_TIME_DIFF = 200; // ms
29 constexpr int64_t EVENT_TIME_CANCEL = 3000; // ms
GetCurrentTimeMillis()30 inline int64_t GetCurrentTimeMillis()
31 {
32 return std::chrono::duration_cast<std::chrono::milliseconds>(
33 std::chrono::steady_clock::now().time_since_epoch()).count();
34 }
35 }
EventHandlerWrap()36 EventHandlerWrap::EventHandlerWrap() : taskHandler_(TaskHandlerWrap::GetFfrtHandler())
37 {
38 eventMutex_ = std::make_unique<ffrt::mutex>();
39 }
40
EventHandlerWrap(std::shared_ptr<TaskHandlerWrap> taskHandler)41 EventHandlerWrap::EventHandlerWrap(std::shared_ptr<TaskHandlerWrap> taskHandler)
42 : taskHandler_(taskHandler)
43 {
44 eventMutex_ = std::make_unique<ffrt::mutex>();
45 }
46
47 EventHandlerWrap::~EventHandlerWrap() = default;
48
ProcessEvent(const EventWrap & event)49 void EventHandlerWrap::ProcessEvent(const EventWrap &event)
50 {
51 if (eventCallback_) {
52 eventCallback_(event);
53 }
54 }
SendEvent(uint32_t eventId)55 bool EventHandlerWrap::SendEvent(uint32_t eventId)
56 {
57 return SendEvent(EventWrap(eventId, 0));
58 }
SendEvent(uint32_t eventId,int64_t delayMillis)59 bool EventHandlerWrap::SendEvent(uint32_t eventId, int64_t delayMillis)
60 {
61 return SendEvent(EventWrap(eventId, 0), delayMillis);
62 }
SendEvent(EventWrap event)63 bool EventHandlerWrap::SendEvent(EventWrap event)
64 {
65 return SendEvent(event, 0);
66 }
SendEvent(EventWrap event,int64_t delayMillis,bool forceInsert)67 bool EventHandlerWrap::SendEvent(EventWrap event, int64_t delayMillis, bool forceInsert)
68 {
69 if (!taskHandler_) {
70 return false;
71 }
72 auto eventStr = event.GetEventString();
73 std::lock_guard<ffrt::mutex> guard(*eventMutex_);
74 auto it = eventMap_.find(eventStr);
75 if (it != eventMap_.end() && !forceInsert) {
76 return false;
77 }
78
79 event.SetTimeout(delayMillis);
80 event.SetCreateTime(GetCurrentTimeMillis());
81 event.SetEventTask(taskHandler_->SubmitTaskJust([wthis = weak_from_this(), event]() {
82 auto timeCost = GetCurrentTimeMillis() - event.GetCreateTime();
83 if (timeCost - event.GetTimeout() > EVENT_TIME_DIFF) {
84 TAG_LOGW(AAFwkTag::DEFAULT, "createtime: %{public}" PRId64 ", timeout: %{public}" PRId64,
85 event.GetCreateTime(), event.GetTimeout());
86 }
87 auto pthis = wthis.lock();
88 if (pthis) {
89 pthis->ProcessEvent(event);
90 pthis->RemoveEvent(event, false);
91 }
92 }, eventStr, delayMillis));
93
94 if (it != eventMap_.end()) {
95 it->second = event;
96 } else {
97 eventMap_.emplace(eventStr, event);
98 }
99
100 return true;
101 }
102
RemoveEvent(uint32_t eventId,int64_t param)103 bool EventHandlerWrap::RemoveEvent(uint32_t eventId, int64_t param)
104 {
105 return RemoveEvent(EventWrap(eventId, param));
106 }
107
RemoveEvent(uint32_t eventId,const std::string & taskName)108 bool EventHandlerWrap::RemoveEvent(uint32_t eventId, const std::string &taskName)
109 {
110 return RemoveEvent(EventWrap(eventId, taskName));
111 }
112
RemoveEvent(EventWrap event,bool force)113 bool EventHandlerWrap::RemoveEvent(EventWrap event, bool force)
114 {
115 std::lock_guard<ffrt::mutex> guard(*eventMutex_);
116 auto it = eventMap_.find(event.GetEventString());
117 if (it == eventMap_.end()) {
118 TAG_LOGW(AAFwkTag::DEFAULT, "can't find event: %{public}s ", event.GetEventString().c_str());
119 return false;
120 }
121 auto isSame = it->second.IsSame(event);
122 const auto &origin = it->second;
123 auto timeCost = GetCurrentTimeMillis() - origin.GetCreateTime();
124 if (force && timeCost > EVENT_TIME_CANCEL) {
125 TAG_LOGW(AAFwkTag::DEFAULT, "event: %{public}s, timecost: %{public}" PRId64", delay: %{public}" PRId64,
126 origin.GetEventString().c_str(), timeCost, origin.GetTimeout());
127 }
128 if (force || isSame) {
129 auto result = it->second.GetEventTask().Cancel();
130 if (!result) {
131 TAG_LOGE(AAFwkTag::DEFAULT, "remove fail: %{public}s", event.GetEventString().c_str());
132 }
133 eventMap_.erase(it);
134 return true;
135 }
136 TAG_LOGD(AAFwkTag::DEFAULT, "force: %{public}d , IsSame: %{public}d", force, isSame);
137 return false;
138 }
139 } // namespace AAFWK
140 } // namespace OHOS