• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 <memory>
17 
18 #include "avsession_log.h"
19 #include "avsession_info.h"
20 #include "avsession_trace.h"
21 #include "napi_session_listener.h"
22 
23 namespace OHOS::AVSession {
NapiSessionListener()24 NapiSessionListener::NapiSessionListener()
25 {
26     SLOGI("construct");
27     isValid_ = std::make_shared<bool>(true);
28 }
29 
~NapiSessionListener()30 NapiSessionListener::~NapiSessionListener()
31 {
32     SLOGI("destroy");
33     *isValid_ = false;
34 }
35 
36 template<typename T>
HandleEvent(int32_t event,const T & param)37 void NapiSessionListener::HandleEvent(int32_t event, const T& param)
38 {
39     std::lock_guard<std::mutex> lockGuard(lock_);
40     if (callbacks_[event].empty()) {
41         SLOGE("not register callback event=%{public}d", event);
42         return;
43     }
44 
45     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
46         SLOGI("call with flag for event %{public}d", event);
47         asyncCallback_->CallWithFunc(*ref, isValid_,
48             [this, ref, event]() {
49                 std::lock_guard<std::mutex> lockGuard(lock_);
50                 if (callbacks_[event].empty()) {
51                     SLOGE("checkCallbackValid with empty list for event %{public}d", event);
52                     return false;
53                 }
54                 bool hasFunc = false;
55                 for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) {
56                     hasFunc = (ref == it ? true : hasFunc);
57                 }
58                 SLOGD("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event);
59                 return hasFunc;
60             },
61             [param](napi_env env, int& argc, napi_value* argv) {
62                 argc = 1;
63                 NapiUtils::SetValue(env, param, *argv);
64             });
65     }
66 }
67 
68 template<typename T>
HandleEvent(int32_t event,const T & param,bool checkValid)69 void NapiSessionListener::HandleEvent(int32_t event, const T& param, bool checkValid)
70 {
71     std::lock_guard<std::mutex> lockGuard(lock_);
72     if (callbacks_[event].empty()) {
73         SLOGE("not register callback event=%{public}d", event);
74         return;
75     }
76     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
77         SLOGI("call with flag for event %{public}d", event);
78         asyncCallback_->CallWithFunc(*ref, isValid_,
79             [this, ref, event]() {
80                 std::lock_guard<std::mutex> lockGuard(lock_);
81                 if (callbacks_[event].empty()) {
82                     SLOGE("checkCallbackValid with empty list for event %{public}d", event);
83                     return false;
84                 }
85                 bool hasFunc = false;
86                 for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) {
87                     hasFunc = (ref == it ? true : hasFunc);
88                 }
89                 SLOGD("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event);
90                 return hasFunc;
91             },
92             [param](napi_env env, int& argc, napi_value* argv) {
93                 argc = 1;
94                 NapiUtils::SetValue(env, param, *argv);
95             });
96     }
97     SLOGI("handle event %{public}d", static_cast<int32_t>(event));
98 }
99 
100 template<typename T, typename N>
HandleEvent(int32_t event,const T & firstParam,const N & secondParam)101 void NapiSessionListener::HandleEvent(int32_t event, const T& firstParam, const N& secondParam)
102 {
103     std::lock_guard<std::mutex> lockGuard(lock_);
104     if (callbacks_[event].empty()) {
105         SLOGE("not register callback event=%{public}d", event);
106         return;
107     }
108 
109     for (auto ref = callbacks_[event].begin(); ref != callbacks_[event].end(); ++ref) {
110         SLOGI("call with flag for event %{public}d", event);
111         asyncCallback_->CallWithFunc(*ref, isValid_,
112             [this, ref, event]() {
113                 std::lock_guard<std::mutex> lockGuard(lock_);
114                 if (callbacks_[event].empty()) {
115                     SLOGE("checkCallbackValid with empty list for event %{public}d", event);
116                     return false;
117                 }
118                 bool hasFunc = false;
119                 for (auto it = callbacks_[event].begin(); it != callbacks_[event].end(); ++it) {
120                     hasFunc = (ref == it ? true : hasFunc);
121                 }
122                 SLOGD("checkCallbackValid return hasFunc %{public}d, %{public}d", hasFunc, event);
123                 return hasFunc;
124             },
125             [firstParam, secondParam](napi_env env, int& argc, napi_value* argv) {
126                 argc = NapiUtils::ARGC_TWO;
127                 auto status = NapiUtils::SetValue(env, firstParam, argv[0]);
128                 CHECK_RETURN_VOID(status == napi_ok, "set firstParam invalid");
129                 status = NapiUtils::SetValue(env, secondParam, argv[1]);
130                 CHECK_RETURN_VOID(status == napi_ok, "set secondParam invalid");
131             });
132     }
133     SLOGI("handle event %{public}d", static_cast<int32_t>(event));
134 }
135 
OnSessionCreate(const AVSessionDescriptor & descriptor)136 void NapiSessionListener::OnSessionCreate(const AVSessionDescriptor& descriptor)
137 {
138     AVSESSION_TRACE_SYNC_START("NapiSessionListener::OnSessionCreate");
139     SLOGI("sessionId=%{public}s", descriptor.sessionId_.c_str());
140     HandleEvent(EVENT_SESSION_CREATED, descriptor);
141 }
142 
OnSessionRelease(const AVSessionDescriptor & descriptor)143 void NapiSessionListener::OnSessionRelease(const AVSessionDescriptor& descriptor)
144 {
145     SLOGI("sessionId=%{public}s", descriptor.sessionId_.c_str());
146     HandleEvent(EVENT_SESSION_DESTROYED, descriptor);
147 }
148 
OnTopSessionChange(const AVSessionDescriptor & descriptor)149 void NapiSessionListener::OnTopSessionChange(const AVSessionDescriptor& descriptor)
150 {
151     AVSESSION_TRACE_SYNC_START("NapiSessionListener::OnTopSessionChange");
152     SLOGI("sessionId=%{public}s", descriptor.sessionId_.c_str());
153     HandleEvent(EVENT_TOP_SESSION_CHANGED, descriptor);
154 }
155 
OnAudioSessionChecked(const int32_t uid)156 void NapiSessionListener::OnAudioSessionChecked(const int32_t uid)
157 {
158     AVSESSION_TRACE_SYNC_START("NapiSessionListener::OnAudioSessionCheck");
159     SLOGI("uid=%{public}d checked", uid);
160     HandleEvent(EVENT_AUDIO_SESSION_CHECKED, uid);
161 }
162 
OnDeviceAvailable(const OutputDeviceInfo & castOutputDeviceInfo)163 void NapiSessionListener::OnDeviceAvailable(const OutputDeviceInfo& castOutputDeviceInfo)
164 {
165     AVSESSION_TRACE_SYNC_START("NapiSessionListener::OnDeviceAvailable");
166     SLOGI("Start handle device found event");
167     HandleEvent(EVENT_DEVICE_AVAILABLE, castOutputDeviceInfo, true);
168 }
169 
OnDeviceLogEvent(const DeviceLogEventCode eventId,const int64_t param)170 void NapiSessionListener::OnDeviceLogEvent(const DeviceLogEventCode eventId, const int64_t param)
171 {
172     AVSESSION_TRACE_SYNC_START("NapiSessionListener::OnDeviceLogEvent");
173     SLOGI("Start device log event");
174     HandleEvent(EVENT_DEVICE_LOG_EVENT, eventId, param);
175 }
176 
OnDeviceOffline(const std::string & deviceId)177 void NapiSessionListener::OnDeviceOffline(const std::string& deviceId)
178 {
179     AVSESSION_TRACE_SYNC_START("NapiSessionListener::OnDeviceOffline");
180     SLOGI("Start handle device offline event");
181     HandleEvent(EVENT_DEVICE_OFFLINE, deviceId);
182 }
183 
AddCallback(napi_env env,int32_t event,napi_value callback)184 napi_status NapiSessionListener::AddCallback(napi_env env, int32_t event, napi_value callback)
185 {
186     std::lock_guard<std::mutex> lockGuard(lock_);
187     napi_ref ref = nullptr;
188     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
189                              napi_generic_failure, "get callback reference failed");
190     CHECK_AND_RETURN_RET_LOG(ref == nullptr, napi_ok, "callback has been registered");
191     napi_status status = napi_create_reference(env, callback, 1, &ref);
192     if (status != napi_ok) {
193         SLOGE("napi_create_reference failed");
194         return status;
195     }
196     if (asyncCallback_ == nullptr) {
197         asyncCallback_ = std::make_shared<NapiAsyncCallback>(env);
198     }
199     callbacks_[event].push_back(ref);
200     SLOGI("add callback %{public}d", static_cast<int32_t>(event));
201     return napi_ok;
202 }
203 
RemoveCallback(napi_env env,int32_t event,napi_value callback)204 napi_status NapiSessionListener::RemoveCallback(napi_env env, int32_t event, napi_value callback)
205 {
206     std::lock_guard<std::mutex> lockGuard(lock_);
207     SLOGI("remove callback %{public}d", static_cast<int32_t>(event));
208 
209     if (callback == nullptr) {
210         for (auto& callbackRef : callbacks_[event]) {
211             napi_status ret = napi_delete_reference(env, callbackRef);
212             CHECK_AND_RETURN_RET_LOG(napi_ok == ret, ret, "delete callback reference failed");
213             callbackRef = nullptr;
214         }
215         callbacks_[event].clear();
216         return napi_ok;
217     }
218     napi_ref ref = nullptr;
219     CHECK_AND_RETURN_RET_LOG(napi_ok == NapiUtils::GetRefByCallback(env, callbacks_[event], callback, ref),
220                              napi_generic_failure, "get callback reference failed");
221     CHECK_AND_RETURN_RET_LOG(ref != nullptr, napi_ok, "callback has been remove");
222     callbacks_[event].remove(ref);
223     return napi_delete_reference(env, ref);
224 }
225 }