1 /*
2 * Copyright (C) 2023-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 * Description: implement the cast session manager
15 * Author: zhangge
16 * Create: 2022-06-15
17 */
18
19 #include <thread>
20
21 #include "cast_session_manager.h"
22
23 #include "cast_engine_errors.h"
24 #include "cast_engine_log.h"
25 #include "cast_session_manager_adaptor.h"
26 #include "cast_session_manager_service_proxy.h"
27 #include "i_cast_session.h"
28 #include "if_system_ability_manager.h"
29 #include "iservice_registry.h"
30 #include "system_ability_definition.h"
31
32 namespace OHOS {
33 namespace CastEngine {
34 namespace CastEngineClient {
35 DEFINE_CAST_ENGINE_LABEL("Cast-Client-SessionManager");
36 namespace {
37 constexpr int WAIT_SERVICE_LOAD_TIME_OUT_SECOND = 2;
38 }
39
CastSessionManager()40 CastSessionManager::CastSessionManager()
41 {
42 CLOGI("in");
43 }
44
GetInstance()45 CastSessionManager &CastSessionManager::GetInstance()
46 {
47 static CastSessionManager instance {};
48 return instance;
49 }
50
GetAdaptor()51 std::shared_ptr<ICastSessionManagerAdaptor> CastSessionManager::GetAdaptor()
52 {
53 CLOGI("in");
54 std::unique_lock<std::mutex> lock(mutex_);
55 if (adaptor_) {
56 return adaptor_;
57 }
58
59 auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
60 if (samgr == nullptr) {
61 CLOGE("Failed to get SA manager");
62 return nullptr;
63 }
64 sptr<CastEngineServiceLoadCallback> loadCallback = new (std::nothrow) CastEngineServiceLoadCallback();
65 if (loadCallback == nullptr) {
66 CLOGE("Failed to new object");
67 return nullptr;
68 }
69 constexpr int32_t retryTimes = 5;
70 int retryTime = 0;
71 bool ret = false;
72 isNeedLoadService_ = true;
73 while (!ret && retryTime < retryTimes) {
74 retryTime++;
75 if (isNeedLoadService_) {
76 auto result = samgr->LoadSystemAbility(CAST_ENGINE_SA_ID, loadCallback);
77 if (result != ERR_OK) {
78 CLOGE("systemAbilityId: %d load failed, result code: %d", CAST_ENGINE_SA_ID, result);
79 return nullptr;
80 }
81 isNeedLoadService_ = false;
82 }
83 ret = loadServiceCond_.wait_for(lock, std::chrono::seconds(WAIT_SERVICE_LOAD_TIME_OUT_SECOND),
84 [this] { return (adaptor_ != nullptr); });
85 }
86 if (!ret) {
87 CLOGE("wait service loaded timeout");
88 return nullptr;
89 }
90 return adaptor_;
91 }
92
RegisterListener(std::shared_ptr<ICastSessionManagerListener> listener)93 int32_t CastSessionManager::RegisterListener(std::shared_ptr<ICastSessionManagerListener> listener)
94 {
95 CLOGI("in");
96 if (listener == nullptr) {
97 CLOGE("Failed to init due to the null listener");
98 return CAST_ENGINE_ERROR;
99 }
100 constexpr int32_t sleepTimeMs = 200;
101 constexpr int32_t retryTimes = 1;
102 int retryTime = 0;
103 bool retry = false;
104 do {
105 retry = false;
106 auto adaptor = GetAdaptor();
107 if (!adaptor) {
108 return CAST_ENGINE_ERROR;
109 }
110 sptr<CastEngineServiceDeathRecipient> deathRecipient(
111 new (std::nothrow) CastEngineServiceDeathRecipient(listener));
112 if (!deathRecipient) {
113 CLOGE("Death recipient malloc failed");
114 return CAST_ENGINE_ERROR;
115 }
116 int32_t ret = adaptor->RegisterListener(listener, deathRecipient);
117 if (ret == CAST_ENGINE_SUCCESS) {
118 std::lock_guard<std::mutex> lock(mutex_);
119 deathRecipient_ = deathRecipient;
120 return CAST_ENGINE_SUCCESS;
121 }
122 if (ret == ERR_SERVICE_IS_UNLOADING && retryTime < retryTimes) {
123 CLOGI("cast service is unloading, wait and retry angain");
124 std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeMs));
125 retry = true;
126 retryTime++;
127 std::lock_guard<std::mutex> lock(mutex_);
128 adaptor_ = nullptr;
129 }
130 } while (retry);
131 return CAST_ENGINE_ERROR;
132 }
133
UnregisterListener()134 int32_t CastSessionManager::UnregisterListener()
135 {
136 CLOGI("in");
137 ReleaseServiceDeathRecipient();
138 auto adaptor = GetAdaptor();
139 int32_t ret = adaptor ? adaptor->UnregisterListener() : CAST_ENGINE_ERROR;
140 std::lock_guard<std::mutex> lock(mutex_);
141 adaptor_.reset();
142 return ret;
143 }
144
Release()145 int32_t CastSessionManager::Release()
146 {
147 CLOGI("in");
148 ReleaseServiceDeathRecipient();
149 auto adaptor = GetAdaptor();
150 int32_t ret = adaptor ? adaptor->Release() : CAST_ENGINE_ERROR;
151 std::lock_guard<std::mutex> lock(mutex_);
152 adaptor_.reset();
153 return ret;
154 }
155
SetLocalDevice(const CastLocalDevice & localDevice)156 int32_t CastSessionManager::SetLocalDevice(const CastLocalDevice &localDevice)
157 {
158 CLOGI("in");
159 if (localDevice.deviceId.empty()) {
160 CLOGE("Local device id is null");
161 return CAST_ENGINE_ERROR;
162 }
163 auto adaptor = GetAdaptor();
164 return adaptor ? adaptor->SetLocalDevice(localDevice) : CAST_ENGINE_ERROR;
165 }
166
CreateCastSession(const CastSessionProperty & property,std::shared_ptr<ICastSession> & castSession)167 int32_t CastSessionManager::CreateCastSession(const CastSessionProperty &property,
168 std::shared_ptr<ICastSession> &castSession)
169 {
170 CLOGI("in");
171 auto adaptor = GetAdaptor();
172 return adaptor ? adaptor->CreateCastSession(property, castSession) : CAST_ENGINE_ERROR;
173 }
174
SetSinkSessionCapacity(int sessionCapacity)175 int32_t CastSessionManager::SetSinkSessionCapacity(int sessionCapacity)
176 {
177 CLOGD("in");
178 auto adaptor = GetAdaptor();
179 return adaptor ? adaptor->SetSinkSessionCapacity(sessionCapacity) : CAST_ENGINE_ERROR;
180 }
181
StartDiscovery(int protocols,std::vector<std::string> drmSchemes)182 int32_t CastSessionManager::StartDiscovery(int protocols, std::vector<std::string> drmSchemes)
183 {
184 CLOGD("in");
185 auto adaptor = GetAdaptor();
186 return adaptor ? adaptor->StartDiscovery(protocols, drmSchemes) : CAST_ENGINE_ERROR;
187 }
188
SetDiscoverable(bool enable)189 int32_t CastSessionManager::SetDiscoverable(bool enable)
190 {
191 CLOGI("in");
192 auto adaptor = GetAdaptor();
193 return adaptor ? adaptor->SetDiscoverable(enable) : CAST_ENGINE_ERROR;
194 }
195
StopDiscovery()196 int32_t CastSessionManager::StopDiscovery()
197 {
198 CLOGI("in");
199 auto adaptor = GetAdaptor();
200 return adaptor ? adaptor->StopDiscovery() : CAST_ENGINE_ERROR;
201 }
202
StartDeviceLogging(int32_t fd,uint32_t maxSize)203 int32_t CastSessionManager::StartDeviceLogging(int32_t fd, uint32_t maxSize)
204 {
205 CLOGI("in");
206 auto adaptor = GetAdaptor();
207 return adaptor ? adaptor->StartDeviceLogging(fd, maxSize) : CAST_ENGINE_ERROR;
208 }
209
GetCastSession(std::string sessionId,std::shared_ptr<ICastSession> & castSession)210 int32_t CastSessionManager::GetCastSession(std::string sessionId, std::shared_ptr<ICastSession> &castSession)
211 {
212 CLOGI("in");
213 auto adaptor = GetAdaptor();
214 return adaptor ? adaptor->GetCastSession(sessionId, castSession) : CAST_ENGINE_ERROR;
215 }
216
ReleaseClientResources()217 void CastSessionManager::ReleaseClientResources()
218 {
219 CLOGD("Release client resources");
220 std::shared_ptr<ICastSessionManagerListener> listener;
221 {
222 std::lock_guard<std::mutex> lock(mutex_);
223 if (!!deathRecipient_) {
224 listener = deathRecipient_->GetListener();
225 }
226
227 deathRecipient_.clear();
228 adaptor_.reset();
229 }
230 if (listener) {
231 listener->OnServiceDied();
232 } else {
233 CLOGE("Report is nullptr");
234 }
235 }
236
ReleaseServiceDeathRecipient()237 void CastSessionManager::ReleaseServiceDeathRecipient()
238 {
239 std::lock_guard<std::mutex> lock(mutex_);
240 deathRecipient_.clear();
241 }
242
NotifyServiceLoadResult(const sptr<IRemoteObject> & remoteObject)243 void CastSessionManager::NotifyServiceLoadResult(const sptr<IRemoteObject> &remoteObject)
244 {
245 std::lock_guard<std::mutex> lock(mutex_);
246 isNeedLoadService_ = true;
247 if (!remoteObject || adaptor_) {
248 CLOGE("object is nullptr or adaptor_ is existed");
249 loadServiceCond_.notify_all();
250 return;
251 }
252 auto proxy = iface_cast<CastSessionManagerServiceProxy>(remoteObject);
253 adaptor_ = std::make_shared<CastSessionManagerAdaptor>(proxy);
254 loadServiceCond_.notify_all();
255 }
256
OnRemoteDied(const wptr<IRemoteObject> & object)257 void CastSessionManager::CastEngineServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
258 {
259 CLOGE("Service died, need release resources");
260 CastSessionManager::GetInstance().ReleaseClientResources();
261 }
262 } // namespace CastEngineClient
263 } // namespace CastEngine
264 } // namespace OHOS
265