• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <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 "miscdevice_log.h"
26 #include "vibrator_agent.h"
27 #include "vibrator_napi_error.h"
28 #include "vibrator_napi_utils.h"
29 
30 namespace OHOS {
31 namespace Sensors {
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, MISC_LOG_DOMAIN, "VibratorJs" };
34 constexpr int32_t VIBRATE_SHORT_DURATION = 35;
35 constexpr int32_t VIBRATE_LONG_DURATION = 1000;
36 }  // namespace
37 
38 static std::map<std::string, int32_t> g_usageType = {
39     {"unknown", USAGE_UNKNOWN},
40     {"alarm", USAGE_ALARM},
41     {"ring", USAGE_RING},
42     {"notification", USAGE_NOTIFICATION},
43     {"communication", USAGE_COMMUNICATION},
44     {"touch", USAGE_TOUCH},
45     {"media", USAGE_MEDIA},
46     {"physicalFeedback", USAGE_PHYSICAL_FEEDBACK},
47     {"simulateReality", USAGE_SIMULATE_REALITY},
48 };
49 
50 struct VibrateInfo {
51     std::string type;
52     std::string usage;
53     int32_t duration = 0;
54     std::string effectId;
55     int32_t count = 0;
56 };
57 
VibrateTime(napi_env env,napi_value args[],size_t argc)58 static napi_value VibrateTime(napi_env env, napi_value args[], size_t argc)
59 {
60     NAPI_ASSERT(env, (argc == 1 || argc == 2), "Wrong argument number");
61     int32_t duration = 0;
62     NAPI_ASSERT(env, GetInt32Value(env, args[0], duration), "Get int number fail");
63     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
64     CHKPP(asyncCallbackInfo);
65 
66     asyncCallbackInfo->error.code = StartVibratorOnce(duration);
67     if (argc == 2) {
68         NAPI_ASSERT(env, IsMatchType(env, args[1], napi_function), "Wrong argument type. function expected");
69         NAPI_CALL(env, napi_create_reference(env, args[1], 1, &asyncCallbackInfo->callback[0]));
70         EmitAsyncCallbackWork(asyncCallbackInfo);
71         return nullptr;
72     }
73 
74     napi_deferred deferred = nullptr;
75     napi_value promise = nullptr;
76     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
77     asyncCallbackInfo->deferred = deferred;
78     EmitPromiseWork(asyncCallbackInfo);
79     return promise;
80 }
81 
VibrateEffectId(napi_env env,napi_value args[],size_t argc)82 static napi_value VibrateEffectId(napi_env env, napi_value args[], size_t argc)
83 {
84     NAPI_ASSERT(env, (argc == 1 || argc == 2), "Wrong argument number");
85     string effectId;
86     NAPI_ASSERT(env, GetStringValue(env, args[0], effectId), "Wrong argument type. String or function expected");
87     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
88     CHKPP(asyncCallbackInfo);
89     asyncCallbackInfo->error.code = StartVibrator(effectId.c_str());
90 
91     if (argc == 2) {
92         NAPI_ASSERT(env, IsMatchType(env, args[1], napi_function), "Wrong argument type. function expected");
93         NAPI_CALL(env, napi_create_reference(env, args[1], 1, &asyncCallbackInfo->callback[0]));
94         EmitAsyncCallbackWork(asyncCallbackInfo);
95         return nullptr;
96     }
97 
98     napi_deferred deferred = nullptr;
99     napi_value promise = nullptr;
100     NAPI_CALL(env, napi_create_promise(env, &deferred, &promise));
101     asyncCallbackInfo->deferred = deferred;
102     EmitPromiseWork(asyncCallbackInfo);
103     return promise;
104 }
105 
GetCallbackInfo(const napi_env & env,napi_value args[],sptr<AsyncCallbackInfo> & asyncCallbackInfo,string & mode)106 static bool GetCallbackInfo(const napi_env &env, napi_value args[],
107     sptr<AsyncCallbackInfo> &asyncCallbackInfo, string &mode)
108 {
109     CHKPF(asyncCallbackInfo);
110     CHKPF(args);
111     napi_value value = nullptr;
112     NAPI_CALL_BASE(env, napi_get_named_property(env, args[0], "success", &value), false);
113     NAPI_CALL_BASE(env, napi_create_reference(env, value, 1, &asyncCallbackInfo->callback[0]), false);
114 
115     bool result = false;
116     NAPI_CALL_BASE(env, napi_has_named_property(env, args[0], "mode", &result), false);
117     if (result) {
118         NAPI_CALL_BASE(env, napi_get_named_property(env, args[0], "mode", &value), false);
119         NAPI_ASSERT_BASE(env, GetStringValue(env, value, mode),
120             "Wrong argument type. String or function expected", false);
121         NAPI_ASSERT_BASE(env, (mode == "long" || mode == "short"),
122             "Wrong argument type. Invalid mode value", false);
123     }
124     NAPI_CALL_BASE(env, napi_has_named_property(env, args[0], "fail", &result), false);
125     if (result) {
126         NAPI_CALL_BASE(env, napi_get_named_property(env, args[0], "fail", &value), false);
127         NAPI_CALL_BASE(env, napi_create_reference(env, value, 1, &asyncCallbackInfo->callback[1]), false);
128     }
129     NAPI_CALL_BASE(env, napi_has_named_property(env, args[0], "complete", &result), false);
130     if (result) {
131         NAPI_CALL_BASE(env, napi_get_named_property(env, args[0], "complete", &value), false);
132         NAPI_CALL_BASE(env, napi_create_reference(env, value, 1, &asyncCallbackInfo->callback[2]), false);
133     }
134     return true;
135 }
136 
VibrateMode(napi_env env,napi_value args[],size_t argc)137 static napi_value VibrateMode(napi_env env, napi_value args[], size_t argc)
138 {
139     if (argc == 0) {
140         NAPI_ASSERT(env, (StartVibratorOnce(VIBRATE_LONG_DURATION) == 0), "Vibrate long mode fail");
141         return nullptr;
142     }
143     NAPI_ASSERT(env, (argc == 1), "Param number is invalid");
144     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
145     CHKPP(asyncCallbackInfo);
146     asyncCallbackInfo->callbackType = TYPE_SYSTEM_VIBRATE;
147     string mode = "long";
148     NAPI_ASSERT(env, GetCallbackInfo(env, args, asyncCallbackInfo, mode), "Get callback info fail");
149     int32_t duration = ((mode == "long") ? VIBRATE_LONG_DURATION : VIBRATE_SHORT_DURATION);
150     asyncCallbackInfo->error.code = StartVibratorOnce(duration);
151     if (asyncCallbackInfo->error.code != SUCCESS) {
152         asyncCallbackInfo->error.message = "Vibrator vibrate fail";
153     }
154     EmitAsyncCallbackWork(asyncCallbackInfo);
155     return nullptr;
156 }
157 
ParseParameter(napi_env env,napi_value args[],size_t argc,VibrateInfo & info)158 bool ParseParameter(napi_env env, napi_value args[], size_t argc, VibrateInfo &info)
159 {
160     CHKCF((argc >= 2), "Wrong argument number");
161     CHKCF(GetPropertyString(env, args[0], "type", info.type), "Get vibrate type fail");
162     if (info.type == "time") {
163         CHKCF(GetPropertyInt32(env, args[0], "duration", info.duration), "Get vibrate type fail");
164     } else if (info.type == "preset") {
165         CHKCF(GetPropertyInt32(env, args[0], "count", info.count), "Get vibrate count fail");
166         CHKCF(GetPropertyString(env, args[0], "effectId", info.effectId), "Get vibrate effectId fail");
167     }
168     CHKCF(GetPropertyString(env, args[1], "usage", info.usage), "Get vibrate usage fail");
169     return true;
170 }
171 
SetUsage(const std::string & usage)172 bool SetUsage(const std::string &usage)
173 {
174     if (auto iter = g_usageType.find(usage); iter == g_usageType.end()) {
175         MISC_HILOGE("Wrong usage type");
176         return false;
177     }
178     return SetUsage(g_usageType[usage]);
179 }
180 
StartVibrate(const VibrateInfo & info)181 int32_t StartVibrate(const VibrateInfo &info)
182 {
183     if (!SetUsage(info.usage)) {
184         MISC_HILOGE("SetUsage fail");
185         return PARAMETER_ERROR;
186     }
187     if ((info.type != "time") && (info.type != "preset")) {
188         MISC_HILOGE("Invalid vibrate type");
189         return PARAMETER_ERROR;
190     }
191     if (info.type == "preset") {
192         if (!SetLoopCount(info.count)) {
193             MISC_HILOGE("SetLoopCount fail");
194             return PARAMETER_ERROR;
195         }
196         return StartVibrator(info.effectId.c_str());
197     }
198     return StartVibratorOnce(info.duration);
199 }
200 
VibrateEffect(napi_env env,napi_value args[],size_t argc)201 static napi_value VibrateEffect(napi_env env, napi_value args[], size_t argc)
202 {
203     VibrateInfo info;
204     if (!ParseParameter(env, args, argc, info)) {
205         ThrowErr(env, PARAMETER_ERROR, "parameter fail");
206         return nullptr;
207     }
208     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
209     CHKPP(asyncCallbackInfo);
210     asyncCallbackInfo->error.code = StartVibrate(info);
211     if ((asyncCallbackInfo->error.code != SUCCESS) && (asyncCallbackInfo->error.code == PARAMETER_ERROR)) {
212         ThrowErr(env, PARAMETER_ERROR, "parameters invalid");
213         return nullptr;
214     }
215     if (argc >= 3) {
216         if (!IsMatchType(env, args[2], napi_function)) {
217             ThrowErr(env, PARAMETER_ERROR, "IsMatchType fail, should be function");
218             return nullptr;
219         }
220         if (napi_create_reference(env, args[2], 1, &asyncCallbackInfo->callback[0]) != napi_ok) {
221             ThrowErr(env, PARAMETER_ERROR, "napi_create_reference fail");
222             return nullptr;
223         }
224         EmitAsyncCallbackWork(asyncCallbackInfo);
225         return nullptr;
226     }
227     napi_deferred deferred = nullptr;
228     napi_value promise = nullptr;
229     CHKCP((napi_create_promise(env, &deferred, &promise) == napi_ok), "napi_create_promise fail");
230     asyncCallbackInfo->deferred = deferred;
231     EmitPromiseWork(asyncCallbackInfo);
232     return promise;
233 }
234 
Vibrate(napi_env env,napi_callback_info info)235 static napi_value Vibrate(napi_env env, napi_callback_info info)
236 {
237     CHKPP(env);
238     CHKPP(info);
239     size_t argc = 3;
240     napi_value args[3] = {};
241     napi_value thisArg = nullptr;
242     napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
243     if ((status != napi_ok) || (argc == 0)) {
244         ThrowErr(env, PARAMETER_ERROR, "napi_get_cb_info fail or number of parameter invalid");
245         return nullptr;
246     }
247     if (IsMatchType(env, args[0], napi_number)) {
248         return VibrateTime(env, args, argc);
249     }
250     if (IsMatchType(env, args[0], napi_string)) {
251         return VibrateEffectId(env, args, argc);
252     }
253     if (IsMatchType(env, args[0], napi_object) && argc == 1) {
254         return VibrateMode(env, args, argc);
255     }
256     return VibrateEffect(env, args, argc);
257 }
258 
Stop(napi_env env,napi_callback_info info)259 static napi_value Stop(napi_env env, napi_callback_info info)
260 {
261     size_t argc = 2;
262     napi_value args[2] = {};
263     napi_value thisArg = nullptr;
264     napi_status status = napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
265     if ((status != napi_ok) || (argc == 0)) {
266         ThrowErr(env, PARAMETER_ERROR, "napi_get_cb_info fail or number of parameter invalid");
267         return nullptr;
268     }
269     string mode;
270     if (!GetStringValue(env, args[0], mode)) {
271         ThrowErr(env, PARAMETER_ERROR, "GetStringValue fail");
272         return nullptr;
273     }
274     sptr<AsyncCallbackInfo> asyncCallbackInfo = new (std::nothrow) AsyncCallbackInfo(env);
275     CHKPP(asyncCallbackInfo);
276     asyncCallbackInfo->error.code = StopVibrator(mode.c_str());
277     if ((asyncCallbackInfo->error.code != SUCCESS) && (asyncCallbackInfo->error.code == PARAMETER_ERROR)) {
278         ThrowErr(env, PARAMETER_ERROR, "Parameters invalid");
279         return nullptr;
280     }
281     if (argc >= 2) {
282         if (!IsMatchType(env, args[1], napi_function)) {
283             ThrowErr(env, PARAMETER_ERROR, "IsMatchType fail, should be function");
284             return nullptr;
285         }
286         if (napi_create_reference(env, args[1], 1, &asyncCallbackInfo->callback[0]) != napi_ok) {
287             ThrowErr(env, PARAMETER_ERROR, "napi_create_reference fail");
288             return nullptr;
289         }
290         EmitAsyncCallbackWork(asyncCallbackInfo);
291         return nullptr;
292     }
293     napi_deferred deferred = nullptr;
294     napi_value promise = nullptr;
295     CHKCP((napi_create_promise(env, &deferred, &promise) == napi_ok), "napi_create_promise fail");
296     asyncCallbackInfo->deferred = deferred;
297     EmitPromiseWork(asyncCallbackInfo);
298     return promise;
299 }
300 
EnumClassConstructor(const napi_env env,const napi_callback_info info)301 static napi_value EnumClassConstructor(const napi_env env, const napi_callback_info info)
302 {
303     size_t argc = 0;
304     napi_value args[1] = {0};
305     napi_value res = nullptr;
306     void *data = nullptr;
307     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &res, &data));
308     return res;
309 }
310 
CreateEnumStopMode(const napi_env env,napi_value exports)311 static napi_value CreateEnumStopMode(const napi_env env, napi_value exports)
312 {
313     napi_value timeMode = nullptr;
314     napi_value presetMode = nullptr;
315     NAPI_CALL(env, napi_create_string_utf8(env, "time", NAPI_AUTO_LENGTH, &timeMode));
316     NAPI_CALL(env, napi_create_string_utf8(env, "preset", NAPI_AUTO_LENGTH, &presetMode));
317 
318     napi_property_descriptor desc[] = {
319         DECLARE_NAPI_STATIC_PROPERTY("VIBRATOR_STOP_MODE_TIME", timeMode),
320         DECLARE_NAPI_STATIC_PROPERTY("VIBRATOR_STOP_MODE_PRESET", presetMode),
321     };
322     napi_value result = nullptr;
323     NAPI_CALL(env, napi_define_class(env, "VibratorStopMode", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
324         sizeof(desc) / sizeof(*desc), desc, &result));
325     NAPI_CALL(env, napi_set_named_property(env, exports, "VibratorStopMode", result));
326     return exports;
327 }
328 
CreateEnumEffectId(const napi_env env,const napi_value exports)329 static napi_value CreateEnumEffectId(const napi_env env, const napi_value exports)
330 {
331     napi_value clockTime = nullptr;
332     napi_create_string_utf8(env, "haptic.clock.timer", NAPI_AUTO_LENGTH, &clockTime);
333     napi_property_descriptor desc[] = {
334         DECLARE_NAPI_STATIC_PROPERTY("EFFECT_CLOCK_TIMER", clockTime),
335     };
336     napi_value result = nullptr;
337     NAPI_CALL(env, napi_define_class(env, "EffectId", NAPI_AUTO_LENGTH, EnumClassConstructor, nullptr,
338         sizeof(desc) / sizeof(*desc), desc, &result));
339     NAPI_CALL(env, napi_set_named_property(env, exports, "EffectId", result));
340     return exports;
341 }
342 
Init(napi_env env,napi_value exports)343 static napi_value Init(napi_env env, napi_value exports)
344 {
345     napi_property_descriptor desc[] = {
346         DECLARE_NAPI_FUNCTION("vibrate", Vibrate),
347         DECLARE_NAPI_FUNCTION("stop", Stop),
348         DECLARE_NAPI_FUNCTION("startVibration", Vibrate),
349         DECLARE_NAPI_FUNCTION("stopVibration", Stop),
350     };
351     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(napi_property_descriptor), desc));
352     NAPI_ASSERT_BASE(env, CreateEnumStopMode(env, exports) != nullptr, "Create enum stop mode fail", exports);
353     NAPI_ASSERT_BASE(env, CreateEnumEffectId(env, exports) != nullptr, "Create enum effect id fail", exports);
354     return exports;
355 }
356 
357 static napi_module _module = {
358     .nm_version = 1,
359     .nm_flags = 0,
360     .nm_filename = nullptr,
361     .nm_register_func = Init,
362     .nm_modname = "vibrator",
363     .nm_priv = ((void *)0),
364     .reserved = {0}
365 };
366 
RegisterModule(void)367 extern "C" __attribute__((constructor)) void RegisterModule(void)
368 {
369     napi_module_register(&_module);
370 }
371 }  // namespace Sensors
372 }  // namespace OHOS
373