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 <thread>
24 
25 #include "cast_engine_errors.h"
26 #include "cast_engine_log.h"
27 #include "cast_engine_service_load_callback.h"
28 #include "cast_session_manager_adaptor.h"
29 #include "cast_session_manager_service_proxy.h"
30 #include "i_cast_session.h"
31 #include "if_system_ability_manager.h"
32 #include "iservice_registry.h"
33 #include "system_ability_definition.h"
34 
35 namespace OHOS {
36 namespace CastEngine {
37 namespace CastEngineClient {
38 DEFINE_CAST_ENGINE_LABEL("Cast-Client-SessionManager");
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::lock_guard<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 
70     auto result = samgr->LoadSystemAbility(CAST_ENGINE_SA_ID, loadCallback);
71     if (result != ERR_OK) {
72         CLOGE("systemAbilityId: %d load failed, result code: %d", CAST_ENGINE_SA_ID, result);
73         return nullptr;
74     }
75 
76     constexpr int32_t sleepTimeMs = 30;
77     constexpr int32_t retryTimes = 150; // The service startup timeout interval is 4s.
78     int32_t retryTime = 0;
79 
80     sptr<IRemoteObject> object;
81     while ((object = samgr->CheckSystemAbility(CAST_ENGINE_SA_ID)) == nullptr && (retryTime < retryTimes)) {
82         std::this_thread::sleep_for(std::chrono::milliseconds(sleepTimeMs));
83         retryTime++;
84     }
85     if (object == nullptr) {
86         CLOGE("Failed to get cast engine manager");
87         return nullptr;
88     }
89 
90     auto proxy = iface_cast<CastSessionManagerServiceProxy>(object);
91     adaptor_ = std::make_shared<CastSessionManagerAdaptor>(proxy);
92     return adaptor_;
93 }
94 
RegisterListener(std::shared_ptr<ICastSessionManagerListener> listener)95 int32_t CastSessionManager::RegisterListener(std::shared_ptr<ICastSessionManagerListener> listener)
96 {
97     CLOGI("in");
98     if (listener == nullptr) {
99         CLOGE("Failed to init due to the null listener");
100         return CAST_ENGINE_ERROR;
101     }
102     auto adaptor = GetAdaptor();
103     if (!adaptor) {
104         return CAST_ENGINE_ERROR;
105     }
106     sptr<CastEngineServiceDeathRecipient> deathRecipient(
107         new (std::nothrow) CastEngineServiceDeathRecipient(listener));
108     if (!deathRecipient) {
109         CLOGE("Death recipient malloc failed");
110         return CAST_ENGINE_ERROR;
111     }
112     if (adaptor->RegisterListener(listener, deathRecipient) == CAST_ENGINE_SUCCESS) {
113         std::lock_guard<std::mutex> lock(mutex_);
114         deathRecipient_ = deathRecipient;
115         return CAST_ENGINE_SUCCESS;
116     }
117     return CAST_ENGINE_ERROR;
118 }
119 
UnregisterListener()120 int32_t CastSessionManager::UnregisterListener()
121 {
122     CLOGI("in");
123     ReleaseServiceDeathRecipient();
124     auto adaptor = GetAdaptor();
125     int32_t ret = adaptor ? adaptor->UnregisterListener() : CAST_ENGINE_ERROR;
126     std::lock_guard<std::mutex> lock(mutex_);
127     adaptor_ = nullptr;
128     return ret;
129 }
130 
Release()131 int32_t CastSessionManager::Release()
132 {
133     CLOGI("in");
134     ReleaseServiceDeathRecipient();
135     auto adaptor = GetAdaptor();
136     int32_t ret = adaptor ? adaptor->Release() : CAST_ENGINE_ERROR;
137     std::lock_guard<std::mutex> lock(mutex_);
138     adaptor_ = nullptr;
139     return ret;
140 }
141 
SetLocalDevice(const CastLocalDevice &localDevice)142 int32_t CastSessionManager::SetLocalDevice(const CastLocalDevice &localDevice)
143 {
144     CLOGI("in");
145     if (localDevice.deviceId.empty()) {
146         CLOGE("Local device id is null");
147         return CAST_ENGINE_ERROR;
148     }
149     auto adaptor = GetAdaptor();
150     return adaptor ? adaptor->SetLocalDevice(localDevice) : CAST_ENGINE_ERROR;
151 }
152 
CreateCastSession(const CastSessionProperty &property, std::shared_ptr<ICastSession> &castSession)153 int32_t CastSessionManager::CreateCastSession(const CastSessionProperty &property,
154     std::shared_ptr<ICastSession> &castSession)
155 {
156     CLOGI("in");
157     auto adaptor = GetAdaptor();
158     return adaptor ? adaptor->CreateCastSession(property, castSession) : CAST_ENGINE_ERROR;
159 }
160 
SetSinkSessionCapacity(int sessionCapacity)161 int32_t CastSessionManager::SetSinkSessionCapacity(int sessionCapacity)
162 {
163     CLOGD("in");
164     auto adaptor = GetAdaptor();
165     return adaptor ? adaptor->SetSinkSessionCapacity(sessionCapacity) : CAST_ENGINE_ERROR;
166 }
167 
StartDiscovery(int protocols)168 int32_t CastSessionManager::StartDiscovery(int protocols)
169 {
170     CLOGD("in");
171     auto adaptor = GetAdaptor();
172     return adaptor ? adaptor->StartDiscovery(protocols) : CAST_ENGINE_ERROR;
173 }
174 
SetDiscoverable(bool enable)175 int32_t CastSessionManager::SetDiscoverable(bool enable)
176 {
177     CLOGI("in");
178     auto adaptor = GetAdaptor();
179     return adaptor ? adaptor->SetDiscoverable(enable) : CAST_ENGINE_ERROR;
180 }
181 
StopDiscovery()182 int32_t CastSessionManager::StopDiscovery()
183 {
184     CLOGI("in");
185     auto adaptor = GetAdaptor();
186     return adaptor ? adaptor->StopDiscovery() : CAST_ENGINE_ERROR;
187 }
188 
GetCastSession(std::string sessionId, std::shared_ptr<ICastSession> &castSession)189 int32_t CastSessionManager::GetCastSession(std::string sessionId, std::shared_ptr<ICastSession> &castSession)
190 {
191     CLOGI("in");
192     auto adaptor = GetAdaptor();
193     return adaptor ? adaptor->GetCastSession(sessionId, castSession) : CAST_ENGINE_ERROR;
194 }
195 
ReleaseClientResources()196 void CastSessionManager::ReleaseClientResources()
197 {
198     CLOGD("Release client resources");
199     std::lock_guard<std::mutex> lock(mutex_);
200     std::shared_ptr<ICastSessionManagerListener> listener;
201     {
202         if (!!deathRecipient_) {
203             listener = deathRecipient_->GetListener();
204         }
205         deathRecipient_ = nullptr;
206         adaptor_ = nullptr;
207     }
208     if (listener) {
209         listener->OnServiceDied();
210     } else {
211         CLOGE("Report is nullptr");
212     }
213 }
214 
ReleaseServiceDeathRecipient()215 void CastSessionManager::ReleaseServiceDeathRecipient()
216 {
217     std::lock_guard<std::mutex> lock(mutex_);
218     deathRecipient_ = nullptr;
219 }
220 
OnRemoteDied(const wptr<IRemoteObject> &object)221 void CastSessionManager::CastEngineServiceDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
222 {
223     CLOGE("Service died, need release resources");
224     CastSessionManager::GetInstance().ReleaseClientResources();
225 }
226 } // namespace CastEngineClient
227 } // namespace CastEngine
228 } // namespace OHOS
229