• 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 "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 &param, 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