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
RemoveCallback(int32_t eventType)85 bool MotionEventNapi::RemoveCallback(int32_t eventType)
86 {
87 FI_HILOGD("Enter, 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
94 if (iter->second == nullptr) {
95 FI_HILOGE("listener is nullptr");
96 return false;
97 }
98
99 if (iter->second->onRefSets.empty()) {
100 FI_HILOGE("Refs is empty");
101 return false;
102 }
103
104 for (auto it = iter->second->onRefSets.begin(); it != iter->second->onRefSets.end();) {
105 if (*it == nullptr) {
106 ++it;
107 continue;
108 }
109 napi_status status = napi_delete_reference(env_, *it);
110 if (status != napi_ok) {
111 FI_HILOGE("napi_delete_reference failed");
112 ++it;
113 continue;
114 }
115 it = iter->second->onRefSets.erase(it);
116 }
117 if (iter->second->onRefSets.empty()) {
118 FI_HILOGE("onRefSets is empty");
119 events_.erase(iter);
120 }
121 return true;
122 }
123
InsertRef(std::shared_ptr<MotionEventListener> listener,const napi_value & handler)124 bool MotionEventNapi::InsertRef(std::shared_ptr<MotionEventListener> listener, const napi_value &handler)
125 {
126 if (listener == nullptr) {
127 FI_HILOGE("listener is nullptr");
128 return false;
129 }
130 for (auto item : listener->onRefSets) {
131 napi_value onHandler = nullptr;
132 napi_status status = napi_get_reference_value(env_, item, &onHandler);
133 if (status != napi_ok) {
134 FI_HILOGE("napi_get_reference_value failed");
135 status = napi_delete_reference(env_, item);
136 if (status != napi_ok) {
137 FI_HILOGE("napi_delete_reference failed");
138 continue;
139 }
140 continue;
141 }
142
143 if (IsSameValue(env_, handler, onHandler)) {
144 continue;
145 }
146
147 napi_ref onHandlerRef = nullptr;
148 status = napi_create_reference(env_, handler, 1, &(onHandlerRef));
149 if (status != napi_ok) {
150 FI_HILOGE("napi_create_reference failed");
151 return false;
152 }
153
154 FI_HILOGD("Insert new ref");
155 auto ret = listener->onRefSets.insert(onHandlerRef);
156 if (!ret.second) {
157 FI_HILOGE("Failed to insert");
158 return false;
159 }
160 }
161 FI_HILOGD("ref size %{public}zu", listener->onRefSets.size());
162 return true;
163 }
164
OnEventOperatingHand(int32_t eventType,size_t argc,const MotionEvent & event)165 void MotionEventNapi::OnEventOperatingHand(int32_t eventType, size_t argc, const MotionEvent &event)
166 {
167 FI_HILOGD("eventType: %{public}d", eventType);
168 auto typeIter = events_.find(eventType);
169 if (typeIter == events_.end()) {
170 FI_HILOGE("eventType: %{public}d not found", eventType);
171 return;
172 }
173 for (auto item : typeIter->second->onRefSets) {
174 napi_value handler = nullptr;
175 napi_status ret = napi_get_reference_value(env_, item, &handler);
176 if (ret != napi_ok) {
177 FI_HILOGE("napi_get_reference_value for %{public}d failed, status: %{public}d", eventType, ret);
178 return;
179 }
180 ConvertOperatingHandData(handler, argc, event);
181 }
182 }
183
ConvertOperatingHandData(napi_value handler,size_t argc,const MotionEvent & event)184 void MotionEventNapi::ConvertOperatingHandData(napi_value handler, size_t argc, const MotionEvent &event)
185 {
186 napi_value result;
187 napi_status ret = napi_create_int32(env_, event.status, &result);
188 if (ret != napi_ok) {
189 FI_HILOGE("napi_create_int32 failed");
190 return;
191 }
192 napi_value callResult = nullptr;
193 ret = napi_call_function(env_, nullptr, handler, argc, &result, &callResult);
194 if (ret != napi_ok) {
195 FI_HILOGE("napi_call_function ret %{public}d", ret);
196 return;
197 }
198 }
199
CreateIntData(napi_env env,napi_value motionValue,napi_value result,std::string name,int32_t value)200 void MotionEventNapi::CreateIntData(napi_env env, napi_value motionValue, napi_value result, std::string name,
201 int32_t value)
202 {
203 napi_status ret = napi_create_int32(env, value, &motionValue);
204 if (ret != napi_ok) {
205 FI_HILOGE("napi_create_int32 failed");
206 return;
207 }
208
209 ret = napi_set_named_property(env, result, name.c_str(), motionValue);
210 if (ret != napi_ok) {
211 FI_HILOGE("napi_set_named_property failed");
212 return;
213 }
214 }
215
IsSameValue(const napi_env & env,const napi_value & lhs,const napi_value & rhs)216 bool MotionEventNapi::IsSameValue(const napi_env &env, const napi_value &lhs, const napi_value &rhs)
217 {
218 FI_HILOGD("Enter");
219 bool result = false;
220 napi_status status = napi_strict_equals(env, lhs, rhs, &result);
221 if (status != napi_ok) {
222 FI_HILOGE("napi_strict_equals failed");
223 return result;
224 }
225 return result;
226 }
227
CheckEvents(int32_t eventType)228 bool MotionEventNapi::CheckEvents(int32_t eventType)
229 {
230 FI_HILOGD("Enter");
231 auto typeIter = events_.find(eventType);
232 if (typeIter == events_.end()) {
233 FI_HILOGD("eventType not find");
234 return true;
235 }
236 if (typeIter->second->onRefSets.empty()) {
237 return true;
238 }
239 return false;
240 }
241 #endif
242 } // namespace Msdp
243 } // namespace OHOS
244