• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "devicestatus_event.h"
17 
18 #include <js_native_api.h>
19 #include <map>
20 #include <uv.h>
21 
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 
25 #include "devicestatus_define.h"
26 
27 namespace OHOS {
28 namespace Msdp {
29 namespace DeviceStatus {
30 namespace {
31 constexpr ::OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DeviceStatusEvent" };
32 constexpr size_t EVENT_MAP_MAX { 20 };
33 } // namespace
34 
DeviceStatusEvent(napi_env env)35 DeviceStatusEvent::DeviceStatusEvent(napi_env env)
36 {
37     env_ = env;
38 }
39 
~DeviceStatusEvent()40 DeviceStatusEvent::~DeviceStatusEvent()
41 {
42     eventOnceMap_.clear();
43     eventMap_.clear();
44 }
45 
On(int32_t eventType,napi_value handler,bool isOnce)46 bool DeviceStatusEvent::On(int32_t eventType, napi_value handler, bool isOnce)
47 {
48     FI_HILOGD("On for event:%{public}d, isOnce:%{public}d", eventType, isOnce);
49     if ((eventMap_.size() > EVENT_MAP_MAX) || (eventOnceMap_.size() > EVENT_MAP_MAX)) {
50         FI_HILOGE("EventMap_ or eventOnceMap_ size over");
51         return false;
52     }
53     napi_handle_scope scope = nullptr;
54     napi_open_handle_scope(env_, &scope);
55     CHKPF(scope);
56     napi_ref onHandlerRef = nullptr;
57     napi_status status = napi_ok;
58     if (isOnce) {
59         auto iter = eventOnceMap_.find(eventType);
60         if (iter == eventOnceMap_.end()) {
61             FI_HILOGD("EventType:%{public}d not exists", eventType);
62             eventOnceMap_[eventType] = std::list<std::shared_ptr<DeviceStatusEventListener>>();
63         }
64         status = napi_create_reference(env_, handler, 1, &onHandlerRef);
65         if (status != napi_ok) {
66             FI_HILOGE("Failed to create reference");
67             napi_close_handle_scope(env_, scope);
68             return false;
69         }
70         auto listener = std::make_shared<DeviceStatusEventListener>();
71         listener->onHandlerRef = onHandlerRef;
72         eventOnceMap_[eventType].push_back(listener);
73         FI_HILOGI("Add once handler to list %{public}d", eventType);
74     } else {
75         auto iter = eventMap_.find(eventType);
76         if (iter == eventMap_.end()) {
77             FI_HILOGD("EventType:%{public}d not exists", eventType);
78             eventMap_[eventType] = std::list<std::shared_ptr<DeviceStatusEventListener>>();
79         }
80         status = napi_create_reference(env_, handler, 1, &onHandlerRef);
81         if (status != napi_ok) {
82             FI_HILOGE("Failed to create reference");
83             napi_close_handle_scope(env_, scope);
84             return false;
85         }
86         auto listener = std::make_shared<DeviceStatusEventListener>();
87         listener->onHandlerRef = onHandlerRef;
88         eventMap_[eventType].push_back(listener);
89         FI_HILOGI("Add handler to list %{public}d", eventType);
90     }
91     napi_close_handle_scope(env_, scope);
92     return true;
93 }
94 
Off(int32_t eventType,napi_value handler)95 bool DeviceStatusEvent::Off(int32_t eventType, napi_value handler)
96 {
97     FI_HILOGD("DeviceStatusEvent off in for event:%{public}d", eventType);
98     auto iter = eventMap_.find(eventType);
99     if (iter == eventMap_.end()) {
100         FI_HILOGE("EventType %{public}d not found", eventType);
101         return false;
102     }
103     bool equal = false;
104     napi_value result = nullptr;
105 
106     for (auto listener : eventMap_[eventType]) {
107         napi_status status = napi_get_reference_value(env_, listener->onHandlerRef, &result);
108         if (status != napi_ok) {
109             FI_HILOGE("Failed to get_reference_value");
110             return false;
111         }
112         status = napi_strict_equals(env_, result, handler, &equal);
113         if (status != napi_ok) {
114             FI_HILOGE("Failed to strict_equals");
115             return false;
116         }
117         if (equal) {
118             FI_HILOGI("Delete handler from list %{public}d", eventType);
119             status = napi_delete_reference(env_, listener->onHandlerRef);
120             if (status != napi_ok) {
121                 FI_HILOGW("Delete failed");
122             }
123             eventMap_[eventType].remove(listener);
124             break;
125         }
126     }
127     FI_HILOGI("%{public}zu listeners in the list of %{public}d",
128         eventMap_[eventType].size(), eventType);
129     return eventMap_[eventType].empty();
130 }
131 
OffOnce(int32_t eventType,napi_value handler)132 bool DeviceStatusEvent::OffOnce(int32_t eventType, napi_value handler)
133 {
134     FI_HILOGD("DeviceStatusEvent OffOnce in for event:%{public}d", eventType);
135     auto iter = eventOnceMap_.find(eventType);
136     if (iter == eventOnceMap_.end()) {
137         FI_HILOGE("EventType %{public}d not found", eventType);
138         return false;
139     }
140     bool equal = false;
141     napi_value result = nullptr;
142     for (auto listener : eventOnceMap_[eventType]) {
143         napi_get_reference_value(env_, listener->onHandlerRef, &result);
144         napi_strict_equals(env_, result, handler, &equal);
145         if (equal) {
146             FI_HILOGI("Delete once handler from list %{public}d", eventType);
147             napi_status status = napi_delete_reference(env_, listener->onHandlerRef);
148             if (status != napi_ok) {
149                 FI_HILOGW("Delete failed");
150             }
151             eventOnceMap_[eventType].remove(listener);
152             break;
153         }
154     }
155     FI_HILOGI("%{public}zu listeners in the once list of %{public}d",
156         eventOnceMap_[eventType].size(), eventType);
157     return eventMap_[eventType].empty();
158 }
159 
RemoveAllCallback(int32_t eventType)160 bool DeviceStatusEvent::RemoveAllCallback(int32_t eventType)
161 {
162     CALL_DEBUG_ENTER;
163     auto iter = eventMap_.find(eventType);
164     if (iter == eventMap_.end()) {
165         FI_HILOGE("EvenType %{public}d not found", eventType);
166         return false;
167     }
168     eventMap_.erase(eventType);
169     return true;
170 }
171 
CheckRet(int32_t eventType,size_t argc,int32_t value,std::shared_ptr<DeviceStatusEventListener> & typeHandler)172 void DeviceStatusEvent::CheckRet(int32_t eventType, size_t argc, int32_t value,
173     std::shared_ptr<DeviceStatusEventListener> &typeHandler)
174 {
175     CHKPV(typeHandler);
176     napi_handle_scope scope = nullptr;
177     napi_open_handle_scope(env_, &scope);
178     CHKPV(scope);
179     napi_value handler = nullptr;
180     napi_status status = napi_ok;
181     status = napi_get_reference_value(env_, typeHandler->onHandlerRef, &handler);
182     if (status != napi_ok) {
183         FI_HILOGE("OnEvent handler for %{public}d failed, status:%{public}d", eventType, status);
184         napi_close_handle_scope(env_, scope);
185         return;
186     }
187     napi_value result = nullptr;
188     SendRet(eventType, value, result);
189     napi_value callResult = nullptr;
190     FI_HILOGD("Report to hap");
191     status = napi_call_function(env_, nullptr, handler, argc, &result, &callResult);
192     if (status != napi_ok) {
193         FI_HILOGE("CheckRet:napi_call_function for %{public}d failed, status:%{public}d", eventType, status);
194         napi_close_handle_scope(env_, scope);
195         return;
196     }
197     napi_close_handle_scope(env_, scope);
198 }
199 
SendRet(int32_t eventType,int32_t value,napi_value & result)200 void DeviceStatusEvent::SendRet(int32_t eventType, int32_t value, napi_value &result)
201 {
202     napi_status status = napi_create_object(env_, &result);
203     if (status != napi_ok) {
204         FI_HILOGE("Failed to create object");
205         return;
206     }
207     napi_value tmpValue = nullptr;
208     status = napi_create_int32(env_, eventType, &tmpValue);
209     if (status != napi_ok) {
210         FI_HILOGE("Failed to create object");
211         return;
212     }
213     status = napi_set_named_property(env_, result, "type", tmpValue);
214     if (status != napi_ok) {
215         FI_HILOGE("Failed to set name");
216         return;
217     }
218 
219     status = napi_create_int32(env_, value, &tmpValue);
220     if (status != napi_ok) {
221         FI_HILOGE("Failed to create value");
222         return;
223     }
224     status = napi_set_named_property(env_, result, "value", tmpValue);
225     if (status != napi_ok) {
226         FI_HILOGE("Failed to set_named");
227         return;
228     }
229 }
230 
OnEvent(int32_t eventType,size_t argc,int32_t value,bool isOnce)231 void DeviceStatusEvent::OnEvent(int32_t eventType, size_t argc, int32_t value, bool isOnce)
232 {
233     CALL_DEBUG_ENTER;
234     FI_HILOGD("OnEvent for %{public}d, isOnce:%{public}d", eventType, isOnce);
235     napi_handle_scope scope = nullptr;
236     napi_open_handle_scope(env_, &scope);
237     CHKPV(scope);
238     std::map<int32_t, std::list<std::shared_ptr<DeviceStatusEventListener>>>::iterator typeHandler;
239     if (isOnce) {
240         typeHandler = eventOnceMap_.find(eventType);
241         if (typeHandler == eventOnceMap_.end()) {
242             FI_HILOGE("OnEvent eventType %{public}d not found", eventType);
243             napi_close_handle_scope(env_, scope);
244             return;
245         }
246     } else {
247         typeHandler = eventMap_.find(eventType);
248         if (typeHandler == eventMap_.end()) {
249             FI_HILOGE("OnEvent:eventType %{public}d not found", eventType);
250             napi_close_handle_scope(env_, scope);
251             return;
252         }
253     }
254     FI_HILOGD("%{public}zu callbacks of eventType %{public}d are sent",
255         typeHandler->second.size(), eventType);
256     for (auto handler : typeHandler->second) {
257         CheckRet(eventType, argc, value, handler);
258     }
259     napi_close_handle_scope(env_, scope);
260 }
261 
ClearEventMap()262 void DeviceStatusEvent::ClearEventMap()
263 {
264     for (const auto &iter : eventMap_) {
265         for (const auto &eventListener : iter.second) {
266             napi_status status = napi_delete_reference(env_, eventListener->onHandlerRef);
267             if (status != napi_ok) {
268                 FI_HILOGW("Failed to delete reference");
269             }
270         }
271     }
272     for (const auto &iter : eventOnceMap_) {
273         for (const auto &eventListener : iter.second) {
274             napi_status status = napi_delete_reference(env_, eventListener->onHandlerRef);
275             if (status != napi_ok) {
276                 FI_HILOGW("Failed to delete reference");
277                 napi_delete_reference(env_, eventListener->onHandlerRef);
278             }
279         }
280     }
281     eventMap_.clear();
282     eventOnceMap_.clear();
283 }
284 } // namespace DeviceStatus
285 } // namespace Msdp
286 } // namespace OHOS
287