• 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 "system_tone_player_napi.h"
17 
18 #include "system_sound_log.h"
19 #include "common_napi.h"
20 
21 namespace {
22 /* Constants for array index */
23 const int32_t PARAM0 = 0;
24 const int32_t PARAM1 = 1;
25 
26 /* Constants for array size */
27 const int32_t ARGS_ONE = 1;
28 const int32_t ARGS_TWO = 2;
29 
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "SystemTonePlayerNapi"};
31 }
32 
33 namespace OHOS {
34 namespace Media {
35 thread_local napi_ref SystemTonePlayerNapi::sConstructor_ = nullptr;
36 std::shared_ptr<SystemTonePlayer> SystemTonePlayerNapi::sSystemTonePlayer_ = nullptr;
37 
SystemTonePlayerNapi()38 SystemTonePlayerNapi::SystemTonePlayerNapi() : env_(nullptr) {}
39 
40 SystemTonePlayerNapi::~SystemTonePlayerNapi() = default;
41 
Init(napi_env env,napi_value exports)42 napi_value SystemTonePlayerNapi::Init(napi_env env, napi_value exports)
43 {
44     napi_status status;
45     napi_value ctorObj;
46     int32_t refCount = 1;
47 
48     napi_property_descriptor system_tone_player_prop[] = {
49         DECLARE_NAPI_FUNCTION("getTitle", GetTitle),
50         DECLARE_NAPI_FUNCTION("prepare", Prepare),
51         DECLARE_NAPI_FUNCTION("start", Start),
52         DECLARE_NAPI_FUNCTION("stop", Stop),
53         DECLARE_NAPI_FUNCTION("release", Release),
54     };
55 
56     status = napi_define_class(env, SYSTEM_TONE_PLAYER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
57         SystemTonePlayerNapiConstructor, nullptr, sizeof(system_tone_player_prop) / sizeof(system_tone_player_prop[0]),
58         system_tone_player_prop, &ctorObj);
59     if (status == napi_ok) {
60         if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
61             status = napi_set_named_property(env, exports, SYSTEM_TONE_PLAYER_NAPI_CLASS_NAME.c_str(), ctorObj);
62             if (status == napi_ok) {
63                 return exports;
64             }
65         }
66     }
67 
68     return nullptr;
69 }
70 
SystemTonePlayerNapiConstructor(napi_env env,napi_callback_info info)71 napi_value SystemTonePlayerNapi::SystemTonePlayerNapiConstructor(napi_env env, napi_callback_info info)
72 {
73     napi_status status;
74     napi_value result = nullptr;
75     napi_value thisVar = nullptr;
76 
77     napi_get_undefined(env, &result);
78     status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
79     if (status == napi_ok && thisVar != nullptr) {
80         std::unique_ptr<SystemTonePlayerNapi> obj = std::make_unique<SystemTonePlayerNapi>();
81         if (obj != nullptr) {
82             ObjectRefMap<SystemTonePlayerNapi>::Insert(obj.get());
83             obj->env_ = env;
84             if (obj->sSystemTonePlayer_ != nullptr) {
85                 obj->systemTonePlayer_ = move(obj->sSystemTonePlayer_);
86             } else {
87                 MEDIA_LOGE("Failed to create sSystemTonePlayer_ instance.");
88                 return result;
89             }
90 
91             status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
92                 SystemTonePlayerNapi::SystemTonePlayerNapiDestructor, nullptr, nullptr);
93             if (status == napi_ok) {
94                 obj.release();
95                 return thisVar;
96             } else {
97                 ObjectRefMap<SystemTonePlayerNapi>::Erase(obj.get());
98                 MEDIA_LOGE("Failed to wrap the native system tone player object with JS.");
99             }
100         }
101     }
102 
103     return result;
104 }
105 
SystemTonePlayerNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)106 void SystemTonePlayerNapi::SystemTonePlayerNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
107 {
108     SystemTonePlayerNapi *systemTonePlayerHelper = reinterpret_cast<SystemTonePlayerNapi*>(nativeObject);
109     if (systemTonePlayerHelper != nullptr) {
110         ObjectRefMap<SystemTonePlayerNapi>::DecreaseRef(systemTonePlayerHelper);
111     }
112 }
113 
GetSystemTonePlayerInstance(napi_env env,std::shared_ptr<SystemTonePlayer> & systemTonePlayer)114 napi_value SystemTonePlayerNapi::GetSystemTonePlayerInstance(napi_env env,
115     std::shared_ptr<SystemTonePlayer> &systemTonePlayer)
116 {
117     napi_status status;
118     napi_value result = nullptr;
119     napi_value ctor;
120 
121     status = napi_get_reference_value(env, sConstructor_, &ctor);
122     if (status == napi_ok) {
123         sSystemTonePlayer_ = systemTonePlayer;
124         status = napi_new_instance(env, ctor, 0, nullptr, &result);
125         if (status == napi_ok) {
126             return result;
127         } else {
128             MEDIA_LOGE("GetSystemTonePlayerInstance: New instance could not be obtained.");
129         }
130     }
131 
132     napi_get_undefined(env, &result);
133     return result;
134 }
135 
CommonAsyncCallbackComplete(napi_env env,napi_status status,void * data)136 void SystemTonePlayerNapi::CommonAsyncCallbackComplete(napi_env env, napi_status status, void* data)
137 {
138     auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
139     napi_value callback = nullptr;
140     napi_value retVal = nullptr;
141     napi_value result[2] = {};
142 
143     napi_get_undefined(env, &result[PARAM1]);
144     if (!context->status) {
145         napi_get_undefined(env, &result[PARAM0]);
146     } else {
147         napi_value message = nullptr;
148         napi_create_string_utf8(env, "Error: Operation is not supported or failed", NAPI_AUTO_LENGTH, &message);
149         napi_create_error(env, nullptr, message, &result[PARAM0]);
150     }
151 
152     if (context->deferred) {
153         if (!context->status) {
154             napi_resolve_deferred(env, context->deferred, result[PARAM1]);
155         } else {
156             napi_reject_deferred(env, context->deferred, result[PARAM0]);
157         }
158     } else {
159         napi_get_reference_value(env, context->callbackRef, &callback);
160         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
161         napi_delete_reference(env, context->callbackRef);
162     }
163     napi_delete_async_work(env, context->work);
164 
165     delete context;
166     context = nullptr;
167 }
168 
GetTitleAsyncCallbackComplete(napi_env env,napi_status status,void * data)169 void SystemTonePlayerNapi::GetTitleAsyncCallbackComplete(napi_env env, napi_status status, void *data)
170 {
171     auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
172     napi_value getTitleCallback = nullptr;
173     napi_value retVal = nullptr;
174     napi_value result[2] = {};
175 
176     if (!context->status) {
177         napi_get_undefined(env, &result[PARAM0]);
178         napi_create_string_utf8(env, context->title.c_str(), NAPI_AUTO_LENGTH, &result[PARAM1]);
179     } else {
180         napi_value message = nullptr;
181         napi_create_string_utf8(env, "GetTitle Error: Operation is not supported or failed",
182             NAPI_AUTO_LENGTH, &message);
183         napi_create_error(env, nullptr, message, &result[PARAM0]);
184         napi_get_undefined(env, &result[PARAM1]);
185     }
186 
187     if (context->deferred) {
188         if (!context->status) {
189             napi_resolve_deferred(env, context->deferred, result[PARAM1]);
190         } else {
191             napi_reject_deferred(env, context->deferred, result[PARAM0]);
192         }
193     } else {
194         napi_get_reference_value(env, context->callbackRef, &getTitleCallback);
195         napi_call_function(env, nullptr, getTitleCallback, ARGS_TWO, result, &retVal);
196         napi_delete_reference(env, context->callbackRef);
197     }
198     napi_delete_async_work(env, context->work);
199 
200     delete context;
201     context = nullptr;
202 }
203 
GetTitle(napi_env env,napi_callback_info info)204 napi_value SystemTonePlayerNapi::GetTitle(napi_env env, napi_callback_info info)
205 {
206     napi_value result = nullptr;
207     napi_value resource = nullptr;
208     size_t argc = ARGS_ONE;
209     napi_value argv[ARGS_ONE] = {0};
210     napi_value thisVar = nullptr;
211     const int32_t refCount = 1;
212 
213     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
214     napi_get_undefined(env, &result);
215     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result, "GetTitle: napi_get_cb_info failed");
216 
217     NAPI_ASSERT(env, argc <= ARGS_ONE, "GetTitle: requires 1 parameter maximum");
218     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
219     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
220     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
221         if (argc == ARGS_ONE) {
222             napi_valuetype valueType = napi_undefined;
223             napi_typeof(env, argv[PARAM0], &valueType);
224             CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
225                 "GetTitle: the param type is not napi_function");
226             napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
227         } else {
228             napi_create_promise(env, &asyncContext->deferred, &result);
229         }
230 
231         napi_create_string_utf8(env, "GetTitle", NAPI_AUTO_LENGTH, &resource);
232         status = napi_create_async_work(env, nullptr, resource,
233             [](napi_env env, void *data) {
234                 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
235                 auto obj = reinterpret_cast<SystemTonePlayerNapi*>(context->objectInfo);
236                 ObjectRefMap objectGuard(obj);
237                 auto *napiSystemTonePlayer = objectGuard.GetPtr();
238                 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
239                     MEDIA_LOGE("The system tone player is nullptr!");
240                     context->status = MSERR_INVALID_STATE;
241                     return;
242                 }
243                 context->title = napiSystemTonePlayer->systemTonePlayer_->GetTitle();
244                 context->status = MSERR_OK;
245             },
246             GetTitleAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
247         if (status != napi_ok) {
248             MEDIA_LOGE("GetTitle: Failed to get create async work");
249             napi_get_undefined(env, &result);
250         } else {
251             napi_queue_async_work(env, asyncContext->work);
252             asyncContext.release();
253         }
254     }
255 
256     return result;
257 }
258 
Prepare(napi_env env,napi_callback_info info)259 napi_value SystemTonePlayerNapi::Prepare(napi_env env, napi_callback_info info)
260 {
261     napi_status status;
262     napi_value result = nullptr;
263     napi_value resource = nullptr;
264     size_t argc = ARGS_ONE;
265     napi_value argv[ARGS_ONE] = {0};
266     napi_value thisVar = nullptr;
267     const int32_t refCount = 1;
268 
269     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
270     napi_get_undefined(env, &result);
271     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
272         "Prepare: Failed to retrieve details about the callback");
273 
274     NAPI_ASSERT(env, argc <= ARGS_ONE, "Prepare: requires 1 parameter maximum");
275     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
276     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
277     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
278         if (argc == ARGS_ONE) {
279             napi_valuetype valueType = napi_undefined;
280             napi_typeof(env, argv[PARAM0], &valueType);
281             CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
282                 "Prepare: the param type is not napi_function");
283             napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
284         } else {
285             napi_create_promise(env, &asyncContext->deferred, &result);
286         }
287 
288         napi_create_string_utf8(env, "Prepare", NAPI_AUTO_LENGTH, &resource);
289         status = napi_create_async_work(env, nullptr, resource,
290             [](napi_env env, void* data) {
291                 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
292                 auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
293                 ObjectRefMap objectGuard(obj);
294                 auto *napiSystemTonePlayer = objectGuard.GetPtr();
295                 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
296                     MEDIA_LOGE("The system tone player is nullptr!");
297                     context->status = MSERR_INVALID_STATE;
298                     return;
299                 }
300                 context->status = napiSystemTonePlayer->systemTonePlayer_->Prepare();
301             },
302             CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
303         if (status != napi_ok) {
304             MEDIA_LOGE("Prepare: Failed to get create async work");
305             napi_get_undefined(env, &result);
306         } else {
307             napi_queue_async_work(env, asyncContext->work);
308             asyncContext.release();
309         }
310     }
311 
312     return result;
313 }
314 
StartAsyncCallbackComplete(napi_env env,napi_status status,void * data)315 void SystemTonePlayerNapi::StartAsyncCallbackComplete(napi_env env, napi_status status, void *data)
316 {
317     auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
318     napi_value getTitleCallback = nullptr;
319     napi_value retVal = nullptr;
320     napi_value result[2] = {};
321 
322     if (!context->status) {
323         napi_get_undefined(env, &result[PARAM0]);
324         napi_create_int32(env, context->streamID, &result[PARAM1]);
325     } else {
326         napi_value message = nullptr;
327         napi_create_string_utf8(env, "GetTitle Error: Operation is not supported or failed",
328             NAPI_AUTO_LENGTH, &message);
329         napi_create_error(env, nullptr, message, &result[PARAM0]);
330         napi_get_undefined(env, &result[PARAM1]);
331     }
332 
333     if (context->deferred) {
334         if (!context->status) {
335             napi_resolve_deferred(env, context->deferred, result[PARAM1]);
336         } else {
337             napi_reject_deferred(env, context->deferred, result[PARAM0]);
338         }
339     } else {
340         napi_get_reference_value(env, context->callbackRef, &getTitleCallback);
341         napi_call_function(env, nullptr, getTitleCallback, ARGS_TWO, result, &retVal);
342         napi_delete_reference(env, context->callbackRef);
343     }
344     napi_delete_async_work(env, context->work);
345 
346     delete context;
347     context = nullptr;
348 }
349 
Start(napi_env env,napi_callback_info info)350 napi_value SystemTonePlayerNapi::Start(napi_env env, napi_callback_info info)
351 {
352     napi_value result = nullptr;
353     napi_value resource = nullptr;
354     napi_value property = nullptr;
355     size_t argc = ARGS_ONE;
356     napi_value argv[ARGS_TWO] = {0};
357     napi_value thisVar = nullptr;
358     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
359     napi_get_undefined(env, &result);
360     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result, "Start: napi_get_cb_info failed");
361     NAPI_ASSERT(env, argc <= ARGS_TWO, "Start: requires 2 parameter maximum");
362 
363     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
364     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
365     CHECK_AND_RETURN_RET_LOG(status == napi_ok && asyncContext->objectInfo != nullptr, result,
366         "Start: napi_unwrap failed or objectInfo is nullptr.");
367 
368     if (argc == 0) {
369         napi_create_promise(env, &asyncContext->deferred, &result);
370     }
371     for (size_t i = PARAM0; i < argc; i++) {
372         napi_valuetype valueType = napi_undefined;
373         napi_typeof(env, argv[i], &valueType);
374         if (i == PARAM0 && valueType == napi_object) {
375             if (napi_get_named_property(env, argv[PARAM0], "muteAudio", &property) == napi_ok) {
376                 napi_get_value_bool(env, property, &(asyncContext->systemToneOptions.muteAudio));
377             }
378             if (napi_get_named_property(env, argv[PARAM0], "muteHaptics", &property) == napi_ok) {
379                 napi_get_value_bool(env, property, &(asyncContext->systemToneOptions.muteHaptics));
380             }
381             if (argc == ARGS_ONE) {
382                 napi_create_promise(env, &asyncContext->deferred, &result);
383             }
384         } else if ((i == PARAM0 || i == PARAM1) && valueType == napi_function) {
385             napi_create_reference(env, argv[PARAM0], 1, &asyncContext->callbackRef);
386         } else {
387             NAPI_ASSERT(env, false, "Start: type mismatch");
388         }
389     }
390 
391     napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
392     status = napi_create_async_work(env, nullptr, resource, AsyncStart,
393         StartAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
394     if (status != napi_ok) {
395         napi_get_undefined(env, &result);
396     } else {
397         napi_queue_async_work(env, asyncContext->work);
398         asyncContext.release();
399     }
400     return result;
401 }
402 
AsyncStart(napi_env env,void * data)403 void SystemTonePlayerNapi::AsyncStart(napi_env env, void *data)
404 {
405     SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
406     auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
407     ObjectRefMap objectGuard(obj);
408     auto *napiSystemTonePlayer = objectGuard.GetPtr();
409     if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
410         MEDIA_LOGE("The system tone player is nullptr!");
411         context->status = MSERR_INVALID_STATE;
412         return;
413     }
414     context->streamID = napiSystemTonePlayer->systemTonePlayer_->Start(context->systemToneOptions);
415     context->status = MSERR_OK;
416 }
417 
Stop(napi_env env,napi_callback_info info)418 napi_value SystemTonePlayerNapi::Stop(napi_env env, napi_callback_info info)
419 {
420     napi_status status;
421     napi_value result = nullptr;
422     napi_value resource = nullptr;
423     size_t argc = ARGS_ONE;
424     napi_value argv[ARGS_TWO] = {0};
425     napi_value thisVar = nullptr;
426     const int32_t refCount = 1;
427 
428     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
429     napi_get_undefined(env, &result);
430     if (status != napi_ok || thisVar == nullptr) {
431         MEDIA_LOGE("Stop: Failed to retrieve details about the callback");
432         return result;
433     }
434 
435     NAPI_ASSERT(env, argc == ARGS_ONE || argc == ARGS_TWO, "Stop: requires 1 or 2 parameter");
436     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
437     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
438     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
439         napi_valuetype valueType = napi_undefined;
440         napi_typeof(env, argv[PARAM0], &valueType);
441         if (valueType == napi_number) {
442             napi_get_value_int32(env, argv[PARAM0], &(asyncContext->streamID));
443             napi_create_promise(env, &asyncContext->deferred, &result);
444         } else {
445             NAPI_ASSERT(env, false, "Stop: type mismatch");
446         }
447         if (argc == ARGS_TWO) {
448             napi_typeof(env, argv[PARAM1], &valueType);
449             CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result, "Stop: the param type is not napi_function");
450             napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
451         } else {
452             napi_create_promise(env, &asyncContext->deferred, &result);
453         }
454 
455         napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
456         status = napi_create_async_work(env, nullptr, resource, AsyncStop,
457             CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
458         if (status != napi_ok) {
459             MEDIA_LOGE("Stop: Failed to get create async work");
460             napi_get_undefined(env, &result);
461         } else {
462             napi_queue_async_work(env, asyncContext->work);
463             asyncContext.release();
464         }
465     }
466 
467     return result;
468 }
469 
AsyncStop(napi_env env,void * data)470 void SystemTonePlayerNapi::AsyncStop(napi_env env, void *data)
471 {
472     SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
473     auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
474     ObjectRefMap objectGuard(obj);
475     auto *napiSystemTonePlayer = objectGuard.GetPtr();
476     if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
477         MEDIA_LOGE("The system tone player is nullptr!");
478         context->status = MSERR_INVALID_STATE;
479         return;
480     }
481     context->status = napiSystemTonePlayer->systemTonePlayer_->Stop(context->streamID);
482 }
483 
Release(napi_env env,napi_callback_info info)484 napi_value SystemTonePlayerNapi::Release(napi_env env, napi_callback_info info)
485 {
486     napi_status status;
487     napi_value result = nullptr;
488     napi_value resource = nullptr;
489     size_t argc = ARGS_ONE;
490     napi_value argv[ARGS_ONE] = {0};
491     napi_value thisVar = nullptr;
492     const int32_t refCount = 1;
493 
494     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
495     napi_get_undefined(env, &result);
496     if (status != napi_ok || thisVar == nullptr) {
497         MEDIA_LOGE("Release: Failed to retrieve details about the callback");
498         return result;
499     }
500 
501     NAPI_ASSERT(env, argc <= ARGS_ONE, "Release: requires 1 parameter maximum");
502     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
503     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
504     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
505         if (argc == ARGS_ONE) {
506             napi_valuetype valueType = napi_undefined;
507             napi_typeof(env, argv[PARAM0], &valueType);
508             CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
509                 "Release: the param type is not napi_function");
510             napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
511         } else {
512             napi_create_promise(env, &asyncContext->deferred, &result);
513         }
514 
515         napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
516         status = napi_create_async_work(env, nullptr, resource, AsyncRelease,
517             CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
518         if (status != napi_ok) {
519             MEDIA_LOGE("Release: Failed to get create async work");
520             napi_get_undefined(env, &result);
521         } else {
522             napi_queue_async_work(env, asyncContext->work);
523             asyncContext.release();
524         }
525     }
526 
527     return result;
528 }
529 
AsyncRelease(napi_env env,void * data)530 void SystemTonePlayerNapi::AsyncRelease(napi_env env, void *data)
531 {
532     SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
533     auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
534     ObjectRefMap objectGuard(obj);
535     auto *napiSystemTonePlayer = objectGuard.GetPtr();
536     if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
537         MEDIA_LOGE("The system tone player is nullptr!");
538         context->status = MSERR_INVALID_STATE;
539         return;
540     }
541     context->status = napiSystemTonePlayer->systemTonePlayer_->Release();
542 }
543 } // namespace Media
544 } // namespace OHOS