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 #ifndef LOG_TAG
16 #define LOG_TAG "NapiAudioVolumeKeyEvent"
17 #endif
18 
19 #include "napi_audio_volume_key_event.h"
20 #include "napi_audio_enum.h"
21 #include "napi_audio_error.h"
22 #include "napi_param_utils.h"
23 #include "audio_manager_log.h"
24 
25 using namespace std;
26 namespace OHOS {
27 namespace AudioStandard {
NapiAudioVolumeKeyEvent(napi_env env)28 NapiAudioVolumeKeyEvent::NapiAudioVolumeKeyEvent(napi_env env)
29     :env_(env)
30 {
31     AUDIO_DEBUG_LOG("NapiAudioVolumeKeyEvent::Constructor");
32 }
33 
~NapiAudioVolumeKeyEvent()34 NapiAudioVolumeKeyEvent::~NapiAudioVolumeKeyEvent()
35 {
36     AUDIO_DEBUG_LOG("NapiAudioVolumeKeyEvent::Destructor");
37 }
38 
OnVolumeKeyEvent(VolumeEvent volumeEvent)39 void NapiAudioVolumeKeyEvent::OnVolumeKeyEvent(VolumeEvent volumeEvent)
40 {
41     std::lock_guard<std::mutex> lock(mutex_);
42     AUDIO_PRERELEASE_LOGI("OnVolumeKeyEvent is called volumeType=%{public}d, volumeLevel=%{public}d,"
43         "isUpdateUi=%{public}d", volumeEvent.volumeType, volumeEvent.volume, volumeEvent.updateUi);
44     CHECK_AND_RETURN_LOG(audioVolumeKeyEventJsCallback_ != nullptr,
45         "NapiAudioVolumeKeyEvent:No JS callback registered return");
46     std::unique_ptr<AudioVolumeKeyEventJsCallback> cb = std::make_unique<AudioVolumeKeyEventJsCallback>();
47     CHECK_AND_RETURN_LOG(cb != nullptr, "No memory");
48     cb->callback = audioVolumeKeyEventJsCallback_;
49     cb->callbackName = VOLUME_KEY_EVENT_CALLBACK_NAME;
50     cb->volumeEvent.volumeType = volumeEvent.volumeType;
51     cb->volumeEvent.volume = volumeEvent.volume;
52     cb->volumeEvent.updateUi = volumeEvent.updateUi;
53     cb->volumeEvent.volumeGroupId = volumeEvent.volumeGroupId;
54     cb->volumeEvent.networkId = volumeEvent.networkId;
55 
56     return OnJsCallbackVolumeEvent(cb);
57 }
58 
SaveCallbackReference(const std::string & callbackName,napi_value args)59 void NapiAudioVolumeKeyEvent::SaveCallbackReference(const std::string &callbackName, napi_value args)
60 {
61     std::lock_guard<std::mutex> lock(mutex_);
62     napi_ref callback = nullptr;
63     const int32_t refCount = 1;
64     napi_status status = napi_create_reference(env_, args, refCount, &callback);
65     CHECK_AND_RETURN_LOG(status == napi_ok && callback != nullptr,
66         "NapiAudioVolumeKeyEvent: creating reference for callback fail");
67     callback_ = callback;
68     std::shared_ptr<AutoRef> cb = std::make_shared<AutoRef>(env_, callback);
69     if (callbackName == VOLUME_KEY_EVENT_CALLBACK_NAME) {
70         audioVolumeKeyEventJsCallback_ = cb;
71     } else {
72         AUDIO_ERR_LOG("NapiAudioVolumeKeyEvent: Unknown callback type: %{public}s", callbackName.c_str());
73     }
74 }
75 
OnJsCallbackVolumeEvent(std::unique_ptr<AudioVolumeKeyEventJsCallback> & jsCb)76 void NapiAudioVolumeKeyEvent::OnJsCallbackVolumeEvent(std::unique_ptr<AudioVolumeKeyEventJsCallback> &jsCb)
77 {
78     if (jsCb.get() == nullptr) {
79         AUDIO_ERR_LOG("OnJsCallbackVolumeEvent: jsCb.get() is null");
80         return;
81     }
82 
83     AudioVolumeKeyEventJsCallback *event = jsCb.get();
84     auto task = [event]() {
85         std::shared_ptr<AudioVolumeKeyEventJsCallback> context(
86             static_cast<AudioVolumeKeyEventJsCallback*>(event),
87             [](AudioVolumeKeyEventJsCallback* ptr) {
88                 delete ptr;
89         });
90         CHECK_AND_RETURN_LOG(event != nullptr, "event is nullptr");
91         std::string request = event->callbackName;
92         CHECK_AND_RETURN_LOG(event->callback != nullptr, "event is nullptr");
93         napi_env env = event->callback->env_;
94         napi_ref callback = event->callback->cb_;
95         napi_handle_scope scope = nullptr;
96         napi_open_handle_scope(env, &scope);
97         CHECK_AND_RETURN_LOG(scope != nullptr, "scope is nullptr");
98         AUDIO_INFO_LOG("JsCallBack %{public}s, doWork", request.c_str());
99         do {
100             napi_value jsCallback = nullptr;
101             napi_status nstatus = napi_get_reference_value(env, callback, &jsCallback);
102             CHECK_AND_BREAK_LOG(nstatus == napi_ok && jsCallback != nullptr, "%{public}s get reference value fail",
103                 request.c_str());
104             napi_value args[ARGS_ONE] = { nullptr };
105             NapiParamUtils::SetValueVolumeEvent(env, event->volumeEvent, args[PARAM0]);
106             CHECK_AND_BREAK_LOG(nstatus == napi_ok && args[PARAM0] != nullptr,
107                 "%{public}s fail to create volumeChange callback", request.c_str());
108 
109             const size_t argCount = ARGS_ONE;
110             napi_value result = nullptr;
111             nstatus = napi_call_function(env, nullptr, jsCallback, argCount, args, &result);
112             CHECK_AND_BREAK_LOG(nstatus == napi_ok, "%{public}s fail to call volumeChange callback",
113                 request.c_str());
114         } while (0);
115         napi_close_handle_scope(env, scope);
116     };
117     if (napi_status::napi_ok != napi_send_event(env_, task, napi_eprio_immediate)) {
118         AUDIO_ERR_LOG("OnJsCallbackVolumeEvent: Failed to SendEvent");
119     } else {
120         jsCb.release();
121     }
122 }
123 
ContainSameJsCallback(napi_value args)124 bool NapiAudioVolumeKeyEvent::ContainSameJsCallback(napi_value args)
125 {
126     bool isEquals = false;
127     napi_value copyValue = nullptr;
128 
129     napi_get_reference_value(env_, callback_, &copyValue);
130     CHECK_AND_RETURN_RET_LOG(args != nullptr, false, "args is nullptr");
131     CHECK_AND_RETURN_RET_LOG(napi_strict_equals(env_, copyValue, args, &isEquals) == napi_ok, false,
132         "Get napi_strict_equals failed");
133 
134     return isEquals;
135 }
136 } // namespace AudioStandard
137 } // namespace OHOS