• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 #include "napi_app_event_watcher.h"
16 
17 #include "app_event_observer_mgr.h"
18 #include "app_event_store.h"
19 #include "app_event_util.h"
20 #include "hiappevent_base.h"
21 #include "hilog/log.h"
22 #include "napi_env_watcher_manager.h"
23 #include "napi_util.h"
24 #include "uv.h"
25 
26 #undef LOG_DOMAIN
27 #define LOG_DOMAIN 0xD002D07
28 
29 #undef LOG_TAG
30 #define LOG_TAG "NapiWatcher"
31 
32 namespace OHOS {
33 namespace HiviewDFX {
34 namespace {
35 constexpr size_t CALLBACK_PARAM_NUM = 3;
36 constexpr size_t RECEIVE_PARAM_NUM = 2;
37 
DeleteEventMappingAsync(int64_t observerSeq,const std::vector<std::shared_ptr<AppEventPack>> & events)38 void DeleteEventMappingAsync(int64_t observerSeq, const std::vector<std::shared_ptr<AppEventPack>>& events)
39 {
40     std::vector<int64_t> eventSeqs;
41     for (const auto& event : events) {
42         eventSeqs.emplace_back(event->GetSeq());
43     }
44     AppEventObserverMgr::GetInstance().SubmitTaskToFFRTQueue([observerSeq, eventSeqs]() {
45         if (!AppEventStore::GetInstance().DeleteData(observerSeq, eventSeqs)) {
46             HILOG_ERROR(LOG_CORE, "failed to delete mapping data, seq=%{public}" PRId64 ", event num=%{public}zu",
47                 observerSeq, eventSeqs.size());
48         }
49         }, "appevent_del_map");
50 }
51 }
~OnTriggerContext()52 OnTriggerContext::~OnTriggerContext()
53 {
54     if (onTrigger != nullptr) {
55         napi_delete_reference(env, onTrigger);
56     }
57     if (holder != nullptr) {
58         napi_delete_reference(env, holder);
59     }
60 }
61 
~OnReceiveContext()62 OnReceiveContext::~OnReceiveContext()
63 {
64     if (onReceive != nullptr) {
65         napi_delete_reference(env, onReceive);
66     }
67 }
68 
NapiAppEventWatcher(const std::string & name,const std::vector<AppEventFilter> & filters,TriggerCondition cond)69 NapiAppEventWatcher::NapiAppEventWatcher(
70     const std::string& name,
71     const std::vector<AppEventFilter>& filters,
72     TriggerCondition cond)
73     : AppEventWatcher(name, filters, cond)
74 {}
75 
~NapiAppEventWatcher()76 NapiAppEventWatcher::~NapiAppEventWatcher()
77 {
78     HILOG_DEBUG(LOG_CORE, "start to destroy NapiAppEventWatcher object");
79     EnvWatcherManager::GetInstance().RemoveEnvWatcherRecord(this);
80     std::lock_guard<std::mutex> lockGuard(mutex_);
81     napi_env env = nullptr;
82     if (receiveContext_ != nullptr) {
83         env = receiveContext_->env;
84     } else if (triggerContext_ != nullptr) {
85         env = triggerContext_->env;
86     } else {
87         return;
88     }
89     auto task = [receiveContext = std::move(receiveContext_), triggerContext = std::move(triggerContext_)] () {
90         HILOG_DEBUG(LOG_CORE, "start to destroy OnTriggerContext or OnReceiveContext object");
91     };
92     if (napi_send_event(env, task, napi_eprio_high) != napi_status::napi_ok) {
93         HILOG_ERROR(LOG_CORE, "failed to SendEvent.");
94     }
95 }
96 
DeleteWatcherContext()97 void NapiAppEventWatcher::DeleteWatcherContext()
98 {
99     std::lock_guard<std::mutex> lockGuard(mutex_);
100     triggerContext_ = nullptr;
101     receiveContext_ = nullptr;
102 }
103 
InitHolder(const napi_env env,const napi_value holder)104 void NapiAppEventWatcher::InitHolder(const napi_env env, const napi_value holder)
105 {
106     std::lock_guard<std::mutex> lockGuard(mutex_);
107     if (triggerContext_ == nullptr) {
108         triggerContext_ = std::make_shared<OnTriggerContext>();
109     }
110     triggerContext_->env = env;
111     triggerContext_->holder = NapiUtil::CreateReference(env, holder);
112 }
113 
OnTrigger(const TriggerCondition & triggerCond)114 void NapiAppEventWatcher::OnTrigger(const TriggerCondition& triggerCond)
115 {
116     HILOG_DEBUG(LOG_CORE, "onTrigger start");
117     std::lock_guard<std::mutex> lockGuard(mutex_);
118     if (triggerContext_ == nullptr) {
119         HILOG_ERROR(LOG_CORE, "onTrigger context is null");
120         return;
121     }
122     auto onTriggerWork = [row = triggerCond.row, size = triggerCond.size, holder = triggerContext_->holder,
123         onTrigger = triggerContext_->onTrigger, env = triggerContext_->env] () {
124         napi_handle_scope scope = nullptr;
125         napi_open_handle_scope(env, &scope);
126         if (scope == nullptr) {
127             HILOG_ERROR(LOG_CORE, "failed to open handle scope");
128             return;
129         }
130         napi_value callback = NapiUtil::GetReferenceValue(env, onTrigger);
131         if (callback == nullptr) {
132             HILOG_ERROR(LOG_CORE, "failed to get callback from the context");
133             napi_close_handle_scope(env, scope);
134             return;
135         }
136         napi_value argv[CALLBACK_PARAM_NUM] = {
137             NapiUtil::CreateInt32(env, row),
138             NapiUtil::CreateInt32(env, size),
139             NapiUtil::GetReferenceValue(env, holder)
140         };
141         napi_value ret = nullptr;
142         if (napi_call_function(env, nullptr, callback, CALLBACK_PARAM_NUM, argv, &ret) != napi_ok) {
143             HILOG_ERROR(LOG_CORE, "failed to call onTrigger function");
144         }
145         napi_close_handle_scope(env, scope);
146     };
147     if (napi_send_event(triggerContext_->env, onTriggerWork, napi_eprio_high) != napi_status::napi_ok) {
148         HILOG_ERROR(LOG_CORE, "failed to SendEvent.");
149     }
150 }
151 
InitTrigger(const napi_env env,const napi_value triggerFunc)152 void NapiAppEventWatcher::InitTrigger(const napi_env env, const napi_value triggerFunc)
153 {
154     HILOG_DEBUG(LOG_CORE, "start to init OnTrigger");
155     std::lock_guard<std::mutex> lockGuard(mutex_);
156     if (triggerContext_ == nullptr) {
157         triggerContext_ = std::make_shared<OnTriggerContext>();
158     }
159     triggerContext_->env = env;
160     triggerContext_->onTrigger = NapiUtil::CreateReference(env, triggerFunc);
161 }
162 
InitReceiver(const napi_env env,const napi_value receiveFunc)163 void NapiAppEventWatcher::InitReceiver(const napi_env env, const napi_value receiveFunc)
164 {
165     HILOG_DEBUG(LOG_CORE, "start to init onReceive");
166     std::lock_guard<std::mutex> lockGuard(mutex_);
167     if (receiveContext_ == nullptr) {
168         receiveContext_ = std::make_shared<OnReceiveContext>();
169     }
170     receiveContext_->env = env;
171     receiveContext_->onReceive = NapiUtil::CreateReference(env, receiveFunc);
172 }
173 
OnEvents(const std::vector<std::shared_ptr<AppEventPack>> & events)174 void NapiAppEventWatcher::OnEvents(const std::vector<std::shared_ptr<AppEventPack>>& events)
175 {
176     HILOG_DEBUG(LOG_CORE, "onEvents start, seq=%{public}" PRId64 ", event num=%{public}zu", GetSeq(), events.size());
177     std::lock_guard<std::mutex> lockGuard(mutex_);
178     if (receiveContext_ == nullptr || events.empty()) {
179         HILOG_ERROR(LOG_CORE, "onReceive context is null or events is empty");
180         return;
181     }
182     auto domain = events[0]->GetDomain();
183     auto observerSeq = GetSeq();
184     std::string watcherName = GetName();
185     auto onReceiveWork = [watcherName, events, domain, observerSeq, onReceive = receiveContext_->onReceive,
186         env = receiveContext_->env] () {
187         napi_handle_scope scope = nullptr;
188         napi_open_handle_scope(env, &scope);
189         if (scope == nullptr) {
190             HILOG_ERROR(LOG_CORE, "failed to open handle scope");
191             return;
192         }
193         napi_value callback = NapiUtil::GetReferenceValue(env, onReceive);
194         if (callback == nullptr) {
195             HILOG_ERROR(LOG_CORE, "failed to get callback from the context");
196             napi_close_handle_scope(env, scope);
197             return;
198         }
199         napi_value argv[RECEIVE_PARAM_NUM] = {
200             NapiUtil::CreateString(env, domain),
201             NapiUtil::CreateEventGroups(env, events)
202         };
203         napi_value ret = nullptr;
204         if (napi_call_function(env, nullptr, callback, RECEIVE_PARAM_NUM, argv, &ret) == napi_ok) {
205             AppEventUtil::ReportAppEventReceive(events, watcherName, "onReceive");
206             DeleteEventMappingAsync(observerSeq, events);
207         } else {
208             HILOG_ERROR(LOG_CORE, "failed to call onReceive function");
209         }
210         napi_close_handle_scope(env, scope);
211     };
212     if (napi_send_event(receiveContext_->env, onReceiveWork, napi_eprio_high) != napi_status::napi_ok) {
213         HILOG_ERROR(LOG_CORE, "failed to SendEvent.");
214     }
215 }
216 
IsRealTimeEvent(std::shared_ptr<AppEventPack> event)217 bool NapiAppEventWatcher::IsRealTimeEvent(std::shared_ptr<AppEventPack> event)
218 {
219     std::lock_guard<std::mutex> lockGuard(mutex_);
220     return (receiveContext_ != nullptr);
221 }
222 } // namespace HiviewDFX
223 } // namespace OHOS
224