• 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 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