• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_input_device_cooperate_context.h"
17 
18 #include <cstddef>
19 #include <cstdint>
20 
21 #include "define_multimodal.h"
22 #include "mmi_log.h"
23 #include "napi_constants.h"
24 #include "util_napi.h"
25 #include "util_napi_error.h"
26 
27 namespace OHOS {
28 namespace MMI {
29 namespace {
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MMI_LOG_DOMAIN, "JsInputDeviceCooperateContext" };
31 constexpr const char *INPUT_DEVICE_CLASS = "multimodalinput_input_device_class";
32 constexpr const char *INPUT_DEVICE_COOPERATE = "multimodal_input_device_cooperate";
33 } // namespace
34 
JsInputDeviceCooperateContext()35 JsInputDeviceCooperateContext::JsInputDeviceCooperateContext()
36     : mgr_(std::make_shared<JsInputDeviceCooperateManager>()) {}
37 
~JsInputDeviceCooperateContext()38 JsInputDeviceCooperateContext::~JsInputDeviceCooperateContext()
39 {
40     std::lock_guard<std::mutex> guard(mutex_);
41     auto jsInputDeviceMgr = mgr_;
42     mgr_.reset();
43     if (jsInputDeviceMgr != nullptr) {
44         jsInputDeviceMgr->ResetEnv();
45     }
46 }
47 
Export(napi_env env,napi_value exports)48 napi_value JsInputDeviceCooperateContext::Export(napi_env env, napi_value exports)
49 {
50     CALL_INFO_TRACE;
51     auto instance = CreateInstance(env);
52     if (instance == nullptr) {
53         MMI_HILOGE("instance is nullptr");
54         return nullptr;
55     }
56     DeclareDeviceCooperateInterface(env, exports);
57     DeclareDeviceCooperateData(env, exports);
58     return exports;
59 }
60 
Enable(napi_env env,napi_callback_info info)61 napi_value JsInputDeviceCooperateContext::Enable(napi_env env, napi_callback_info info)
62 {
63     CALL_INFO_TRACE;
64     size_t argc = 2;
65     napi_value argv[2] = {};
66     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
67 
68     if (argc == 0) {
69         MMI_HILOGE("Wrong number of parameters");
70         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "enable", "boolean");
71         return nullptr;
72     }
73     if (!UtilNapi::TypeOf(env, argv[0], napi_boolean)) {
74         MMI_HILOGE("Thr first parameter is not boolean");
75         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "enable", "boolean");
76         return nullptr;
77     }
78     bool enable = false;
79     CHKRP(env, napi_get_value_bool(env, argv[0], &enable), GET_BOOL);
80 
81     JsInputDeviceCooperateContext *jsDev = JsInputDeviceCooperateContext::GetInstance(env);
82     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceCooperateMgr();
83     if (argc == 1) {
84         return jsInputDeviceMgr->Enable(env, enable);
85     }
86     if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
87         MMI_HILOGE("The second parameter is not function");
88         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
89         return nullptr;
90     }
91     return jsInputDeviceMgr->Enable(env, enable, argv[1]);
92 }
93 
Start(napi_env env,napi_callback_info info)94 napi_value JsInputDeviceCooperateContext::Start(napi_env env, napi_callback_info info)
95 {
96     CALL_INFO_TRACE;
97     size_t argc = 3;
98     napi_value argv[3] = {};
99     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
100 
101     if (argc < 2) {
102         MMI_HILOGE("Wrong number of parameters");
103         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "sinkDeviceDescriptor", "string");
104         return nullptr;
105     }
106     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
107         MMI_HILOGE("Thr first parameter is not boolean");
108         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "sinkDeviceDescriptor", "string");
109         return nullptr;
110     }
111     if (!UtilNapi::TypeOf(env, argv[1], napi_number)) {
112         MMI_HILOGE("The second parameter is not number");
113         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "srcInputDeviceId", "number");
114         return nullptr;
115     }
116     char sinkDeviceDescriptor[MAX_STRING_LEN] = {};
117     int32_t srcInputDeviceId = 0;
118     size_t length = 0;
119     CHKRP(env, napi_get_value_string_utf8(env, argv[0], sinkDeviceDescriptor,
120         sizeof(sinkDeviceDescriptor), &length), GET_STRING);
121     std::string sinkDeviceDescriptor_ = sinkDeviceDescriptor;
122     CHKRP(env, napi_get_value_int32(env, argv[1], &srcInputDeviceId), GET_INT32);
123 
124     JsInputDeviceCooperateContext *jsDev = JsInputDeviceCooperateContext::GetInstance(env);
125     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceCooperateMgr();
126     if (argc == 2) {
127         return jsInputDeviceMgr->Start(env, sinkDeviceDescriptor, srcInputDeviceId);
128     }
129     if (!UtilNapi::TypeOf(env, argv[2], napi_function)) {
130         MMI_HILOGE("Thr third parameter is not function");
131         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
132         return nullptr;
133     }
134     return jsInputDeviceMgr->Start(env, std::string(sinkDeviceDescriptor), srcInputDeviceId, argv[2]);
135 }
136 
Stop(napi_env env,napi_callback_info info)137 napi_value JsInputDeviceCooperateContext::Stop(napi_env env, napi_callback_info info)
138 {
139     CALL_INFO_TRACE;
140     size_t argc = 1;
141     napi_value argv[1] = {};
142     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
143 
144     JsInputDeviceCooperateContext *jsDev = JsInputDeviceCooperateContext::GetInstance(env);
145     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceCooperateMgr();
146     if (argc == 0) {
147         return jsInputDeviceMgr->Stop(env);
148     }
149     if (!UtilNapi::TypeOf(env, argv[0], napi_function)) {
150         MMI_HILOGE("The first parameter is not function");
151         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
152         return nullptr;
153     }
154     return jsInputDeviceMgr->Stop(env, argv[0]);
155 }
156 
GetState(napi_env env,napi_callback_info info)157 napi_value JsInputDeviceCooperateContext::GetState(napi_env env, napi_callback_info info)
158 {
159     CALL_INFO_TRACE;
160     size_t argc = 2;
161     napi_value argv[2] = {};
162     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
163 
164     if (argc == 0) {
165         MMI_HILOGE("Wrong number of parameters");
166         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "deviceDescriptor", "string");
167         return nullptr;
168     }
169     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
170         MMI_HILOGE("The first parameter is not string");
171         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "deviceDescriptor", "string");
172         return nullptr;
173     }
174     char deviceDescriptor[MAX_STRING_LEN] = { 0 };
175     size_t length = 0;
176     CHKRP(env, napi_get_value_string_utf8(env, argv[0], deviceDescriptor,
177         sizeof(deviceDescriptor), &length), GET_STRING);
178     std::string deviceDescriptor_ = deviceDescriptor;
179 
180     JsInputDeviceCooperateContext *jsDev = JsInputDeviceCooperateContext::GetInstance(env);
181     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceCooperateMgr();
182     if (argc == 1) {
183         return jsInputDeviceMgr->GetState(env, deviceDescriptor_);
184     }
185     if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
186         MMI_HILOGE("The second parameter is not function");
187         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
188         return nullptr;
189     }
190     return jsInputDeviceMgr->GetState(env, deviceDescriptor_, argv[1]);
191 }
192 
On(napi_env env,napi_callback_info info)193 napi_value JsInputDeviceCooperateContext::On(napi_env env, napi_callback_info info)
194 {
195     CALL_INFO_TRACE;
196     size_t argc = 2;
197     napi_value argv[2] = {};
198     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
199 
200     if (argc == 0) {
201         MMI_HILOGE("Wrong number of parameters");
202         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
203         return nullptr;
204     }
205     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
206         MMI_HILOGE("The first parameter is not string");
207         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
208         return nullptr;
209     }
210     char type[MAX_STRING_LEN] = {};
211     size_t length = 0;
212     CHKRP(env, napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &length), GET_STRING);
213     if (std::strcmp(type, "cooperation") != 0) {
214         THROWERR(env, "Register listener failed, the first parameter is invalid");
215         MMI_HILOGE("Register listener failed, the first parameter is invalid");
216         return nullptr;
217     }
218     JsInputDeviceCooperateContext *jsDev = JsInputDeviceCooperateContext::GetInstance(env);
219     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceCooperateMgr();
220     if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
221         MMI_HILOGE("The seocond parameter is not function");
222         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
223         return nullptr;
224     }
225     jsInputDeviceMgr->RegisterListener(env, type, argv[1]);
226     return nullptr;
227 }
228 
Off(napi_env env,napi_callback_info info)229 napi_value JsInputDeviceCooperateContext::Off(napi_env env, napi_callback_info info)
230 {
231     CALL_INFO_TRACE;
232     size_t argc = 2;
233     napi_value argv[2] = {};
234     CHKRP(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr), GET_CB_INFO);
235 
236     if (argc == 0) {
237         MMI_HILOGE("Wrong number of parameters");
238         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
239         return nullptr;
240     }
241     if (!UtilNapi::TypeOf(env, argv[0], napi_string)) {
242         MMI_HILOGE("The first parameter is not string");
243         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "type", "string");
244         return nullptr;
245     }
246     char type[MAX_STRING_LEN] = {};
247     size_t length = 0;
248     CHKRP(env, napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &length), GET_STRING);
249     std::string type_ = type;
250 
251     JsInputDeviceCooperateContext *jsDev = JsInputDeviceCooperateContext::GetInstance(env);
252     auto jsInputDeviceMgr = jsDev->GetJsInputDeviceCooperateMgr();
253     if (argc == 1) {
254         jsInputDeviceMgr->UnregisterListener(env, type_);
255         return nullptr;
256     }
257     if (!UtilNapi::TypeOf(env, argv[1], napi_function)) {
258         MMI_HILOGE("The second parameter is not function");
259         THROWERR_API9(env, COMMON_PARAMETER_ERROR, "callback", "function");
260         return nullptr;
261     }
262     jsInputDeviceMgr->UnregisterListener(env, type_, argv[1]);
263     return nullptr;
264 }
265 
GetJsInputDeviceCooperateMgr()266 std::shared_ptr<JsInputDeviceCooperateManager> JsInputDeviceCooperateContext::GetJsInputDeviceCooperateMgr()
267 {
268     std::lock_guard<std::mutex> guard(mutex_);
269     return mgr_;
270 }
271 
CreateInstance(napi_env env)272 napi_value JsInputDeviceCooperateContext::CreateInstance(napi_env env)
273 {
274     CALL_INFO_TRACE;
275     napi_value global = nullptr;
276     CHKRP(env, napi_get_global(env, &global), GET_GLOBAL);
277 
278     constexpr char className[] = "JsInputDeviceCooperateContext";
279     napi_value jsClass = nullptr;
280     napi_property_descriptor desc[] = {};
281     napi_status status = napi_define_class(env, className, sizeof(className),
282         JsInputDeviceCooperateContext::JsConstructor, nullptr, sizeof(desc) / sizeof(desc[0]), nullptr, &jsClass);
283     CHKRP(env, status, DEFINE_CLASS);
284 
285     status = napi_set_named_property(env, global, INPUT_DEVICE_CLASS, jsClass);
286     CHKRP(env, status, SET_NAMED_PROPERTY);
287 
288     napi_value jsInstance = nullptr;
289     CHKRP(env, napi_new_instance(env, jsClass, 0, nullptr, &jsInstance), NEW_INSTANCE);
290     CHKRP(env, napi_set_named_property(env, global, INPUT_DEVICE_COOPERATE, jsInstance),
291         SET_NAMED_PROPERTY);
292 
293     JsInputDeviceCooperateContext *jsContext = nullptr;
294     CHKRP(env, napi_unwrap(env, jsInstance, (void**)&jsContext), UNWRAP);
295     CHKPP(jsContext);
296     CHKRP(env, napi_create_reference(env, jsInstance, 1, &(jsContext->contextRef_)), CREATE_REFERENCE);
297 
298     uint32_t refCount = 0;
299     status = napi_reference_ref(env, jsContext->contextRef_, &refCount);
300     if (status != napi_ok) {
301         MMI_HILOGE("ref is nullptr");
302         napi_delete_reference(env, jsContext->contextRef_);
303         return nullptr;
304     }
305     return jsInstance;
306 }
307 
JsConstructor(napi_env env,napi_callback_info info)308 napi_value JsInputDeviceCooperateContext::JsConstructor(napi_env env, napi_callback_info info)
309 {
310     CALL_INFO_TRACE;
311     napi_value thisVar = nullptr;
312     void *data = nullptr;
313     CHKRP(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data), GET_CB_INFO);
314 
315     JsInputDeviceCooperateContext *jsContext = new (std::nothrow) JsInputDeviceCooperateContext();
316     CHKPP(jsContext);
317     napi_status status = napi_wrap(env, thisVar, jsContext, [](napi_env env, void *data, void *hin) {
318         MMI_HILOGI("jsvm ends");
319         JsInputDeviceCooperateContext *context = static_cast<JsInputDeviceCooperateContext*>(data);
320         delete context;
321     }, nullptr, nullptr);
322     if (status != napi_ok) {
323         delete jsContext;
324         MMI_HILOGE("%{public}s failed", std::string(WRAP).c_str());
325         auto infoTemp = std::string(__FUNCTION__) + ": " + std::string(WRAP) + " failed";
326         napi_throw_error(env, nullptr, infoTemp.c_str());
327         return nullptr;
328     }
329     return thisVar;
330 }
331 
GetInstance(napi_env env)332 JsInputDeviceCooperateContext *JsInputDeviceCooperateContext::GetInstance(napi_env env)
333 {
334     CALL_INFO_TRACE;
335     napi_value global = nullptr;
336     CHKRP(env, napi_get_global(env, &global), GET_GLOBAL);
337 
338     bool result = false;
339     CHKRP(env, napi_has_named_property(env, global, INPUT_DEVICE_COOPERATE, &result), HAS_NAMED_PROPERTY);
340     if (!result) {
341         MMI_HILOGE("multimodal_input_device_cooperate was not found");
342         return nullptr;
343     }
344 
345     napi_value object = nullptr;
346     CHKRP(env, napi_get_named_property(env, global, INPUT_DEVICE_COOPERATE, &object), GET_NAMED_PROPERTY);
347     if (object == nullptr) {
348         MMI_HILOGE("object is nullptr");
349         return nullptr;
350     }
351 
352     JsInputDeviceCooperateContext *instance = nullptr;
353     CHKRP(env, napi_unwrap(env, object, (void**)&instance), UNWRAP);
354     if (instance == nullptr) {
355         MMI_HILOGE("instance is nullptr");
356         return nullptr;
357     }
358     return instance;
359 }
360 
DeclareDeviceCooperateInterface(napi_env env,napi_value exports)361 void JsInputDeviceCooperateContext::DeclareDeviceCooperateInterface(napi_env env, napi_value exports)
362 {
363     napi_value infoStart = nullptr;
364     CHKRV(env, napi_create_int32(env, static_cast<int32_t>(CooperationMessage::INFO_START), &infoStart),
365         CREATE_INT32);
366     napi_value infoSuccess = nullptr;
367     CHKRV(env, napi_create_int32(env, static_cast<int32_t>(CooperationMessage::INFO_SUCCESS), &infoSuccess),
368         CREATE_INT32);
369     napi_value infoFail = nullptr;
370     CHKRV(env, napi_create_int32(env, static_cast<int32_t>(CooperationMessage::INFO_FAIL), &infoFail),
371         CREATE_INT32);
372     napi_value stateOn = nullptr;
373     CHKRV(env, napi_create_int32(env, static_cast<int32_t>(CooperationMessage::STATE_ON), &stateOn),
374         CREATE_INT32);
375     napi_value stateOff = nullptr;
376     CHKRV(env, napi_create_int32(env, static_cast<int32_t>(CooperationMessage::STATE_OFF), &stateOff),
377         CREATE_INT32);
378 
379     napi_property_descriptor msg[] = {
380         DECLARE_NAPI_STATIC_PROPERTY("MSG_COOPERATE_INFO_START", infoStart),
381         DECLARE_NAPI_STATIC_PROPERTY("MSG_COOPERATE_INFO_SUCCESS", infoSuccess),
382         DECLARE_NAPI_STATIC_PROPERTY("MSG_COOPERATE_INFO_FAIL", infoFail),
383         DECLARE_NAPI_STATIC_PROPERTY("MSG_COOPERATE_STATE_ON", stateOn),
384         DECLARE_NAPI_STATIC_PROPERTY("MSG_COOPERATE_STATE_OFF", stateOff),
385     };
386 
387     napi_value eventMsg = nullptr;
388     CHKRV(env, napi_define_class(env, "EventMsg", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
389         sizeof(msg) / sizeof(*msg), msg, &eventMsg), DEFINE_CLASS);
390     CHKRV(env, napi_set_named_property(env, exports, "EventMsg", eventMsg), SET_NAMED_PROPERTY);
391 }
392 
DeclareDeviceCooperateData(napi_env env,napi_value exports)393 void JsInputDeviceCooperateContext::DeclareDeviceCooperateData(napi_env env, napi_value exports)
394 {
395     napi_property_descriptor functions[] = {
396         DECLARE_NAPI_STATIC_FUNCTION("enable", Enable),
397         DECLARE_NAPI_STATIC_FUNCTION("start", Start),
398         DECLARE_NAPI_STATIC_FUNCTION("stop", Stop),
399         DECLARE_NAPI_STATIC_FUNCTION("getState", GetState),
400         DECLARE_NAPI_STATIC_FUNCTION("on", On),
401         DECLARE_NAPI_STATIC_FUNCTION("off", Off),
402     };
403     CHKRV(env, napi_define_properties(env, exports,
404         sizeof(functions) / sizeof(*functions), functions), DEFINE_PROPERTIES);
405 }
406 
EnumClassConstructor(napi_env env,napi_callback_info info)407 napi_value JsInputDeviceCooperateContext::EnumClassConstructor(napi_env env, napi_callback_info info)
408 {
409     size_t argc = 0;
410     napi_value args[1] = {};
411     napi_value result = nullptr;
412     void *data = nullptr;
413     CHKRP(env, napi_get_cb_info(env, info, &argc, args, &result, &data), GET_CB_INFO);
414     return result;
415 }
416 } // namespace MMI
417 } // namespace OHOS
418