• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }