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