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 "motion_event_napi.h"
17
18 #include "fi_log.h"
19
20 #undef LOG_TAG
21 #define LOG_TAG "DeviceMotionEvent"
22
23 namespace OHOS {
24 namespace Msdp {
MotionEventNapi(napi_env env,napi_value thisVar)25 MotionEventNapi::MotionEventNapi(napi_env env, napi_value thisVar)
26 {
27 env_ = env;
28 thisVarRef_ = nullptr;
29 napi_create_reference(env, thisVar, 1, &thisVarRef_);
30 }
31
~MotionEventNapi()32 MotionEventNapi::~MotionEventNapi()
33 {
34 events_.clear();
35 if (env_ != nullptr && thisVarRef_ != nullptr) {
36 napi_delete_reference(env_, thisVarRef_);
37 }
38 }
39
40 #ifdef MOTION_ENABLE
AddCallback(int32_t eventType,napi_value handler)41 bool MotionEventNapi::AddCallback(int32_t eventType, napi_value handler)
42 {
43 FI_HILOGD("Enter");
44 auto iter = events_.find(eventType);
45 if (iter == events_.end()) {
46 FI_HILOGD("found event:%{public}d", eventType);
47 std::shared_ptr<MotionEventListener> listener = std::make_shared<MotionEventListener>();
48 std::set<napi_ref> onRefSets;
49 listener->onRefSets = onRefSets;
50 napi_ref onHandlerRef = nullptr;
51 napi_status status = napi_create_reference(env_, handler, 1, &onHandlerRef);
52 if (status != napi_ok) {
53 FI_HILOGE("napi_create_reference failed");
54 return false;
55 }
56
57 auto ret = listener->onRefSets.insert(onHandlerRef);
58 if (!ret.second) {
59 FI_HILOGE("Failed to insert refs");
60 return false;
61 }
62
63 events_.insert(std::make_pair(eventType, listener));
64 FI_HILOGD("Insert finish");
65 return true;
66 }
67 FI_HILOGD("found event: %{public}d", eventType);
68 if (iter->second == nullptr) {
69 FI_HILOGE("listener is nullptr");
70 return false;
71 }
72 if (iter->second->onRefSets.empty()) {
73 FI_HILOGE("Refs is empty()");
74 return false;
75 }
76
77 FI_HILOGD("Check type: %{public}d same handle", eventType);
78 if (!InsertRef(iter->second, handler)) {
79 FI_HILOGE("Failed to insert ref");
80 return false;
81 }
82 return true;
83 }
84
RemoveAllCallback(int32_t eventType)85 bool MotionEventNapi::RemoveAllCallback(int32_t eventType)
86 {
87 FI_HILOGD("RemoveAllCallback in, event:%{public}d", eventType);
88 auto iter = events_.find(eventType);
89 if (iter == events_.end()) {
90 FI_HILOGE("EventType %{public}d not found", eventType);
91 return false;
92 }
93 if (iter->second == nullptr) {
94 FI_HILOGE("listener is nullptr");
95 return false;
96 }
97 if (iter->second->onRefSets.empty()) {
98 FI_HILOGE("onRefSets is empty");
99 return false;
100 }
101 for (auto it = iter->second->onRefSets.begin(); it != iter->second->onRefSets.end();) {
102 if (*it == nullptr) {
103 ++it;
104 continue;
105 }
106 napi_status status = napi_delete_reference(env_, *it);
107 if (status != napi_ok) {
108 FI_HILOGE("napi_delete_reference failed");
109 ++it;
110 continue;
111 }
112 it = iter->second->onRefSets.erase(it);
113 }
114 if (iter->second->onRefSets.empty()) {
115 FI_HILOGE("onRefSets is empty");
116 events_.erase(iter);
117 }
118 return true;
119 }
120
RemoveCallback(int32_t eventType,napi_value handler)121 bool MotionEventNapi::RemoveCallback(int32_t eventType, napi_value handler)
122 {
123 FI_HILOGD("RemoveCallback in, event:%{public}d", eventType);
124 auto iter = events_.find(eventType);
125 if (iter == events_.end()) {
126 FI_HILOGE("EventType %{public}d not found", eventType);
127 return false;
128 }
129 if (iter->second == nullptr) {
130 FI_HILOGE("listener is nullptr");
131 return false;
132 }
133 if (iter->second->onRefSets.empty()) {
134 FI_HILOGE("onRefSets is empty");
135 return false;
136 }
137 for (auto it = iter->second->onRefSets.begin(); it != iter->second->onRefSets.end();) {
138 if (*it == nullptr) {
139 ++it;
140 continue;
141 }
142 napi_value deleteHandler;
143 napi_status status = napi_get_reference_value(env_, *it, &deleteHandler);
144 if (status != napi_ok) {
145 FI_HILOGE("napi_get_reference_value failed");
146 ++it;
147 continue;
148 }
149 if (IsSameValue(env_, handler, deleteHandler)) {
150 status = napi_delete_reference(env_, *it);
151 if (status != napi_ok) {
152 FI_HILOGE("napi_delete_reference failed");
153 ++it;
154 continue;
155 }
156 iter->second->onRefSets.erase(it++);
157 break;
158 }
159 ++it;
160 }
161 if (iter->second->onRefSets.empty()) {
162 events_.erase(eventType);
163 }
164 return true;
165 }
166
InsertRef(std::shared_ptr<MotionEventListener> listener,const napi_value & handler)167 bool MotionEventNapi::InsertRef(std::shared_ptr<MotionEventListener> listener, const napi_value &handler)
168 {
169 if (listener == nullptr) {
170 FI_HILOGE("listener is nullptr");
171 return false;
172 }
173 bool hasHandler = false;
174 for (auto item : listener->onRefSets) {
175 napi_value onHandler = nullptr;
176 napi_status status = napi_get_reference_value(env_, item, &onHandler);
177 if (status != napi_ok) {
178 FI_HILOGE("napi_get_reference_value failed");
179 status = napi_delete_reference(env_, item);
180 if (status != napi_ok) {
181 FI_HILOGE("napi_delete_reference failed");
182 continue;
183 }
184 continue;
185 }
186 if (IsSameValue(env_, handler, onHandler)) {
187 hasHandler = true;
188 break;
189 }
190 }
191 if (hasHandler) {
192 FI_HILOGD("napi repeat subscribe");
193 return true;
194 }
195 napi_ref onHandlerRef = nullptr;
196 napi_status status = napi_create_reference(env_, handler, 1, &(onHandlerRef));
197 if (status != napi_ok) {
198 FI_HILOGE("napi_create_reference failed");
199 return false;
200 }
201
202 FI_HILOGD("Insert new ref");
203 auto ret = listener->onRefSets.insert(onHandlerRef);
204 if (!ret.second) {
205 FI_HILOGE("Failed to insert");
206 return false;
207 }
208 FI_HILOGD("ref size %{public}zu", listener->onRefSets.size());
209 return true;
210 }
211
OnEventOperatingHand(int32_t eventType,size_t argc,const MotionEvent & event)212 void MotionEventNapi::OnEventOperatingHand(int32_t eventType, size_t argc, const MotionEvent &event)
213 {
214 FI_HILOGD("eventType: %{public}d", eventType);
215 auto typeIter = events_.find(eventType);
216 if (typeIter == events_.end()) {
217 FI_HILOGE("eventType: %{public}d not found", eventType);
218 return;
219 }
220 for (auto item : typeIter->second->onRefSets) {
221 napi_value handler = nullptr;
222 napi_status ret = napi_get_reference_value(env_, item, &handler);
223 if (ret != napi_ok) {
224 FI_HILOGE("napi_get_reference_value for %{public}d failed, status: %{public}d", eventType, ret);
225 return;
226 }
227 ConvertOperatingHandData(handler, argc, event);
228 }
229 }
230
ConvertOperatingHandData(napi_value handler,size_t argc,const MotionEvent & event)231 void MotionEventNapi::ConvertOperatingHandData(napi_value handler, size_t argc, const MotionEvent &event)
232 {
233 napi_value result;
234 napi_status ret = napi_create_int32(env_, event.status, &result);
235 if (ret != napi_ok) {
236 FI_HILOGE("napi_create_int32 failed");
237 return;
238 }
239 napi_value callResult = nullptr;
240 ret = napi_call_function(env_, nullptr, handler, argc, &result, &callResult);
241 if (ret != napi_ok) {
242 FI_HILOGE("napi_call_function ret %{public}d", ret);
243 return;
244 }
245 }
246
CreateIntData(napi_env env,napi_value motionValue,napi_value result,std::string name,int32_t value)247 void MotionEventNapi::CreateIntData(napi_env env, napi_value motionValue, napi_value result, std::string name,
248 int32_t value)
249 {
250 napi_status ret = napi_create_int32(env, value, &motionValue);
251 if (ret != napi_ok) {
252 FI_HILOGE("napi_create_int32 failed");
253 return;
254 }
255
256 ret = napi_set_named_property(env, result, name.c_str(), motionValue);
257 if (ret != napi_ok) {
258 FI_HILOGE("napi_set_named_property failed");
259 return;
260 }
261 }
262
IsSameValue(const napi_env & env,const napi_value & lhs,const napi_value & rhs)263 bool MotionEventNapi::IsSameValue(const napi_env &env, const napi_value &lhs, const napi_value &rhs)
264 {
265 FI_HILOGD("Enter");
266 bool result = false;
267 napi_status status = napi_strict_equals(env, lhs, rhs, &result);
268 if (status != napi_ok) {
269 FI_HILOGE("napi_strict_equals failed");
270 return result;
271 }
272 return result;
273 }
274
CheckEvents(int32_t eventType)275 bool MotionEventNapi::CheckEvents(int32_t eventType)
276 {
277 FI_HILOGD("Enter");
278 auto typeIter = events_.find(eventType);
279 if (typeIter == events_.end()) {
280 FI_HILOGD("eventType not find");
281 return true;
282 }
283 if (typeIter->second->onRefSets.empty()) {
284 return true;
285 }
286 return false;
287 }
288 #endif
289 } // namespace Msdp
290 } // namespace OHOS
291