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 <cstdio>
17 #include <map>
18 #include <string>
19 #include <unistd.h>
20 
21 #include "hilog/log.h"
22 #include "napi/native_api.h"
23 #include "napi/native_node_api.h"
24 
25 #include "file_utils.h"
26 #include "miscdevice_log.h"
27 #include "vibrator_agent.h"
28 #include "vibrator_napi_error.h"
29 #include "vibrator_napi_utils.h"
30 
31 #undef LOG_TAG
32 #define LOG_TAG "VibratorJs"
33 
34 namespace OHOS {
35 namespace Sensors {
36 namespace {
37 constexpr int32_t VIBRATE_SHORT_DURATION = 35;
38 constexpr int32_t VIBRATE_LONG_DURATION = 1000;
39 constexpr int32_t PARAMETER_TWO = 2;
40 constexpr int32_t PARAMETER_THREE = 3;
41 constexpr int32_t INTENSITY_ADJUST_MAX = 100;
42 }  // namespace
43 
44 static std::map<std::string, int32_t> g_usageType = {
45     {"unknown", USAGE_UNKNOWN},
46     {"alarm", USAGE_ALARM},
47     {"ring", USAGE_RING},
48     {"notification", USAGE_NOTIFICATION},
49     {"communication", USAGE_COMMUNICATION},
50     {"touch", USAGE_TOUCH},
51     {"media", USAGE_MEDIA},
52     {"physicalFeedback", USAGE_PHYSICAL_FEEDBACK},
53     {"simulateReality", USAGE_SIMULATE_REALITY},
54 };
55 
56 struct VibrateInfo {
57     std::string type;
58     std::string usage;
59     bool systemUsage;
60     int32_t duration = 0;
61     std::string effectId;
62     int32_t count = 0;
63     int32_t fd = -1;
64     int64_t offset = 0;
65     int64_t length = -1;
66     int32_t intensity = 0;
67 };
68 
EmitAsyncWork(napi_value param,sptr<AsyncCallbackInfo> info)69 static napi_value EmitAsyncWork(napi_value param, sptr<AsyncCallbackInfo> info)
70 {
71     CHKPP(info);
72     napi_status status = napi_generic_failure;
73     if (param != nullptr) {
74         status = napi_create_reference(info->env, param, 1, &info->callback[0]);
75         if (status != napi_ok) {
76             MISC_HILOGE("napi_create_reference fail");
77             return nullptr;
78         }
79         EmitAsyncCallbackWork(info);
80         return nullptr;
81     }
82     napi_deferred deferred = nullptr;
83     napi_value promise = nullptr;
84     status = napi_create_promise(info->env, &deferred, &promise);
85     if (status != napi_ok) {
86         MISC_HILOGE("napi_create_promise fail");
87         return nullptr;
88     }
89     info->deferred = deferred;
90     EmitPromiseWork(info);
91     return promise;
92 }
93 
VibrateTime(napi_env env,napi_value args[],size_t argc)94 static napi_value VibrateTime(napi_env env, napi_value args[], size_t argc)
95 {
96     NAPI_ASSERT(env, (argc >= 1), "Wrong argument number");
97     int32_t duration = 0;
98     NAPI_ASSERT(env, GetInt32Value(env, args[0], duration), "Get int number fail");
99     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
100     CHKPP(asyncCallbackInfo);
101     asyncCallbackInfo->error.code = StartVibratorOnce(duration);
102     if (argc >= PARAMETER_TWO && IsMatchType(env, args[1], napi_function)) {
103         return EmitAsyncWork(args[1], asyncCallbackInfo);
104     }
105     return EmitAsyncWork(nullptr, asyncCallbackInfo);
106 }
107 
VibrateEffectId(napi_env env,napi_value args[],size_t argc)108 static napi_value VibrateEffectId(napi_env env, napi_value args[], size_t argc)
109 {
110     NAPI_ASSERT(env, (argc >= 1), "Wrong argument number");
111     string effectId;
112     NAPI_ASSERT(env, GetStringValue(env, args[0], effectId), "Wrong argument type. String or function expected");
113     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
114     CHKPP(asyncCallbackInfo);
115     asyncCallbackInfo->error.code = StartVibrator(effectId.c_str());
116     if (argc >= PARAMETER_TWO && IsMatchType(env, args[1], napi_function)) {
117         return EmitAsyncWork(args[1], asyncCallbackInfo);
118     }
119     return EmitAsyncWork(nullptr, asyncCallbackInfo);
120 }
121 
GetCallbackInfo(const napi_env & env,napi_value args[],sptr<AsyncCallbackInfo> & asyncCallbackInfo,string & mode)122 static bool GetCallbackInfo(const napi_env &env, napi_value args[],
123     sptr<AsyncCallbackInfo> &asyncCallbackInfo, string &mode)
124 {
125     CHKPF(asyncCallbackInfo);
126     CHKPF(args);
127     napi_value value = nullptr;
128 
129     CHKCF(napi_get_named_property(env, args[0], "success", &value) == napi_ok, "napi get sucess property fail");
130     CHKCF(napi_create_reference(env, value, 1, &asyncCallbackInfo->callback[0]) == napi_ok,
131         "napi_create_reference fail");
132 
133     if (napi_get_named_property(env, args[0], "fail", &value) == napi_ok) {
134         if (IsMatchType(env, value, napi_function)) {
135             CHKCF(napi_create_reference(env, value, 1, &asyncCallbackInfo->callback[1]) == napi_ok,
136                 "napi_create_reference fail");
137         }
138     }
139     if (napi_get_named_property(env, args[0], "complete", &value) == napi_ok) {
140         if (IsMatchType(env, value, napi_function)) {
141             CHKCF(napi_create_reference(env, value, 1, &asyncCallbackInfo->callback[2]) == napi_ok,
142                 "napi_create_reference fail");
143         }
144     }
145     if (napi_get_named_property(env, args[0], "mode", &value) == napi_ok) {
146         bool result = GetStringValue(env, value, mode);
147         if (!result || (mode != "long" && mode != "short")) {
148             mode = "long";
149         }
150     }
151     return true;
152 }
153 
VibrateMode(napi_env env,napi_value args[],size_t argc)154 static napi_value VibrateMode(napi_env env, napi_value args[], size_t argc)
155 {
156     if (argc == 0) {
157         if (StartVibratorOnce(VIBRATE_LONG_DURATION) != 0) {
158             MISC_HILOGE("Vibrate long mode fail");
159         }
160         return nullptr;
161     }
162     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
163     CHKPP(asyncCallbackInfo);
164     asyncCallbackInfo->callbackType = SYSTEM_VIBRATE_CALLBACK;
165     string mode = "long";
166     if (!GetCallbackInfo(env, args, asyncCallbackInfo, mode)) {
167         MISC_HILOGE("Get callback info fail");
168         return nullptr;
169     }
170     int32_t duration = ((mode == "long") ? VIBRATE_LONG_DURATION : VIBRATE_SHORT_DURATION);
171     asyncCallbackInfo->error.code = StartVibratorOnce(duration);
172     if (asyncCallbackInfo->error.code != SUCCESS) {
173         asyncCallbackInfo->error.message = "Vibrator vibrate fail";
174     }
175     EmitAsyncCallbackWork(asyncCallbackInfo);
176     return nullptr;
177 }
178 
ParseParameter(napi_env env,napi_value args[],size_t argc,VibrateInfo & info)179 bool ParseParameter(napi_env env, napi_value args[], size_t argc, VibrateInfo &info)
180 {
181     CHKCF((argc >= PARAMETER_TWO), "Wrong argument number");
182     CHKCF(GetPropertyString(env, args[0], "type", info.type), "Get vibrate type fail");
183     if (info.type == "time") {
184         CHKCF(GetPropertyInt32(env, args[0], "duration", info.duration), "Get vibrate duration fail");
185     } else if (info.type == "preset") {
186         CHKCF(GetPropertyString(env, args[0], "effectId", info.effectId), "Get vibrate effectId fail");
187         if (!GetPropertyInt32(env, args[0], "count", info.count)) {
188             info.count = 1;
189         }
190         if (!GetPropertyInt32(env, args[0], "intensity", info.intensity)) {
191             info.intensity = INTENSITY_ADJUST_MAX;
192         }
193     } else if (info.type == "file") {
194         napi_value hapticFd = nullptr;
195         CHKCF(GetPropertyItem(env, args[0], "hapticFd", hapticFd), "Get vibrate hapticFd fail");
196         CHKCF(IsMatchType(env, hapticFd, napi_object), "Wrong argument type. Napi object expected");
197         CHKCF(GetPropertyInt32(env, hapticFd, "fd", info.fd), "Get vibrate fd fail");
198         GetPropertyInt64(env, hapticFd, "offset", info.offset);
199         int64_t fdSize = GetFileSize(info.fd);
200         CHKCF((info.offset >= 0) && (info.offset <= fdSize), "The parameter of offset is invalid");
201         info.length = fdSize - info.offset;
202         GetPropertyInt64(env, hapticFd, "length", info.length);
203     }
204     CHKCF(GetPropertyString(env, args[1], "usage", info.usage), "Get vibrate usage fail");
205     if (!GetPropertyBool(env, args[1], "systemUsage", info.systemUsage)) {
206         info.systemUsage = false;
207     }
208     return true;
209 }
210 
SetUsage(const std::string & usage,bool systemUsage)211 bool SetUsage(const std::string &usage, bool systemUsage)
212 {
213     if (auto iter = g_usageType.find(usage); iter == g_usageType.end()) {
214         MISC_HILOGE("Wrong usage type");
215         return false;
216     }
217     return SetUsage(g_usageType[usage], systemUsage);
218 }
219 
StartVibrate(const VibrateInfo & info)220 int32_t StartVibrate(const VibrateInfo &info)
221 {
222     CALL_LOG_ENTER;
223     if (!SetUsage(info.usage, info.systemUsage)) {
224         MISC_HILOGE("SetUsage fail");
225         return PARAMETER_ERROR;
226     }
227     if ((info.type != "time") && (info.type != "preset") && (info.type != "file")) {
228         MISC_HILOGE("Invalid vibrate type, type:%{public}s", info.type.c_str());
229         return PARAMETER_ERROR;
230     }
231     if (info.type == "preset") {
232         if (!SetLoopCount(info.count)) {
233             MISC_HILOGE("SetLoopCount fail");
234             return PARAMETER_ERROR;
235         }
236         return PlayPrimitiveEffect(info.effectId.c_str(), info.intensity);
237     } else if (info.type == "file") {
238         return PlayVibratorCustom(info.fd, info.offset, info.length);
239     }
240     return StartVibratorOnce(info.duration);
241 }
242 
VibrateEffect(napi_env env,napi_value args[],size_t argc)243 static napi_value VibrateEffect(napi_env env, napi_value args[], size_t argc)
244 {
245     VibrateInfo info;
246     if (!ParseParameter(env, args, argc, info)) {
247         ThrowErr(env, PARAMETER_ERROR, "parameter fail");
248         return nullptr;
249     }
250     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
251     CHKPP(asyncCallbackInfo);
252     asyncCallbackInfo->error.code = StartVibrate(info);
253     if ((asyncCallbackInfo->error.code != SUCCESS) && (asyncCallbackInfo->error.code == PARAMETER_ERROR)) {
254         ThrowErr(env, PARAMETER_ERROR, "parameters invalid");
255         return nullptr;
256     }
257     if (argc >= PARAMETER_THREE && IsMatchType(env, args[2], napi_function)) {
258         return EmitAsyncWork(args[2], asyncCallbackInfo);
259     }
260     return EmitAsyncWork(nullptr, asyncCallbackInfo);
261 }
262 
StartVibrate(napi_env env,napi_callback_info info)263 static napi_value StartVibrate(napi_env env, napi_callback_info info)
264 {
265     CHKPP(env);
266     CHKPP(info);
267     size_t argc = 3;
268     napi_value args[3] = {};
269     napi_value thisArg = nullptr;
270     napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
271     if (status != napi_ok || argc < PARAMETER_TWO) {
272         ThrowErr(env, PARAMETER_ERROR, "napi_get_cb_info fail or number of parameter invalid");
273         return nullptr;
274     }
275     if (!IsMatchType(env, args[0], napi_object) || !IsMatchType(env, args[1], napi_object)) {
276         ThrowErr(env, PARAMETER_ERROR, "args[0] and args[1] should is napi_object");
277         return nullptr;
278     }
279     return VibrateEffect(env, args, argc);
280 }
281 
Vibrate(napi_env env,napi_callback_info info)282 static napi_value Vibrate(napi_env env, napi_callback_info info)
283 {
284     CHKPP(env);
285     CHKPP(info);
286     size_t argc = 2;
287     napi_value args[2] = {};
288     napi_value thisArg = nullptr;
289     napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
290     if (status != napi_ok) {
291         ThrowErr(env, PARAMETER_ERROR, "napi_get_cb_info fail");
292         return nullptr;
293     }
294     if (argc >= 1 && IsMatchType(env, args[0], napi_number)) {
295         return VibrateTime(env, args, argc);
296     }
297     if (argc >= 1 && IsMatchType(env, args[0], napi_string)) {
298         return VibrateEffectId(env, args, argc);
299     }
300     return VibrateMode(env, args, argc);
301 }
302 
Cancel(napi_env env,napi_callback_info info)303 static napi_value Cancel(napi_env env, napi_callback_info info)
304 {
305     size_t argc = 1;
306     napi_value args[1] = {};
307     napi_value thisArg = nullptr;
308     napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
309     if (status != napi_ok) {
310         ThrowErr(env, PARAMETER_ERROR, "napi_get_cb_info fail");
311         return nullptr;
312     }
313     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
314     CHKPP(asyncCallbackInfo);
315     asyncCallbackInfo->error.code = Cancel();
316     if ((argc > 0) && (IsMatchType(env, args[0], napi_function))) {
317         return EmitAsyncWork(args[0], asyncCallbackInfo);
318     }
319     return EmitAsyncWork(nullptr, asyncCallbackInfo);
320 }
321 
Stop(napi_env env,napi_callback_info info)322 static napi_value Stop(napi_env env, napi_callback_info info)
323 {
324     size_t argc = 2;
325     napi_value args[2] = {};
326     napi_value thisArg = nullptr;
327     napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
328     if (status != napi_ok) {
329         ThrowErr(env, PARAMETER_ERROR, "napi_get_cb_info fail");
330         return nullptr;
331     }
332     if (argc >= 1 && IsMatchType(env, args[0], napi_string)) {
333         string mode;
334         if (!GetStringValue(env, args[0], mode)) {
335             ThrowErr(env, PARAMETER_ERROR, "Parameters invalid");
336             return nullptr;
337         }
338         sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
339         CHKPP(asyncCallbackInfo);
340         asyncCallbackInfo->error.code = StopVibrator(mode.c_str());
341         if ((asyncCallbackInfo->error.code != SUCCESS) && (asyncCallbackInfo->error.code == PARAMETER_ERROR)) {
342             ThrowErr(env, PARAMETER_ERROR, "Parameters invalid");
343             return nullptr;
344         }
345         if (argc >= PARAMETER_TWO && IsMatchType(env, args[1], napi_function)) {
346             return EmitAsyncWork(args[1], asyncCallbackInfo);
347         }
348         return EmitAsyncWork(nullptr, asyncCallbackInfo);
349     } else {
350         return Cancel(env, info);
351     }
352 }
353 
StopVibrationSync(napi_env env,napi_callback_info info)354 static napi_value StopVibrationSync(napi_env env, napi_callback_info info)
355 {
356     napi_value result = nullptr;
357     napi_get_undefined(env, &result);
358     napi_value thisArg = nullptr;
359     size_t argc = 0;
360     napi_status status = napi_get_cb_info(env, info, &argc, nullptr, &thisArg, nullptr);
361     if (status != napi_ok) {
362         ThrowErr(env, PARAMETER_ERROR, "Get the parameter info fail");
363         return result;
364     }
365     int32_t ret = Cancel();
366     if (ret != SUCCESS) {
367         ThrowErr(env, ret, "Cancel execution fail");
368     }
369     return result;
370 }
371 
IsHdHapticSupported(napi_env env,napi_callback_info info)372 static napi_value IsHdHapticSupported(napi_env env, napi_callback_info info)
373 {
374     napi_value result = nullptr;
375     napi_get_undefined(env, &result);
376     napi_value thisArg = nullptr;
377     size_t argc = 0;
378     napi_status status = napi_get_cb_info(env, info, &argc, nullptr, &thisArg, nullptr);
379     if (status != napi_ok) {
380         ThrowErr(env, PARAMETER_ERROR, "Get the parameter info fail");
381         return result;
382     }
383     status= napi_get_boolean(env, IsHdHapticSupported(), &result);
384     if (status != napi_ok) {
385         ThrowErr(env, PARAMETER_ERROR, "Get the value of boolean fail");
386     }
387     return result;
388 }
389 
IsSupportEffect(napi_env env,napi_callback_info info)390 static napi_value IsSupportEffect(napi_env env, napi_callback_info info)
391 {
392     size_t argc = 2;
393     napi_value args[2] = {};
394     napi_value thisArg = nullptr;
395     napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
396     if ((status != napi_ok) || (argc == 0)) {
397         ThrowErr(env, PARAMETER_ERROR, "napi_get_cb_info fail or number of parameter invalid");
398         return nullptr;
399     }
400     string effectId;
401     if (!GetStringValue(env, args[0], effectId)) {
402         ThrowErr(env, PARAMETER_ERROR, "GetStringValue fail");
403         return nullptr;
404     }
405     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
406     CHKPP(asyncCallbackInfo);
407     asyncCallbackInfo->callbackType = IS_SUPPORT_EFFECT_CALLBACK;
408     asyncCallbackInfo->error.code = IsSupportEffect(effectId.c_str(), &asyncCallbackInfo->isSupportEffect);
409     if ((argc > 1) && (IsMatchType(env, args[1], napi_function))) {
410         return EmitAsyncWork(args[1], asyncCallbackInfo);
411     }
412     return EmitAsyncWork(nullptr, asyncCallbackInfo);
413 }
414 
IsSupportEffectSync(napi_env env,napi_callback_info info)415 static napi_value IsSupportEffectSync(napi_env env, napi_callback_info info)
416 {
417     size_t argc = 1;
418     napi_value args[1] = {};
419     napi_value result = nullptr;
420     napi_get_undefined(env, &result);
421     napi_value thisArg = nullptr;
422     napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
423     if ((status != napi_ok) || (argc == 0)) {
424         ThrowErr(env, PARAMETER_ERROR, "Get the parameter info fail or number of parameter invalid");
425         return result;
426     }
427     string effectId;
428     if (!GetStringValue(env, args[0], effectId)) {
429         ThrowErr(env, PARAMETER_ERROR, "Get the value of string fail");
430         return result;
431     }
432     bool isSupportEffect = false;
433     int32_t ret = IsSupportEffect(effectId.c_str(), &isSupportEffect);
434     if (ret != SUCCESS) {
435         ThrowErr(env, ret, "IsSupportEffect execution failed");
436         return result;
437     }
438     status= napi_get_boolean(env, isSupportEffect, &result);
439     if (status != napi_ok) {
440         ThrowErr(env, PARAMETER_ERROR, "Get the value of boolean fail");
441     }
442     return result;
443 }
444 
EnumClassConstructor(const napi_env env,const napi_callback_info info)445 static napi_value EnumClassConstructor(const napi_env env, const napi_callback_info info)
446 {
447     size_t argc = 0;
448     napi_value args[1] = {0};
449     napi_value res = nullptr;
450     void *data = nullptr;
451     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &res, &data));
452     return res;
453 }
454 
CreateEnumStopMode(const napi_env env,napi_value exports)455 static napi_value CreateEnumStopMode(const napi_env env, napi_value exports)
456 {
457     napi_value timeMode = nullptr;
458     napi_value presetMode = nullptr;
459     NAPI_CALL(env, napi_create_string_utf8(env, "time", NAPI_AUTO_LENGTH, &timeMode));
460     NAPI_CALL(env, napi_create_string_utf8(env, "preset", NAPI_AUTO_LENGTH, &presetMode));
461 
462     napi_property_descriptor desc[] = {
463         DECLARE_NAPI_STATIC_PROPERTY("VIBRATOR_STOP_MODE_TIME", timeMode),
464         DECLARE_NAPI_STATIC_PROPERTY("VIBRATOR_STOP_MODE_PRESET", presetMode),
465     };
466     napi_value result = nullptr;
467     NAPI_CALL(env, napi_define_class(env, "VibratorStopMode", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
468         sizeof(desc) / sizeof(*desc), desc, &result));
469     NAPI_CALL(env, napi_set_named_property(env, exports, "VibratorStopMode", result));
470     return exports;
471 }
472 
CreateEnumEffectId(const napi_env env,const napi_value exports)473 static napi_value CreateEnumEffectId(const napi_env env, const napi_value exports)
474 {
475     napi_value clockTime = nullptr;
476     napi_create_string_utf8(env, "haptic.clock.timer", NAPI_AUTO_LENGTH, &clockTime);
477     napi_property_descriptor desc[] = {
478         DECLARE_NAPI_STATIC_PROPERTY("EFFECT_CLOCK_TIMER", clockTime),
479     };
480     napi_value result = nullptr;
481     NAPI_CALL(env, napi_define_class(env, "EffectId", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
482         sizeof(desc) / sizeof(*desc), desc, &result));
483     NAPI_CALL(env, napi_set_named_property(env, exports, "EffectId", result));
484     return exports;
485 }
486 
CreateEnumHapticFeedback(const napi_env env,napi_value exports)487 static napi_value CreateEnumHapticFeedback(const napi_env env, napi_value exports)
488 {
489     napi_value effectSoft = nullptr;
490     napi_value effectHard = nullptr;
491     napi_value effectSharp = nullptr;
492     NAPI_CALL(env, napi_create_string_utf8(env, "haptic.effect.soft", NAPI_AUTO_LENGTH, &effectSoft));
493     NAPI_CALL(env, napi_create_string_utf8(env, "haptic.effect.hard", NAPI_AUTO_LENGTH, &effectHard));
494     NAPI_CALL(env, napi_create_string_utf8(env, "haptic.effect.sharp", NAPI_AUTO_LENGTH, &effectSharp));
495 
496     napi_property_descriptor desc[] = {
497         DECLARE_NAPI_STATIC_PROPERTY("EFFECT_SOFT", effectSoft),
498         DECLARE_NAPI_STATIC_PROPERTY("EFFECT_HARD", effectHard),
499         DECLARE_NAPI_STATIC_PROPERTY("EFFECT_SHARP", effectSharp),
500     };
501     napi_value result = nullptr;
502     NAPI_CALL(env, napi_define_class(env, "HapticFeedback", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
503         sizeof(desc) / sizeof(*desc), desc, &result));
504     NAPI_CALL(env, napi_set_named_property(env, exports, "HapticFeedback", result));
505     return exports;
506 }
507 
Init(napi_env env,napi_value exports)508 static napi_value Init(napi_env env, napi_value exports)
509 {
510     napi_property_descriptor desc[] = {
511         DECLARE_NAPI_FUNCTION("vibrate", Vibrate),
512         DECLARE_NAPI_FUNCTION("stop", Stop),
513         DECLARE_NAPI_FUNCTION("startVibration", StartVibrate),
514         DECLARE_NAPI_FUNCTION("stopVibration", Stop),
515         DECLARE_NAPI_FUNCTION("stopVibrationSync", StopVibrationSync),
516         DECLARE_NAPI_FUNCTION("isHdHapticSupported", IsHdHapticSupported),
517         DECLARE_NAPI_FUNCTION("isSupportEffect", IsSupportEffect),
518         DECLARE_NAPI_FUNCTION("isSupportEffectSync", IsSupportEffectSync),
519     };
520     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
521     NAPI_ASSERT_BASE(env, CreateEnumStopMode(env, exports) != nullptr, "Create enum stop mode fail", exports);
522     NAPI_ASSERT_BASE(env, CreateEnumEffectId(env, exports) != nullptr, "Create enum effect id fail", exports);
523     NAPI_ASSERT_BASE(env, CreateEnumHapticFeedback(env, exports) != nullptr, "Create enum haptic feedback fail",
524                      exports);
525     return exports;
526 }
527 
528 static napi_module _module = {
529     .nm_version = 1,
530     .nm_flags = 0,
531     .nm_filename = nullptr,
532     .nm_register_func = Init,
533     .nm_modname = "vibrator",
534     .nm_priv = ((void *)0),
535     .reserved = {0}
536 };
537 
RegisterModule(void)538 extern "C" __attribute__((constructor)) void RegisterModule(void)
539 {
540     napi_module_register(&_module);
541 }
542 }  // namespace Sensors
543 }  // namespace OHOS
544