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