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