1 /*
2 * Copyright (c) 2025 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 "ani_input_device_context.h"
17
18 #include <ani.h>
19 #include <array>
20 #include <iostream>
21 #include <linux/input.h>
22 #include <list>
23 #include <map>
24 #include <set>
25 #include <string>
26
27 #include "define_multimodal.h"
28 #include "input_device.h"
29 #include "input_manager.h"
30 #include "mmi_log.h"
31 #include "napi_constants.h"
32 #include "oh_input_manager.h"
33
34 #undef MMI_LOG_TAG
35 #define MMI_LOG_TAG "AniInputDeviceContext"
36
37 using namespace OHOS::MMI;
38
39 enum AniErrorCode : int32_t {
40 COMMON_PARAMETER_ERROR = 401,
41 };
42
43 static std::unordered_map<int32_t, std::string> axisType = {
44 { ABS_MT_TOUCH_MAJOR, "touchmajor" }, { ABS_MT_TOUCH_MINOR, "touchminor" }, { ABS_MT_ORIENTATION, "orientation" },
45 { ABS_MT_POSITION_X, "x" }, { ABS_MT_POSITION_Y, "y" }, { ABS_MT_PRESSURE, "pressure" },
46 { ABS_MT_WIDTH_MAJOR, "toolmajor" }, { ABS_MT_WIDTH_MINOR, "toolminor" },
47 };
48
49
50 constexpr uint32_t EVDEV_UDEV_TAG_TOUCHSCREEN = (1 << 4);
51 constexpr uint32_t EVDEV_UDEV_TAG_JOYSTICK = (1 << 6);
52 constexpr uint32_t EVDEV_UDEV_TAG_TRACKBALL = (1 << 10);
53
54 static AniUtil::DeviceType g_deviceType[] = {
55 { "keyboard", EVDEV_UDEV_TAG_KEYBOARD },
56 { "mouse", EVDEV_UDEV_TAG_MOUSE },
57 { "touchpad", EVDEV_UDEV_TAG_TOUCHPAD },
58 { "touchscreen", EVDEV_UDEV_TAG_TOUCHSCREEN },
59 { "joystick", EVDEV_UDEV_TAG_JOYSTICK },
60 { "trackball", EVDEV_UDEV_TAG_TRACKBALL },
61 };
62
ThrowBusinessError(ani_env * env,int errCode,std::string && errMsg)63 static void ThrowBusinessError(ani_env *env, int errCode, std::string&& errMsg)
64 {
65 MMI_HILOGD("Begin ThrowBusinessError.");
66 static const char *errorClsName = "L@ohos/base/BusinessError;";
67 ani_class cls {};
68 if (ANI_OK != env->FindClass(errorClsName, &cls)) {
69 MMI_HILOGE("find class BusinessError %{public}s failed", errorClsName);
70 return;
71 }
72 ani_method ctor;
73 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", ":V", &ctor)) {
74 MMI_HILOGE("find method BusinessError.constructor failed");
75 return;
76 }
77 ani_object errorObject;
78 if (ANI_OK != env->Object_New(cls, ctor, &errorObject)) {
79 MMI_HILOGE("create BusinessError object failed");
80 return;
81 }
82 ani_double aniErrCode = static_cast<ani_double>(errCode);
83 ani_string errMsgStr;
84 if (ANI_OK != env->String_NewUTF8(errMsg.c_str(), errMsg.size(), &errMsgStr)) {
85 MMI_HILOGE("convert errMsg to ani_string failed");
86 return;
87 }
88 if (ANI_OK != env->Object_SetFieldByName_Double(errorObject, "code", aniErrCode)) {
89 MMI_HILOGE("set error code failed");
90 return;
91 }
92 if (ANI_OK != env->Object_SetPropertyByName_Ref(errorObject, "message", errMsgStr)) {
93 MMI_HILOGE("set error message failed");
94 return;
95 }
96 env->ThrowError(static_cast<ani_error>(errorObject));
97 return;
98 }
99
SetID(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)100 static bool SetID(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
101 {
102 if (obj == nullptr) {
103 MMI_HILOGE("obj is nullptr");
104 return false;
105 }
106
107 if (inputDevice == nullptr) {
108 MMI_HILOGE("inputDevice is nullptr");
109 return false;
110 }
111 double id = inputDevice->GetId();
112 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "id", id)) {
113 MMI_HILOGE("Set id Failed");
114 return false;
115 }
116 return true;
117 }
118
SetDeviceName(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)119 static bool SetDeviceName(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
120 {
121 if (obj == nullptr) {
122 MMI_HILOGE("obj is nullptr");
123 return false;
124 }
125
126 if (inputDevice == nullptr) {
127 MMI_HILOGE("inputDevice is nullptr");
128 return false;
129 }
130
131 std::string name = inputDevice->GetName();
132 ani_string aniStr = nullptr;
133 if (ANI_OK != env->String_NewUTF8(name.data(), name.size(), &aniStr)) {
134 MMI_HILOGE("Create aniStr Failed");
135 return false;
136 }
137
138 if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "name", aniStr)) {
139 MMI_HILOGE("Set deviceName Failed");
140 return false;
141 }
142 return true;
143 }
144
SetDeviceBus(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)145 static bool SetDeviceBus(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
146 {
147 if (obj == nullptr) {
148 MMI_HILOGE("obj is nullptr");
149 return false;
150 }
151
152 if (inputDevice == nullptr) {
153 MMI_HILOGE("inputDevice is nullptr");
154 return false;
155 }
156
157 int32_t bus = inputDevice->GetBus();
158 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "bus", bus)) {
159 MMI_HILOGE("Set deviceBus Failed");
160 return false;
161 }
162 return true;
163 }
164
SetDeviceVendor(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)165 static bool SetDeviceVendor(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
166 {
167 if (obj == nullptr) {
168 MMI_HILOGE("obj is nullptr");
169 return false;
170 }
171
172 if (inputDevice == nullptr) {
173 MMI_HILOGE("inputDevice is nullptr");
174 return false;
175 }
176
177 int32_t vendor = inputDevice->GetVendor();
178 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "vendor", vendor)) {
179 MMI_HILOGE("Set deviceVendor Failed");
180 return false;
181 }
182 return true;
183 }
184
SetDeviceProduct(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)185 static bool SetDeviceProduct(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
186 {
187 if (obj == nullptr) {
188 MMI_HILOGE("obj is nullptr");
189 return false;
190 }
191
192 if (inputDevice == nullptr) {
193 MMI_HILOGE("inputDevice is nullptr");
194 return false;
195 }
196
197 int32_t product = inputDevice->GetProduct();
198 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "product", product)) {
199 MMI_HILOGE("Set deviceProduct Failed");
200 return false;
201 }
202 return true;
203 }
204
SetDeviceVersion(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> inputDevice)205 static bool SetDeviceVersion(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> inputDevice)
206 {
207 if (obj == nullptr) {
208 MMI_HILOGE("obj is nullptr");
209 return false;
210 }
211
212 if (inputDevice == nullptr) {
213 MMI_HILOGE("inputDevice is nullptr");
214 return false;
215 }
216
217 int32_t version = inputDevice->GetVersion();
218 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "version", version)) {
219 MMI_HILOGE("Set deviceVersion Failed");
220 return false;
221 }
222 return true;
223 }
224
SetDeviceUniq(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)225 static bool SetDeviceUniq(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
226 {
227 if (obj == nullptr) {
228 MMI_HILOGE("obj is nullptr");
229 return false;
230 }
231
232 if (inputDevice == nullptr) {
233 MMI_HILOGE("inputDevice is nullptr");
234 return false;
235 }
236
237 std::string uniq = inputDevice->GetUniq();
238 ani_string aniUniq = nullptr;
239 if (ANI_OK != env->String_NewUTF8(uniq.data(), uniq.size(), &aniUniq)) {
240 MMI_HILOGE("Create aniUniq Failed");
241 return false;
242 }
243
244 if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "uniq", aniUniq)) {
245 MMI_HILOGE("Set uniq Failed");
246 return false;
247 }
248 return true;
249 }
250
SetDevicePhys(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)251 static bool SetDevicePhys(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
252 {
253 if (obj == nullptr) {
254 MMI_HILOGE("obj is nullptr");
255 return false;
256 }
257
258 if (inputDevice == nullptr) {
259 MMI_HILOGE("inputDevice is nullptr");
260 return false;
261 }
262
263 std::string phys = inputDevice->GetPhys();
264 ani_string aniPhys = nullptr;
265 if (ANI_OK != env->String_NewUTF8(phys.data(), phys.size(), &aniPhys)) {
266 MMI_HILOGE("Create aniUniq Failed");
267 return false;
268 }
269
270 if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "phys", aniPhys)) {
271 MMI_HILOGE("Set uniq Failed");
272 return false;
273 }
274 return true;
275 }
276
StringArrayToObject(ani_env * env,const std::vector<std::string> & values)277 static ani_object StringArrayToObject(ani_env *env, const std::vector<std::string> &values)
278 {
279 ani_object arrayObj = nullptr;
280 ani_class arrayCls = nullptr;
281 if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) {
282 MMI_HILOGE("FindClass Lescompat/Array; Failed");
283 }
284
285 ani_method arrayCtor;
286 if (ANI_OK != env->Class_FindMethod(arrayCls, "<ctor>", "I:V", &arrayCtor)) {
287 MMI_HILOGE("Class_FindMethod <ctor> Failed");
288 return arrayObj;
289 }
290
291 if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, values.size())) {
292 MMI_HILOGE("Object_New Array Faild");
293 return arrayObj;
294 }
295 ani_size index = 0;
296 for (auto value : values) {
297 ani_string ani_str;
298 if (ANI_OK != env->String_NewUTF8(value.c_str(), value.size(), &ani_str)) {
299 MMI_HILOGE("String_NewUTF8 Faild ");
300 break;
301 }
302 if (ANI_OK != env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, ani_str)) {
303 MMI_HILOGE("Object_CallMethodByName_Void $_set Faild ");
304 break;
305 }
306 index++;
307 }
308 return arrayObj;
309 }
310
SetDeviceSources(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)311 static bool SetDeviceSources(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
312 {
313 ani_object arrayStringObj = nullptr;
314 if (obj == nullptr) {
315 MMI_HILOGE("obj is nullptr");
316 return false;
317 }
318
319 if (inputDevice == nullptr) {
320 MMI_HILOGE("inputDevice is nullptr");
321 return false;
322 }
323
324 uint32_t types = static_cast<uint32_t>(inputDevice->GetType());
325 std::vector<std::string> sources;
326 for (const auto &item : g_deviceType) {
327 if (types & item.typeBit) {
328 sources.push_back(item.sourceTypeName);
329 }
330 }
331
332 arrayStringObj = StringArrayToObject(env, sources);
333 if (arrayStringObj == nullptr) {
334 MMI_HILOGE("Create Sources arrayStringObj Failed");
335 return false;
336 }
337 if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "sources", arrayStringObj)) {
338 MMI_HILOGE("Set uniq Failed");
339 return false;
340 }
341 return true;
342 }
343
EmptyAxisRangesSource(ani_env * env,ani_object obj,std::shared_ptr<InputDevice> & inputDevice)344 static std::string EmptyAxisRangesSource(ani_env *env, ani_object obj, std::shared_ptr<InputDevice> &inputDevice)
345 {
346 if (obj == nullptr) {
347 MMI_HILOGE("obj is nullptr");
348 return "";
349 }
350
351 if (inputDevice == nullptr) {
352 MMI_HILOGE("inputDevice is nullptr");
353 return "";
354 }
355
356 std::string sourceType = nullptr;
357 uint32_t types = static_cast<uint32_t>(inputDevice->GetType());
358 for (const auto &item : g_deviceType) {
359 if (types & item.typeBit) {
360 sourceType = item.sourceTypeName;
361 break;
362 }
363 }
364
365 if (sourceType.empty()) {
366 MMI_HILOGD("SourceType not found");
367 ani_object arrayObj = nullptr;
368 ani_class arrayCls = nullptr;
369 if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) {
370 MMI_HILOGE("FindClass Lescompat/Array; Failed");
371 }
372
373 ani_method arrayCtor;
374 if (ANI_OK != env->Class_FindMethod(arrayCls, "<ctor>", ":V", &arrayCtor)) {
375 MMI_HILOGE("Class_FindMethod <ctor> Failed");
376 return "";
377 }
378
379 if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj)) {
380 MMI_HILOGE("Object_New Array Faild");
381 return "";
382 }
383
384 if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "axisRanges", arrayObj)) {
385 MMI_HILOGE("Set axisRanges Failed");
386 }
387 }
388 return sourceType;
389 }
390
SetAxisRangesResolution(ani_env * env,ani_object obj,const InputDevice::AxisInfo & axisInfo)391 static bool SetAxisRangesResolution(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo)
392 {
393 if (obj == nullptr) {
394 MMI_HILOGE("obj is nullptr");
395 return false;
396 }
397
398 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "resolution", axisInfo.GetResolution())) {
399 MMI_HILOGE("Set AxisResolution Failed");
400 return false;
401 }
402 return true;
403 }
404
SetAxisRangesFlat(ani_env * env,ani_object obj,const InputDevice::AxisInfo & axisInfo)405 static bool SetAxisRangesFlat(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo)
406 {
407 if (obj == nullptr) {
408 MMI_HILOGE("obj is nullptr");
409 return false;
410 }
411
412 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "flat", axisInfo.GetFlat())) {
413 MMI_HILOGE("Set AxisFlat Failed");
414 return false;
415 }
416 return true;
417 }
418
SetAxisRangesFuzz(ani_env * env,ani_object obj,const InputDevice::AxisInfo & axisInfo)419 static bool SetAxisRangesFuzz(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo)
420 {
421 if (obj == nullptr) {
422 MMI_HILOGE("obj is nullptr");
423 return false;
424 }
425
426 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "fuzz", axisInfo.GetFuzz())) {
427 MMI_HILOGE("Set AxisFuzz Failed");
428 return false;
429 }
430 return true;
431 }
432
SetAxisRangesMax(ani_env * env,ani_object obj,const InputDevice::AxisInfo & axisInfo)433 static bool SetAxisRangesMax(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo)
434 {
435 if (obj == nullptr) {
436 MMI_HILOGE("obj is nullptr");
437 return false;
438 }
439
440 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "max", axisInfo.GetMaximum())) {
441 MMI_HILOGE("Set AxisMax Failed");
442 return false;
443 }
444 return true;
445 }
446
SetAxisRangesMin(ani_env * env,ani_object obj,const InputDevice::AxisInfo & axisInfo)447 static bool SetAxisRangesMin(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo)
448 {
449 if (obj == nullptr) {
450 MMI_HILOGE("obj is nullptr");
451 return false;
452 }
453
454 if (ANI_OK != env->Object_SetPropertyByName_Double(obj, "min", axisInfo.GetMinimum())) {
455 MMI_HILOGE("Set AxisMin Failed");
456 return false;
457 }
458 return true;
459 }
460
SetAxisRangesAxis(ani_env * env,ani_object obj,const InputDevice::AxisInfo & axisInfo)461 static bool SetAxisRangesAxis(ani_env *env, ani_object obj, const InputDevice::AxisInfo &axisInfo)
462 {
463 if (obj == nullptr) {
464 MMI_HILOGE("obj is nullptr");
465 return false;
466 }
467
468 auto iter = axisType.find(axisInfo.GetAxisType());
469 std::string axis = iter->second;
470 ani_string aniStr = nullptr;
471 if (ANI_OK != env->String_NewUTF8(axis.data(), axis.size(), &aniStr)) {
472 MMI_HILOGE("Create aniStr Failed");
473 return false;
474 }
475
476 if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "axis", aniStr)) {
477 MMI_HILOGE("Set AxisRangesAxis Failed");
478 return false;
479 }
480 return true;
481 }
482
SetAxisRangesSource(ani_env * env,ani_object obj,const std::string & sourceType)483 static bool SetAxisRangesSource(ani_env *env, ani_object obj, const std::string &sourceType)
484 {
485 if (obj == nullptr) {
486 MMI_HILOGE("obj is nullptr");
487 return false;
488 }
489
490 ani_string aniStr = nullptr;
491 if (ANI_OK != env->String_NewUTF8(sourceType.data(), sourceType.size(), &aniStr)) {
492 MMI_HILOGE("Create aniStr Failed");
493 return false;
494 }
495
496 if (ANI_OK != env->Object_SetPropertyByName_Ref(obj, "source", aniStr)) {
497 MMI_HILOGE("Set AxisRangesSource Failed");
498 return false;
499 }
500 return true;
501 }
502
CreatAxisRangesObj(ani_env * env,const std::string & sourceType,const InputDevice::AxisInfo & axisInfo)503 static ani_object CreatAxisRangesObj(ani_env *env, const std::string &sourceType, const InputDevice::AxisInfo &axisInfo)
504 {
505 ani_object AxisRangesObj = nullptr;
506
507 ani_namespace ns{};
508 if (ANI_OK != env->FindNamespace("L@ohos/multimodalInput/inputDevice/inputDevice;", &ns)) {
509 MMI_HILOGE("Not found namespace 'LinputDevice'");
510 return AxisRangesObj;
511 }
512
513 static const char *className = "LAxisRangeImpl;";
514 ani_class cls;
515 if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) {
516 MMI_HILOGE("Not found className %{public}s.", className);
517 return AxisRangesObj;
518 }
519
520 ani_method ctor;
521 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "J:V", &ctor)) {
522 MMI_HILOGE("get ctor Failed %{public}s.'", className);
523 return AxisRangesObj;
524 }
525
526 int64_t nativePtr = 0;
527 if (ANI_OK != env->Object_New(cls, ctor, &AxisRangesObj, reinterpret_cast<ani_long>(nativePtr))) {
528 MMI_HILOGE("Create Object Failed %{public}s.", className);
529 return AxisRangesObj;
530 }
531
532 if (!SetAxisRangesAxis(env, AxisRangesObj, axisInfo) || !SetAxisRangesSource(env, AxisRangesObj, sourceType) ||
533 !SetAxisRangesMax(env, AxisRangesObj, axisInfo) || !SetAxisRangesMin(env, AxisRangesObj, axisInfo) ||
534 !SetAxisRangesFuzz(env, AxisRangesObj, axisInfo) || !SetAxisRangesResolution(env, AxisRangesObj, axisInfo) ||
535 !SetAxisRangesFlat(env, AxisRangesObj, axisInfo)) {
536 MMI_HILOGE("Set AxisRanges Failed");
537 return AxisRangesObj;
538 }
539 return AxisRangesObj;
540 }
541
SetCreateArrayAxisRangesObj(ani_env * env,std::shared_ptr<InputDevice> & inputDevice,const std::string & sourceType)542 static ani_object SetCreateArrayAxisRangesObj(ani_env *env, std::shared_ptr<InputDevice> &inputDevice,
543 const std::string &sourceType)
544 {
545 ani_object arrayAxisRangesObj = nullptr;
546 ani_class arrayCls = nullptr;
547 if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) {
548 MMI_HILOGE("FindClass Lescompat/Array; Failed");
549 }
550
551 ani_method arrayCtor;
552 if (ANI_OK != env->Class_FindMethod(arrayCls, "<ctor>", ":V", &arrayCtor)) {
553 MMI_HILOGE("Class_FindMethod <ctor> Failed");
554 return arrayAxisRangesObj;
555 }
556
557 if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayAxisRangesObj)) {
558 MMI_HILOGE("Object_New Array Faild");
559 return arrayAxisRangesObj;
560 }
561
562 ani_size index = 0;
563 for (const auto &item : inputDevice->GetAxisInfo()) {
564 auto iter = axisType.find(item.GetAxisType());
565 if (iter == axisType.end()) {
566 MMI_HILOGD("Find axisType failed");
567 continue;
568 }
569 ani_object objAxisRanges = CreatAxisRangesObj(env, sourceType, item);
570 if (ANI_OK != env->Object_CallMethodByName_Void(arrayAxisRangesObj, "$_set", "ILstd/core/Object;:V", index,
571 objAxisRanges)) {
572 MMI_HILOGE("%{public}s Object_CallMethodByName_Void $_set Faild", __FUNCTION__);
573 return arrayAxisRangesObj;
574 }
575 index++;
576 }
577 MMI_HILOGI("Create CreateAxisRangesObj succeed.");
578 return arrayAxisRangesObj;
579 }
580
CreateDeviceInfoObj(ani_env * env,std::shared_ptr<InputDevice> & inputDevice)581 static ani_object CreateDeviceInfoObj(ani_env *env, std::shared_ptr<InputDevice> &inputDevice)
582 {
583 ani_namespace ns{};
584 if (ANI_OK != env->FindNamespace("L@ohos/multimodalInput/inputDevice/inputDevice;", &ns)) {
585 MMI_HILOGE("Not found namespace 'LinputDevice'");
586 return nullptr;
587 }
588
589 static const char *className = "LInputDeviceDataImpl;";
590 ani_class cls;
591 if (ANI_OK != env->Namespace_FindClass(ns, className, &cls)) {
592 MMI_HILOGE("Not found className %{public}s.", className);
593 return nullptr;
594 }
595
596 ani_method ctor;
597 if (ANI_OK != env->Class_FindMethod(cls, "<ctor>", "J:V", &ctor)) {
598 MMI_HILOGE("get ctor Failed %{public}s.'", className);
599 return nullptr;
600 }
601 ani_object inputDeviceDataObj = nullptr;
602 int64_t nativePtr = 0;
603 if (ANI_OK != env->Object_New(cls, ctor, &inputDeviceDataObj, reinterpret_cast<ani_long>(nativePtr))) {
604 MMI_HILOGE("Create Object Failed %{public}s.", className);
605 return nullptr;
606 }
607
608 if (!SetID(env, inputDeviceDataObj, inputDevice) || !SetDeviceName(env, inputDeviceDataObj, inputDevice) ||
609 !SetDeviceBus(env, inputDeviceDataObj, inputDevice) || !SetDeviceVendor(env, inputDeviceDataObj, inputDevice) ||
610 !SetDeviceProduct(env, inputDeviceDataObj, inputDevice) ||
611 !SetDeviceVersion(env, inputDeviceDataObj, inputDevice) ||
612 !SetDeviceUniq(env, inputDeviceDataObj, inputDevice) || !SetDevicePhys(env, inputDeviceDataObj, inputDevice) ||
613 !SetDeviceSources(env, inputDeviceDataObj, inputDevice)) {
614 MMI_HILOGE("Set DeviceInfoObj Failed");
615 return nullptr;
616 }
617
618 std::string sourceType = EmptyAxisRangesSource(env, inputDeviceDataObj, inputDevice);
619 if (!sourceType.empty()) {
620 MMI_HILOGD("Set Empty AxisRanges to axisRanges");
621 SetCreateArrayAxisRangesObj(env, inputDevice, sourceType);
622 }
623 MMI_HILOGI("Create DeviceInfoObj succeed.");
624 return inputDeviceDataObj;
625 }
626
DoubleToObject(ani_env * env,double value)627 static ani_object DoubleToObject(ani_env *env, double value)
628 {
629 ani_object aniObject = nullptr;
630 ani_double doubleValue = static_cast<ani_double>(value);
631 static const char *className = "Lstd/core/Double;";
632 ani_class aniClass;
633 if (ANI_OK != env->FindClass(className, &aniClass)) {
634 MMI_HILOGE("Not found '%{public}s'.", className);
635 return aniObject;
636 }
637 ani_method objCtor;
638 if (ANI_OK != env->Class_FindMethod(aniClass, "<ctor>", "D:V", &objCtor)) {
639 MMI_HILOGE("Class_GetMethod Failed '%{public}s <ctor>.'", className);
640 return aniObject;
641 }
642
643 if (ANI_OK != env->Object_New(aniClass, objCtor, &aniObject, doubleValue)) {
644 MMI_HILOGE("Object_New Failed '%{public}s. <ctor>", className);
645 return aniObject;
646 }
647 return aniObject;
648 }
649
DoubleArrayToObject(ani_env * env,const std::shared_ptr<std::vector<int32_t>> & ids)650 static ani_object DoubleArrayToObject(ani_env *env, const std::shared_ptr<std::vector<int32_t>> &ids)
651 {
652 ani_object arrayObj = nullptr;
653 ani_class arrayCls = nullptr;
654 if (ANI_OK != env->FindClass("Lescompat/Array;", &arrayCls)) {
655 MMI_HILOGE("FindClass Lescompat/Array; Failed");
656 return arrayObj;
657 }
658
659 ani_method arrayCtor;
660 if (ANI_OK != env->Class_FindMethod(arrayCls, "<ctor>", "I:V", &arrayCtor)) {
661 MMI_HILOGE("Class_FindMethod <ctor> Failed");
662 return arrayObj;
663 }
664
665 if (ids == nullptr) {
666 MMI_HILOGE("ids is null");
667 return arrayObj;
668 }
669 size_t size = ids->size();
670 if (ANI_OK != env->Object_New(arrayCls, arrayCtor, &arrayObj, size)) {
671 MMI_HILOGE("Object_New Array Faild");
672 return arrayObj;
673 }
674 ani_int index = 0;
675 for (auto id : *ids) {
676 ani_object aniValue = DoubleToObject(env, id);
677 if (ANI_OK != env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniValue)) {
678 MMI_HILOGI("Object_CallMethodByName_Void $_set Faild ");
679 break;
680 }
681 index++;
682 }
683 return arrayObj;
684 }
685
AniStringToString(ani_env * env,ani_string aniStr)686 static std::string AniStringToString(ani_env *env, ani_string aniStr)
687 {
688 ani_size strSize;
689 env->String_GetUTF8Size(aniStr, &strSize);
690
691 std::vector<char> buffer(strSize + 1);
692 char *utf8Buffer = buffer.data();
693
694 ani_size bytes_written = 0;
695 env->String_GetUTF8(aniStr, utf8Buffer, strSize + 1, &bytes_written);
696
697 utf8Buffer[bytes_written] = '\0';
698 std::string content = std::string(utf8Buffer);
699 return content;
700 }
701
GetDeviceList(ani_env * env)702 static ani_object GetDeviceList(ani_env *env)
703 {
704 std::shared_ptr<std::vector<int32_t>> deviceIds = std::make_shared<std::vector<int32_t>>();
705 auto callback = [deviceIds](std::vector<int32_t> &ids) { deviceIds->assign(ids.begin(), ids.end()); };
706 InputManager::GetInstance()->GetDeviceIds(callback);
707
708 ani_object object = DoubleArrayToObject(env, deviceIds);
709 return object;
710 }
711
GetDeviceInfo(ani_env * env,ani_double deviceId)712 static ani_object GetDeviceInfo(ani_env *env, ani_double deviceId)
713 {
714 std::shared_ptr<InputDevice> inputDevice = nullptr;
715 InputManager::GetInstance()->GetDevice(deviceId, [&](std::shared_ptr<InputDevice> device) {
716 inputDevice = device;
717 });
718
719 if (inputDevice == nullptr) {
720 MMI_HILOGE("Get DeviceInfo Failed");
721 return nullptr;
722 }
723
724 ani_object object = CreateDeviceInfoObj(env, inputDevice);
725 return object;
726 }
727
728 std::shared_ptr<AniInputDeviceContext> g_inputDeviceContext = nullptr;
729
AniInputDeviceContext()730 AniInputDeviceContext::AniInputDeviceContext()
731 {
732 CALL_DEBUG_ENTER;
733 mgr_ = std::make_shared<AniInputDeviceManager>();
734 }
735
~AniInputDeviceContext()736 AniInputDeviceContext::~AniInputDeviceContext()
737 {
738 CALL_DEBUG_ENTER;
739 std::lock_guard<std::mutex> guard(mtx_);
740 auto aniInputDeviceMgr = mgr_;
741 mgr_.reset();
742 if (aniInputDeviceMgr) {
743 aniInputDeviceMgr->ResetEnv();
744 }
745 }
746
On(ani_env * env,ani_string aniStr,ani_object callback)747 void AniInputDeviceContext::On(ani_env *env, ani_string aniStr, ani_object callback)
748 {
749 CALL_DEBUG_ENTER;
750 std::string type = AniStringToString(env, aniStr);
751 if (type != CHANGED_TYPE) {
752 MMI_HILOGE("%{public}s: Type is not change", __func__);
753 ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "type must be change");
754 return;
755 }
756 if (mgr_ == nullptr) {
757 MMI_HILOGE("%{public}s: aniInputDeviceMgr is nullptr", __func__);
758 ThrowBusinessError(env, COMMON_PARAMETER_ERROR, "aniInputDeviceMgr is nullptr");
759 return;
760 }
761 mgr_->RegisterDevListener(env, type, callback);
762 }
763
OnChange(ani_env * env,ani_string aniStr,ani_object callback)764 static void OnChange(ani_env *env, ani_string aniStr, ani_object callback)
765 {
766 CALL_DEBUG_ENTER;
767 if (g_inputDeviceContext == nullptr) {
768 MMI_HILOGE("%{public}s: g_inputDeviceContext is nullptr", __func__);
769 return;
770 }
771 g_inputDeviceContext->On(env, aniStr, callback);
772 }
773
ANI_Constructor(ani_vm * vm,uint32_t * result)774 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
775 {
776 MMI_HILOGD("%{public}s: enter ANI_Constructor", __func__);
777 ani_env *env;
778 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
779 MMI_HILOGE("%{public}s: Unsupported ANI_VERSION_1", __func__);
780 return ANI_ERROR;
781 }
782
783 static const char *name = "L@ohos/multimodalInput/inputDevice/inputDevice;";
784 ani_namespace ns;
785 if (ANI_OK != env->FindNamespace(name, &ns)) {
786 MMI_HILOGE("%{public}s: Not found %{public}s", __func__, name);
787 return ANI_NOT_FOUND;
788 }
789
790 std::array methods = {
791 ani_native_function{ "getDeviceListInner", nullptr, reinterpret_cast<void *>(GetDeviceList) },
792 ani_native_function{ "getDeviceInfoInner", nullptr, reinterpret_cast<void *>(GetDeviceInfo) },
793 ani_native_function{ "on", nullptr, reinterpret_cast<void *>(OnChange) },
794 };
795
796 if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
797 MMI_HILOGE("%{public}s:Cannot bind native methods to '%{public}s'", __func__, name);
798 return ANI_ERROR;
799 };
800
801 g_inputDeviceContext = std::make_shared<AniInputDeviceContext>();
802
803 *result = ANI_VERSION_1;
804 return ANI_OK;
805 }