1 /*
2 * Copyright (c) 2022 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 "js_util.h"
17
18 #include <unordered_map>
19
20 #include <linux/input.h>
21
22 #include "mmi_log.h"
23 #include "napi_constants.h"
24 #include "util_napi.h"
25 #include "util_napi_error.h"
26
27 #undef MMI_LOG_TAG
28 #define MMI_LOG_TAG "JsUtil"
29
30 namespace OHOS {
31 namespace MMI {
32 namespace {
33 std::unordered_map<int32_t, std::string> axisType = {
34 { ABS_MT_TOUCH_MAJOR, "touchmajor" },
35 { ABS_MT_TOUCH_MINOR, "touchminor" },
36 { ABS_MT_ORIENTATION, "orientation" },
37 { ABS_MT_POSITION_X, "x" },
38 { ABS_MT_POSITION_Y, "y" },
39 { ABS_MT_PRESSURE, "pressure" },
40 { ABS_MT_WIDTH_MAJOR, "toolmajor" },
41 { ABS_MT_WIDTH_MINOR, "toolminor" },
42 };
43
44 constexpr uint32_t EVDEV_UDEV_TAG_TOUCHSCREEN = (1 << 4);
45 constexpr uint32_t EVDEV_UDEV_TAG_JOYSTICK = (1 << 6);
46 constexpr uint32_t EVDEV_UDEV_TAG_TRACKBALL = (1 << 10);
47
48 JsUtil::DeviceType g_deviceType[] = {
49 { "keyboard", EVDEV_UDEV_TAG_KEYBOARD },
50 { "mouse", EVDEV_UDEV_TAG_MOUSE },
51 { "touchpad", EVDEV_UDEV_TAG_TOUCHPAD },
52 { "touchscreen", EVDEV_UDEV_TAG_TOUCHSCREEN },
53 { "joystick", EVDEV_UDEV_TAG_JOYSTICK },
54 { "trackball", EVDEV_UDEV_TAG_TRACKBALL },
55 };
56 } // namespace
IsSameHandle(napi_env env, napi_value handle, napi_ref ref)57 bool JsUtil::IsSameHandle(napi_env env, napi_value handle, napi_ref ref)
58 {
59 napi_handle_scope scope = nullptr;
60 napi_open_handle_scope(env, &scope);
61 napi_value handlerTemp = nullptr;
62 if (napi_get_reference_value(env, ref, &handlerTemp) != napi_ok) {
63 MMI_HILOGE("%{public}s failed", std::string(GET_REFERENCE_VALUE).c_str());
64 napi_close_handle_scope(env, scope);
65 return false;
66 }
67 bool isEqual = false;
68 if (napi_strict_equals(env, handle, handlerTemp, &isEqual) != napi_ok) {
69 MMI_HILOGE("%{public}s failed", std::string(STRICT_EQUALS).c_str());
70 napi_close_handle_scope(env, scope);
71 return false;
72 }
73 napi_close_handle_scope(env, scope);
74 return isEqual;
75 }
76
GetDeviceInfo(sptr<CallbackInfo> cb)77 napi_value JsUtil::GetDeviceInfo(sptr<CallbackInfo> cb)
78 {
79 CHKPP(cb);
80 CHKPP(cb->env);
81 CHKPP(cb->data.device);
82 napi_value object = nullptr;
83 CHKRP(napi_create_object(cb->env, &object), CREATE_OBJECT);
84 napi_value id = nullptr;
85 CHKRP(napi_create_int32(cb->env, cb->data.device->GetId(), &id), CREATE_INT32);
86 napi_value name = nullptr;
87 CHKRP(napi_create_string_utf8(cb->env, (cb->data.device->GetName()).c_str(),
88 NAPI_AUTO_LENGTH, &name), CREATE_STRING_UTF8);
89 CHKRP(napi_set_named_property(cb->env, object, "id", id), SET_NAMED_PROPERTY);
90 CHKRP(napi_set_named_property(cb->env, object, "name", name), SET_NAMED_PROPERTY);
91 napi_value busType = nullptr;
92 CHKRP(napi_create_int32(cb->env, cb->data.device->GetBus(), &busType), CREATE_INT32);
93 CHKRP(napi_set_named_property(cb->env, object, "bus", busType), SET_NAMED_PROPERTY);
94 napi_value product = nullptr;
95 CHKRP(napi_create_int32(cb->env, cb->data.device->GetProduct(), &product), CREATE_INT32);
96 CHKRP(napi_set_named_property(cb->env, object, "product", product), SET_NAMED_PROPERTY);
97 napi_value vendor = nullptr;
98 CHKRP(napi_create_int32(cb->env, cb->data.device->GetVendor(), &vendor), CREATE_INT32);
99 CHKRP(napi_set_named_property(cb->env, object, "vendor", vendor), SET_NAMED_PROPERTY);
100 napi_value version = nullptr;
101 CHKRP(napi_create_int32(cb->env, cb->data.device->GetVersion(), &version), CREATE_INT32);
102 CHKRP(napi_set_named_property(cb->env, object, "version", version), SET_NAMED_PROPERTY);
103 napi_value uniq = nullptr;
104 CHKRP(napi_create_string_utf8(cb->env, (cb->data.device->GetUniq()).c_str(),
105 NAPI_AUTO_LENGTH, &uniq), CREATE_STRING_UTF8);
106 CHKRP(napi_set_named_property(cb->env, object, "uniq", uniq), SET_NAMED_PROPERTY);
107 napi_value phys = nullptr;
108 CHKRP(napi_create_string_utf8(cb->env, (cb->data.device->GetPhys()).c_str(),
109 NAPI_AUTO_LENGTH, &phys), CREATE_STRING_UTF8);
110 CHKRP(napi_set_named_property(cb->env, object, "phys", phys), SET_NAMED_PROPERTY);
111
112 if (!GetDeviceSourceType(cb, object)) {
113 MMI_HILOGE("Get device source type failed");
114 return nullptr;
115 }
116 if (!GetDeviceAxisInfo(cb, object)) {
117 MMI_HILOGE("Get device axis failed");
118 return nullptr;
119 }
120 return object;
121 }
122
GetDeviceAxisInfo(sptr<CallbackInfo> cb, napi_value &object)123 bool JsUtil::GetDeviceAxisInfo(sptr<CallbackInfo> cb, napi_value &object)
124 {
125 CHKPF(cb);
126 CHKPF(cb->env);
127 CHKPF(cb->data.device);
128 napi_value sourceType = nullptr;
129 uint32_t types = static_cast<uint32_t>(cb->data.device->GetType());
130 for (const auto &item : g_deviceType) {
131 if (types &item.typeBit) {
132 CHKRF(napi_create_string_utf8(cb->env, item.sourceTypeName.c_str(),
133 NAPI_AUTO_LENGTH, &sourceType), CREATE_STRING_UTF8);
134 break;
135 }
136 }
137 napi_value axisRanges = nullptr;
138 CHKRF(napi_create_array(cb->env, &axisRanges), CREATE_ARRAY);
139 if (sourceType == nullptr) {
140 CHKRF(napi_set_named_property(cb->env, object, "axisRanges", axisRanges), SET_NAMED_PROPERTY);
141 MMI_HILOGD("SourceType not found");
142 return true;
143 }
144 napi_value axisRange = nullptr;
145 uint32_t i = 0;
146 for (const auto &item : cb->data.device->GetAxisInfo()) {
147 auto iter = axisType.find(item.GetAxisType());
148 if (iter == axisType.end()) {
149 MMI_HILOGD("Find axisType failed");
150 continue;
151 }
152 CHKRF(napi_create_object(cb->env, &axisRange), CREATE_OBJECT);
153 CHKRF(napi_set_named_property(cb->env, axisRange, "source", sourceType), SET_NAMED_PROPERTY);
154 napi_value axisType = nullptr;
155 CHKRF(napi_create_string_utf8(cb->env, iter->second.c_str(),
156 NAPI_AUTO_LENGTH, &axisType), CREATE_STRING_UTF8);
157 CHKRF(napi_set_named_property(cb->env, axisRange, "axis", axisType), SET_NAMED_PROPERTY);
158 napi_value min = nullptr;
159 CHKRF(napi_create_int32(cb->env, item.GetMinimum(), &min), CREATE_INT32);
160 CHKRF(napi_set_named_property(cb->env, axisRange, "min", min), SET_NAMED_PROPERTY);
161 napi_value max = nullptr;
162 CHKRF(napi_create_int32(cb->env, item.GetMaximum(), &max), CREATE_INT32);
163 CHKRF(napi_set_named_property(cb->env, axisRange, "max", max), SET_NAMED_PROPERTY);
164 napi_value fuzz = nullptr;
165 CHKRF(napi_create_int32(cb->env, item.GetFuzz(), &fuzz), CREATE_INT32);
166 CHKRF(napi_set_named_property(cb->env, axisRange, "fuzz", fuzz), SET_NAMED_PROPERTY);
167 napi_value flat = nullptr;
168 CHKRF(napi_create_int32(cb->env, item.GetFlat(), &flat), CREATE_INT32);
169 CHKRF(napi_set_named_property(cb->env, axisRange, "flat", flat), SET_NAMED_PROPERTY);
170 napi_value resolution = nullptr;
171 CHKRF(napi_create_int32(cb->env, item.GetResolution(), &resolution), CREATE_INT32);
172 CHKRF(napi_set_named_property(cb->env, axisRange, "resolution", resolution), SET_NAMED_PROPERTY);
173 CHKRF(napi_set_element(cb->env, axisRanges, i, axisRange), SET_ELEMENT);
174 ++i;
175 }
176 CHKRF(napi_set_named_property(cb->env, object, "axisRanges", axisRanges), SET_NAMED_PROPERTY);
177 return true;
178 }
179
GetDeviceSourceType(sptr<CallbackInfo> cb, napi_value &object)180 bool JsUtil::GetDeviceSourceType(sptr<CallbackInfo> cb, napi_value &object)
181 {
182 CHKPF(cb);
183 CHKPF(cb->env);
184 CHKPF(cb->data.device);
185 uint32_t types = static_cast<uint32_t>(cb->data.device->GetType());
186 std::vector<std::string> sources;
187 for (const auto &item : g_deviceType) {
188 if (types &item.typeBit) {
189 sources.push_back(item.sourceTypeName);
190 }
191 }
192 napi_value devSources = nullptr;
193 CHKRF(napi_create_array(cb->env, &devSources), CREATE_ARRAY);
194 napi_value value = nullptr;
195 for (size_t i = 0; i < sources.size(); ++i) {
196 CHKRF(napi_create_string_utf8(cb->env, sources[i].c_str(), NAPI_AUTO_LENGTH, &value),
197 CREATE_STRING_UTF8);
198 CHKRF(napi_set_element(cb->env, devSources, i, value), SET_ELEMENT);
199 }
200 CHKRF(napi_set_named_property(cb->env, object, "sources", devSources), SET_NAMED_PROPERTY);
201 return true;
202 }
203
TypeOf(napi_env env, napi_value value, napi_valuetype type)204 bool JsUtil::TypeOf(napi_env env, napi_value value, napi_valuetype type)
205 {
206 napi_valuetype valueType = napi_undefined;
207 CHKRF(napi_typeof(env, value, &valueType), TYPEOF);
208 if (valueType != type) {
209 return false;
210 }
211 return true;
212 }
213
DeleteCallbackInfo(std::unique_ptr<CallbackInfo> callback)214 void JsUtil::DeleteCallbackInfo(std::unique_ptr<CallbackInfo> callback)
215 {
216 CALL_DEBUG_ENTER;
217 if (callback->ref != nullptr && callback->env != nullptr) {
218 CHKRV(napi_delete_reference(callback->env, callback->ref), DELETE_REFERENCE);
219 callback->env = nullptr;
220 }
221 }
222
CheckType(napi_env env, napi_value value, napi_valuetype type)223 bool JsUtil::CheckType(napi_env env, napi_value value, napi_valuetype type)
224 {
225 napi_valuetype valuetype = napi_undefined;
226 napi_typeof(env, value, &valuetype);
227 return valuetype == type;
228 }
229
ParseDouble(napi_env env, napi_value value, double& result)230 bool JsUtil::ParseDouble(napi_env env, napi_value value, double& result)
231 {
232 if (!CheckType(env, value, napi_number)) {
233 MMI_HILOGE("ParseDouble type not number");
234 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "parameter", "number");
235 return false;
236 }
237 if (napi_get_value_double(env, value, &result) != napi_ok) {
238 MMI_HILOGE("ParseDouble cannot get value double");
239 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "parameter", "double");
240 return false;
241 }
242 return true;
243 }
244
IsArray(napi_env env, napi_value value)245 bool JsUtil::IsArray(napi_env env, napi_value value)
246 {
247 bool isArray = false;
248 if (napi_is_array(env, value, &isArray) != napi_ok) {
249 MMI_HILOGE("napi_is_array failed");
250 return false;
251 }
252 return isArray;
253 }
254
ParseInt32(napi_env env, napi_value value, int32_t& result)255 bool JsUtil::ParseInt32(napi_env env, napi_value value, int32_t& result)
256 {
257 if (!CheckType(env, value, napi_number)) {
258 MMI_HILOGE("ParseInt32 type not number");
259 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element", "number");
260 return false;
261 }
262 if (napi_get_value_int32(env, value, &result) != napi_ok) {
263 MMI_HILOGE("ParseInt32 cannot get value int32_t");
264 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element", "int32_t");
265 return false;
266 }
267 return true;
268 }
269
ParseString(napi_env env, napi_value value, char* result)270 bool JsUtil::ParseString(napi_env env, napi_value value, char* result)
271 {
272 if (!CheckType(env, value, napi_string)) {
273 MMI_HILOGE("ParseString type not string");
274 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element", "string");
275 return false;
276 }
277
278 size_t len = 0;
279 if (napi_get_value_string_utf8(env, value, result, MAX_STRING_LEN - 1, &len) != napi_ok) {
280 MMI_HILOGE("ParseString cannot get value string");
281 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element", "char[]");
282 return false;
283 }
284 return true;
285 }
286
ParseBool(napi_env env, napi_value value, bool& result)287 bool JsUtil::ParseBool(napi_env env, napi_value value, bool& result)
288 {
289 if (!CheckType(env, value, napi_boolean)) {
290 MMI_HILOGE("ParseBool type not boolean");
291 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element", "boolean");
292 return false;
293 }
294 if (napi_get_value_bool(env, value, &result) != napi_ok) {
295 MMI_HILOGE("ParseBool cannot get value bool");
296 THROWERR_API9(env, COMMON_PARAMETER_ERROR, "element", "bool");
297 return false;
298 }
299 return true;
300 }
301
GetNapiInt32(napi_env env, int32_t code)302 napi_value JsUtil::GetNapiInt32(napi_env env, int32_t code)
303 {
304 CALL_DEBUG_ENTER;
305 napi_value ret = nullptr;
306 CHKRP(napi_create_int32(env, code, &ret), CREATE_INT32);
307 return ret;
308 }
309 } // namespace MMI
310 } // namespace OHOS