1 /*
2 * Copyright (c) 2023 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 #include "intell_voice_manager_napi.h"
16 #include "intell_voice_log.h"
17 #include "intell_voice_common_napi.h"
18 #include "intell_voice_napi_util.h"
19 #include "enroll_intell_voice_engine_napi.h"
20 #include "wakeup_intell_voice_engine_napi.h"
21 #include "wakeup_manager_napi.h"
22 #include "intell_voice_update_callback_napi.h"
23 #include "intell_voice_info.h"
24
25 #define LOG_TAG "IntellVoiceManagerNapi"
26
27 using namespace std;
28 using namespace OHOS::IntellVoice;
29
30 namespace OHOS {
31 namespace IntellVoiceNapi {
32 static const std::string INTELLIGENT_VOICE_MANAGER_NAPI_CLASS_NAME = "IntelligentVoiceManager";
33 static const std::string SERVICE_CHANGE_CALLBACK_NAME = "serviceChange";
34
35 static __thread napi_ref g_managerConstructor = nullptr;
36 napi_ref IntellVoiceManagerNapi::serviceChangeTypeRef_ = nullptr;
37 napi_ref IntellVoiceManagerNapi::engineTypeRef_ = nullptr;
38 napi_ref IntellVoiceManagerNapi::sensibilityTypeRef_ = nullptr;
39 napi_ref IntellVoiceManagerNapi::enrollEventTypeRef_ = nullptr;
40 napi_ref IntellVoiceManagerNapi::wakeupEventTypeRef_ = nullptr;
41 napi_ref IntellVoiceManagerNapi::errorCodeRef_ = nullptr;
42 napi_ref IntellVoiceManagerNapi::enrollResultRef_ = nullptr;
43 napi_ref IntellVoiceManagerNapi::uploadFileTypeRef_ = nullptr;
44 napi_ref IntellVoiceManagerNapi::evaluationResultCodeRef_ = nullptr;
45
46 static const std::map<std::string, OHOS::IntellVoice::ServiceChangeType> SERVICE_CHANGE_TYPE_MAP = {
47 {"SERVICE_UNAVAILABLE", SERVICE_UNAVAILABLE},
48 };
49
50 static const std::map<std::string, OHOS::IntellVoice::IntelligentVoiceEngineType> ENGINE_TYPE_MAP = {
51 {"ENROLL_ENGINE_TYPE", ENROLL_ENGINE_TYPE},
52 {"WAKEUP_ENGINE_TYPE", WAKEUP_ENGINE_TYPE},
53 {"UPDATE_ENGINE_TYPE", UPDATE_ENGINE_TYPE},
54 };
55
56 static const std::map<std::string, OHOS::IntellVoice::SensibilityType> SENSIBILITY_TYPE_MAP = {
57 {"LOW_SENSIBILITY", LOW_SENSIBILITY},
58 {"MIDDLE_SENSIBILITY", MIDDLE_SENSIBILITY},
59 {"HIGH_SENSIBILITY", HIGH_SENSIBILITY},
60 };
61
62 static const std::map<std::string, OHOS::IntellVoice::EnrollIntelligentVoiceEventType> ENROLL_EVENT_TYPE_MAP = {
63 {"INTELLIGENT_VOICE_EVENT_ENROLL_NONE", INTELLIGENT_VOICE_EVENT_ENROLL_NONE},
64 {"INTELLIGENT_VOICE_EVENT_ENROLL_INIT_DONE", INTELLIGENT_VOICE_EVENT_ENROLL_INIT_DONE},
65 {"INTELLIGENT_VOICE_EVENT_ENROLL_COMPLETE", INTELLIGENT_VOICE_EVENT_ENROLL_COMPLETE},
66 {"INTELLIGENT_VOICE_EVENT_COMMIT_ENROLL_COMPLETE", INTELLIGENT_VOICE_EVENT_COMMIT_ENROLL_COMPLETE},
67 };
68
69 static const std::map<std::string, OHOS::IntellVoice::WakeupIntelligentVoiceEventType> WAKEUP_EVENT_TYPE_MAP = {
70 {"INTELLIGENT_VOICE_EVENT_WAKEUP_NONE", INTELLIGENT_VOICE_EVENT_WAKEUP_NONE},
71 {"INTELLIGENT_VOICE_EVENT_RECOGNIZE_COMPLETE", INTELLIGENT_VOICE_EVENT_RECOGNIZE_COMPLETE},
72 {"INTELLIGENT_VOICE_EVENT_HEADSET_RECOGNIZE_COMPLETE", INTELLIGENT_VOICE_EVENT_HEADSET_RECOGNIZE_COMPLETE},
73 };
74
75 static const std::map<std::string, OHOS::IntellVoice::IntelligentVoiceErrorCode> ERROR_CODE_MAP = {
76 {"INTELLIGENT_VOICE_NO_MEMORY", INTELLIGENT_VOICE_NO_MEMORY},
77 {"INTELLIGENT_VOICE_INVALID_PARAM", INTELLIGENT_VOICE_INVALID_PARAM},
78 {"INTELLIGENT_VOICE_INIT_FAILED", INTELLIGENT_VOICE_INIT_FAILED},
79 {"INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED", INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED},
80 {"INTELLIGENT_VOICE_SYSTEM_ERROR", INTELLIGENT_VOICE_SYSTEM_ERROR},
81 };
82
83 static const std::map<std::string, OHOS::IntellVoice::EnrollResult> ENROLL_RESULT_MAP = {
84 {"SUCCESS", OHOS::IntellVoice::EnrollResult::SUCCESS},
85 {"VPR_TRAIN_FAILED", OHOS::IntellVoice::EnrollResult::VPR_TRAIN_FAILED},
86 {"WAKEUP_PHRASE_NOT_MATCH", OHOS::IntellVoice::EnrollResult::WAKEUP_PHRASE_NOT_MATCH},
87 {"TOO_NOISY", OHOS::IntellVoice::EnrollResult::TOO_NOISY},
88 {"TOO_LOUD", OHOS::IntellVoice::EnrollResult::TOO_LOUD},
89 {"INTERVAL_LARGE", OHOS::IntellVoice::EnrollResult::INTERVAL_LARGE},
90 {"DIFFERENT_PERSON", OHOS::IntellVoice::EnrollResult::DIFFERENT_PERSON},
91 {"UNKNOWN_ERROR", OHOS::IntellVoice::EnrollResult::UNKNOWN_ERROR},
92 };
93
94 static const std::map<std::string, OHOS::IntellVoice::UploadFileType> UPLOAD_FILE_TYPE_MAP = {
95 {"ENROLL_FILE", OHOS::IntellVoice::UploadFileType::ENROLL_FILE},
96 {"WAKEUP_FILE", OHOS::IntellVoice::UploadFileType::WAKEUP_FILE},
97 };
98
99 static const std::map<std::string, OHOS::IntellVoice::EvaluationResultCode> EVALUATION_RESULT_CODE_MAP = {
100 {"UNKNOWN", OHOS::IntellVoice::UNKNOWN},
101 {"PASS", OHOS::IntellVoice::PASS},
102 {"WORD_EMPTY", OHOS::IntellVoice::WORD_EMPTY},
103 {"CHINESE_ONLY", OHOS::IntellVoice::CHINESE_ONLY},
104 {"INVALID_LENGTH", OHOS::IntellVoice::INVALID_LENGTH},
105 {"UNUSUAL_WORD", OHOS::IntellVoice::UNUSUAL_WORD},
106 {"CONSECUTIVE_SAME_WORD", OHOS::IntellVoice::CONSECUTIVE_SAME_WORD},
107 {"TOO_FEW_PHONEMES", OHOS::IntellVoice::TOO_FEW_PHONEMES},
108 {"TOO_MANY_PHONEMES", OHOS::IntellVoice::TOO_MANY_PHONEMES},
109 {"COMMON_INSTRUCTION", OHOS::IntellVoice::COMMON_INSTRUCTION},
110 {"COMMON_SPOKEN_LANGUAGE", OHOS::IntellVoice::COMMON_SPOKEN_LANGUAGE},
111 {"SENSITIVE_WORD", OHOS::IntellVoice::SENSITIVE_WORD},
112 {"NO_INITIAL_CONSONANT", OHOS::IntellVoice::NO_INITIAL_CONSONANT},
113 {"REPEATED_PHONEME", OHOS::IntellVoice::REPEATED_PHONEME},
114 };
115
IntellVoiceManagerNapi()116 IntellVoiceManagerNapi::IntellVoiceManagerNapi()
117 {
118 INTELL_VOICE_LOG_INFO("enter");
119 }
120
~IntellVoiceManagerNapi()121 IntellVoiceManagerNapi::~IntellVoiceManagerNapi()
122 {
123 INTELL_VOICE_LOG_INFO("enter");
124 if (wrapper_ != nullptr) {
125 napi_delete_reference(env_, wrapper_);
126 }
127 }
128
Destruct(napi_env env,void * nativeObject,void * finalizeHint)129 void IntellVoiceManagerNapi::Destruct(napi_env env, void *nativeObject, void *finalizeHint)
130 {
131 INTELL_VOICE_LOG_INFO("enter");
132 if (nativeObject != nullptr) {
133 auto obj = static_cast<IntellVoiceManagerNapi *>(nativeObject);
134 delete obj;
135 }
136 }
137
Construct(napi_env env,napi_callback_info info)138 napi_value IntellVoiceManagerNapi::Construct(napi_env env, napi_callback_info info)
139 {
140 INTELL_VOICE_LOG_INFO("enter");
141 napi_status status;
142 size_t argCount = 0;
143 napi_value jsThis = nullptr;
144 napi_value undefinedResult = nullptr;
145 napi_get_undefined(env, &undefinedResult);
146
147 status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
148 if (status != napi_ok) {
149 INTELL_VOICE_LOG_ERROR("invalid number of arguments");
150 return undefinedResult;
151 }
152
153 unique_ptr<IntellVoiceManagerNapi> managerNapi = make_unique<IntellVoiceManagerNapi>();
154 if (managerNapi == nullptr) {
155 INTELL_VOICE_LOG_ERROR("no memory");
156 return undefinedResult;
157 }
158 managerNapi->env_ = env;
159 managerNapi->manager_ = IntellVoiceManager::GetInstance();
160 if (managerNapi->manager_ == nullptr) {
161 INTELL_VOICE_LOG_ERROR("create native manager failed");
162 return undefinedResult;
163 }
164
165 status = napi_wrap(env,
166 jsThis,
167 static_cast<void *>(managerNapi.get()),
168 IntellVoiceManagerNapi::Destruct,
169 nullptr,
170 &(managerNapi->wrapper_));
171 if (status == napi_ok) {
172 managerNapi.release();
173 return jsThis;
174 }
175
176 INTELL_VOICE_LOG_ERROR("failed to construct intell voice manager napi");
177 return undefinedResult;
178 }
179
Export(napi_env env,napi_value exports)180 napi_value IntellVoiceManagerNapi::Export(napi_env env, napi_value exports)
181 {
182 napi_status status;
183 napi_value constructor;
184 napi_value result = nullptr;
185 const int32_t refCount = 1;
186 napi_get_undefined(env, &result);
187
188 napi_property_descriptor properties[] = {
189 DECLARE_NAPI_FUNCTION("getCapabilityInfo", GetCapabilityInfo),
190 DECLARE_NAPI_FUNCTION("on", On),
191 DECLARE_NAPI_FUNCTION("off", Off),
192 };
193
194 napi_property_descriptor staticProperties[] = {
195 DECLARE_NAPI_STATIC_FUNCTION("getIntelligentVoiceManager", GetIntelligentVoiceManager),
196 DECLARE_NAPI_PROPERTY("ServiceChangeType",
197 CreatePropertyBase(env, SERVICE_CHANGE_TYPE_MAP, serviceChangeTypeRef_)),
198 DECLARE_NAPI_PROPERTY("IntelligentVoiceEngineType", CreatePropertyBase(env, ENGINE_TYPE_MAP, engineTypeRef_)),
199 DECLARE_NAPI_PROPERTY("SensibilityType", CreatePropertyBase(env, SENSIBILITY_TYPE_MAP, sensibilityTypeRef_)),
200 DECLARE_NAPI_PROPERTY("EnrollIntelligentVoiceEventType",
201 CreatePropertyBase(env, ENROLL_EVENT_TYPE_MAP, enrollEventTypeRef_)),
202 DECLARE_NAPI_PROPERTY("WakeupIntelligentVoiceEventType",
203 CreatePropertyBase(env, WAKEUP_EVENT_TYPE_MAP, wakeupEventTypeRef_)),
204 DECLARE_NAPI_PROPERTY("IntelligentVoiceErrorCode", CreatePropertyBase(env, ERROR_CODE_MAP, errorCodeRef_)),
205 DECLARE_NAPI_PROPERTY("EnrollResult", CreatePropertyBase(env, ENROLL_RESULT_MAP, enrollResultRef_)),
206 DECLARE_NAPI_PROPERTY("UploadFileType", CreatePropertyBase(env, UPLOAD_FILE_TYPE_MAP, uploadFileTypeRef_)),
207 DECLARE_NAPI_PROPERTY("EvaluationResultCode",
208 CreatePropertyBase(env, EVALUATION_RESULT_CODE_MAP, evaluationResultCodeRef_)),
209 };
210
211 status = napi_define_class(env, INTELLIGENT_VOICE_MANAGER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct,
212 nullptr, sizeof(properties) / sizeof(properties[0]), properties, &constructor);
213 if (status != napi_ok) {
214 return result;
215 }
216
217 status = napi_create_reference(env, constructor, refCount, &g_managerConstructor);
218 if (status == napi_ok) {
219 status = napi_set_named_property(env, exports, INTELLIGENT_VOICE_MANAGER_NAPI_CLASS_NAME.c_str(), constructor);
220 if (status == napi_ok) {
221 status = napi_define_properties(
222 env, exports, sizeof(staticProperties) / sizeof(staticProperties[0]), staticProperties);
223 if (status == napi_ok) {
224 return exports;
225 }
226 }
227 }
228
229 INTELL_VOICE_LOG_ERROR("failed to export intelligent voice manager napi");
230 return result;
231 }
232
GetCapabilityInfo(napi_env env,napi_callback_info info)233 napi_value IntellVoiceManagerNapi::GetCapabilityInfo(napi_env env, napi_callback_info info)
234 {
235 INTELL_VOICE_LOG_INFO("enter");
236 napi_value result = nullptr;
237 napi_create_array(env, &result);
238 napi_set_element(env, result, 0, SetValue(env, ENROLL_ENGINE_TYPE));
239 napi_set_element(env, result, 1, SetValue(env, WAKEUP_ENGINE_TYPE));
240 return result;
241 }
242
On(napi_env env,napi_callback_info info)243 napi_value IntellVoiceManagerNapi::On(napi_env env, napi_callback_info info)
244 {
245 INTELL_VOICE_LOG_INFO("enter");
246
247 napi_value undefinedResult = nullptr;
248 napi_get_undefined(env, &undefinedResult);
249
250 const size_t expectArgCount = ARGC_TWO;
251 size_t argCount = ARGC_TWO;
252 napi_value args[expectArgCount] = { nullptr, nullptr };
253 napi_value jsThis = nullptr;
254
255 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
256 if (status != napi_ok || argCount != expectArgCount) {
257 INTELL_VOICE_LOG_ERROR("failed to get parameters");
258 return undefinedResult;
259 }
260
261 napi_valuetype eventType = napi_undefined;
262 if (napi_typeof(env, args[0], &eventType) != napi_ok || eventType != napi_string) {
263 INTELL_VOICE_LOG_ERROR("callback event name type mismatch");
264 return undefinedResult;
265 }
266
267 string callbackName = "";
268 status = GetValue(env, args[ARG_INDEX_0], callbackName);
269 if (status != napi_ok) {
270 INTELL_VOICE_LOG_ERROR("failed to get callbackName");
271 return undefinedResult;
272 }
273 INTELL_VOICE_LOG_INFO("callbackName: %{public}s", callbackName.c_str());
274 if (callbackName != SERVICE_CHANGE_CALLBACK_NAME) {
275 INTELL_VOICE_LOG_ERROR("No such off callback supported");
276 return undefinedResult;
277 }
278
279 napi_valuetype handler = napi_undefined;
280 if (napi_typeof(env, args[ARG_INDEX_1], &handler) != napi_ok || handler != napi_function) {
281 INTELL_VOICE_LOG_ERROR("callback handler type mismatch");
282 return undefinedResult;
283 }
284
285 return RegisterCallback(env, jsThis, args);
286 }
287
RegisterCallback(napi_env env,napi_value jsThis,napi_value * args)288 napi_value IntellVoiceManagerNapi::RegisterCallback(napi_env env, napi_value jsThis, napi_value *args)
289 {
290 INTELL_VOICE_LOG_INFO("enter");
291 napi_value result = nullptr;
292 napi_get_undefined(env, &result);
293
294 IntellVoiceManagerNapi *managerNapi = nullptr;
295 napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&managerNapi));
296 if (status != napi_ok || managerNapi == nullptr) {
297 INTELL_VOICE_LOG_ERROR("Failed to get engine napi instance");
298 return result;
299 }
300
301 managerNapi->serviceChangeCb_ = new (std::nothrow) ServiceChangeCallbackNapi(env);
302 if (managerNapi->serviceChangeCb_ == nullptr) {
303 INTELL_VOICE_LOG_ERROR("allocate service change callback failed");
304 return result;
305 }
306
307 managerNapi->serviceChangeCb_->SaveCallbackReference(args[ARG_INDEX_1]);
308 IntellVoiceManager::GetInstance()->RegisterServiceDeathRecipient(managerNapi->serviceChangeCb_);
309 return result;
310 }
311
Off(napi_env env,napi_callback_info info)312 napi_value IntellVoiceManagerNapi::Off(napi_env env, napi_callback_info info)
313 {
314 INTELL_VOICE_LOG_INFO("enter");
315 napi_value undefinedResult = nullptr;
316 napi_get_undefined(env, &undefinedResult);
317
318 const size_t expectArgCount = ARGC_TWO;
319 size_t argCount = ARGC_TWO;
320 napi_value args[expectArgCount] = {0};
321 napi_value jsThis = nullptr;
322
323 napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
324 if (status != napi_ok || argCount != expectArgCount) {
325 INTELL_VOICE_LOG_ERROR("failed to get parameters");
326 return undefinedResult;
327 }
328
329 napi_valuetype eventType = napi_undefined;
330 if (napi_typeof(env, args[ARG_INDEX_0], &eventType) != napi_ok || eventType != napi_string) {
331 INTELL_VOICE_LOG_ERROR("callback event name type mismatch");
332 return undefinedResult;
333 }
334
335 string callbackName = "";
336 status = GetValue(env, args[ARG_INDEX_0], callbackName);
337 if (status != napi_ok) {
338 INTELL_VOICE_LOG_ERROR("failed to get callbackName");
339 return undefinedResult;
340 }
341 INTELL_VOICE_LOG_INFO("callbackName: %{public}s", callbackName.c_str());
342 if (callbackName != SERVICE_CHANGE_CALLBACK_NAME) {
343 INTELL_VOICE_LOG_ERROR("No such off callback supported");
344 return undefinedResult;
345 }
346
347 return DeregisterCallback(env, jsThis);
348 }
349
DeregisterCallback(napi_env env,napi_value jsThis)350 napi_value IntellVoiceManagerNapi::DeregisterCallback(napi_env env, napi_value jsThis)
351 {
352 INTELL_VOICE_LOG_INFO("enter");
353 napi_value result = nullptr;
354 napi_get_undefined(env, &result);
355
356 IntellVoiceManagerNapi *managerNapi = nullptr;
357 napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&managerNapi));
358 if (status != napi_ok || managerNapi == nullptr) {
359 INTELL_VOICE_LOG_ERROR("Failed to get engine napi instance");
360 return result;
361 }
362 if (managerNapi->serviceChangeCb_ == nullptr) {
363 INTELL_VOICE_LOG_ERROR("service change callback is nullptr");
364 return result;
365 }
366
367 IntellVoiceManager::GetInstance()->DeregisterServiceDeathRecipient(managerNapi->serviceChangeCb_);
368 managerNapi->serviceChangeCb_ = nullptr;
369 return result;
370 }
371
GetIntelligentVoiceManager(napi_env env,napi_callback_info info)372 napi_value IntellVoiceManagerNapi::GetIntelligentVoiceManager(napi_env env, napi_callback_info info)
373 {
374 INTELL_VOICE_LOG_INFO("enter");
375
376 napi_status status;
377 size_t argCount = 0;
378
379 status = napi_get_cb_info(env, info, &argCount, nullptr, nullptr, nullptr);
380 if (status != napi_ok || argCount != 0) {
381 INTELL_VOICE_LOG_ERROR("Invalid arguments");
382 IntellVoiceCommonNapi::ThrowError(env, NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
383 return nullptr;
384 }
385
386 return IntellVoiceManagerNapi::GetIntelligentVoiceManagerWrapper(env);
387 }
388
GetIntelligentVoiceManagerWrapper(napi_env env)389 napi_value IntellVoiceManagerNapi::GetIntelligentVoiceManagerWrapper(napi_env env)
390 {
391 napi_status status;
392 napi_value result = nullptr;
393 napi_value constructor;
394
395 status = napi_get_reference_value(env, g_managerConstructor, &constructor);
396 if (status == napi_ok) {
397 status = napi_new_instance(env, constructor, 0, nullptr, &result);
398 if (status == napi_ok) {
399 return result;
400 }
401 }
402
403 INTELL_VOICE_LOG_ERROR("failed to get intell voice manager wrapper");
404 IntellVoiceCommonNapi::ThrowError(env, NAPI_INTELLIGENT_VOICE_NO_MEMORY);
405 napi_get_undefined(env, &result);
406
407 return result;
408 }
409
410 template <typename T>
CreatePropertyBase(napi_env env,T & propertyMap,napi_ref ref)411 napi_value IntellVoiceManagerNapi::CreatePropertyBase(napi_env env, T &propertyMap, napi_ref ref)
412 {
413 napi_value result = nullptr;
414 napi_status status;
415 napi_value enumNapiValue;
416
417 status = napi_create_object(env, &result);
418 if (status != napi_ok) {
419 INTELL_VOICE_LOG_ERROR("failed to create object");
420 napi_get_undefined(env, &result);
421 return result;
422 }
423
424 for (const auto &iter : propertyMap) {
425 std::string propName = iter.first;
426 int32_t enumValue = iter.second;
427
428 enumNapiValue = SetValue(env, enumValue);
429 status = napi_set_named_property(env, result, propName.c_str(), enumNapiValue);
430 if (status != napi_ok) {
431 break;
432 }
433 propName.clear();
434 }
435
436 if (status != napi_ok) {
437 INTELL_VOICE_LOG_ERROR("failed to set base property");
438 napi_get_undefined(env, &result);
439 return result;
440 }
441
442 status = napi_create_reference(env, result, 1, &ref);
443 if (status != napi_ok) {
444 INTELL_VOICE_LOG_ERROR("failed to create base property");
445 napi_get_undefined(env, &result);
446 return result;
447 }
448
449 INTELL_VOICE_LOG_INFO("create base property success");
450 return result;
451 }
452
Export(napi_env env,napi_value exports)453 static napi_value Export(napi_env env, napi_value exports)
454 {
455 IntellVoiceManagerNapi::Export(env, exports);
456 WakeupManagerNapi::Export(env, exports);
457 EnrollIntellVoiceEngineNapi::Export(env, exports);
458 WakeupIntellVoiceEngineNapi::Export(env, exports);
459 return exports;
460 }
461
462 static napi_module g_module = {
463 .nm_version = 1,
464 .nm_flags = 0,
465 .nm_filename = nullptr,
466 .nm_register_func = Export,
467 .nm_modname = "ai.intelligentVoice",
468 .nm_priv = ((void *)0),
469 .reserved = {0},
470 };
471
RegisterModule(void)472 extern "C" __attribute__((constructor)) void RegisterModule(void)
473 {
474 napi_module_register(&g_module);
475 }
476 } // namespace IntellVoiceNapi
477 } // namespace OHOS
478