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
16 #include "enroll_intell_voice_engine_napi.h"
17
18 #include "iservice_registry.h"
19 #include "system_ability_definition.h"
20
21 #include "intell_voice_common_napi.h"
22 #include "intell_voice_napi_util.h"
23 #include "intell_voice_napi_queue.h"
24 #include "intell_voice_log.h"
25 #include "i_intell_voice_engine_callback.h"
26
27 #define LOG_TAG "EnrollEngineNapi"
28
29 using namespace OHOS::IntellVoice;
30 using namespace std;
31
32 namespace OHOS {
33 namespace IntellVoiceNapi {
34 class EvaluateContext : public AsyncContext {
35 public:
EvaluateContext(napi_env env)36 explicit EvaluateContext(napi_env env) : AsyncContext(env) {};
37 string word;
38 EvaluationResultInfo info;
39 };
40
41 static __thread napi_ref g_enrollEngineConstructor = nullptr;
42 EnrollIntelligentVoiceEngineDescriptor EnrollIntellVoiceEngineNapi::g_enrollEngineDesc_;
43 int32_t EnrollIntellVoiceEngineNapi::constructResult_ = NAPI_INTELLIGENT_VOICE_SUCCESS;
44
45 static const std::string ENROLL_ENGINE_NAPI_CLASS_NAME = "EnrollIntelligentVoiceEngine";
46
EnrollIntellVoiceEngineNapi()47 EnrollIntellVoiceEngineNapi::EnrollIntellVoiceEngineNapi()
48 {
49 INTELL_VOICE_LOG_INFO("enter, %{public}p", this);
50 }
51
~EnrollIntellVoiceEngineNapi()52 EnrollIntellVoiceEngineNapi::~EnrollIntellVoiceEngineNapi()
53 {
54 INTELL_VOICE_LOG_INFO("enter");
55 if (wrapper_ != nullptr) {
56 napi_delete_reference(env_, wrapper_);
57 }
58 }
59
Export(napi_env env,napi_value exports)60 napi_value EnrollIntellVoiceEngineNapi::Export(napi_env env, napi_value exports)
61 {
62 napi_status status;
63 napi_value constructor;
64 napi_value result = nullptr;
65 const int32_t refCount = 1;
66 napi_get_undefined(env, &result);
67
68 napi_property_descriptor properties[] = {
69 DECLARE_NAPI_FUNCTION("getSupportedRegions", GetSupportedRegions),
70 DECLARE_NAPI_FUNCTION("init", Init),
71 DECLARE_NAPI_FUNCTION("enrollForResult", EnrollForResult),
72 DECLARE_NAPI_FUNCTION("stop", Stop),
73 DECLARE_NAPI_FUNCTION("setSensibility", SetSensibility),
74 DECLARE_NAPI_FUNCTION("setWakeupHapInfo", SetWakeupHapInfo),
75 DECLARE_NAPI_FUNCTION("setParameter", SetParameter),
76 DECLARE_NAPI_FUNCTION("getParameter", GetParameter),
77 DECLARE_NAPI_FUNCTION("evaluateForResult", EvaluateForResult),
78 DECLARE_NAPI_FUNCTION("release", Release),
79 DECLARE_NAPI_FUNCTION("commit", Commit),
80 };
81
82 napi_property_descriptor static_prop[] = {
83 DECLARE_NAPI_STATIC_FUNCTION(
84 "createEnrollIntelligentVoiceEngine", CreateEnrollIntelligentVoiceEngine)
85 };
86
87 status = napi_define_class(env,
88 ENROLL_ENGINE_NAPI_CLASS_NAME.c_str(),
89 NAPI_AUTO_LENGTH,
90 Construct,
91 nullptr,
92 sizeof(properties) / sizeof(properties[0]),
93 properties,
94 &constructor);
95 if (status != napi_ok) {
96 return result;
97 }
98
99 status = napi_create_reference(env, constructor, refCount, &g_enrollEngineConstructor);
100 if (status == napi_ok) {
101 status = napi_set_named_property(env, exports, ENROLL_ENGINE_NAPI_CLASS_NAME.c_str(), constructor);
102 if (status == napi_ok) {
103 status = napi_define_properties(env, exports,
104 sizeof(static_prop) / sizeof(static_prop[0]), static_prop);
105 if (status == napi_ok) {
106 return exports;
107 }
108 }
109 }
110
111 return result;
112 }
113
Destruct(napi_env env,void * nativeObject,void * finalizeHint)114 void EnrollIntellVoiceEngineNapi::Destruct(napi_env env, void *nativeObject, void *finalizeHint)
115 {
116 if (nativeObject != nullptr) {
117 auto obj = static_cast<EnrollIntellVoiceEngineNapi *>(nativeObject);
118 delete obj;
119 }
120 }
121
Construct(napi_env env,napi_callback_info info)122 napi_value EnrollIntellVoiceEngineNapi::Construct(napi_env env, napi_callback_info info)
123 {
124 INTELL_VOICE_LOG_INFO("enter");
125 napi_status status;
126 size_t argc = ARGC_ONE;
127 napi_value args[ARGC_ONE] = { nullptr };
128 napi_value jsThis = nullptr;
129 napi_value undefinedResult = nullptr;
130 napi_get_undefined(env, &undefinedResult);
131
132 constructResult_ = NAPI_INTELLIGENT_VOICE_SUCCESS;
133 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &jsThis, nullptr));
134
135 unique_ptr<EnrollIntellVoiceEngineNapi> engineNapi = make_unique<EnrollIntellVoiceEngineNapi>();
136 if (engineNapi == nullptr) {
137 INTELL_VOICE_LOG_ERROR("Failed to create EnrollIntellVoiceEngineNapi, No memory");
138 constructResult_ = NAPI_INTELLIGENT_VOICE_NO_MEMORY;
139 return undefinedResult;
140 }
141
142 engineNapi->env_ = env;
143 engineNapi->engine_ = std::make_shared<EnrollIntellVoiceEngine>(g_enrollEngineDesc_);
144 if (engineNapi->engine_ == nullptr) {
145 INTELL_VOICE_LOG_ERROR("create intell voice engine failed");
146 constructResult_ = NAPI_INTELLIGENT_VOICE_NO_MEMORY;
147 return undefinedResult;
148 }
149 engineNapi->callbackNapi_ = std::make_shared<EnrollIntellVoiceEngineCallbackNapi>(env);
150 if (engineNapi->callbackNapi_ == nullptr) {
151 INTELL_VOICE_LOG_ERROR("create intell voice engine callback napi failed");
152 constructResult_ = NAPI_INTELLIGENT_VOICE_NO_MEMORY;
153 return undefinedResult;
154 }
155
156 if (engineNapi->engine_->SetCallback(engineNapi->callbackNapi_) != 0) {
157 INTELL_VOICE_LOG_ERROR("set callback failed");
158 constructResult_ = NAPI_INTELLIGENT_VOICE_PERMISSION_DENIED;
159 return undefinedResult;
160 }
161
162 status = napi_wrap(env, jsThis, static_cast<void *>(engineNapi.get()),
163 EnrollIntellVoiceEngineNapi::Destruct, nullptr, &(engineNapi->wrapper_));
164 if (status == napi_ok) {
165 engineNapi.release();
166 return jsThis;
167 }
168
169 INTELL_VOICE_LOG_ERROR("wrap enroll intell voice engine failed");
170 return undefinedResult;
171 }
172
CreateEnrollIntelligentVoiceEngine(napi_env env,napi_callback_info info)173 napi_value EnrollIntellVoiceEngineNapi::CreateEnrollIntelligentVoiceEngine(napi_env env, napi_callback_info info)
174 {
175 INTELL_VOICE_LOG_INFO("enter");
176 size_t cbIndex = ARG_INDEX_1;
177
178 auto context = make_shared<AsyncContext>(env);
179 if (context == nullptr) {
180 INTELL_VOICE_LOG_ERROR("create Context failed, No memory");
181 return nullptr;
182 }
183
184 CbInfoParser parser = [env](size_t argc, napi_value *argv) -> bool {
185 CHECK_CONDITION_RETURN_FALSE((argc < ARGC_ONE), "argc less than 1");
186 napi_valuetype valueType = napi_undefined;
187 napi_typeof(env, argv[0], &valueType);
188 CHECK_CONDITION_RETURN_FALSE((valueType != napi_object), "arg type mismatch");
189 napi_value temp = nullptr;
190 napi_status status = napi_get_named_property(env, argv[0], "wakeupPhrase", &temp);
191 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get property failed");
192 status = GetValue(env, temp, g_enrollEngineDesc_.wakeupPhrase);
193 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get wakeup phrase failed");
194 return true;
195 };
196
197 context->result_ = (context->GetCbInfo(env, info, cbIndex, parser) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
198 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
199
200 AsyncExecute execute = [](napi_env env, void *data) {};
201
202 context->complete_ = [](napi_env env, AsyncContext *asyncContext, napi_value &result) {
203 napi_value constructor = nullptr;
204 napi_status status = napi_get_reference_value(env, g_enrollEngineConstructor, &constructor);
205 if (status != napi_ok) {
206 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_NO_MEMORY;
207 napi_get_undefined(env, &result);
208 return;
209 }
210
211 status = napi_new_instance(env, constructor, 0, nullptr, &result);
212 asyncContext->result_ = constructResult_;
213 if (status != napi_ok) {
214 napi_get_undefined(env, &result);
215 }
216 };
217
218 return NapiAsync::AsyncWork(env, context, "CreateEnrollIntelligentVoiceEngine", execute);
219 }
220
GetSupportedRegions(napi_env env,napi_callback_info info)221 napi_value EnrollIntellVoiceEngineNapi::GetSupportedRegions(napi_env env, napi_callback_info info)
222 {
223 INTELL_VOICE_LOG_INFO("enter");
224 size_t cbIndex = ARG_INDEX_0;
225 shared_ptr<AsyncContext> context = make_shared<AsyncContext>(env);
226 if (context == nullptr) {
227 INTELL_VOICE_LOG_ERROR("create AsyncContext failed, No memory");
228 return nullptr;
229 }
230
231 context->result_ = (context->GetCbInfo(env, info, cbIndex, nullptr) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
232 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
233
234 AsyncExecute execute = [](napi_env env, void *data) {};
235
236 context->complete_ = [](napi_env env, AsyncContext *asyncContext, napi_value &result) {
237 napi_create_array(env, &result);
238 napi_set_element(env, result, 0, SetValue(env, "CN"));
239 };
240
241 return NapiAsync::AsyncWork(env, context, "GetSupportedRegions", execute);
242 }
243
Init(napi_env env,napi_callback_info info)244 napi_value EnrollIntellVoiceEngineNapi::Init(napi_env env, napi_callback_info info)
245 {
246 INTELL_VOICE_LOG_INFO("enter");
247 size_t cbIndex = ARG_INDEX_1;
248 auto context = make_shared<EnrollAsyncContext>(env);
249 if (context == nullptr) {
250 INTELL_VOICE_LOG_ERROR("create InitContext failed, No memory");
251 return nullptr;
252 }
253
254 CbInfoParser parser = [env, context](size_t argc, napi_value *argv) -> bool {
255 CHECK_CONDITION_RETURN_FALSE((argc < ARGC_ONE), "argc less than 1");
256 napi_valuetype valueType = napi_undefined;
257 napi_typeof(env, argv[0], &valueType);
258 CHECK_CONDITION_RETURN_FALSE((valueType != napi_object), "arg type mismatch");
259 napi_value temp = nullptr;
260 napi_status status = napi_get_named_property(env, argv[0], "language", &temp);
261 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get property failed");
262 status = GetValue(env, temp,
263 reinterpret_cast<EnrollIntellVoiceEngineNapi *>(context->instanceNapi_)->config_.language);
264 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get language failed");
265 status = napi_get_named_property(env, argv[0], "region", &temp);
266 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get property failed");
267 status = GetValue(env, temp,
268 reinterpret_cast<EnrollIntellVoiceEngineNapi *>(context->instanceNapi_)->config_.region);
269 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get region failed");
270 return true;
271 };
272
273 context->result_ = (context->GetCbInfo(env, info, cbIndex, parser) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
274 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
275
276 context->type = ASYNC_WORK_INIT;
277 context->callbackInfo.result = UNKNOWN_ERROR;
278 context->processWork = [&](AsyncContext *asyncContext) -> int32_t {
279 auto engineNapi = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_);
280 auto engine = engineNapi->engine_;
281 if (engine == nullptr) {
282 INTELL_VOICE_LOG_ERROR("get engine instance failed");
283 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_INIT_FAILED;
284 return -1;
285 }
286
287 auto ret = engine->Init(engineNapi->config_);
288 if (ret != 0) {
289 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_INIT_FAILED;
290 }
291 return ret;
292 };
293
294 AsyncExecute execute = [](napi_env env, void *data) {};
295
296 return NapiAsync::AsyncWork(env, context, "Init", execute, CompleteCallback);
297 }
298
EnrollForResult(napi_env env,napi_callback_info info)299 napi_value EnrollIntellVoiceEngineNapi::EnrollForResult(napi_env env, napi_callback_info info)
300 {
301 INTELL_VOICE_LOG_INFO("enter");
302 size_t cbIndex = ARG_INDEX_1;
303 auto context = make_shared<EnrollAsyncContext>(env);
304 if (context == nullptr) {
305 INTELL_VOICE_LOG_ERROR("create StartContext failed, No memory");
306 return nullptr;
307 }
308
309 CbInfoParser parser = [env, context](size_t argc, napi_value *argv) -> bool {
310 CHECK_CONDITION_RETURN_FALSE((argc < ARGC_ONE), "argc less than 1");
311 napi_status status = GetValue(env, argv[0],
312 reinterpret_cast<EnrollIntellVoiceEngineNapi *>(context->instanceNapi_)->isLast_);
313 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "Failed to get isLast");
314 return true;
315 };
316
317 context->result_ = (context->GetCbInfo(env, info, cbIndex, parser) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
318 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
319
320 context->type = ASYNC_WORK_START;
321 context->callbackInfo.result = UNKNOWN_ERROR;
322 context->processWork = [&](AsyncContext *asyncContext) {
323 EnrollIntellVoiceEngineNapi *engineNapi = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(
324 asyncContext->instanceNapi_);
325 auto engine = engineNapi->engine_;
326 if (engine == nullptr) {
327 INTELL_VOICE_LOG_ERROR("get engine instance failed");
328 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_PERMISSION_DENIED;
329 return -1;
330 }
331
332 auto ret = engine->Start(engineNapi->isLast_);
333 if (ret != 0) {
334 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_PERMISSION_DENIED;
335 }
336 return ret;
337 };
338
339 AsyncExecute execute = [](napi_env env, void *data) {};
340
341 return NapiAsync::AsyncWork(env, context, "Start", execute, CompleteCallback);
342 }
343
Stop(napi_env env,napi_callback_info info)344 napi_value EnrollIntellVoiceEngineNapi::Stop(napi_env env, napi_callback_info info)
345 {
346 INTELL_VOICE_LOG_INFO("enter");
347 size_t cbIndex = ARG_INDEX_0;
348 auto context = make_shared<AsyncContext>(env);
349 if (context == nullptr) {
350 INTELL_VOICE_LOG_ERROR("create AsyncContext failed, No memory");
351 return nullptr;
352 }
353
354 context->result_ = (context->GetCbInfo(env, info, cbIndex, nullptr) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
355 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
356
357 auto cb = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(context->instanceNapi_)->callbackNapi_;
358 if (cb != nullptr) {
359 cb->ClearAsyncWork(false, "the requests was aborted because user called stop");
360 }
361
362 AsyncExecute execute;
363 if (context->result_ == NAPI_INTELLIGENT_VOICE_SUCCESS) {
364 execute = [](napi_env env, void *data) {
365 CHECK_CONDITION_RETURN_VOID((data == nullptr), "data is nullptr");
366 auto asyncContext = static_cast<AsyncContext *>(data);
367 auto engine = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->engine_;
368 CHECK_CONDITION_RETURN_VOID((engine == nullptr), "get engine instance failed");
369 engine->Stop();
370 };
371 } else {
372 execute = [](napi_env env, void *data) {};
373 }
374
375 return NapiAsync::AsyncWork(env, context, "Stop", execute);
376 }
377
SetParameter(napi_env env,napi_callback_info info)378 napi_value EnrollIntellVoiceEngineNapi::SetParameter(napi_env env, napi_callback_info info)
379 {
380 INTELL_VOICE_LOG_INFO("enter");
381 size_t cbIndex = ARG_INDEX_2;
382 class SetParameterContext : public AsyncContext {
383 public:
384 explicit SetParameterContext(napi_env napiEnv): AsyncContext(napiEnv) {};
385 string key;
386 string value;
387 };
388 auto context = make_shared<SetParameterContext>(env);
389 if (context == nullptr) {
390 INTELL_VOICE_LOG_ERROR("create SetParameterContext failed, No memory");
391 return nullptr;
392 }
393
394 CbInfoParser parser = [env, context](size_t argc, napi_value *argv) -> bool {
395 CHECK_CONDITION_RETURN_FALSE((argc < ARGC_TWO), "argc less than 2");
396 napi_status status = GetValue(env, argv[0], context->key);
397 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "Failed to get key");
398 status = GetValue(env, argv[1], context->value);
399 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "Failed to get value");
400 return true;
401 };
402
403 context->result_ = (context->GetCbInfo(env, info, cbIndex, parser) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
404 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
405
406 AsyncExecute execute;
407 if (context->result_ == NAPI_INTELLIGENT_VOICE_SUCCESS) {
408 execute = [](napi_env env, void *data) {
409 CHECK_CONDITION_RETURN_VOID((data == nullptr), "data is nullptr");
410 auto asyncContext = static_cast<SetParameterContext *>(data);
411 auto engine = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->engine_;
412 CHECK_CONDITION_RETURN_VOID((engine == nullptr), "get engine instance failed");
413 engine->SetParameter(asyncContext->key, asyncContext->value);
414 };
415 } else {
416 execute = [](napi_env env, void *data) {};
417 }
418
419 return NapiAsync::AsyncWork(env, context, "SetParameter", execute);
420 }
421
GetParameter(napi_env env,napi_callback_info info)422 napi_value EnrollIntellVoiceEngineNapi::GetParameter(napi_env env, napi_callback_info info)
423 {
424 INTELL_VOICE_LOG_INFO("enter");
425 size_t cbIndex = ARG_INDEX_1;
426 shared_ptr<AsyncContext> context = make_shared<AsyncContext>(env);
427 if (context == nullptr) {
428 INTELL_VOICE_LOG_ERROR("create AsyncContext failed, No memory");
429 return nullptr;
430 }
431
432 context->result_ = (context->GetCbInfo(env, info, cbIndex, nullptr) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
433 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
434
435 AsyncExecute execute = [](napi_env env, void *data) {};
436
437 context->complete_ = [](napi_env env, AsyncContext *asyncContext, napi_value &result) {
438 INTELL_VOICE_LOG_INFO("get parameter enter");
439 result = SetValue(env, "value");
440 };
441
442 return NapiAsync::AsyncWork(env, context, "GetParameter", execute);
443 }
444
SetSensibility(napi_env env,napi_callback_info info)445 napi_value EnrollIntellVoiceEngineNapi::SetSensibility(napi_env env, napi_callback_info info)
446 {
447 INTELL_VOICE_LOG_INFO("enter");
448 size_t cbIndex = ARG_INDEX_1;
449 class SetSensibilityContext : public AsyncContext {
450 public:
451 explicit SetSensibilityContext(napi_env napiEnv) : AsyncContext(napiEnv) {};
452 int32_t sensibility = 1;
453 };
454 auto context = make_shared<SetSensibilityContext>(env);
455 if (context == nullptr) {
456 INTELL_VOICE_LOG_ERROR("create SetSensibilityContext failed, No memory");
457 return nullptr;
458 }
459
460 CbInfoParser parser = [env, context](size_t argc, napi_value *argv) -> bool {
461 CHECK_CONDITION_RETURN_FALSE((argc < ARGC_ONE), "argc less than 1");
462 napi_status status = GetValue(env, argv[0], context->sensibility);
463 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "Failed to get sensibility");
464 return true;
465 };
466
467 context->result_ = (context->GetCbInfo(env, info, cbIndex, parser) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
468 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
469
470 AsyncExecute execute = [](napi_env env, void *data) {
471 CHECK_CONDITION_RETURN_VOID((data == nullptr), "data is nullptr");
472 auto asyncContext = static_cast<SetSensibilityContext *>(data);
473 CHECK_CONDITION_RETURN_VOID((asyncContext->result_ != NAPI_INTELLIGENT_VOICE_SUCCESS), "no need to execute");
474 auto engine = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->engine_;
475 CHECK_CONDITION_RETURN_VOID((engine == nullptr), "get engine instance failed");
476 engine->SetSensibility(asyncContext->sensibility);
477 };
478
479 return NapiAsync::AsyncWork(env, context, "SetSensibility", execute);
480 }
481
SetWakeupHapInfo(napi_env env,napi_callback_info info)482 napi_value EnrollIntellVoiceEngineNapi::SetWakeupHapInfo(napi_env env, napi_callback_info info)
483 {
484 INTELL_VOICE_LOG_INFO("enter");
485 size_t cbIndex = ARG_INDEX_1;
486 class SetWakeupHapContext : public AsyncContext {
487 public:
488 explicit SetWakeupHapContext(napi_env napiEnv) : AsyncContext(napiEnv) {};
489 WakeupHapInfo hapInfo;
490 };
491 auto context = make_shared<SetWakeupHapContext>(env);
492 if (context == nullptr) {
493 INTELL_VOICE_LOG_ERROR("create SetWakeupHapContext failed, No memory");
494 return nullptr;
495 }
496
497 CbInfoParser parser = [env, context](size_t argc, napi_value *argv) -> bool {
498 CHECK_CONDITION_RETURN_FALSE((argc < ARGC_ONE), "argc less than 1");
499 napi_value temp = nullptr;
500 napi_status status = napi_get_named_property(env, argv[0], "bundleName", &temp);
501 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get property failed");
502 status = GetValue(env, temp, context->hapInfo.bundleName);
503 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get bundle name failed");
504 status = napi_get_named_property(env, argv[0], "abilityName", &temp);
505 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get property failed");
506 status = GetValue(env, temp, context->hapInfo.abilityName);
507 CHECK_CONDITION_RETURN_FALSE((status != napi_ok), "get ability name failed");
508 return true;
509 };
510
511 context->result_ = (context->GetCbInfo(env, info, cbIndex, parser) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
512 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
513
514 AsyncExecute execute = [](napi_env env, void *data) {
515 CHECK_CONDITION_RETURN_VOID((data == nullptr), "data is nullptr");
516 auto asyncContext = static_cast<SetWakeupHapContext *>(data);
517 CHECK_CONDITION_RETURN_VOID((asyncContext->result_ != NAPI_INTELLIGENT_VOICE_SUCCESS), "no need to execute");
518 auto engine = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->engine_;
519 CHECK_CONDITION_RETURN_VOID((engine == nullptr), "get engine instance failed");
520 engine->SetWakeupHapInfo(asyncContext->hapInfo);
521 };
522
523 return NapiAsync::AsyncWork(env, context, "SetWakeupHapInfo", execute);
524 }
525
Commit(napi_env env,napi_callback_info info)526 napi_value EnrollIntellVoiceEngineNapi::Commit(napi_env env, napi_callback_info info)
527 {
528 INTELL_VOICE_LOG_INFO("enter");
529 size_t cbIndex = ARG_INDEX_0;
530 auto context = make_shared<EnrollAsyncContext>(env);
531 if (context == nullptr) {
532 INTELL_VOICE_LOG_ERROR("create IntellVoiceContext failed, No memory");
533 return nullptr;
534 }
535
536 context->result_ = (context->GetCbInfo(env, info, cbIndex, nullptr) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
537 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
538
539 context->type = ASYNC_WORK_COMMIT;
540 context->callbackInfo.result = UNKNOWN_ERROR;
541 context->processWork = [&](AsyncContext *asyncContext) {
542 auto engineNapi = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_);
543 auto engine = engineNapi->engine_;
544 if (engine == nullptr) {
545 INTELL_VOICE_LOG_ERROR("get engine instance failed");
546 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED;
547 return -1;
548 }
549
550 auto ret = engine->Commit();
551 if (ret != 0) {
552 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_COMMIT_ENROLL_FAILED;
553 }
554 return ret;
555 };
556
557 AsyncExecute execute = [](napi_env env, void *data) {};
558
559 return NapiAsync::AsyncWork(env, context, "Commit", execute, CompleteCallback);
560 }
561
EvaluateForResult(napi_env env,napi_callback_info info)562 napi_value EnrollIntellVoiceEngineNapi::EvaluateForResult(napi_env env, napi_callback_info info)
563 {
564 INTELL_VOICE_LOG_INFO("enter");
565 size_t cbIndex = ARG_INDEX_1;
566 auto context = make_shared<EvaluateContext>(env);
567 if (context == nullptr) {
568 INTELL_VOICE_LOG_ERROR("create EvaluateContext failed, No memory");
569 return nullptr;
570 }
571
572 CbInfoParser parser = [env, context](size_t argc, napi_value *argv) -> bool {
573 CHECK_CONDITION_RETURN_FALSE((argc < ARGC_ONE), "argc less than 1");
574 CHECK_CONDITION_RETURN_FALSE((GetValue(env, argv[ARG_INDEX_0], context->word) != napi_ok),
575 "failed to get word");
576 return true;
577 };
578
579 context->result_ = (context->GetCbInfo(env, info, cbIndex, parser) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
580 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
581
582 AsyncExecute execute;
583 if (context->result_ == NAPI_INTELLIGENT_VOICE_SUCCESS) {
584 execute = [](napi_env env, void *data) {
585 CHECK_CONDITION_RETURN_VOID((data == nullptr), "data is nullptr");
586 auto context = static_cast<EvaluateContext *>(data);
587 auto engine = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(context->instanceNapi_)->engine_;
588 if (engine == nullptr) {
589 INTELL_VOICE_LOG_ERROR("engine is nullptr");
590 context->result_ = NAPI_INTELLIGENT_VOICE_NO_MEMORY;
591 return;
592 }
593 auto ret = engine->Evaluate(context->word, context->info);
594 if (ret != 0) {
595 INTELL_VOICE_LOG_ERROR("failed to evaluate");
596 context->result_ = NAPI_INTELLIGENT_VOICE_SYSTEM_ERROR;
597 }
598 };
599 } else {
600 execute = [](napi_env env, void *data) {};
601 }
602
603 context->complete_ = [](napi_env env, AsyncContext *asyncContext, napi_value &result) {
604 INTELL_VOICE_LOG_INFO("enter to evaluate");
605 auto context = static_cast<EvaluateContext *>(asyncContext);
606 napi_status status = napi_create_object(env, &result);
607 if (status != napi_ok || result == nullptr) {
608 INTELL_VOICE_LOG_ERROR("failed to create js callbackInfo, error: %{public}d", status);
609 context->result_ = NAPI_INTELLIGENT_VOICE_NO_MEMORY;
610 return;
611 }
612
613 napi_set_named_property(env, result, "score", SetValue(env, context->info.score));
614 napi_set_named_property(env, result, "resultCode", SetValue(env, context->info.resultCode));
615 };
616 return NapiAsync::AsyncWork(env, context, "Evaluate", execute);
617 }
618
Release(napi_env env,napi_callback_info info)619 napi_value EnrollIntellVoiceEngineNapi::Release(napi_env env, napi_callback_info info)
620 {
621 INTELL_VOICE_LOG_INFO("enter");
622 size_t cbIndex = ARG_INDEX_0;
623 shared_ptr<AsyncContext> context = make_shared<AsyncContext>(env);
624 if (context == nullptr) {
625 INTELL_VOICE_LOG_ERROR("create AsyncContext failed, No memory");
626 return nullptr;
627 }
628
629 context->result_ = (context->GetCbInfo(env, info, cbIndex, nullptr) ? NAPI_INTELLIGENT_VOICE_SUCCESS :
630 NAPI_INTELLIGENT_VOICE_INVALID_PARAM);
631
632 AsyncExecute execute;
633 if (context->result_ == NAPI_INTELLIGENT_VOICE_SUCCESS) {
634 execute = [](napi_env env, void *data) {
635 CHECK_CONDITION_RETURN_VOID((data == nullptr), "data is nullptr");
636 auto asyncContext = static_cast<AsyncContext *>(data);
637 auto cb = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->callbackNapi_;
638 if (cb != nullptr) {
639 cb->ClearAsyncWork(false, "the requests was aborted because user called release");
640 }
641 auto engine = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->engine_;
642 CHECK_CONDITION_RETURN_VOID((engine == nullptr), "get engine instance failed");
643 engine->Release();
644 reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->engine_ = nullptr;
645 reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->callbackNapi_ = nullptr;
646 };
647 } else {
648 execute = [](napi_env env, void *data) {};
649 }
650
651 return NapiAsync::AsyncWork(env, context, "Release", execute);
652 }
653
CompleteCallback(napi_env env,napi_status status,void * data)654 void EnrollIntellVoiceEngineNapi::CompleteCallback(napi_env env, napi_status status, void *data)
655 {
656 INTELL_VOICE_LOG_INFO("enter");
657 CHECK_CONDITION_RETURN_VOID((data == nullptr), "async complete callback data is nullptr");
658 napi_value result = nullptr;
659
660 auto asyncContext = static_cast<EnrollAsyncContext *>(data);
661 if (asyncContext->result_ != NAPI_INTELLIGENT_VOICE_SUCCESS) {
662 napi_get_undefined(env, &result);
663 NapiAsync::CommonCallbackRoutine(env, asyncContext, result);
664 return;
665 }
666
667 if (asyncContext->processWork == nullptr) {
668 INTELL_VOICE_LOG_ERROR("process work is nullptr");
669 napi_get_undefined(env, &result);
670 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_NO_MEMORY;
671 NapiAsync::CommonCallbackRoutine(env, asyncContext, result);
672 return;
673 }
674
675 auto cb = reinterpret_cast<EnrollIntellVoiceEngineNapi *>(asyncContext->instanceNapi_)->callbackNapi_;
676 if (cb == nullptr) {
677 INTELL_VOICE_LOG_ERROR("get callback napi failed");
678 napi_get_undefined(env, &result);
679 asyncContext->result_ = NAPI_INTELLIGENT_VOICE_NO_MEMORY;
680 NapiAsync::CommonCallbackRoutine(env, asyncContext, result);
681 return;
682 }
683
684 cb->QueueAsyncWork(asyncContext);
685 if (asyncContext->processWork(asyncContext) != 0) {
686 INTELL_VOICE_LOG_ERROR("process work failed");
687 cb->ClearAsyncWork(true, "the request was aborted because intelligent voice processWork error");
688 }
689 }
690 } // namespace IntellVoiceNapi
691 } // namespace OHOS
692