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], ¶mArg1);
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], ¶mArg2);
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