• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "ability.h"
17 #include "audio_common_napi.h"
18 #include "audio_errors.h"
19 #include "audio_info.h"
20 #include "audio_log.h"
21 #include "audio_manager_napi.h"
22 #include "audio_parameters_napi.h"
23 #include "hilog/log.h"
24 #include "napi_base_context.h"
25 #include "securec.h"
26 #include "tone_player.h"
27 #include "toneplayer_napi.h"
28 
29 using namespace std;
30 using OHOS::HiviewDFX::HiLog;
31 using OHOS::HiviewDFX::HiLogLabel;
32 
33 namespace OHOS {
34 namespace AudioStandard {
35 static __thread napi_ref g_tonePlayerConstructor = nullptr;
36 std::unique_ptr<AudioRendererInfo> TonePlayerNapi::sRendererInfo_ = nullptr;
37 napi_ref TonePlayerNapi::toneType_ = nullptr;
38 mutex TonePlayerNapi::createMutex_;
39 namespace {
40     const int ARGS_ONE = 1;
41     const int ARGS_TWO = 2;
42 
43     const int PARAM0 = 0;
44     const int PARAM1 = 1;
45 
46     constexpr HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "TonePlayerNapi"};
47 
48 #define GET_PARAMS(env, info, num) \
49     size_t argc = num;             \
50     napi_value argv[num] = {0};    \
51     napi_value thisVar = nullptr;  \
52     void *data;                    \
53     napi_get_cb_info(env, info, &argc, argv, &thisVar, &data)
54 }
TonePlayerNapi()55 TonePlayerNapi::TonePlayerNapi()
56     : env_(nullptr), tonePlayer_(nullptr) {}
57 
58 TonePlayerNapi::~TonePlayerNapi() = default;
59 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)60 void TonePlayerNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
61 {
62     if (nativeObject != nullptr) {
63         auto obj = static_cast<TonePlayerNapi *>(nativeObject);
64         delete obj;
65         obj = nullptr;
66     }
67 }
68 
AddNamedProperty(napi_env env,napi_value object,const std::string name,int32_t enumValue)69 napi_status TonePlayerNapi::AddNamedProperty(napi_env env, napi_value object,
70     const std::string name, int32_t enumValue)
71 {
72     napi_status status;
73     napi_value enumNapiValue;
74 
75     status = napi_create_int32(env, enumValue, &enumNapiValue);
76     if (status == napi_ok) {
77         status = napi_set_named_property(env, object, name.c_str(), enumNapiValue);
78     }
79     return status;
80 }
81 
CreateToneTypeObject(napi_env env)82 napi_value TonePlayerNapi::CreateToneTypeObject(napi_env env)
83 {
84     napi_value result = nullptr;
85     napi_status status;
86     AUDIO_DEBUG_LOG("CreateToneTypeObject start");
87     status = napi_create_object(env, &result);
88     if (status == napi_ok) {
89         AUDIO_DEBUG_LOG("CreateToneTypeObject: napi_create_object");
90         std::string propName;
91         for (auto &iter: toneTypeMap) {
92             propName = iter.first;
93             status = AddNamedProperty(env, result, propName, iter.second);
94             if (status != napi_ok) {
95                 HiLog::Error(LABEL, "Failed to add named prop in CreateToneTypeObject!");
96                 break;
97             }
98             propName.clear();
99         }
100         int32_t refCount = 1;
101         if (status == napi_ok) {
102             AUDIO_DEBUG_LOG("CreateToneTypeObject: AddNamedProperty");
103             status = napi_create_reference(env, result, refCount, &toneType_);
104             if (status == napi_ok) {
105                 return result;
106             }
107         }
108     }
109     HiLog::Error(LABEL, "CreateToneTypeObject is Failed!");
110     napi_get_undefined(env, &result);
111 
112     return result;
113 }
114 
ParseRendererInfo(napi_env env,napi_value root,AudioRendererInfo * rendererInfo)115 bool TonePlayerNapi::ParseRendererInfo(napi_env env, napi_value root, AudioRendererInfo *rendererInfo)
116 {
117     napi_value tempValue = nullptr;
118     int32_t intValue = {0};
119     AUDIO_DEBUG_LOG("ParseRendererInfo::Init");
120     if (napi_get_named_property(env, root, "content", &tempValue) == napi_ok) {
121         napi_get_value_int32(env, tempValue, &intValue);
122         rendererInfo->contentType = static_cast<ContentType>(intValue);
123     }
124 
125     if (napi_get_named_property(env, root, "usage", &tempValue) == napi_ok) {
126         napi_get_value_int32(env, tempValue, &intValue);
127         rendererInfo->streamUsage = static_cast<StreamUsage>(intValue);
128     }
129 
130     if (napi_get_named_property(env, root, "rendererFlags", &tempValue) == napi_ok) {
131         napi_get_value_int32(env, tempValue, &(rendererInfo->rendererFlags));
132     }
133     return true;
134 }
135 
CreateTonePlayerWrapper(napi_env env,unique_ptr<AudioRendererInfo> & rendererInfo)136 napi_value TonePlayerNapi::CreateTonePlayerWrapper(napi_env env, unique_ptr<AudioRendererInfo> &rendererInfo)
137 {
138     lock_guard<mutex> lock(createMutex_);
139     napi_status status;
140     napi_value result = nullptr;
141     napi_value constructor;
142 
143     if (rendererInfo != nullptr) {
144         status = napi_get_reference_value(env, g_tonePlayerConstructor, &constructor);
145         if (status == napi_ok) {
146             sRendererInfo_ = move(rendererInfo);
147             status = napi_new_instance(env, constructor, 0, nullptr, &result);
148             sRendererInfo_.release();
149             if (status == napi_ok) {
150                 return result;
151             }
152         }
153         HiLog::Error(LABEL, "Failed in CreateAudioRendererWrapper, %{public}d", status);
154     }
155 
156     napi_get_undefined(env, &result);
157     return result;
158 }
159 
CommonCallbackRoutine(napi_env env,TonePlayerAsyncContext * & asyncContext,const napi_value & valueParam)160 void TonePlayerNapi::CommonCallbackRoutine(napi_env env, TonePlayerAsyncContext* &asyncContext,
161     const napi_value &valueParam)
162 {
163     napi_value result[ARGS_TWO] = {0};
164     napi_value retVal;
165 
166     if (!asyncContext->status) {
167         napi_get_undefined(env, &result[PARAM0]);
168         result[PARAM1] = valueParam;
169     } else {
170         napi_value message = nullptr;
171         std::string messageValue = AudioCommonNapi::getMessageByCode(asyncContext->status);
172         napi_create_string_utf8(env, messageValue.c_str(), NAPI_AUTO_LENGTH, &message);
173 
174         napi_value code = nullptr;
175         napi_create_string_utf8(env, (std::to_string(asyncContext->status)).c_str(), NAPI_AUTO_LENGTH, &code);
176 
177         napi_create_error(env, code, message, &result[PARAM0]);
178         napi_get_undefined(env, &result[PARAM1]);
179     }
180 
181     if (asyncContext->deferred) {
182         if (!asyncContext->status) {
183             napi_resolve_deferred(env, asyncContext->deferred, result[PARAM1]);
184         } else {
185             napi_reject_deferred(env, asyncContext->deferred, result[PARAM0]);
186         }
187     } else {
188         napi_value callback = nullptr;
189         napi_get_reference_value(env, asyncContext->callbackRef, &callback);
190         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
191         napi_delete_reference(env, asyncContext->callbackRef);
192     }
193     napi_delete_async_work(env, asyncContext->work);
194 
195     delete asyncContext;
196     asyncContext = nullptr;
197 }
198 
GetTonePlayerAsyncCallbackComplete(napi_env env,napi_status status,void * data)199 void TonePlayerNapi::GetTonePlayerAsyncCallbackComplete(napi_env env, napi_status status, void *data)
200 {
201     napi_value valueParam = nullptr;
202     auto asyncContext = static_cast<TonePlayerAsyncContext *>(data);
203 
204     if (asyncContext != nullptr) {
205         if (!asyncContext->status) {
206             unique_ptr<AudioRendererInfo> rendererInfo = make_unique<AudioRendererInfo>();
207             rendererInfo->contentType = asyncContext->rendererInfo.contentType;
208             rendererInfo->streamUsage = asyncContext->rendererInfo.streamUsage;
209             rendererInfo->rendererFlags = asyncContext->rendererInfo.rendererFlags;
210 
211             valueParam = CreateTonePlayerWrapper(env, rendererInfo);
212         }
213         CommonCallbackRoutine(env, asyncContext, valueParam);
214     } else {
215         HiLog::Error(LABEL, "ERROR: GetTonePlayerAsyncCallbackComplete asyncContext is Null!");
216     }
217 }
218 
CreateTonePlayer(napi_env env,napi_callback_info info)219 napi_value TonePlayerNapi::CreateTonePlayer(napi_env env, napi_callback_info info)
220 {
221     HiLog::Info(LABEL, "%{public}s IN", __func__);
222     napi_status status;
223     napi_value result = nullptr;
224     bool inputRight = true;
225 
226     GET_PARAMS(env, info, ARGS_TWO);
227 
228     unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
229     CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "TonePlayerAsyncContext object creation failed");
230     if (argc < ARGS_ONE) {
231         asyncContext->status = NAPI_ERR_INVALID_PARAM;
232     }
233 
234     for (size_t i = PARAM0; i < argc; i++) {
235         napi_valuetype valueType = napi_undefined;
236         napi_typeof(env, argv[i], &valueType);
237         if (i == PARAM0 && valueType == napi_object) {
238             if (!ParseRendererInfo(env, argv[i], &(asyncContext->rendererInfo))) {
239                 HiLog::Error(LABEL, "Parsing of renderer options failed");
240                 inputRight = false;
241             }
242         } else if (i == PARAM1) {
243             if (valueType == napi_function) {
244                 napi_create_reference(env, argv[i], REFERENCE_CREATION_COUNT, &asyncContext->callbackRef);
245             }
246             break;
247         } else {
248             HiLog::Error(LABEL, "type mismatch");
249             inputRight = false;
250         }
251     }
252 
253     if (asyncContext->callbackRef == nullptr) {
254         napi_create_promise(env, &asyncContext->deferred, &result);
255     } else {
256         napi_get_undefined(env, &result);
257     }
258     AUDIO_DEBUG_LOG("CreateTonePlayer::CreateAsyncWork");
259     napi_value resource = nullptr;
260     napi_create_string_utf8(env, "CreateTonePlayer", NAPI_AUTO_LENGTH, &resource);
261 
262     if (!inputRight) {
263         status = napi_create_async_work(
264             env, nullptr, resource,
265             [](napi_env env, void *data) {
266                 auto context = static_cast<TonePlayerAsyncContext *>(data);
267                 context->status = NAPI_ERR_INVALID_PARAM;
268                 HiLog::Error(LABEL, "CreateTonePlayer fail, invalid param!");
269             },
270             GetTonePlayerAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
271     } else {
272         status = napi_create_async_work(
273             env, nullptr, resource,
274             [](napi_env env, void *data) {
275                 auto context = static_cast<TonePlayerAsyncContext *>(data);
276                 context->status = SUCCESS;
277             },
278             GetTonePlayerAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
279     }
280     if (status != napi_ok) {
281         napi_delete_reference(env, asyncContext->callbackRef);
282         result = nullptr;
283     } else {
284         status = napi_queue_async_work(env, asyncContext->work);
285         if (status == napi_ok) {
286             asyncContext.release();
287         } else {
288             result = nullptr;
289         }
290     }
291     AUDIO_DEBUG_LOG("CreateTonePlayer::finished");
292     return result;
293 }
294 
GetAbilityContext(napi_env env)295 static shared_ptr<AbilityRuntime::Context> GetAbilityContext(napi_env env)
296 {
297     HiLog::Info(LABEL, "Getting context with FA model");
298     auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
299     if (ability == nullptr) {
300         HiLog::Error(LABEL, "Failed to obtain ability in FA mode");
301         return nullptr;
302     }
303 
304     auto faContext = ability->GetAbilityContext();
305     if (faContext == nullptr) {
306         HiLog::Error(LABEL, "GetAbilityContext returned null in FA model");
307         return nullptr;
308     }
309     return faContext;
310 }
311 
Construct(napi_env env,napi_callback_info info)312 napi_value TonePlayerNapi::Construct(napi_env env, napi_callback_info info)
313 {
314     napi_status status;
315     napi_value result = nullptr;
316     napi_get_undefined(env, &result);
317 
318     GET_PARAMS(env, info, ARGS_TWO);
319 
320     unique_ptr<TonePlayerNapi> tonePlayerNapi = make_unique<TonePlayerNapi>();
321     CHECK_AND_RETURN_RET_LOG(tonePlayerNapi != nullptr, result, "No memory");
322 
323     tonePlayerNapi->env_ = env;
324     AudioRendererInfo rendererInfo = {};
325     CHECK_AND_RETURN_RET_LOG(sRendererInfo_ != nullptr, result, "Construct sRendererInfo_ is null");
326     rendererInfo.contentType = sRendererInfo_->contentType;
327     rendererInfo.streamUsage = sRendererInfo_->streamUsage;
328     rendererInfo.rendererFlags = sRendererInfo_->rendererFlags;
329     std::shared_ptr<AbilityRuntime::Context> abilityContext = GetAbilityContext(env);
330     std::string cacheDir = "";
331     if (abilityContext != nullptr) {
332         cacheDir = abilityContext->GetCacheDir();
333     } else {
334         cacheDir = "/data/storage/el2/base/haps/entry/files";
335     }
336     tonePlayerNapi->tonePlayer_ = TonePlayer::Create(cacheDir, rendererInfo);
337 
338     CHECK_AND_RETURN_RET_LOG(tonePlayerNapi->tonePlayer_ != nullptr, result, "Toneplayer Create failed");
339 
340     status = napi_wrap(env, thisVar, static_cast<void*>(tonePlayerNapi.get()),
341                        TonePlayerNapi::Destructor, nullptr, nullptr);
342     if (status == napi_ok) {
343         tonePlayerNapi.release();
344         return thisVar;
345     }
346 
347     HiLog::Error(LABEL, "Failed in TonePlayerNapi::Construct()!");
348     return result;
349 }
350 
toneTypeCheck(napi_env env,int32_t type)351 bool TonePlayerNapi::toneTypeCheck(napi_env env, int32_t type)
352 {
353     int32_t len = sizeof(toneTypeArr) / sizeof(toneTypeArr[0]);
354     for (int32_t i = 0; i < len; i++) {
355         if (toneTypeArr[i] == type) {
356             return true;
357         }
358     }
359     return false;
360 }
361 
Load(napi_env env,napi_callback_info info)362 napi_value TonePlayerNapi::Load(napi_env env, napi_callback_info info)
363 {
364     napi_status status;
365     const int32_t refCount = 1;
366     napi_value result = nullptr;
367     bool inputRight = true;
368 
369     GET_PARAMS(env, info, ARGS_TWO);
370 
371     unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
372     CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, result, "Load TonePlayerAsyncContext object creation failed");
373     if (argc < ARGS_ONE) {
374         asyncContext->status = NAPI_ERR_INVALID_PARAM;
375     }
376 
377     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
378     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
379         for (size_t i = PARAM0; i < argc; i++) {
380             napi_valuetype valueType = napi_undefined;
381             napi_typeof(env, argv[i], &valueType);
382 
383             if (i == PARAM0 && valueType == napi_number) {
384                 napi_get_value_int32(env, argv[PARAM0], &asyncContext->toneType);
385                 if (!toneTypeCheck(env, asyncContext->toneType)) {
386                     HiLog::Error(LABEL, "The Load parameter is invalid");
387                     inputRight = false;
388                 }
389             } else if (i == PARAM1) {
390                 if (valueType == napi_function) {
391                     napi_create_reference(env, argv[i], refCount, &asyncContext->callbackRef);
392                 }
393                 break;
394             } else {
395                 HiLog::Error(LABEL, "type mismatch");
396                 inputRight = false;
397             }
398         }
399 
400         if (asyncContext->callbackRef == nullptr) {
401             napi_create_promise(env, &asyncContext->deferred, &result);
402         } else {
403             napi_get_undefined(env, &result);
404         }
405 
406         napi_value resource = nullptr;
407         napi_create_string_utf8(env, "Load", NAPI_AUTO_LENGTH, &resource);
408 
409         if (!inputRight) {
410             status = napi_create_async_work(
411                 env, nullptr, resource,
412                 [](napi_env env, void *data) {
413                     auto context = static_cast<TonePlayerAsyncContext *>(data);
414                     context->status = NAPI_ERR_INVALID_PARAM;
415                     HiLog::Error(LABEL, "The Load parameter is invalid");
416                 },
417                 VoidAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
418         } else {
419             status = napi_create_async_work(
420                 env, nullptr, resource,
421                 [](napi_env env, void *data) {
422                     auto context = static_cast<TonePlayerAsyncContext *>(data);
423                     if (context->status == SUCCESS) {
424                         ToneType toneType = static_cast<ToneType>(context->toneType);
425                         context->intValue = context->objectInfo->tonePlayer_->LoadTone(toneType);
426                         if (context->intValue) {
427                             context->status = SUCCESS;
428                         } else {
429                             context->status = NAPI_ERR_SYSTEM;
430                         }
431                     }
432                 },
433                 VoidAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
434         }
435         if (status != napi_ok) {
436             result = nullptr;
437         } else {
438             status = napi_queue_async_work(env, asyncContext->work);
439             if (status == napi_ok) {
440                 asyncContext.release();
441             } else {
442                 result = nullptr;
443             }
444         }
445     }
446     return result;
447 }
448 
Start(napi_env env,napi_callback_info info)449 napi_value TonePlayerNapi::Start(napi_env env, napi_callback_info info)
450 {
451     napi_status status;
452     const int32_t refCount = 1;
453     napi_value result = nullptr;
454 
455     GET_PARAMS(env, info, ARGS_ONE);
456 
457     unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
458     CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "Start TonePlayerAsyncContext object creation failed");
459 
460     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
461     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
462         if (argc > PARAM0) {
463             napi_valuetype valueType = napi_undefined;
464             napi_typeof(env, argv[PARAM0], &valueType);
465             if (valueType == napi_function) {
466                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
467             }
468         }
469 
470         if (asyncContext->callbackRef == nullptr) {
471             napi_create_promise(env, &asyncContext->deferred, &result);
472         } else {
473             napi_get_undefined(env, &result);
474         }
475 
476         napi_value resource = nullptr;
477         napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
478 
479         status = napi_create_async_work(
480             env, nullptr, resource,
481             [](napi_env env, void *data) {
482                 auto context = static_cast<TonePlayerAsyncContext *>(data);
483                 context->isTrue = context->objectInfo->tonePlayer_->StartTone();
484                 if (context->isTrue) {
485                     context->status = SUCCESS;
486                 } else {
487                     HiLog::Error(LABEL, "Start call failed, wrong timing!");
488                     context->status = NAPI_ERR_SYSTEM;
489                 }
490             },
491             VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
492         if (status != napi_ok) {
493             result = nullptr;
494         } else {
495             status = napi_queue_async_work(env, asyncContext->work);
496             if (status == napi_ok) {
497                 asyncContext.release();
498             } else {
499                 result = nullptr;
500             }
501         }
502     }
503     return result;
504 }
505 
Stop(napi_env env,napi_callback_info info)506 napi_value TonePlayerNapi::Stop(napi_env env, napi_callback_info info)
507 {
508     napi_status status;
509     const int32_t refCount = 1;
510     napi_value result = nullptr;
511 
512     GET_PARAMS(env, info, ARGS_ONE);
513 
514     unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
515     CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "Stop TonePlayerAsyncContext object creation failed");
516 
517     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
518     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
519         if (argc > PARAM0) {
520             napi_valuetype valueType = napi_undefined;
521             napi_typeof(env, argv[PARAM0], &valueType);
522             if (valueType == napi_function) {
523                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
524             }
525         }
526 
527         if (asyncContext->callbackRef == nullptr) {
528             napi_create_promise(env, &asyncContext->deferred, &result);
529         } else {
530             napi_get_undefined(env, &result);
531         }
532 
533         napi_value resource = nullptr;
534         napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
535 
536         status = napi_create_async_work(
537             env, nullptr, resource,
538             [](napi_env env, void *data) {
539                 auto context = static_cast<TonePlayerAsyncContext *>(data);
540                 context->isTrue = context->objectInfo->tonePlayer_->StopTone();
541                 if (context->isTrue) {
542                     context->status = SUCCESS;
543                 } else {
544                     HiLog::Error(LABEL, "Stop call failed, wrong timing");
545                     context->status = NAPI_ERR_SYSTEM;
546                 }
547             },
548             VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
549         if (status != napi_ok) {
550             result = nullptr;
551         } else {
552             status = napi_queue_async_work(env, asyncContext->work);
553             if (status == napi_ok) {
554                 asyncContext.release();
555             } else {
556                 result = nullptr;
557             }
558         }
559     }
560     return result;
561 }
562 
Release(napi_env env,napi_callback_info info)563 napi_value TonePlayerNapi::Release(napi_env env, napi_callback_info info)
564 {
565     napi_status status;
566     const int32_t refCount = 1;
567     napi_value result = nullptr;
568 
569     GET_PARAMS(env, info, ARGS_ONE);
570 
571     unique_ptr<TonePlayerAsyncContext> asyncContext = make_unique<TonePlayerAsyncContext>();
572     CHECK_AND_RETURN_RET_LOG(asyncContext != nullptr, nullptr, "Release TonePlayerAsyncContext object creation failed");
573 
574     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
575     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
576         if (argc > PARAM0) {
577             napi_valuetype valueType = napi_undefined;
578             napi_typeof(env, argv[PARAM0], &valueType);
579             if (valueType == napi_function) {
580                 napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
581             }
582         }
583 
584         if (asyncContext->callbackRef == nullptr) {
585             napi_create_promise(env, &asyncContext->deferred, &result);
586         } else {
587             napi_get_undefined(env, &result);
588         }
589 
590         napi_value resource = nullptr;
591         napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
592 
593         status = napi_create_async_work(
594             env, nullptr, resource,
595             [](napi_env env, void *data) {
596                 auto context = static_cast<TonePlayerAsyncContext *>(data);
597                 context->isTrue = context->objectInfo->tonePlayer_->Release();
598                 if (context->isTrue) {
599                     context->status = SUCCESS;
600                 } else {
601                     HiLog::Error(LABEL, "Release call failed, wrong timing");
602                     context->status = NAPI_ERR_SYSTEM;
603                 }
604             },
605             VoidAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
606         if (status != napi_ok) {
607             result = nullptr;
608         } else {
609             status = napi_queue_async_work(env, asyncContext->work);
610             if (status == napi_ok) {
611                 asyncContext.release();
612             } else {
613                 result = nullptr;
614             }
615         }
616     }
617     return result;
618 }
619 
VoidAsyncCallbackComplete(napi_env env,napi_status status,void * data)620 void TonePlayerNapi::VoidAsyncCallbackComplete(napi_env env, napi_status status, void *data)
621 {
622     auto asyncContext = static_cast<TonePlayerAsyncContext*>(data);
623     napi_value valueParam = nullptr;
624 
625     if (asyncContext != nullptr) {
626         if (!asyncContext->status) {
627             napi_get_undefined(env, &valueParam);
628         }
629         CommonCallbackRoutine(env, asyncContext, valueParam);
630     } else {
631         HiLog::Error(LABEL, "ERROR: VoidAsyncCallbackComplete* is Null!");
632     }
633 }
634 
Init(napi_env env,napi_value exports)635 napi_value TonePlayerNapi::Init(napi_env env, napi_value exports)
636 {
637     napi_status status;
638     napi_value constructor;
639     napi_value result = nullptr;
640     const int32_t refCount = 1;
641     napi_get_undefined(env, &result);
642     AUDIO_DEBUG_LOG("TonePlayerNapi::Init");
643     napi_property_descriptor audio_toneplayer_properties[] = {
644         DECLARE_NAPI_FUNCTION("load", Load),
645         DECLARE_NAPI_FUNCTION("start", Start),
646         DECLARE_NAPI_FUNCTION("stop", Stop),
647         DECLARE_NAPI_FUNCTION("release", Release),
648     };
649 
650     napi_property_descriptor static_prop[] = {
651         DECLARE_NAPI_STATIC_FUNCTION("createTonePlayer", CreateTonePlayer),
652         DECLARE_NAPI_PROPERTY("ToneType", CreateToneTypeObject(env)),
653     };
654 
655     status = napi_define_class(env, TONE_PLAYER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Construct, nullptr,
656         sizeof(audio_toneplayer_properties) / sizeof(audio_toneplayer_properties[PARAM0]),
657         audio_toneplayer_properties, &constructor);
658     if (status != napi_ok) {
659         return result;
660     }
661 
662     status = napi_create_reference(env, constructor, refCount, &g_tonePlayerConstructor);
663     if (status == napi_ok) {
664         AUDIO_DEBUG_LOG("TonePlayerNapi::Init napi_create_reference");
665         status = napi_set_named_property(env, exports, TONE_PLAYER_NAPI_CLASS_NAME.c_str(), constructor);
666         if (status == napi_ok) {
667             AUDIO_DEBUG_LOG("TonePlayerNapi::Init napi_set_named_property");
668             status = napi_define_properties(env, exports,
669                                             sizeof(static_prop) / sizeof(static_prop[PARAM0]), static_prop);
670             if (status == napi_ok) {
671                 AUDIO_DEBUG_LOG("TonePlayerNapi::Init napi_define_properties");
672                 return exports;
673             }
674         }
675     }
676 
677     HiLog::Error(LABEL, "Failure in TonePlayerNapi::Init()");
678     return result;
679 }
680 }
681 } //