• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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_input_device_context.h"
17 #include "mmi_log.h"
18 #include "napi_constants.h"
19 #include "util_napi_error.h"
20 
21 namespace OHOS {
22 namespace MMI {
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "JsInputDeviceContext" };
25 
26 enum KeyboardType {
27     NONE = 0,
28     UNKNOWN = 1,
29     ALPHABETIC_KEYBOARD = 2,
30     DIGITAL_KEYBOARD = 3,
31     HANDWRITING_PEN = 4,
32     REMOTE_CONTROL = 5,
33 };
34 } // namespace
35 
JsInputDeviceContext()36 JsInputDeviceContext::JsInputDeviceContext()
37 {
38     mgr_ = std::make_shared<JsInputDeviceManager>();
39 }
40 
~JsInputDeviceContext()41 JsInputDeviceContext::~JsInputDeviceContext()
42 {
43     std::lock_guard<std::mutex> guard(mtx_);
44     auto jsInputDeviceMgr = mgr_;
45     mgr_.reset();
46     if (jsInputDeviceMgr) {
47         jsInputDeviceMgr->ResetEnv();
48     }
49 }
50 
CreateInstance(napi_env env)51 napi_value JsInputDeviceContext::CreateInstance(napi_env env)
52 {
53     CALL_DEBUG_ENTER;
54     napi_value global = nullptr;
55     CHKRP(env, napi_get_global(env, &global), GET_GLOBAL);
56 
57     constexpr char className[] = "JsInputDeviceContext";
58     napi_value jsClass = nullptr;
59     napi_property_descriptor desc[] = {};
60     napi_status status = napi_define_class(env, className, sizeof(className), JsInputDeviceContext::JsConstructor,
61                                            nullptr, sizeof(desc) / sizeof(desc[0]), nullptr, &jsClass);
62     CHKRP(env, status, DEFINE_CLASS);
63 
64     status = napi_set_named_property(env, global, "multimodalinput_input_device_class", jsClass);
65     CHKRP(env, status, SET_NAMED_PROPERTY);
66 
67     napi_value jsInstance = nullptr;
68     CHKRP(env, napi_new_instance(env, jsClass, 0, nullptr, &jsInstance), NEW_INSTANCE);
69     CHKRP(env, napi_set_named_property(env, global, "multimodal_input_device", jsInstance), SET_NAMED_PROPERTY);
70 
71     JsInputDeviceContext *jsContext = nullptr;
72     CHKRP(env, napi_unwrap(env, jsInstance, (void**)&jsContext), UNWRAP);
73     CHKPP(jsContext);
74     CHKRP(env, napi_create_reference(env, jsInstance, 1, &(jsContext->contextRef_)), CREATE_REFERENCE);
75 
76     uint32_t refCount = 0;
77     CHKRP(env, napi_reference_ref(env, jsContext->contextRef_, &refCount), REFERENCE_REF);
78     return jsInstance;
79 }
80 
JsConstructor(napi_env env,napi_callback_info info)81 napi_value JsInputDeviceContext::JsConstructor(napi_env env, napi_callback_info info)
82 {
83     CALL_DEBUG_ENTER;
84     napi_value thisVar = nullptr;
85     void *data = nullptr;
86     CHKRP(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data), GET_CB_INFO);
87 
88     JsInputDeviceContext *jsContext = new (std::nothrow) JsInputDeviceContext();
89     CHKPP(jsContext);
90     napi_status status = napi_wrap(env, thisVar, jsContext, [](napi_env env, void* data, void* hin) {
91         MMI_HILOGI("jsvm ends");
92         JsInputDeviceContext *context = static_cast<JsInputDeviceContext*>(data);
93         delete context;
94     }, nullptr, nullptr);
95     if (status != napi_ok) {
96         delete jsContext;
97         MMI_HILOGE("Failed to wrap native instance");
98         return nullptr;
99     }
100     return thisVar;
101 }
102 
GetInstance(napi_env env)103 JsInputDeviceContext* JsInputDeviceContext::GetInstance(napi_env env)
104 {
105     CALL_DEBUG_ENTER;
106     napi_value global = nullptr;
107     CHKRP(env, napi_get_global(env, &global), GET_GLOBAL);
108 
109     bool result = false;
110     CHKRP(env, napi_has_named_property(env, global, "multimodal_input_device", &result), HAS_NAMED_PROPERTY);
111     if (!result) {
112         MMI_HILOGE("multimodal_input_device was not found");
113         return nullptr;
114     }
115 
116     napi_value object = nullptr;
117     CHKRP(env, napi_get_named_property(env, global, "multimodal_input_device", &object), GET_NAMED_PROPERTY);
118     if (object == nullptr) {
119         MMI_HILOGE("object is nullptr");
120         return nullptr;
121     }
122 
123     JsInputDeviceContext *instance = nullptr;
124     CHKRP(env, napi_unwrap(env, object, (void**)&instance), UNWRAP);
125     if (instance == nullptr) {
126         MMI_HILOGE("instance is nullptr");
127         return nullptr;
128     }
129     return instance;
130 }
131 
GetJsInputDeviceMgr() const132 std::shared_ptr<JsInputDeviceManager> JsInputDeviceContext::GetJsInputDeviceMgr() const
133 {
134     return mgr_;
135 }
136 
On(napi_env env,napi_callback_info info)137 napi_value JsInputDeviceContext::On(napi_env env, napi_callback_info info)
138 {
139     CALL_DEBUG_ENTER;
140     size_t argc = 2;
141     napi_value argv[2];
142     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
143     if (argc == 0) {
144         MMI_HILOGE("Require two parameters");
145         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Parameter count error");
146         return nullptr;
147     }
148     if (!JsUtil::TypeOf(env, argv[0], napi_string)) {
149         MMI_HILOGE("First parameter type error");
150         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
151         return nullptr;
152     }
153 
154     char eventType[MAX_STRING_LEN] = {0};
155     size_t ret = 0;
156     CHKRP(env, napi_get_value_string_utf8(env, argv[0], eventType, MAX_STRING_LEN - 1, &ret), GET_STRING_UTF8);
157     std::string type = eventType;
158     if (type != CHANGED_TYPE) {
159         MMI_HILOGE("Type is not change");
160         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "type must be change");
161         return nullptr;
162     }
163     if (!JsUtil::TypeOf(env, argv[1], napi_function)) {
164         MMI_HILOGE("Second parameter type error");
165         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "listener", "function");
166         return nullptr;
167     }
168 
169     JsInputDeviceContext *jsIds = JsInputDeviceContext::GetInstance(env);
170     CHKPP(jsIds);
171     auto jsInputDeviceMgr = jsIds->GetJsInputDeviceMgr();
172     jsInputDeviceMgr->RegisterDevListener(env, type, argv[1]);
173     return nullptr;
174 }
175 
Off(napi_env env,napi_callback_info info)176 napi_value JsInputDeviceContext::Off(napi_env env, napi_callback_info info)
177 {
178     CALL_DEBUG_ENTER;
179     size_t argc = 2;
180     napi_value argv[2];
181     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
182     if (argc == 0) {
183         MMI_HILOGE("Require two parameters");
184         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Parameter count error");
185         return nullptr;
186     }
187     if (!JsUtil::TypeOf(env, argv[0], napi_string)) {
188         MMI_HILOGE("First parameter type error");
189         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
190         return nullptr;
191     }
192 
193     char eventType[MAX_STRING_LEN] = {0};
194     size_t ret = 0;
195     CHKRP(env, napi_get_value_string_utf8(env, argv[0], eventType, MAX_STRING_LEN - 1, &ret), GET_STRING_UTF8);
196     std::string type = eventType;
197     if (type != CHANGED_TYPE) {
198         MMI_HILOGE("Type is not change");
199         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "type must be change");
200         return nullptr;
201     }
202 
203     JsInputDeviceContext *jsIds = JsInputDeviceContext::GetInstance(env);
204     CHKPP(jsIds);
205     auto jsInputDeviceMgr = jsIds->GetJsInputDeviceMgr();
206     if (argc == 1) {
207         jsInputDeviceMgr->UnregisterDevListener(env, type);
208         return nullptr;
209     }
210     if (!JsUtil::TypeOf(env, argv[1], napi_function)) {
211         MMI_HILOGE("Second parameter type error");
212         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "listener", "function");
213         return nullptr;
214     }
215     jsInputDeviceMgr->UnregisterDevListener(env, type, argv[1]);
216     return nullptr;
217 }
218 
GetDeviceIds(napi_env env,napi_callback_info info)219 napi_value JsInputDeviceContext::GetDeviceIds(napi_env env, napi_callback_info info)
220 {
221     CALL_DEBUG_ENTER;
222     size_t argc = 1;
223     napi_value argv[1];
224     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
225     if (argc > 1) {
226         THROWERR(env, "too many parameters");
227         return nullptr;
228     }
229 
230     JsInputDeviceContext *jsIds = JsInputDeviceContext::GetInstance(env);
231     CHKPP(jsIds);
232     auto jsInputDeviceMgr = jsIds->GetJsInputDeviceMgr();
233     if (argc == 0) {
234         return jsInputDeviceMgr->GetDeviceIds(env);
235     }
236     if (!JsUtil::TypeOf(env, argv[0], napi_function)) {
237         THROWERR(env, "The first parameter type is wrong");
238         return nullptr;
239     }
240     return jsInputDeviceMgr->GetDeviceIds(env, argv[0]);
241 }
242 
GetDevice(napi_env env,napi_callback_info info)243 napi_value JsInputDeviceContext::GetDevice(napi_env env, napi_callback_info info)
244 {
245     CALL_DEBUG_ENTER;
246     size_t argc = 2;
247     napi_value argv[2];
248     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
249     if (argc < 1 || argc > 2) {
250         THROWERR(env, "the number of parameters is not as expected");
251         return nullptr;
252     }
253     if (!JsUtil::TypeOf(env, argv[0], napi_number)) {
254         THROWERR(env, "The first parameter type is wrong");
255         return nullptr;
256     }
257     int32_t id = 0;
258     CHKRP(env, napi_get_value_int32(env, argv[0], &id), GET_INT32);
259     JsInputDeviceContext *jsDev = JsInputDeviceContext::GetInstance(env);
260     CHKPP(jsDev);
261     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceMgr();
262     if (argc == 1) {
263         return jsInputDeviceMgr->GetDevice(env, id);
264     }
265     if (!JsUtil::TypeOf(env, argv[1], napi_function)) {
266         THROWERR(env, "The second parameter type is wrong");
267         return nullptr;
268     }
269     return jsInputDeviceMgr->GetDevice(env, id, argv[1]);
270 }
271 
SupportKeys(napi_env env,napi_callback_info info)272 napi_value JsInputDeviceContext::SupportKeys(napi_env env, napi_callback_info info)
273 {
274     CALL_DEBUG_ENTER;
275     size_t argc = 3;
276     napi_value argv[3];
277     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
278     if (argc < 2) {
279         MMI_HILOGE("Require three parameters");
280         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Parameter count error");
281         return nullptr;
282     }
283 
284     if (!JsUtil::TypeOf(env, argv[0], napi_number)) {
285         MMI_HILOGE("First parameter type error");
286         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "deviceId", "number");
287         return nullptr;
288     }
289     int32_t deviceId = 0;
290     CHKRP(env, napi_get_value_int32(env, argv[0], &deviceId), GET_INT32);
291 
292     if (!JsUtil::TypeOf(env, argv[1], napi_object)) {
293         MMI_HILOGE("Second parameter type error");
294         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "keys", "array");
295         return nullptr;
296     }
297     uint32_t size = 0;
298     CHKRP(env, napi_get_array_length(env, argv[1], &size), GET_ARRAY_LENGTH);
299     static constexpr uint32_t minSupportKeys = 1;
300     static constexpr uint32_t maxSupportKeys = 5;
301     if (size < minSupportKeys || size > maxSupportKeys) {
302         MMI_HILOGE("Size range error");
303         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "size range error");
304         return nullptr;
305     }
306 
307     int32_t data = 0;
308     std::vector<int32_t> keyCodes;
309     for (uint32_t i = 0; i < size; ++i) {
310         napi_value keyValue = nullptr;
311         CHKRP(env, napi_get_element(env, argv[1], i, &keyValue), GET_ELEMENT);
312         if (!JsUtil::TypeOf(env, keyValue, napi_number)) {
313             MMI_HILOGE("Second parameter type error");
314             THROWERR_API9(env, COMMON_PARAMETER_ERROR, "KeyCode", "number");
315             return nullptr;
316         }
317         CHKRP(env, napi_get_value_int32(env, keyValue, &data), GET_INT32);
318         keyCodes.push_back(data);
319     }
320 
321     JsInputDeviceContext *jsContext = JsInputDeviceContext::GetInstance(env);
322     auto jsInputDeviceMgr = jsContext->GetJsInputDeviceMgr();
323     if (argc == 2) {
324         return jsInputDeviceMgr->SupportKeys(env, deviceId, keyCodes);
325     }
326     if (!JsUtil::TypeOf(env, argv[2], napi_function)) {
327         MMI_HILOGE("Third parameter type error");
328         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
329         return nullptr;
330     }
331     return jsInputDeviceMgr->SupportKeys(env, deviceId, keyCodes, argv[2]);
332 }
333 
GetKeyboardType(napi_env env,napi_callback_info info)334 napi_value JsInputDeviceContext::GetKeyboardType(napi_env env, napi_callback_info info)
335 {
336     CALL_DEBUG_ENTER;
337     size_t argc = 2;
338     napi_value argv[2];
339     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
340     if (argc == 0) {
341         MMI_HILOGE("Require two parameters");
342         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Parameter count error");
343         return nullptr;
344     }
345 
346     if (!JsUtil::TypeOf(env, argv[0], napi_number)) {
347         MMI_HILOGE("First parameter type error");
348         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "deviceId", "number");
349         return nullptr;
350     }
351     int32_t id = 0;
352     CHKRP(env, napi_get_value_int32(env, argv[0], &id), GET_INT32);
353 
354     JsInputDeviceContext *jsDev = JsInputDeviceContext::GetInstance(env);
355     CHKPP(jsDev);
356     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceMgr();
357     CHKPP(jsInputDeviceMgr);
358     if (argc == 1) {
359         return jsInputDeviceMgr->GetKeyboardType(env, id);
360     }
361     if (!JsUtil::TypeOf(env, argv[1], napi_function)) {
362         MMI_HILOGE("Second parameter type error");
363         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
364         return nullptr;
365     }
366     return jsInputDeviceMgr->GetKeyboardType(env, id, argv[1]);
367 }
368 
GetDeviceList(napi_env env,napi_callback_info info)369 napi_value JsInputDeviceContext::GetDeviceList(napi_env env, napi_callback_info info)
370 {
371     CALL_DEBUG_ENTER;
372     size_t argc = 1;
373     napi_value argv[1];
374     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
375 
376     JsInputDeviceContext *jsIds = JsInputDeviceContext::GetInstance(env);
377     CHKPP(jsIds);
378     auto jsInputDeviceMgr = jsIds->GetJsInputDeviceMgr();
379     if (argc == 0) {
380         return jsInputDeviceMgr->GetDeviceList(env);
381     }
382     if (!JsUtil::TypeOf(env, argv[0], napi_function)) {
383         MMI_HILOGE("First parameter type error");
384         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
385         return nullptr;
386     }
387     return jsInputDeviceMgr->GetDeviceList(env, argv[0]);
388 }
389 
GetDeviceInfo(napi_env env,napi_callback_info info)390 napi_value JsInputDeviceContext::GetDeviceInfo(napi_env env, napi_callback_info info)
391 {
392     CALL_DEBUG_ENTER;
393     size_t argc = 2;
394     napi_value argv[2];
395     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
396     if (argc == 0) {
397         MMI_HILOGE("Require two parameters");
398         THROWERR_CUSTOM(env, COMMON_PARAMETER_ERROR, "Parameter count error");
399         return nullptr;
400     }
401     if (!JsUtil::TypeOf(env, argv[0], napi_number)) {
402         MMI_HILOGE("First parameter type error");
403         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "deviceId", "number");
404         return nullptr;
405     }
406     int32_t id = 0;
407     CHKRP(env, napi_get_value_int32(env, argv[0], &id), GET_INT32);
408 
409     JsInputDeviceContext *jsDev = JsInputDeviceContext::GetInstance(env);
410     CHKPP(jsDev);
411     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceMgr();
412     if (argc == 1) {
413         return jsInputDeviceMgr->GetDeviceInfo(env, id);
414     }
415     if (!JsUtil::TypeOf(env, argv[1], napi_function)) {
416         MMI_HILOGE("Second parameter type error");
417         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
418         return nullptr;
419     }
420     return jsInputDeviceMgr->GetDeviceInfo(env, id, argv[1]);
421 }
422 
EnumClassConstructor(napi_env env,napi_callback_info info)423 napi_value JsInputDeviceContext::EnumClassConstructor(napi_env env, napi_callback_info info)
424 {
425     CALL_DEBUG_ENTER;
426     size_t argc = 0;
427     napi_value args[1] = {0};
428     napi_value ret = nullptr;
429     void *data = nullptr;
430     CHKRP(env, napi_get_cb_info(env, info, &argc, args, &ret, &data), GET_CB_INFO);
431     return ret;
432 }
433 
CreateEnumKeyboardType(napi_env env,napi_value exports)434 napi_value JsInputDeviceContext::CreateEnumKeyboardType(napi_env env, napi_value exports)
435 {
436     CALL_DEBUG_ENTER;
437     napi_value none = nullptr;
438     CHKRP(env, napi_create_int32(env, KeyboardType::NONE, &none), CREATE_INT32);
439     napi_value unknown = nullptr;
440     CHKRP(env, napi_create_int32(env, KeyboardType::UNKNOWN, &unknown), CREATE_INT32);
441     napi_value alphabeticKeyboard = nullptr;
442     CHKRP(env, napi_create_int32(env, KeyboardType::ALPHABETIC_KEYBOARD, &alphabeticKeyboard), CREATE_INT32);
443     napi_value digitalKeyboard = nullptr;
444     CHKRP(env, napi_create_int32(env, KeyboardType::DIGITAL_KEYBOARD, &digitalKeyboard), CREATE_INT32);
445     napi_value handwritingPen = nullptr;
446     CHKRP(env, napi_create_int32(env, KeyboardType::HANDWRITING_PEN, &handwritingPen), CREATE_INT32);
447     napi_value remoteControl = nullptr;
448     CHKRP(env, napi_create_int32(env, KeyboardType::REMOTE_CONTROL, &remoteControl), CREATE_INT32);
449     napi_property_descriptor desc[] = {
450         DECLARE_NAPI_STATIC_PROPERTY("NONE", none),
451         DECLARE_NAPI_STATIC_PROPERTY("UNKNOWN", unknown),
452         DECLARE_NAPI_STATIC_PROPERTY("ALPHABETIC_KEYBOARD", alphabeticKeyboard),
453         DECLARE_NAPI_STATIC_PROPERTY("DIGITAL_KEYBOARD", digitalKeyboard),
454         DECLARE_NAPI_STATIC_PROPERTY("HANDWRITING_PEN", handwritingPen),
455         DECLARE_NAPI_STATIC_PROPERTY("REMOTE_CONTROL", remoteControl),
456     };
457     napi_value result = nullptr;
458     CHKRP(env, napi_define_class(env, "KeyboardType", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
459         sizeof(desc) / sizeof(*desc), desc, &result), DEFINE_CLASS);
460     CHKRP(env, napi_set_named_property(env, exports, "KeyboardType", result), SET_NAMED_PROPERTY);
461     return exports;
462 }
463 
Export(napi_env env,napi_value exports)464 napi_value JsInputDeviceContext::Export(napi_env env, napi_value exports)
465 {
466     CALL_DEBUG_ENTER;
467     auto instance = CreateInstance(env);
468     if (instance == nullptr) {
469         MMI_HILOGE("failed to create instance");
470         return nullptr;
471     }
472     napi_property_descriptor desc[] = {
473         DECLARE_NAPI_STATIC_FUNCTION("on", On),
474         DECLARE_NAPI_STATIC_FUNCTION("off", Off),
475         DECLARE_NAPI_STATIC_FUNCTION("getDevice", GetDevice),
476         DECLARE_NAPI_STATIC_FUNCTION("getDeviceIds", GetDeviceIds),
477         DECLARE_NAPI_STATIC_FUNCTION("supportKeys", SupportKeys),
478         DECLARE_NAPI_STATIC_FUNCTION("getKeyboardType", GetKeyboardType),
479         DECLARE_NAPI_STATIC_FUNCTION("getDeviceList", GetDeviceList),
480         DECLARE_NAPI_STATIC_FUNCTION("getDeviceInfo", GetDeviceInfo),
481     };
482     CHKRP(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc), DEFINE_PROPERTIES);
483     if (CreateEnumKeyboardType(env, exports) == nullptr) {
484         MMI_HILOGE("Failed to create keyboard type enum");
485         return nullptr;
486     }
487     return exports;
488 }
489 } // namespace MMI
490 } // namespace OHOS
491