• 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 #include "access_token.h"
21 #include "accesstoken_kit.h"
22 #include "ipc_skeleton.h"
23 #include "tokenid_kit.h"
24 #include "ringtone_common_napi.h"
25 
26 namespace {
27 /* Constants for array index */
28 const int32_t PARAM0 = 0;
29 const int32_t PARAM1 = 1;
30 const int32_t PARAM2 = 2;
31 
32 /* Constants for array size */
33 const int32_t ARGS_ONE = 1;
34 const int32_t ARGS_TWO = 2;
35 const int32_t ARGS_THREE = 3;
36 const int32_t ALL_STREAMID = 0;
37 const std::string PLAY_FINISHED_CALLBACK_NAME = "playFinished";
38 const std::string ERROR_CALLBACK_NAME = "error";
39 
40 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "SystemTonePlayerNapi"};
41 }
42 
43 namespace OHOS {
44 namespace Media {
45 thread_local napi_ref SystemTonePlayerNapi::sConstructor_ = nullptr;
46 std::shared_ptr<SystemTonePlayer> SystemTonePlayerNapi::sSystemTonePlayer_ = nullptr;
47 
SystemTonePlayerNapi()48 SystemTonePlayerNapi::SystemTonePlayerNapi() : env_(nullptr) {}
49 
50 SystemTonePlayerNapi::~SystemTonePlayerNapi() = default;
51 
Init(napi_env env,napi_value exports)52 napi_value SystemTonePlayerNapi::Init(napi_env env, napi_value exports)
53 {
54     napi_status status;
55     napi_value ctorObj;
56     int32_t refCount = 1;
57 
58     napi_property_descriptor system_tone_player_prop[] = {
59         DECLARE_NAPI_FUNCTION("getTitle", GetTitle),
60         DECLARE_NAPI_FUNCTION("prepare", Prepare),
61         DECLARE_NAPI_FUNCTION("start", Start),
62         DECLARE_NAPI_FUNCTION("stop", Stop),
63         DECLARE_NAPI_FUNCTION("release", Release),
64         DECLARE_NAPI_FUNCTION("setAudioVolumeScale", SetAudioVolumeScale),
65         DECLARE_NAPI_FUNCTION("getAudioVolumeScale", GetAudioVolumeScale),
66         DECLARE_NAPI_FUNCTION("getSupportedHapticsFeatures", GetSupportedHapticsFeatures),
67         DECLARE_NAPI_FUNCTION("setHapticsFeature", SetHapticsFeature),
68         DECLARE_NAPI_FUNCTION("getHapticsFeature", GetHapticsFeature),
69         DECLARE_NAPI_FUNCTION("on", On),
70         DECLARE_NAPI_FUNCTION("off", Off),
71     };
72 
73     status = napi_define_class(env, SYSTEM_TONE_PLAYER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
74         SystemTonePlayerNapiConstructor, nullptr, sizeof(system_tone_player_prop) / sizeof(system_tone_player_prop[0]),
75         system_tone_player_prop, &ctorObj);
76     if (status == napi_ok) {
77         if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
78             status = napi_set_named_property(env, exports, SYSTEM_TONE_PLAYER_NAPI_CLASS_NAME.c_str(), ctorObj);
79             if (status == napi_ok) {
80                 return exports;
81             }
82         }
83     }
84 
85     return nullptr;
86 }
87 
SystemTonePlayerNapiConstructor(napi_env env,napi_callback_info info)88 napi_value SystemTonePlayerNapi::SystemTonePlayerNapiConstructor(napi_env env, napi_callback_info info)
89 {
90     napi_status status;
91     napi_value result = nullptr;
92     napi_value thisVar = nullptr;
93 
94     napi_get_undefined(env, &result);
95     status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
96     if (status == napi_ok && thisVar != nullptr) {
97         std::unique_ptr<SystemTonePlayerNapi> obj = std::make_unique<SystemTonePlayerNapi>();
98         if (obj != nullptr) {
99             ObjectRefMap<SystemTonePlayerNapi>::Insert(obj.get());
100             obj->env_ = env;
101             if (obj->sSystemTonePlayer_ != nullptr) {
102                 obj->systemTonePlayer_ = move(obj->sSystemTonePlayer_);
103             } else {
104                 MEDIA_LOGE("Failed to create sSystemTonePlayer_ instance.");
105                 return result;
106             }
107 
108             if (obj->systemTonePlayer_ != nullptr && obj->callbackNapi_ == nullptr) {
109                 obj->callbackNapi_ = std::make_shared<SystemTonePlayerCallbackNapi>(env);
110                 CHECK_AND_RETURN_RET_LOG(obj->callbackNapi_ != nullptr, result, "No memory");
111                 int32_t ret = obj->systemTonePlayer_->SetSystemTonePlayerFinishedAndErrorCallback(obj->callbackNapi_);
112                 MEDIA_LOGI("SetSystemTonePlayerFinishedAndErrorCallback %{public}s", ret == 0 ? "succeess" : "failed");
113             }
114 
115             status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
116                 SystemTonePlayerNapi::SystemTonePlayerNapiDestructor, nullptr, nullptr);
117             if (status == napi_ok) {
118                 obj.release();
119                 return thisVar;
120             } else {
121                 ObjectRefMap<SystemTonePlayerNapi>::Erase(obj.get());
122                 MEDIA_LOGE("Failed to wrap the native system tone player object with JS.");
123             }
124         }
125     }
126 
127     return result;
128 }
129 
SystemTonePlayerNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)130 void SystemTonePlayerNapi::SystemTonePlayerNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
131 {
132     SystemTonePlayerNapi *systemTonePlayerHelper = reinterpret_cast<SystemTonePlayerNapi*>(nativeObject);
133     if (systemTonePlayerHelper != nullptr) {
134         ObjectRefMap<SystemTonePlayerNapi>::DecreaseRef(systemTonePlayerHelper);
135     }
136 }
137 
GetSystemTonePlayerInstance(napi_env env,std::shared_ptr<SystemTonePlayer> & systemTonePlayer)138 napi_value SystemTonePlayerNapi::GetSystemTonePlayerInstance(napi_env env,
139     std::shared_ptr<SystemTonePlayer> &systemTonePlayer)
140 {
141     napi_status status;
142     napi_value result = nullptr;
143     napi_value ctor;
144 
145     status = napi_get_reference_value(env, sConstructor_, &ctor);
146     if (status == napi_ok) {
147         sSystemTonePlayer_ = systemTonePlayer;
148         status = napi_new_instance(env, ctor, 0, nullptr, &result);
149         if (status == napi_ok) {
150             return result;
151         } else {
152             MEDIA_LOGE("GetSystemTonePlayerInstance: New instance could not be obtained.");
153         }
154     }
155 
156     napi_get_undefined(env, &result);
157     return result;
158 }
159 
CommonAsyncCallbackComplete(napi_env env,napi_status status,void * data)160 void SystemTonePlayerNapi::CommonAsyncCallbackComplete(napi_env env, napi_status status, void* data)
161 {
162     auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
163     napi_value callback = nullptr;
164     napi_value retVal = nullptr;
165     napi_value result[2] = {};
166 
167     napi_get_undefined(env, &result[PARAM1]);
168     if (!context->status) {
169         napi_get_undefined(env, &result[PARAM0]);
170     } else {
171         napi_value message = nullptr;
172         napi_create_string_utf8(env, "Error: Operation is not supported or failed", NAPI_AUTO_LENGTH, &message);
173         napi_create_error(env, nullptr, message, &result[PARAM0]);
174     }
175 
176     if (context->deferred) {
177         if (!context->status) {
178             napi_resolve_deferred(env, context->deferred, result[PARAM1]);
179         } else {
180             napi_reject_deferred(env, context->deferred, result[PARAM0]);
181         }
182     } else {
183         napi_get_reference_value(env, context->callbackRef, &callback);
184         napi_call_function(env, nullptr, callback, ARGS_TWO, result, &retVal);
185         napi_delete_reference(env, context->callbackRef);
186     }
187     napi_delete_async_work(env, context->work);
188 
189     delete context;
190     context = nullptr;
191 }
192 
GetTitleAsyncCallbackComplete(napi_env env,napi_status status,void * data)193 void SystemTonePlayerNapi::GetTitleAsyncCallbackComplete(napi_env env, napi_status status, void *data)
194 {
195     auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
196     napi_value getTitleCallback = nullptr;
197     napi_value retVal = nullptr;
198     napi_value result[2] = {};
199 
200     if (!context->status) {
201         napi_get_undefined(env, &result[PARAM0]);
202         napi_create_string_utf8(env, context->title.c_str(), NAPI_AUTO_LENGTH, &result[PARAM1]);
203     } else {
204         napi_value message = nullptr;
205         napi_create_string_utf8(env, "GetTitle Error: Operation is not supported or failed",
206             NAPI_AUTO_LENGTH, &message);
207         napi_create_error(env, nullptr, message, &result[PARAM0]);
208         napi_get_undefined(env, &result[PARAM1]);
209     }
210 
211     if (context->deferred) {
212         if (!context->status) {
213             napi_resolve_deferred(env, context->deferred, result[PARAM1]);
214         } else {
215             napi_reject_deferred(env, context->deferred, result[PARAM0]);
216         }
217     } else {
218         napi_get_reference_value(env, context->callbackRef, &getTitleCallback);
219         napi_call_function(env, nullptr, getTitleCallback, ARGS_TWO, result, &retVal);
220         napi_delete_reference(env, context->callbackRef);
221     }
222     napi_delete_async_work(env, context->work);
223 
224     delete context;
225     context = nullptr;
226 }
227 
GetTitle(napi_env env,napi_callback_info info)228 napi_value SystemTonePlayerNapi::GetTitle(napi_env env, napi_callback_info info)
229 {
230     napi_value result = nullptr;
231     napi_value resource = nullptr;
232     size_t argc = ARGS_ONE;
233     napi_value argv[ARGS_ONE] = {0};
234     napi_value thisVar = nullptr;
235     const int32_t refCount = 1;
236 
237     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
238     napi_get_undefined(env, &result);
239     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result, "GetTitle: napi_get_cb_info failed");
240 
241     NAPI_ASSERT(env, argc <= ARGS_ONE, "GetTitle: requires 1 parameter maximum");
242     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
243     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
244     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
245         if (argc == ARGS_ONE) {
246             napi_valuetype valueType = napi_undefined;
247             napi_typeof(env, argv[PARAM0], &valueType);
248             CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
249                 "GetTitle: the param type is not napi_function");
250             napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
251         } else {
252             napi_create_promise(env, &asyncContext->deferred, &result);
253         }
254 
255         napi_create_string_utf8(env, "GetTitle", NAPI_AUTO_LENGTH, &resource);
256         status = napi_create_async_work(env, nullptr, resource,
257             [](napi_env env, void *data) {
258                 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
259                 auto obj = reinterpret_cast<SystemTonePlayerNapi*>(context->objectInfo);
260                 ObjectRefMap objectGuard(obj);
261                 auto *napiSystemTonePlayer = objectGuard.GetPtr();
262                 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
263                     MEDIA_LOGE("The system tone player is nullptr!");
264                     context->status = MSERR_INVALID_STATE;
265                     return;
266                 }
267                 context->title = napiSystemTonePlayer->systemTonePlayer_->GetTitle();
268                 context->status = MSERR_OK;
269             },
270             GetTitleAsyncCallbackComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
271         if (status != napi_ok) {
272             MEDIA_LOGE("GetTitle: Failed to get create async work");
273             napi_get_undefined(env, &result);
274         } else {
275             napi_queue_async_work(env, asyncContext->work);
276             asyncContext.release();
277         }
278     }
279 
280     return result;
281 }
282 
Prepare(napi_env env,napi_callback_info info)283 napi_value SystemTonePlayerNapi::Prepare(napi_env env, napi_callback_info info)
284 {
285     napi_status status;
286     napi_value result = nullptr;
287     napi_value resource = nullptr;
288     size_t argc = ARGS_ONE;
289     napi_value argv[ARGS_ONE] = {0};
290     napi_value thisVar = nullptr;
291     const int32_t refCount = 1;
292 
293     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
294     napi_get_undefined(env, &result);
295     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
296         "Prepare: Failed to retrieve details about the callback");
297 
298     NAPI_ASSERT(env, argc <= ARGS_ONE, "Prepare: requires 1 parameter maximum");
299     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
300     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
301     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
302         if (argc == ARGS_ONE) {
303             napi_valuetype valueType = napi_undefined;
304             napi_typeof(env, argv[PARAM0], &valueType);
305             CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
306                 "Prepare: the param type is not napi_function");
307             napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
308         } else {
309             napi_create_promise(env, &asyncContext->deferred, &result);
310         }
311 
312         napi_create_string_utf8(env, "Prepare", NAPI_AUTO_LENGTH, &resource);
313         status = napi_create_async_work(env, nullptr, resource,
314             [](napi_env env, void* data) {
315                 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
316                 auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
317                 ObjectRefMap objectGuard(obj);
318                 auto *napiSystemTonePlayer = objectGuard.GetPtr();
319                 if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
320                     MEDIA_LOGE("The system tone player is nullptr!");
321                     context->status = MSERR_INVALID_STATE;
322                     return;
323                 }
324                 context->status = napiSystemTonePlayer->systemTonePlayer_->Prepare();
325             },
326             CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
327         if (status != napi_ok) {
328             MEDIA_LOGE("Prepare: Failed to get create async work");
329             napi_get_undefined(env, &result);
330         } else {
331             napi_queue_async_work(env, asyncContext->work);
332             asyncContext.release();
333         }
334     }
335 
336     return result;
337 }
338 
StartAsyncCallbackComplete(napi_env env,napi_status status,void * data)339 void SystemTonePlayerNapi::StartAsyncCallbackComplete(napi_env env, napi_status status, void *data)
340 {
341     auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
342     napi_value getTitleCallback = nullptr;
343     napi_value retVal = nullptr;
344     napi_value result[2] = {};
345 
346     if (!context->status) {
347         napi_get_undefined(env, &result[PARAM0]);
348         napi_create_int32(env, context->streamID, &result[PARAM1]);
349     } else {
350         napi_value message = nullptr;
351         napi_create_string_utf8(env, "GetTitle Error: Operation is not supported or failed",
352             NAPI_AUTO_LENGTH, &message);
353         napi_create_error(env, nullptr, message, &result[PARAM0]);
354         napi_get_undefined(env, &result[PARAM1]);
355     }
356 
357     if (context->deferred) {
358         if (!context->status) {
359             napi_resolve_deferred(env, context->deferred, result[PARAM1]);
360         } else {
361             napi_reject_deferred(env, context->deferred, result[PARAM0]);
362         }
363     } else {
364         napi_get_reference_value(env, context->callbackRef, &getTitleCallback);
365         napi_call_function(env, nullptr, getTitleCallback, ARGS_TWO, result, &retVal);
366         napi_delete_reference(env, context->callbackRef);
367     }
368     napi_delete_async_work(env, context->work);
369 
370     delete context;
371     context = nullptr;
372 }
373 
Start(napi_env env,napi_callback_info info)374 napi_value SystemTonePlayerNapi::Start(napi_env env, napi_callback_info info)
375 {
376     napi_value result = nullptr;
377     napi_value resource = nullptr;
378     napi_value property = nullptr;
379     size_t argc = ARGS_ONE;
380     napi_value argv[ARGS_TWO] = {0};
381     napi_value thisVar = nullptr;
382     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
383     napi_get_undefined(env, &result);
384     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result, "Start: napi_get_cb_info failed");
385     NAPI_ASSERT(env, argc <= ARGS_TWO, "Start: requires 2 parameter maximum");
386 
387     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
388     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
389     CHECK_AND_RETURN_RET_LOG(status == napi_ok && asyncContext->objectInfo != nullptr, result,
390         "Start: napi_unwrap failed or objectInfo is nullptr.");
391 
392     if (argc == 0) {
393         napi_create_promise(env, &asyncContext->deferred, &result);
394     }
395     for (size_t i = PARAM0; i < argc; i++) {
396         napi_valuetype valueType = napi_undefined;
397         napi_typeof(env, argv[i], &valueType);
398         if (i == PARAM0 && valueType == napi_object) {
399             if (napi_get_named_property(env, argv[PARAM0], "muteAudio", &property) == napi_ok) {
400                 napi_get_value_bool(env, property, &(asyncContext->systemToneOptions.muteAudio));
401             }
402             if (napi_get_named_property(env, argv[PARAM0], "muteHaptics", &property) == napi_ok) {
403                 napi_get_value_bool(env, property, &(asyncContext->systemToneOptions.muteHaptics));
404             }
405             if (argc == ARGS_ONE) {
406                 napi_create_promise(env, &asyncContext->deferred, &result);
407             }
408         } else if ((i == PARAM0 || i == PARAM1) && valueType == napi_function) {
409             napi_create_reference(env, argv[PARAM0], 1, &asyncContext->callbackRef);
410         } else {
411             NAPI_ASSERT(env, false, "Start: type mismatch");
412         }
413     }
414 
415     napi_create_string_utf8(env, "Start", NAPI_AUTO_LENGTH, &resource);
416     status = napi_create_async_work(env, nullptr, resource, AsyncStart,
417         StartAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
418     if (status != napi_ok) {
419         napi_get_undefined(env, &result);
420     } else {
421         napi_queue_async_work(env, asyncContext->work);
422         asyncContext.release();
423     }
424     return result;
425 }
426 
AsyncStart(napi_env env,void * data)427 void SystemTonePlayerNapi::AsyncStart(napi_env env, void *data)
428 {
429     SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
430     auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
431     ObjectRefMap objectGuard(obj);
432     auto *napiSystemTonePlayer = objectGuard.GetPtr();
433     if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
434         MEDIA_LOGE("The system tone player is nullptr!");
435         context->status = MSERR_INVALID_STATE;
436         return;
437     }
438     context->streamID = napiSystemTonePlayer->systemTonePlayer_->Start(context->systemToneOptions);
439     std::shared_ptr<SystemTonePlayerCallbackNapi> cb =
440         std::static_pointer_cast<SystemTonePlayerCallbackNapi>(napiSystemTonePlayer->callbackNapi_);
441     if (cb) {
442         cb->RemovePlayFinishedCallbackReference(context->streamID);
443     }
444     context->status = MSERR_OK;
445 }
446 
Stop(napi_env env,napi_callback_info info)447 napi_value SystemTonePlayerNapi::Stop(napi_env env, napi_callback_info info)
448 {
449     napi_status status;
450     napi_value result = nullptr;
451     napi_value resource = nullptr;
452     size_t argc = ARGS_ONE;
453     napi_value argv[ARGS_TWO] = {0};
454     napi_value thisVar = nullptr;
455     const int32_t refCount = 1;
456 
457     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
458     napi_get_undefined(env, &result);
459     if (status != napi_ok || thisVar == nullptr) {
460         MEDIA_LOGE("Stop: Failed to retrieve details about the callback");
461         return result;
462     }
463 
464     NAPI_ASSERT(env, argc == ARGS_ONE || argc == ARGS_TWO, "Stop: requires 1 or 2 parameter");
465     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
466     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
467     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
468         napi_valuetype valueType = napi_undefined;
469         napi_typeof(env, argv[PARAM0], &valueType);
470         if (valueType == napi_number) {
471             napi_get_value_int32(env, argv[PARAM0], &(asyncContext->streamID));
472             napi_create_promise(env, &asyncContext->deferred, &result);
473         } else {
474             NAPI_ASSERT(env, false, "Stop: type mismatch");
475         }
476         if (argc == ARGS_TWO) {
477             napi_typeof(env, argv[PARAM1], &valueType);
478             CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result, "Stop: the param type is not napi_function");
479             napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
480         } else {
481             napi_create_promise(env, &asyncContext->deferred, &result);
482         }
483 
484         napi_create_string_utf8(env, "Stop", NAPI_AUTO_LENGTH, &resource);
485         status = napi_create_async_work(env, nullptr, resource, AsyncStop,
486             CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
487         if (status != napi_ok) {
488             MEDIA_LOGE("Stop: Failed to get create async work");
489             napi_get_undefined(env, &result);
490         } else {
491             napi_queue_async_work(env, asyncContext->work);
492             asyncContext.release();
493         }
494     }
495 
496     return result;
497 }
498 
AsyncStop(napi_env env,void * data)499 void SystemTonePlayerNapi::AsyncStop(napi_env env, void *data)
500 {
501     SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
502     auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
503     ObjectRefMap objectGuard(obj);
504     auto *napiSystemTonePlayer = objectGuard.GetPtr();
505     if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
506         MEDIA_LOGE("The system tone player is nullptr!");
507         context->status = MSERR_INVALID_STATE;
508         return;
509     }
510     context->status = napiSystemTonePlayer->systemTonePlayer_->Stop(context->streamID);
511 }
512 
Release(napi_env env,napi_callback_info info)513 napi_value SystemTonePlayerNapi::Release(napi_env env, napi_callback_info info)
514 {
515     napi_status status;
516     napi_value result = nullptr;
517     napi_value resource = nullptr;
518     size_t argc = ARGS_ONE;
519     napi_value argv[ARGS_ONE] = {0};
520     napi_value thisVar = nullptr;
521     const int32_t refCount = 1;
522 
523     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
524     napi_get_undefined(env, &result);
525     if (status != napi_ok || thisVar == nullptr) {
526         MEDIA_LOGE("Release: Failed to retrieve details about the callback");
527         return result;
528     }
529 
530     NAPI_ASSERT(env, argc <= ARGS_ONE, "Release: requires 1 parameter maximum");
531     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
532     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
533     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
534         if (argc == ARGS_ONE) {
535             napi_valuetype valueType = napi_undefined;
536             napi_typeof(env, argv[PARAM0], &valueType);
537             CHECK_AND_RETURN_RET_LOG(valueType == napi_function, result,
538                 "Release: the param type is not napi_function");
539             napi_create_reference(env, argv[PARAM0], refCount, &asyncContext->callbackRef);
540         } else {
541             napi_create_promise(env, &asyncContext->deferred, &result);
542         }
543 
544         napi_create_string_utf8(env, "Release", NAPI_AUTO_LENGTH, &resource);
545         status = napi_create_async_work(env, nullptr, resource, AsyncRelease,
546             CommonAsyncCallbackComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
547         if (status != napi_ok) {
548             MEDIA_LOGE("Release: Failed to get create async work");
549             napi_get_undefined(env, &result);
550         } else {
551             napi_queue_async_work(env, asyncContext->work);
552             asyncContext.release();
553         }
554     }
555 
556     return result;
557 }
558 
AsyncRelease(napi_env env,void * data)559 void SystemTonePlayerNapi::AsyncRelease(napi_env env, void *data)
560 {
561     SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
562     auto obj = reinterpret_cast<SystemTonePlayerNapi *>(context->objectInfo);
563     ObjectRefMap objectGuard(obj);
564     auto *napiSystemTonePlayer = objectGuard.GetPtr();
565     if (napiSystemTonePlayer == nullptr || napiSystemTonePlayer->systemTonePlayer_ == nullptr) {
566         MEDIA_LOGE("The system tone player is nullptr!");
567         context->status = MSERR_INVALID_STATE;
568         return;
569     }
570     context->status = napiSystemTonePlayer->systemTonePlayer_->Release();
571 }
572 
SetAudioVolumeScale(napi_env env,napi_callback_info info)573 napi_value SystemTonePlayerNapi::SetAudioVolumeScale(napi_env env, napi_callback_info info)
574 {
575     napi_status status;
576     napi_value result = nullptr;
577     size_t argc = ARGS_ONE;
578     napi_value argv[ARGS_TWO] = {0};
579     napi_value thisVar = nullptr;
580 
581     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
582     napi_get_undefined(env, &result);
583     if (status != napi_ok || thisVar == nullptr) {
584         MEDIA_LOGE("SetAudioVolumeScale: Failed to retrieve details about the callback");
585         return result;
586     }
587 
588     NAPI_ASSERT(env, argc >= ARGS_ONE, "SetAudioVolumeScale: requires 1 parameter");
589     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
590     SystemTonePlayerNapi *objectInfo = nullptr;
591     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&objectInfo));
592     if (status == napi_ok && objectInfo != nullptr) {
593         napi_valuetype valueType = napi_undefined;
594         napi_typeof(env, argv[PARAM0], &valueType);
595         NAPI_ASSERT(env, valueType == napi_number, "SetAudioVolumeScale: type mismatch");
596         double value;
597         napi_get_value_double(env, argv[PARAM0], &value);
598         float volume  = static_cast<float>(value);
599         ObjectRefMap objectGuard(objectInfo);
600         auto *napiSystemTonePlayer = objectGuard.GetPtr();
601         int32_t ret = napiSystemTonePlayer->systemTonePlayer_->SetAudioVolume(volume);
602         if (ret != MSERR_OK) {
603             napi_throw_error(env, std::to_string(ret).c_str(),
604                 "SetAudioVolumeScale: Operation is not supported or failed");
605         }
606     }
607     return result;
608 }
609 
GetAudioVolumeScale(napi_env env,napi_callback_info info)610 napi_value SystemTonePlayerNapi::GetAudioVolumeScale(napi_env env, napi_callback_info info)
611 {
612     napi_value result = nullptr;
613     size_t argc = ARGS_ONE;
614     napi_value argv[ARGS_ONE] = {0};
615     napi_value thisVar = nullptr;
616 
617     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
618     napi_get_undefined(env, &result);
619     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
620         "GetAudioVolume: napi_get_cb_info failed");
621 
622     SystemTonePlayerNapi* objectInfo = nullptr;
623     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&objectInfo));
624     if (status == napi_ok && objectInfo != nullptr) {
625         ObjectRefMap objectGuard(objectInfo);
626         auto *napiSystemTonePlayer = objectGuard.GetPtr();
627         float volume;
628         int32_t ret = napiSystemTonePlayer->systemTonePlayer_->GetAudioVolume(volume);
629         if (ret != MSERR_OK) {
630             napi_throw_error(env, std::to_string(ret).c_str(),
631                 "SetAudioVolumeScale: Operation is not supported or failed");
632         } else {
633             napi_create_double(env, static_cast<double>(volume), &result);
634         }
635     }
636     return result;
637 }
638 
GetSupportHapticsFeaturesComplete(napi_env env,napi_status status,void * data)639 static void GetSupportHapticsFeaturesComplete(napi_env env, napi_status status, void *data)
640 {
641     auto context = static_cast<SystemTonePlayerAsyncContext *>(data);
642     napi_value result[2] = {};
643     napi_status curStatus;
644 
645     if (!context->status) {
646         napi_get_undefined(env, &result[PARAM0]);
647         napi_create_array_with_length(env, context->toneHapticsFeatures.size(), &result[PARAM1]);
648         napi_value value;
649         for (size_t i = 0; i < context->toneHapticsFeatures.size(); i++) {
650             value = nullptr;
651             curStatus = napi_create_int32(env, static_cast<int32_t>(context->toneHapticsFeatures[i]), &value);
652             if (curStatus != napi_ok || value == nullptr||
653                 napi_set_element(env, result[PARAM1], i, value) != napi_ok) {
654                 MEDIA_LOGE("GetSupportHapticsFeatures error : Failed to create number or add number to array");
655                 napi_value message = nullptr;
656                 napi_create_string_utf8(env,
657                     "GetSupportHapticsFeatures Error: Failed to create number or add number to array",
658                     NAPI_AUTO_LENGTH, &message);
659                 napi_create_error(env, nullptr, message, &result[PARAM0]);
660                 napi_get_undefined(env, &result[PARAM1]);
661                 context->status = MSERR_NO_MEMORY;
662                 break;
663             }
664         }
665     } else {
666         napi_value message = nullptr;
667         napi_create_string_utf8(env, "GetSupportHapticsFeatures Error: Operation is not supported or failed",
668             NAPI_AUTO_LENGTH, &message);
669         napi_create_error(env, nullptr, message, &result[PARAM0]);
670         napi_get_undefined(env, &result[PARAM1]);
671     }
672 
673     if (context->deferred) {
674         if (!context->status) {
675             napi_resolve_deferred(env, context->deferred, result[PARAM1]);
676         } else {
677             napi_reject_deferred(env, context->deferred, result[PARAM0]);
678         }
679     }
680     napi_delete_async_work(env, context->work);
681 
682     delete context;
683     context = nullptr;
684 }
685 
GetSupportedHapticsFeatures(napi_env env,napi_callback_info info)686 napi_value SystemTonePlayerNapi::GetSupportedHapticsFeatures(napi_env env, napi_callback_info info)
687 {
688     napi_value result = nullptr;
689     napi_value resource = nullptr;
690     size_t argc = ARGS_ONE;
691     napi_value argv[ARGS_ONE] = {0};
692     napi_value thisVar = nullptr;
693 
694     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
695     napi_get_undefined(env, &result);
696     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
697         "GetSupportHapticsFeatures: napi_get_cb_info failed");
698 
699     std::unique_ptr<SystemTonePlayerAsyncContext> asyncContext = std::make_unique<SystemTonePlayerAsyncContext>();
700     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&asyncContext->objectInfo));
701     if (status == napi_ok && asyncContext->objectInfo != nullptr) {
702         napi_create_promise(env, &asyncContext->deferred, &result);
703         napi_create_string_utf8(env, "GetSupportHapticsFeatures", NAPI_AUTO_LENGTH, &resource);
704         status = napi_create_async_work(env, nullptr, resource,
705             [](napi_env env, void *data) {
706                 SystemTonePlayerAsyncContext *context = static_cast<SystemTonePlayerAsyncContext *>(data);
707                 auto obj = reinterpret_cast<SystemTonePlayerNapi*>(context->objectInfo);
708                 ObjectRefMap objectGuard(obj);
709                 auto *napiSystemTonePlayer = objectGuard.GetPtr();
710                 context->status = napiSystemTonePlayer->systemTonePlayer_->GetSupportHapticsFeatures(
711                     context->toneHapticsFeatures);
712             },
713             GetSupportHapticsFeaturesComplete, static_cast<void *>(asyncContext.get()), &asyncContext->work);
714         if (status != napi_ok) {
715             MEDIA_LOGE("GetSupportHapticsFeatures: Failed to get create async work");
716             napi_get_undefined(env, &result);
717         } else {
718             napi_queue_async_work(env, asyncContext->work);
719             asyncContext.release();
720         }
721     }
722     return result;
723 }
724 
SetHapticsFeature(napi_env env,napi_callback_info info)725 napi_value SystemTonePlayerNapi::SetHapticsFeature(napi_env env, napi_callback_info info)
726 {
727     napi_status status;
728     napi_value result = nullptr;
729     size_t argc = ARGS_ONE;
730     napi_value argv[ARGS_TWO] = {0};
731     napi_value thisVar = nullptr;
732 
733     status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
734     napi_get_undefined(env, &result);
735     if (status != napi_ok || thisVar == nullptr) {
736         MEDIA_LOGE("SetHapticsFeature: Failed to retrieve details about the callback");
737         return result;
738     }
739 
740     NAPI_ASSERT(env, argc >= ARGS_ONE, "SetHapticsFeature: requires 1 parameter");
741     SystemTonePlayerNapi* objectInfo = nullptr;
742     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&objectInfo));
743     if (status == napi_ok && objectInfo != nullptr) {
744         napi_valuetype valueType = napi_undefined;
745         napi_typeof(env, argv[PARAM0], &valueType);
746         NAPI_ASSERT(env, valueType == napi_number, "SetHapticsFeature: type mismatch");
747         ToneHapticsFeature toneHapticsFeature;
748         napi_get_value_int32(env, argv[PARAM0], reinterpret_cast<int32_t*>(&toneHapticsFeature));
749         ObjectRefMap objectGuard(objectInfo);
750         auto *napiSystemTonePlayer = objectGuard.GetPtr();
751         int32_t ret = napiSystemTonePlayer->systemTonePlayer_->SetHapticsFeature(
752             toneHapticsFeature);
753         if (ret != MSERR_OK) {
754             napi_throw_error(env, std::to_string(ret).c_str(),
755                 "SetHapticsFeature: Operation is not supported or failed");
756         }
757     }
758     return result;
759 }
760 
GetHapticsFeature(napi_env env,napi_callback_info info)761 napi_value SystemTonePlayerNapi::GetHapticsFeature(napi_env env, napi_callback_info info)
762 {
763     napi_value result = nullptr;
764     size_t argc = ARGS_ONE;
765     napi_value argv[ARGS_ONE] = {0};
766     napi_value thisVar = nullptr;
767 
768     napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
769     napi_get_undefined(env, &result);
770     CHECK_AND_RETURN_RET_LOG(status == napi_ok && thisVar != nullptr, result,
771         "GetHapticsFeature: napi_get_cb_info failed");
772 
773     SystemTonePlayerNapi* objectInfo = nullptr;
774     status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&objectInfo));
775     if (status == napi_ok && objectInfo != nullptr) {
776         ObjectRefMap objectGuard(objectInfo);
777         auto *napiSystemTonePlayer = objectGuard.GetPtr();
778         ToneHapticsFeature toneHapticsFeature;
779         int32_t ret = napiSystemTonePlayer->systemTonePlayer_->GetHapticsFeature(toneHapticsFeature);
780         if (ret != MSERR_OK) {
781             napi_throw_error(env, std::to_string(ret).c_str(),
782                 "GetHapticsFeature: Operation is not supported or failed");
783         } else {
784             napi_create_int32(env, static_cast<int32_t>(toneHapticsFeature), &result);
785         }
786     }
787     return result;
788 }
789 
VerifySelfSystemPermission()790 bool SystemTonePlayerNapi::VerifySelfSystemPermission()
791 {
792     Security::AccessToken::FullTokenID selfTokenID = IPCSkeleton::GetSelfTokenID();
793     auto tokenTypeFlag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(static_cast<uint32_t>(selfTokenID));
794     if (tokenTypeFlag == Security::AccessToken::TOKEN_NATIVE ||
795         tokenTypeFlag == Security::AccessToken::TOKEN_SHELL ||
796         Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfTokenID)) {
797         return true;
798     }
799     return false;
800 }
801 
ThrowErrorAndReturn(napi_env env,int32_t errCode,const std::string & errMsg)802 napi_value SystemTonePlayerNapi::ThrowErrorAndReturn(napi_env env, int32_t errCode, const std::string &errMsg)
803 {
804     napi_value message = nullptr;
805     napi_value code = nullptr;
806     napi_value errVal = nullptr;
807     napi_value errNameVal = nullptr;
808     napi_value result{};
809     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
810     napi_create_error(env, nullptr, message, &errVal);
811     napi_create_int32(env, errCode, &code);
812     napi_set_named_property(env, errVal, "code", code);
813     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &errNameVal);
814     napi_set_named_property(env, errVal, "BusinessError", errNameVal);
815     napi_throw(env, errVal);
816     napi_get_undefined(env, &result);
817     return result;
818 }
819 
On(napi_env env,napi_callback_info info)820 napi_value SystemTonePlayerNapi::On(napi_env env, napi_callback_info info)
821 {
822     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(), ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED,
823         NAPI_ERR_PERMISSION_DENIED_INFO), "No system permission");
824 
825     size_t argc = ARGS_THREE;
826     napi_value argv[ARGS_THREE] = {nullptr};
827     napi_value jsThis = nullptr;
828     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
829     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
830         NAPI_ERR_INPUT_INVALID_INFO), "On: napi_get_cb_info fail");
831     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_TWO, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
832         NAPI_ERR_INPUT_INVALID_INFO), "invalid arguments");
833 
834     napi_valuetype argvType = napi_undefined;
835     napi_typeof(env, argv[PARAM0], &argvType);
836     CHECK_AND_RETURN_RET_LOG(argvType == napi_string, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
837         NAPI_ERR_INPUT_INVALID_INFO), "The type of callbackName must be string");
838 
839     std::string callbackName = RingtoneCommonNapi::GetStringArgument(env, argv[0]);
840     MEDIA_LOGI("On: callbackName: %{public}s", callbackName.c_str());
841 
842     if (argc == ARGS_TWO) {
843         napi_valuetype callbackFunction = napi_undefined;
844         napi_typeof(env, argv[PARAM1], &callbackFunction);
845         CHECK_AND_RETURN_RET_LOG(callbackFunction == napi_function, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
846             NAPI_ERR_INPUT_INVALID_INFO), "The type of callback must be function");
847     } else {
848         napi_valuetype paramArg1 = napi_undefined;
849         napi_typeof(env, argv[PARAM1], &paramArg1);
850         CHECK_AND_RETURN_RET_LOG(paramArg1 == napi_number, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
851             NAPI_ERR_INPUT_INVALID_INFO), "The type of streamId must be number");
852 
853         napi_valuetype paramArg2 = napi_undefined;
854         napi_typeof(env, argv[PARAM2], &paramArg2);
855         CHECK_AND_RETURN_RET_LOG(paramArg2 == napi_function, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
856             NAPI_ERR_INPUT_INVALID_INFO), "The type of callback must be function");
857     }
858 
859     return RegisterCallback(env, jsThis, argv, callbackName);
860 }
861 
RegisterCallback(napi_env env,napi_value jsThis,napi_value * argv,const std::string & cbName)862 napi_value SystemTonePlayerNapi::RegisterCallback(napi_env env, napi_value jsThis, napi_value *argv,
863     const std::string &cbName)
864 {
865     SystemTonePlayerNapi *systemTonePlayerNapi = nullptr;
866     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&systemTonePlayerNapi));
867     CHECK_AND_RETURN_RET_LOG(status == napi_ok, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
868         NAPI_ERR_INPUT_INVALID_INFO), "system err");
869     CHECK_AND_RETURN_RET_LOG(systemTonePlayerNapi != nullptr, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
870         NAPI_ERR_INPUT_INVALID_INFO), "systemTonePlayerNapi is nullptr");
871     CHECK_AND_RETURN_RET_LOG(systemTonePlayerNapi->systemTonePlayer_ != nullptr, ThrowErrorAndReturn(env,
872         NAPI_ERR_INPUT_INVALID, NAPI_ERR_INPUT_INVALID_INFO), "systemTonePlayer_ is nullptr");
873 
874     if (!cbName.compare(PLAY_FINISHED_CALLBACK_NAME) ||
875         !cbName.compare(ERROR_CALLBACK_NAME)) {
876         return RegisterSystemTonePlayerCallback(env, argv, cbName, systemTonePlayerNapi);
877     }
878 
879     return ThrowErrorAndReturn(env, NAPI_ERR_PARAM_CHECK_ERROR, NAPI_ERR_PARAM_CHECK_ERROR_INFO);
880 }
881 
RegisterSystemTonePlayerCallback(napi_env env,napi_value * argv,const std::string & cbName,SystemTonePlayerNapi * systemTonePlayerNapi)882 napi_value SystemTonePlayerNapi::RegisterSystemTonePlayerCallback(napi_env env, napi_value *argv,
883     const std::string &cbName, SystemTonePlayerNapi *systemTonePlayerNapi)
884 {
885     CHECK_AND_RETURN_RET_LOG(systemTonePlayerNapi->callbackNapi_ != nullptr, ThrowErrorAndReturn(env,
886         NAPI_ERR_INPUT_INVALID, NAPI_ERR_INPUT_INVALID_INFO), "callbackNapi_ is nullptr");
887 
888     std::shared_ptr<SystemTonePlayerCallbackNapi> cb =
889         std::static_pointer_cast<SystemTonePlayerCallbackNapi>(systemTonePlayerNapi->callbackNapi_);
890     if (cbName == PLAY_FINISHED_CALLBACK_NAME) {
891         int32_t streamId = -1;
892         napi_get_value_int32(env, argv[PARAM1], &streamId);
893         // streamId is 0 means all streamId
894         CHECK_AND_RETURN_RET_LOG(systemTonePlayerNapi->systemTonePlayer_->IsStreamIdExist(streamId) ||
895             streamId == ALL_STREAMID,
896             ThrowErrorAndReturn(env, NAPI_ERR_PARAM_CHECK_ERROR, NAPI_ERR_PARAM_CHECK_ERROR_INFO),
897             "streamId is not exists");
898         cb->SavePlayFinishedCallbackReference(cbName, argv[PARAM2], streamId);
899     } else if (cbName == ERROR_CALLBACK_NAME) {
900         cb->SaveCallbackReference(cbName, argv[PARAM1]);
901     }
902 
903     napi_value result = nullptr;
904     napi_get_undefined(env, &result);
905     return result;
906 }
907 
Off(napi_env env,napi_callback_info info)908 napi_value SystemTonePlayerNapi::Off(napi_env env, napi_callback_info info)
909 {
910     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(), ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED,
911         NAPI_ERR_PERMISSION_DENIED_INFO), "No system permission");
912 
913     size_t argc = ARGS_THREE;
914     napi_value argv[ARGS_THREE] = {nullptr};
915     napi_value jsThis = nullptr;
916     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
917     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
918         NAPI_ERR_INPUT_INVALID_INFO), "Off: napi_get_cb_info fail");
919     CHECK_AND_RETURN_RET_LOG(argc >= ARGS_ONE, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
920         NAPI_ERR_INPUT_INVALID_INFO), "invalid arguments");
921 
922     napi_valuetype argvType = napi_undefined;
923     napi_typeof(env, argv[PARAM0], &argvType);
924     CHECK_AND_RETURN_RET_LOG(argvType == napi_string, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
925         NAPI_ERR_INPUT_INVALID_INFO), "The type of callbackName must be string");
926 
927     std::string callbackName = RingtoneCommonNapi::GetStringArgument(env, argv[0]);
928     MEDIA_LOGI("Off: callbackName: %{public}s", callbackName.c_str());
929 
930     napi_value callback = nullptr;
931     if (argc == ARGS_TWO) {
932         napi_valuetype callbackFunction = napi_undefined;
933         napi_typeof(env, argv[PARAM1], &callbackFunction);
934         CHECK_AND_RETURN_RET_LOG(callbackFunction == napi_function, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
935             NAPI_ERR_INPUT_INVALID_INFO), "The type of callback must be function");
936         callback = argv[PARAM1];
937     }
938 
939     return UnregisterCallback(env, jsThis, callbackName, callback);
940 }
941 
UnregisterCallback(napi_env env,napi_value jsThis,const std::string & cbName,const napi_value & callback)942 napi_value SystemTonePlayerNapi::UnregisterCallback(napi_env env, napi_value jsThis, const std::string &cbName,
943     const napi_value &callback)
944 {
945     SystemTonePlayerNapi *systemTonePlayerNapi = nullptr;
946     napi_status status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&systemTonePlayerNapi));
947     CHECK_AND_RETURN_RET_LOG(status == napi_ok, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
948         NAPI_ERR_INPUT_INVALID_INFO), "system err");
949     CHECK_AND_RETURN_RET_LOG(systemTonePlayerNapi != nullptr, ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID,
950         NAPI_ERR_INPUT_INVALID_INFO), "systemTonePlayerNapi is nullptr");
951     CHECK_AND_RETURN_RET_LOG(systemTonePlayerNapi->systemTonePlayer_  != nullptr, ThrowErrorAndReturn(env,
952         NAPI_ERR_INPUT_INVALID, NAPI_ERR_INPUT_INVALID_INFO), "systemTonePlayer_ is nullptr");
953 
954     if (!cbName.compare(PLAY_FINISHED_CALLBACK_NAME) ||
955         !cbName.compare(ERROR_CALLBACK_NAME)) {
956         UnregisterSystemTonePlayerCallback(env, systemTonePlayerNapi, cbName, callback);
957     } else {
958         ThrowErrorAndReturn(env, NAPI_ERR_PARAM_CHECK_ERROR, NAPI_ERR_PARAM_CHECK_ERROR_INFO);
959     }
960 
961     napi_value result = nullptr;
962     napi_get_undefined(env, &result);
963     return result;
964 }
965 
UnregisterSystemTonePlayerCallback(napi_env env,SystemTonePlayerNapi * systemTonePlayerNapi,const std::string & cbName,const napi_value & callback)966 void SystemTonePlayerNapi::UnregisterSystemTonePlayerCallback(napi_env env, SystemTonePlayerNapi *systemTonePlayerNapi,
967     const std::string &cbName, const napi_value &callback)
968 {
969     if (systemTonePlayerNapi->callbackNapi_ == nullptr) {
970         ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID, NAPI_ERR_INPUT_INVALID_INFO);
971         MEDIA_LOGE("callbackNapi_ is nullptr");
972         return;
973     }
974 
975     std::shared_ptr<SystemTonePlayerCallbackNapi> cb =
976         std::static_pointer_cast<SystemTonePlayerCallbackNapi>(systemTonePlayerNapi->callbackNapi_);
977     cb->RemoveCallbackReference(cbName, callback);
978 }
979 } // namespace Media
980 } // namespace OHOS