1 /*
2 * Copyright (c) 2022-2024 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 "2.0/include/dscreen_manager.h"
17
18 #include <cinttypes>
19 #include <dlfcn.h>
20 #include <fstream>
21 #include <map>
22
23 #include "if_system_ability_manager.h"
24 #include "iservice_registry.h"
25 #include "nlohmann/json.hpp"
26
27 #include "dscreen_constants.h"
28 #include "dscreen_errcode.h"
29 #include "dscreen_fwkkit.h"
30 #include "dscreen_json_util.h"
31 #include "dscreen_log.h"
32 #include "dscreen_util.h"
33 #include "idscreen_sink.h"
34 #include "common/include/screen_manager_adapter.h"
35
36 using json = nlohmann::json;
37
38 namespace OHOS {
39 namespace DistributedHardware {
40 namespace V2_0 {
41 IMPLEMENT_SINGLE_INSTANCE(DScreenManager);
42
43 using AVTransProviderClass = IAVEngineProvider *(*)(const std::string);
44
45 const std::string SENDER_SO_NAME = "libdistributed_av_sender.z.so";
46 const std::string GET_PROVIDER_FUNC = "GetAVSenderEngineProvider";
47
48 const std::map<DScreenState, std::string> stateMap = {
49 { DISABLED, "disabled" },
50 { ENABLED, "enabled" },
51 { DISABLING, "disabling" },
52 { ENABLING, "enabling" },
53 { CONNECTING, "connecting" },
54 { CONNECTED, "connected" },
55 { DISCONNECTING, "disconnecting" }
56 };
57
DScreenManager()58 DScreenManager::DScreenManager()
59 {
60 DHLOGI("DScreenMgr construct.");
61 }
62
~DScreenManager()63 DScreenManager::~DScreenManager()
64 {
65 DHLOGI("DScreenMgr deConstruct.");
66 }
67
Initialize()68 int32_t DScreenManager::Initialize()
69 {
70 DHLOGI("DScreenManager::Init2.0");
71 int32_t ret = LoadAVSenderEngineProvider();
72 if (ret != DH_SUCCESS) {
73 DHLOGE("Load av transport sender engine provider failed.");
74 }
75 return ret;
76 }
77
Release()78 int32_t DScreenManager::Release()
79 {
80 DHLOGI("DScreenManager::UnInit");
81 UnloadAVSenderEngineProvider();
82 ScreenMgrAdapter::GetInstance().UnregisterScreenGroupListener(dScreenGroupListener_);
83 {
84 std::lock_guard<std::mutex> lock(dScreenMapMtx_);
85 dScreens_.clear();
86 }
87 providerPtr_ = nullptr;
88 {
89 std::lock_guard<std::mutex> lock(dScreenCallbackMtx_);
90 dScreenCallback_ = nullptr;
91 }
92 DHLOGI("DScreenManager::UnInit success");
93 return DH_SUCCESS;
94 }
95
OnChange(const std::vector<uint64_t> & screenIds,Rosen::ScreenGroupChangeEvent event)96 void DScreenGroupListener::OnChange(const std::vector<uint64_t> &screenIds, Rosen::ScreenGroupChangeEvent event)
97 {
98 DHLOGI("On Screen change, screenIds size: %{public}zu", screenIds.size());
99 for (uint64_t screenId : screenIds) {
100 std::shared_ptr<DScreen> changedScreen = DScreenManager::GetInstance().FindDScreenById(screenId);
101 if (changedScreen == nullptr) {
102 DHLOGD("screen change not about remote screen, screenId: %{public}" PRIu64, screenId);
103 continue;
104 }
105 DScreenManager::GetInstance().HandleScreenChange(changedScreen, event);
106 }
107 }
108
HandleScreenChange(const std::shared_ptr<DScreen> & changedScreen,Rosen::ScreenGroupChangeEvent event)109 void DScreenManager::HandleScreenChange(const std::shared_ptr<DScreen> &changedScreen,
110 Rosen::ScreenGroupChangeEvent event)
111 {
112 if (changedScreen == nullptr) {
113 DHLOGE("DScreenManager::HandleScreenChange, dScreen is null.");
114 return;
115 }
116 DHLOGI("DScreenManager::HandleScreenChange, screenId: %{public}" PRIu64 " changeEvent: %{public}" PRIu32,
117 changedScreen->GetScreenId(), event);
118 if (event == Rosen::ScreenGroupChangeEvent::ADD_TO_GROUP) {
119 if (StartDScreenMirror(changedScreen) != DH_SUCCESS) {
120 DHLOGE("start dScreen mirror failed.");
121 return;
122 }
123 PublishMessage(DHTopic::TOPIC_START_DSCREEN, changedScreen);
124 } else if (event == Rosen::ScreenGroupChangeEvent::REMOVE_FROM_GROUP) {
125 if (StopDScreenMirror(changedScreen) != DH_SUCCESS) {
126 DHLOGE("stop dScreen mirror failed.");
127 }
128 PublishMessage(DHTopic::TOPIC_STOP_DSCREEN, changedScreen);
129 } else if (event == Rosen::ScreenGroupChangeEvent::CHANGE_GROUP) {
130 DHLOGE("CHANGE_GROUP not implement.");
131 } else {
132 DHLOGE("unknown change type.");
133 }
134 }
135
StartDScreenMirror(const std::shared_ptr<DScreen> & dScreen)136 int32_t DScreenManager::StartDScreenMirror(const std::shared_ptr<DScreen> &dScreen)
137 {
138 if (dScreen == nullptr) {
139 DHLOGE("DScreenManager::StartDScreenMirror, dScreen is null.");
140 return ERR_DH_SCREEN_SA_VALUE_NOT_INIT;
141 }
142 uint64_t screenId = dScreen->GetScreenId();
143 DHLOGI("DScreenManager::StartDScreenMirror, screenId: %{public}" PRIu64, screenId);
144 if (dScreen->GetState() == CONNECTING) {
145 DHLOGD("screen is connecting, no need handle change");
146 return DH_SUCCESS;
147 }
148 int32_t ret = dScreen->InitSenderEngine(providerPtr_, dScreen->GetDevId());
149 if (ret != DH_SUCCESS) {
150 DHLOGE("init av transport sender engine failed.");
151 return ret;
152 }
153 dScreen->AddTask(std::make_shared<Task>(TaskType::TASK_CONNECT, ""));
154 DHLOGI("StartDScreenMirror success, screenId:%{public}" PRIu64 ", peerDeviceId:%{public}s", screenId,
155 GetAnonyString(dScreen->GetDevId()).c_str());
156 return DH_SUCCESS;
157 }
158
StopDScreenMirror(const std::shared_ptr<DScreen> & dScreen)159 int32_t DScreenManager::StopDScreenMirror(const std::shared_ptr<DScreen> &dScreen)
160 {
161 if (dScreen == nullptr) {
162 DHLOGE("DScreenManager::StopDScreenMirror, dScreen is null.");
163 return ERR_DH_SCREEN_SA_VALUE_NOT_INIT;
164 }
165 DHLOGI("DScreenManager::StopDScreenMirror, screenId: %{public}" PRIu64, dScreen->GetScreenId());
166 if (dScreen->GetState() == DISCONNECTING) {
167 DHLOGD("screen is disconnecting, no need handle change");
168 return DH_SUCCESS;
169 }
170 dScreen->AddTask(std::make_shared<Task>(TaskType::TASK_DISCONNECT, ""));
171 return DH_SUCCESS;
172 }
173
OnRegResult(const std::shared_ptr<DScreen> & dScreen,const std::string & reqId,const int32_t status,const std::string & data)174 void DScreenCallback::OnRegResult(const std::shared_ptr<DScreen> &dScreen,
175 const std::string &reqId, const int32_t status, const std::string &data)
176 {
177 if (dScreen == nullptr) {
178 DHLOGE("DScreenCallback::OnRegResult, dScreen id nullptr");
179 return;
180 }
181 DHLOGI("DScreenCallback::OnRegResult, devId: %{public}s, dhId: %{public}s, reqId: %{public}s",
182 GetAnonyString(dScreen->GetDevId()).c_str(), GetAnonyString(dScreen->GetDHId()).c_str(),
183 GetAnonyString(reqId).c_str());
184 DScreenManager::GetInstance().OnRegResult(dScreen, reqId, status, data);
185 }
186
OnUnregResult(const std::shared_ptr<DScreen> & dScreen,const std::string & reqId,const int32_t status,const std::string & data)187 void DScreenCallback::OnUnregResult(const std::shared_ptr<DScreen> &dScreen,
188 const std::string &reqId, const int32_t status, const std::string &data)
189 {
190 if (dScreen == nullptr) {
191 DHLOGE("DScreenCallback::OnUnregResult, dScreen id nullptr");
192 return;
193 }
194 DHLOGI("DScreenCallback::OnUnregResult, devId: %{public}s, dhId: %{public}s, reqId: %{public}s",
195 GetAnonyString(dScreen->GetDevId()).c_str(), GetAnonyString(dScreen->GetDHId()).c_str(),
196 GetAnonyString(reqId).c_str());
197 DScreenManager::GetInstance().OnUnregResult(dScreen, reqId, status, data);
198 }
199
OnRegResult(const std::shared_ptr<DScreen> & dScreen,const std::string & reqId,int32_t status,const std::string & data)200 void DScreenManager::OnRegResult(const std::shared_ptr<DScreen> &dScreen,
201 const std::string &reqId, int32_t status, const std::string &data)
202 {
203 DHLOGI("DScreenManager::OnRegResult, devId: %{public}s, dhId: %{public}s, reqId: %{public}s",
204 GetAnonyString(dScreen->GetDevId()).c_str(), GetAnonyString(dScreen->GetDHId()).c_str(),
205 GetAnonyString(reqId).c_str());
206 if (dScreenSourceCallbackProxy_ == nullptr) {
207 DHLOGE("dScreenSourceCallbackProxy is null");
208 return;
209 }
210 dScreenSourceCallbackProxy_->OnNotifyRegResult(dScreen->GetDevId(), dScreen->GetDHId(), reqId, status, data);
211 }
212
OnUnregResult(const std::shared_ptr<DScreen> & dScreen,const std::string & reqId,int32_t status,const std::string & data)213 void DScreenManager::OnUnregResult(const std::shared_ptr<DScreen> &dScreen,
214 const std::string &reqId, int32_t status, const std::string &data)
215 {
216 DHLOGI("DScreenManager::OnUnregResult, devId: %{public}s, dhId: %{public}s, reqId: %{public}s",
217 GetAnonyString(dScreen->GetDevId()).c_str(), GetAnonyString(dScreen->GetDHId()).c_str(),
218 GetAnonyString(reqId).c_str());
219 if (dScreenSourceCallbackProxy_ == nullptr) {
220 DHLOGE("dScreenSourceCallbackProxy is null");
221 return;
222 }
223 dScreenSourceCallbackProxy_->OnNotifyUnregResult(dScreen->GetDevId(), dScreen->GetDHId(), reqId, status, data);
224 }
225
EnableDistributedScreen(const std::string & devId,const std::string & dhId,const EnableParam & param,const std::string & reqId)226 int32_t DScreenManager::EnableDistributedScreen(const std::string &devId, const std::string &dhId,
227 const EnableParam ¶m, const std::string &reqId)
228 {
229 DHLOGI("EnableDistributedScreen2.0, devId: %{public}s, dhId:%{public}s", GetAnonyString(devId).c_str(),
230 GetAnonyString(dhId).c_str());
231 if (devId.empty() || dhId.empty() || param.sinkVersion.empty() || param.sinkAttrs.empty() || reqId.empty()) {
232 DHLOGE("EnableDistributedScreen2.0 CheckRegParams is inlvalid.");
233 return ERR_DH_SCREEN_SA_ENABLE_FAILED;
234 }
235 if (dScreenGroupListener_ == nullptr) {
236 dScreenGroupListener_ = new (std::nothrow) DScreenGroupListener();
237 int32_t ret = ScreenMgrAdapter::GetInstance().RegisterScreenGroupListener(dScreenGroupListener_);
238 if (ret != DH_SUCCESS) {
239 DHLOGE("DScreenManager2.0 EnableDistributedScreen failed, err: %{public}" PRId32, ret);
240 dScreenGroupListener_ = nullptr;
241 return ERR_DH_SCREEN_SA_ENABLE_FAILED;
242 }
243 }
244 std::string dScreenIdx = devId + SEPERATOR + dhId;
245 std::lock_guard<std::mutex> lock(dScreenMapMtx_);
246 std::shared_ptr<DScreen> dScreen = dScreens_[dScreenIdx];
247 if (dScreen == nullptr) {
248 std::lock_guard<std::mutex> lock(dScreenCallbackMtx_);
249 if (dScreenCallback_ == nullptr) {
250 dScreenCallback_ = std::make_shared<DScreenCallback>();
251 }
252 dScreen = std::make_shared<DScreen>(devId, dhId, dScreenCallback_);
253 }
254 int32_t dScreenState = dScreen->GetState();
255 if (dScreenState == ENABLED || dScreenState == ENABLING) {
256 DHLOGI("dScreen state Already is ENABLED or ENABLING.");
257 return DH_SUCCESS;
258 }
259 dScreens_[dScreenIdx] = dScreen;
260 int32_t ret = dScreen->AddTask(std::make_shared<Task>(TaskType::TASK_ENABLE, reqId, param.sinkAttrs));
261 if (ret != DH_SUCCESS) {
262 DHLOGE("EnableDistributedScreen, add task failed. devId: %{public}s, dhId:%{public}s",
263 GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
264 }
265 return ret;
266 }
267
DisableDistributedScreen(const std::string & devId,const std::string & dhId,const std::string & reqId)268 int32_t DScreenManager::DisableDistributedScreen(const std::string &devId, const std::string &dhId,
269 const std::string &reqId)
270 {
271 DHLOGI("DisableDistributedScreen, devId: %{public}s, dhId:%{public}s", GetAnonyString(devId).c_str(),
272 GetAnonyString(dhId).c_str());
273 std::string dScreenIdx = devId + SEPERATOR + dhId;
274 std::lock_guard<std::mutex> lock(dScreenMapMtx_);
275 if (dScreens_.count(dScreenIdx) == 0) {
276 DHLOGE("dscreen has already disabled, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId).c_str(),
277 GetAnonyString(dhId).c_str());
278 return DH_SUCCESS;
279 }
280 int32_t dScreenState = dScreens_[dScreenIdx]->GetState();
281 int32_t ret = DH_SUCCESS;
282 switch (dScreenState) {
283 case DISABLED:
284 case DISABLING:
285 DHLOGE("dScreen state is invalid.");
286 ret = ERR_DH_SCREEN_SA_DISABLE_FAILED;
287 break;
288 case ENABLED:
289 case ENABLING:
290 ret = dScreens_[dScreenIdx]->AddTask(std::make_shared<Task>(TaskType::TASK_DISABLE, reqId, ""));
291 break;
292 case CONNECTING:
293 case CONNECTED:
294 case DISCONNECTING:
295 ret = dScreens_[dScreenIdx]->AddTask(std::make_shared<Task>(TaskType::TASK_DISCONNECT, ""));
296 if (ret == DH_SUCCESS) {
297 ret = dScreens_[dScreenIdx]->AddTask(std::make_shared<Task>(TaskType::TASK_DISABLE, reqId, ""));
298 }
299 break;
300 default:
301 ret = ERR_DH_SCREEN_SA_DISABLE_FAILED;
302 break;
303 }
304 return ret;
305 }
306
RegisterDScreenCallback(const sptr<IDScreenSourceCallback> & callback)307 void DScreenManager::RegisterDScreenCallback(const sptr<IDScreenSourceCallback> &callback)
308 {
309 DHLOGI("RegisterDScreenCallback");
310 dScreenSourceCallbackProxy_ = callback;
311 }
312
FindDScreenById(uint64_t screenId)313 std::shared_ptr<DScreen> DScreenManager::FindDScreenById(uint64_t screenId)
314 {
315 DHLOGD("FindDScreenById, screenId: %{public}" PRIu64, screenId);
316 std::lock_guard<std::mutex> lock(dScreenMapMtx_);
317 for (const auto &iter : dScreens_) {
318 std::shared_ptr<DScreen> dScreen = iter.second;
319 if (dScreen == nullptr) {
320 continue;
321 }
322 if (dScreen->GetScreenId() == screenId) {
323 return dScreen;
324 }
325 }
326 DHLOGD("DScreen not found, screenId: %{public}" PRIu64, screenId);
327 return nullptr;
328 }
329
GetScreenDumpInfo(std::string & result)330 void DScreenManager::GetScreenDumpInfo(std::string &result)
331 {
332 DHLOGI("GetScreenDumpInfo.");
333 result.clear();
334 result.append("RemoteScreens OnLine:\n[\n");
335 std::lock_guard<std::mutex> lock(dScreenMapMtx_);
336 if (dScreens_.size() == 0) {
337 result.append("]");
338 DHLOGD("no virtual screen enabled in V2_0::DScreenManager.");
339 return;
340 }
341 for (const auto &iter : dScreens_) {
342 result.append(" {\n");
343 std::shared_ptr<DScreen> dScreen = iter.second;
344 if (dScreen == nullptr) {
345 continue;
346 }
347 uint64_t screenId = dScreen->GetScreenId();
348 std::string devId = dScreen->GetDevId();
349 std::shared_ptr<VideoParam> videoParam = dScreen->GetVideoParam();
350 if (videoParam == nullptr) {
351 continue;
352 }
353 uint32_t screenHeight = videoParam->GetScreenHeight();
354 uint32_t screenWidth = videoParam->GetScreenWidth();
355 DScreenState state = dScreen->GetState();
356 std::string screenState =
357 stateMap.find(state) == stateMap.end() ? "unknown state" : stateMap.find(state)->second;
358 std::string screenInfo = " \"virtualScreenId\" : \"" + std::to_string(screenId) + "\",\n" +
359 " \"localDevId\" : \"" + GetAnonyString(localDevId_) + "\",\n" +
360 " \"remoteDevId\" : \"" + GetAnonyString(devId) + "\",\n" +
361 " \"screenWidth\" : \"" + std::to_string(screenWidth) + "\",\n" +
362 " \"screenHeight\" : \"" + std::to_string(screenHeight) + "\",\n" +
363 " \"state\" : \"" + screenState + "\"\n";
364 result.append(screenInfo);
365 }
366 result.append(" }\n]");
367 }
368
PublishMessage(const DHTopic topic,const std::shared_ptr<DScreen> & dScreen)369 void DScreenManager::PublishMessage(const DHTopic topic, const std::shared_ptr<DScreen> &dScreen)
370 {
371 DHLOGD("PublishMessage");
372 if (DScreenFwkKit::GetInstance().GetDHFwkKit() == nullptr) {
373 DHLOGE("GetDHFwkKit fail.");
374 return;
375 }
376 json messageJosn;
377 std::string message;
378 if (topic == DHTopic::TOPIC_START_DSCREEN) {
379 messageJosn[SOURCE_WIN_ID] = dScreen->GetScreenId();
380 messageJosn[SINK_DEV_ID] = dScreen->GetDevId();
381 std::shared_ptr<VideoParam> videoParam = dScreen->GetVideoParam();
382 if (videoParam == nullptr) {
383 DHLOGE("videoParam is nullptr");
384 return;
385 }
386 messageJosn[SOURCE_WIN_WIDTH] = videoParam->GetScreenWidth();
387 messageJosn[SOURCE_WIN_HEIGHT] = videoParam->GetScreenHeight();
388 message = messageJosn.dump();
389 } else if (topic == DHTopic::TOPIC_STOP_DSCREEN) {
390 messageJosn[SOURCE_WIN_ID] = dScreen->GetScreenId();
391 messageJosn[SINK_DEV_ID] = dScreen->GetDevId();
392 message = messageJosn.dump();
393 }
394 DScreenFwkKit::GetInstance().GetDHFwkKit()->PublishMessage(topic, message);
395 }
396
LoadAVSenderEngineProvider()397 int32_t DScreenManager::LoadAVSenderEngineProvider()
398 {
399 DHLOGI("LoadAVSenderEngineProvider enter");
400 void *pHandler = dlopen(SENDER_SO_NAME.c_str(), RTLD_LAZY | RTLD_NODELETE);
401 if (pHandler == nullptr) {
402 DHLOGE("so: %{public}s load failed, failed reason : %{public}s", SENDER_SO_NAME.c_str(), dlerror());
403 return ERR_DH_AV_TRANS_NULL_VALUE;
404 }
405 AVTransProviderClass getEngineFactoryFunc = (AVTransProviderClass)dlsym(pHandler, GET_PROVIDER_FUNC.c_str());
406 if (getEngineFactoryFunc == nullptr) {
407 DHLOGE("av transport engine factory function handler is null, failed reason : %{public}s", dlerror());
408 dlclose(pHandler);
409 pHandler = nullptr;
410 return ERR_DH_AV_TRANS_NULL_VALUE;
411 }
412 providerPtr_ = getEngineFactoryFunc(OWNER_NAME_D_SCREEN);
413 return DH_SUCCESS;
414 }
415
UnloadAVSenderEngineProvider()416 int32_t DScreenManager::UnloadAVSenderEngineProvider()
417 {
418 DHLOGI("UnloadAVSenderEngineProvider enter");
419 void *pHandler = dlopen(SENDER_SO_NAME.c_str(), RTLD_LAZY | RTLD_NODELETE);
420 if (pHandler != nullptr) {
421 dlclose(pHandler);
422 pHandler = nullptr;
423 }
424 return DH_SUCCESS;
425 }
426 } // namespace V2_0
427 } // namespace DistributedHardware
428 } // namespace OHOS
429