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