• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "dscreen_manager.h"
17 
18 #include "if_system_ability_manager.h"
19 #include "iservice_registry.h"
20 #include "nlohmann/json.hpp"
21 
22 #include "dscreen_constants.h"
23 #include "dscreen_errcode.h"
24 #include "dscreen_log.h"
25 #include "dscreen_util.h"
26 #include "idscreen_sink.h"
27 #include "screen_manager_adapter.h"
28 
29 using json = nlohmann::json;
30 
31 namespace OHOS {
32 namespace DistributedHardware {
33 IMPLEMENT_SINGLE_INSTANCE(DScreenManager);
DScreenManager()34 DScreenManager::DScreenManager()
35 {
36     DHLOGI("DScreenMgr construct.");
37 }
38 
~DScreenManager()39 DScreenManager::~DScreenManager()
40 {
41     DHLOGI("DScreenMgr deConstruct.");
42 }
43 
Init()44 int32_t DScreenManager::Init()
45 {
46     DHLOGI("DScreenManager::Init");
47     if (dScreenGroupListener_ == nullptr) {
48         dScreenGroupListener_ = new DScreenGroupListener();
49     }
50     int32_t ret = ScreenMgrAdapter::GetInstance().RegisterScreenGroupListener(dScreenGroupListener_);
51     if (ret != DH_SUCCESS) {
52         DHLOGE("DScreenManager Init failed, err: %d", ret);
53     }
54     if (!dScreenCallback_) {
55         dScreenCallback_ = std::make_shared<DScreenCallback>();
56     }
57     return ret;
58 }
59 
UnInit()60 int32_t DScreenManager::UnInit()
61 {
62     DHLOGI("DScreenManager::UnInit");
63     int32_t ret = DH_SUCCESS;
64     if (dScreenGroupListener_ != nullptr) {
65         ret = ScreenMgrAdapter::GetInstance().UnregisterScreenGroupListener(dScreenGroupListener_);
66     }
67 
68     if (ret != DH_SUCCESS) {
69         DHLOGE("DScreenManager UnInit failed, err: %d", ret);
70     }
71     dScreenCallback_ = nullptr;
72     dScreenSourceCallbackProxy_ = nullptr;
73     dScreenGroupListener_ = nullptr;
74 
75     {
76         std::lock_guard<std::mutex> lock(dScreenMapMtx_);
77         dScreens_.clear();
78     }
79 
80     {
81         std::lock_guard<std::mutex> lock(dScreenMapRelationMtx_);
82         mapRelations_.clear();
83     }
84     DHLOGI("DScreenManager::UnInit success");
85     return ret;
86 }
87 
OnChange(const std::vector<uint64_t> & screenIds,Rosen::ScreenGroupChangeEvent event)88 void DScreenGroupListener::OnChange(const std::vector<uint64_t> &screenIds, Rosen::ScreenGroupChangeEvent event)
89 {
90     DHLOGI("On Screen change, screenIds size: %d", screenIds.size());
91     for (uint64_t screenId : screenIds) {
92         std::shared_ptr<DScreen> changedScreen = nullptr;
93         changedScreen = DScreenManager::GetInstance().FindDScreenByScreenId(screenId);
94         if (!changedScreen) {
95             DHLOGD("screen change not about remote screen, screenId: %ulld", screenId);
96             continue;
97         }
98         DScreenManager::GetInstance().HandleScreenChange(changedScreen, event);
99     }
100 }
101 
HandleScreenChange(const std::shared_ptr<DScreen> & changedScreen,Rosen::ScreenGroupChangeEvent event)102 void DScreenManager::HandleScreenChange(const std::shared_ptr<DScreen> &changedScreen,
103     Rosen::ScreenGroupChangeEvent event)
104 {
105     if (!changedScreen) {
106         DHLOGE("DScreenManager::HandleScreenChange, dScreen is null.");
107         return;
108     }
109     uint64_t screenId = changedScreen->GetScreenId();
110     DHLOGI("DScreenManager::HandleScreenChange, screenId: %ulld, changeEvent: %", screenId, event);
111     if (event == Rosen::ScreenGroupChangeEvent::ADD_TO_GROUP) {
112         if (changedScreen->GetState() == CONNECTING) {
113             DHLOGD("screen is connecting, no need handle change");
114             return;
115         }
116         std::shared_ptr<DScreenMapRelation> mapRelation =
117             ScreenMgrAdapter::GetInstance().GetMapRelation(screenId);
118         if (!mapRelation) {
119             DHLOGE("mapRelation construct failed. screenId: %ulld", screenId);
120             return;
121         }
122 
123         std::shared_ptr<VideoParam> videoParam = changedScreen->GetVideoParam();
124         DisplayRect displayRect = mapRelation->GetDisplayRect();
125         videoParam->SetVideoWidth(displayRect.width);
126         videoParam->SetVideoHeight(displayRect.height);
127         changedScreen->SetState(CONNECTING);
128 
129         {
130             std::lock_guard<std::mutex> lock(dScreenMapRelationMtx_);
131             mapRelations_[screenId] = mapRelation;
132         }
133         NotifyRemoteSinkSetUp(changedScreen);
134     } else if (event == Rosen::ScreenGroupChangeEvent::REMOVE_FROM_GROUP) {
135         if (changedScreen->GetState() == DISCONNECTING) {
136             DHLOGD("screen is disconnecting, no need handle change");
137             return;
138         }
139         std::shared_ptr<DScreenMapRelation> mapRelation = nullptr;
140         {
141             std::lock_guard<std::mutex> lock(dScreenMapRelationMtx_);
142             if (mapRelations_.count(screenId) == 0) {
143                 DHLOGE("destroyed relation not found.");
144                 return;
145             }
146             mapRelation = mapRelations_[screenId];
147             mapRelations_.erase(screenId);
148         }
149         changedScreen->AddTask(std::make_shared<Task>(TaskType::TASK_DISCONNECT, ""));
150     } else if (event == Rosen::ScreenGroupChangeEvent::CHANGE_GROUP) {
151         DHLOGE("CHANGE_GROUP not implement.");
152     } else {
153         DHLOGE("unknown change type.");
154     }
155 }
156 
OnRegResult(const std::shared_ptr<DScreen> & dScreen,const std::string & reqId,int32_t status,const std::string & data)157 void DScreenCallback::OnRegResult(const std::shared_ptr<DScreen> &dScreen,
158     const std::string &reqId, int32_t status, const std::string &data)
159 {
160     DHLOGI("DScreenCallback::OnRegResult, devId: %s, dhId: %s, reqId: %s",
161         GetAnonyString(dScreen->GetDevId()).c_str(), GetAnonyString(dScreen->GetDHId()).c_str(), reqId.c_str());
162     DScreenManager::GetInstance().OnRegResult(dScreen, reqId, status, data);
163 }
164 
OnUnregResult(const std::shared_ptr<DScreen> & dScreen,const std::string & reqId,int32_t status,const std::string & data)165 void DScreenCallback::OnUnregResult(const std::shared_ptr<DScreen> &dScreen,
166     const std::string &reqId, int32_t status, const std::string &data)
167 {
168     DHLOGI("DScreenCallback::OnUnregResult, devId: %s, dhId: %s, reqId: %s",
169         GetAnonyString(dScreen->GetDevId()).c_str(), GetAnonyString(dScreen->GetDHId()).c_str(), reqId.c_str());
170     DScreenManager::GetInstance().OnUnregResult(dScreen, reqId, status, data);
171 }
172 
OnRegResult(const std::shared_ptr<DScreen> & dScreen,const std::string & reqId,int32_t status,const std::string & data)173 void DScreenManager::OnRegResult(const std::shared_ptr<DScreen> &dScreen,
174     const std::string &reqId, int32_t status, const std::string &data)
175 {
176     DHLOGI("DScreenManager::OnRegResult, devId: %s, dhId: %s, reqId: %s",
177         GetAnonyString(dScreen->GetDevId()).c_str(), GetAnonyString(dScreen->GetDHId()).c_str(), reqId.c_str());
178     if (!dScreenSourceCallbackProxy_) {
179         DHLOGE("dScreenSourceCallbackProxy is null");
180         return;
181     }
182     dScreenSourceCallbackProxy_->OnNotifyRegResult(dScreen->GetDevId(), dScreen->GetDHId(), reqId, status, data);
183 }
184 
OnUnregResult(const std::shared_ptr<DScreen> & dScreen,const std::string & reqId,int32_t status,const std::string & data)185 void DScreenManager::OnUnregResult(const std::shared_ptr<DScreen> &dScreen,
186     const std::string &reqId, int32_t status, const std::string &data)
187 {
188     DHLOGI("DScreenManager::OnUnregResult, devId: %s, dhId: %s, reqId: %s",
189         GetAnonyString(dScreen->GetDevId()).c_str(), GetAnonyString(dScreen->GetDHId()).c_str(), reqId.c_str());
190     if (!dScreenSourceCallbackProxy_) {
191         DHLOGE("dScreenSourceCallbackProxy is null");
192         return;
193     }
194     dScreenSourceCallbackProxy_->OnNotifyUnregResult(dScreen->GetDevId(), dScreen->GetDHId(), reqId, status, data);
195 }
196 
EnableDistributedScreen(const std::string & devId,const std::string & dhId,const std::string & attrs,const std::string & reqId)197 int32_t DScreenManager::EnableDistributedScreen(const std::string &devId, const std::string &dhId,
198     const std::string &attrs, const std::string &reqId)
199 {
200     DHLOGI("EnableDistributedScreen, devId: %s, dhId:%s",
201         GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
202     if (!dScreenCallback_) {
203         DHLOGE("dscreen manager not init.");
204         return ERR_DH_SCREEN_SA_ENABLE_FAILED;
205     }
206 
207     std::string dScreenIdx = devId + SEPERATOR + dhId;
208     std::shared_ptr<DScreen> dScreen = nullptr;
209     if (dScreens_.count(dScreenIdx) != 0) {
210         dScreen = dScreens_[dScreenIdx];
211     }
212 
213     if (dScreen == nullptr) {
214         dScreen = std::make_shared<DScreen>(devId, dhId, dScreenCallback_);
215     }
216 
217     int32_t dScreenState = dScreen->GetState();
218     if (dScreenState != DISABLED && dScreenState != DISABLING) {
219         DHLOGE("dScreen state is invalid.");
220         return ERR_DH_SCREEN_SA_ENABLE_FAILED;
221     }
222 
223     dScreens_[dScreenIdx] = dScreen;
224     int32_t ret = dScreen->AddTask(std::make_shared<Task>(TaskType::TASK_ENABLE, reqId, attrs));
225     if (ret != DH_SUCCESS) {
226         DHLOGE("EnableDistributedScreen, add task failed. devId: %s, dhId:%s",
227             GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
228     }
229     return ret;
230 }
231 
DisableDistributedScreen(const std::string & devId,const std::string & dhId,const std::string & reqId)232 int32_t DScreenManager::DisableDistributedScreen(const std::string &devId, const std::string &dhId,
233     const std::string &reqId)
234 {
235     DHLOGI("DisableDistributedScreen, devId: %s, dhId:%s",
236         GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
237 
238     std::string dScreenIdx = devId + SEPERATOR + dhId;
239     if (dScreens_.count(dScreenIdx) == 0) {
240         DHLOGE("dscreen not found, devId: %s, dhId: %s",
241             GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
242         return ERR_DH_SCREEN_SA_DISABLE_FAILED;
243     }
244 
245     int32_t dScreenState = dScreens_[dScreenIdx]->GetState();
246     int32_t ret = DH_SUCCESS;
247     switch (dScreenState) {
248         case DISABLED:
249         case DISABLING:
250             DHLOGE("dScreen state is invalid.");
251             ret = ERR_DH_SCREEN_SA_DISABLE_FAILED;
252             break;
253         case ENABLED:
254         case ENABLING:
255             ret = dScreens_[dScreenIdx]->AddTask(std::make_shared<Task>(TaskType::TASK_DISABLE, reqId, ""));
256             break;
257         case CONNECTING:
258         case CONNECTED:
259         case DISCONNECTING:
260             ret = dScreens_[dScreenIdx]->AddTask(std::make_shared<Task>(TaskType::TASK_DISCONNECT, ""));
261             if (ret == DH_SUCCESS) {
262                 ret = dScreens_[dScreenIdx]->AddTask(std::make_shared<Task>(TaskType::TASK_DISABLE, reqId, ""));
263             }
264             break;
265         default:
266             ret = ERR_DH_SCREEN_SA_DISABLE_FAILED;
267             break;
268     }
269     return ret;
270 }
271 
RegisterDScreenCallback(const sptr<IDScreenSourceCallback> & callback)272 void DScreenManager::RegisterDScreenCallback(const sptr<IDScreenSourceCallback> &callback)
273 {
274     DHLOGI("RegisterDScreenCallback");
275     dScreenSourceCallbackProxy_ = callback;
276 }
277 
FindDScreenByScreenId(uint64_t screenId)278 std::shared_ptr<DScreen> DScreenManager::FindDScreenByScreenId(uint64_t screenId)
279 {
280     DHLOGD("FindDScreenByScreenId, screenId: %ulld", screenId);
281     std::lock_guard<std::mutex> lock(dScreenMapMtx_);
282     for (const auto &iter : dScreens_) {
283         std::shared_ptr<DScreen> dScreen = iter.second;
284         if (!dScreen) {
285             continue;
286         }
287 
288         if (dScreen->GetScreenId() == screenId) {
289             return dScreen;
290         }
291     }
292     DHLOGD("DScreen not found, screenId: %ulld", screenId);
293     return nullptr;
294 }
295 
HandleDScreenNotify(const std::string & devId,int32_t eventCode,const std::string & eventContent)296 void DScreenManager::HandleDScreenNotify(const std::string &devId, int32_t eventCode,
297     const std::string &eventContent)
298 {
299     DHLOGI("HandleDScreenNotify, devId: %s, eventCode: %d", GetAnonyString(devId).c_str(), eventCode);
300     if (eventCode == NOTIFY_SOURCE_SETUP_RESULT) {
301         HandleNotifySetUpResult(devId, eventContent);
302         return;
303     }
304 
305     DHLOGE("invalid eventCode, eventCode: %d", eventCode);
306 }
307 
NotifyRemoteScreenService(const std::string & devId,int32_t eventCode,const std::string & eventContent)308 int32_t DScreenManager::NotifyRemoteScreenService(const std::string &devId, int32_t eventCode,
309     const std::string &eventContent)
310 {
311     DHLOGI("Notify remote sink screen service, remote devId: %s, eventCode: %d",
312         GetAnonyString(devId).c_str(), eventCode);
313     sptr<IDScreenSink> remoteSinkSA = GetDScreenSinkSA(devId);
314     if (!remoteSinkSA) {
315         DHLOGE("get remote sink sa failed.");
316         return ERR_DH_SCREEN_SA_GET_REMOTE_SINK_SERVICE_FAIL;
317     }
318     std::string localDevId;
319     int32_t ret = GetLocalDeviceNetworkId(localDevId);
320     if (ret != DH_SUCCESS) {
321         DHLOGE("notify remote screen service failed, cannot get local device id");
322         return ret;
323     }
324     remoteSinkSA->DScreenNotify(localDevId, eventCode, eventContent);
325     return DH_SUCCESS;
326 }
327 
GetDScreenSinkSA(const std::string & devId)328 sptr<IDScreenSink> DScreenManager::GetDScreenSinkSA(const std::string &devId)
329 {
330     DHLOGI("GetDScreenSinkSA, devId: %s", GetAnonyString(devId).c_str());
331     sptr<ISystemAbilityManager> samgr =
332         SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
333     if (!samgr) {
334         DHLOGE("Failed to get system ability mgr.");
335         return nullptr;
336     }
337     auto remoteObject = samgr->GetSystemAbility(DISTRIBUTED_HARDWARE_SCREEN_SINK_SA_ID, devId);
338     if (remoteObject == nullptr) {
339         DHLOGE("remoteObject is null");
340         return nullptr;
341     }
342 
343     sptr<IDScreenSink> remoteSinkSA = iface_cast<IDScreenSink>(remoteObject);
344     if (remoteSinkSA == nullptr) {
345         DHLOGE("Failed to get remote dscreen sink sa");
346         return nullptr;
347     }
348     return remoteSinkSA;
349 }
350 
NotifyRemoteSinkSetUp(const std::shared_ptr<DScreen> & dScreen)351 void DScreenManager::NotifyRemoteSinkSetUp(const std::shared_ptr<DScreen> &dScreen)
352 {
353     DHLOGI("NotifyRemoteSinkSetUp");
354     int32_t eventCode = NOTIFY_SINK_SETUP;
355     std::string devId = dScreen->GetDevId();
356     json eventContentJson;
357     eventContentJson[KEY_SCREEN_ID] = dScreen->GetScreenId();
358     eventContentJson[KEY_DH_ID] = dScreen->GetDHId();
359     if (dScreen->GetVideoParam() == nullptr) {
360         DHLOGE("videoParam is null, back to enabled state screedId: %ulld", dScreen->GetScreenId());
361         dScreen->SetState(ENABLED);
362         return;
363     }
364     eventContentJson[KEY_VIDEO_PARAM] = *(dScreen->GetVideoParam());
365 
366     if (mapRelations_.count(dScreen->GetScreenId()) == 0) {
367         DHLOGE("mapRelation not found, back to enabled state screedId: %ulld", dScreen->GetScreenId());
368         dScreen->SetState(ENABLED);
369         return;
370     }
371     eventContentJson[KEY_MAPRELATION] = *(mapRelations_[dScreen->GetScreenId()]);
372 
373     std::string eventContent = eventContentJson.dump();
374     DHLOGD("start notify remote screen, eventContent: %s", eventContent.c_str());
375     NotifyRemoteScreenService(devId, eventCode, eventContent);
376 }
377 
HandleNotifySetUpResult(const std::string & remoteDevId,const std::string & eventContent)378 void DScreenManager::HandleNotifySetUpResult(const std::string &remoteDevId, const std::string &eventContent)
379 {
380     DHLOGI("HandleNotifySetUpResult, remoteDevId:%s", GetAnonyString(remoteDevId).c_str());
381     json eventContentJson = json::parse(eventContent, nullptr, false);
382     if (eventContentJson.is_discarded()) {
383         DHLOGE("HandleNotifySetUpResult, eventContent is invalid");
384         return;
385     }
386 
387     if (!eventContentJson.contains(KEY_DH_ID) ||
388         !eventContentJson.contains(KEY_ERR_CODE) ||
389         !eventContentJson.contains(KEY_ERR_CONTENT)) {
390         DHLOGE("HandleNotifySetUpResult, eventContent is invalid");
391         return;
392     }
393 
394     std::string dhId = eventContentJson[KEY_DH_ID];
395     int32_t errCode = eventContentJson[KEY_ERR_CODE];
396     std::string errContent = eventContentJson[KEY_ERR_CONTENT];
397 
398     std::string dScreenIdx = remoteDevId + SEPERATOR + dhId;
399     if (dScreens_.count(dScreenIdx) == 0) {
400         DHLOGE("dScreen not found, remoteDevId:%s, dhId:%s",
401             GetAnonyString(remoteDevId).c_str(), GetAnonyString(dhId).c_str());
402         return;
403     }
404 
405     if (errCode != DH_SUCCESS) {
406         DHLOGE("remote sink set up failed, errCode: %d, reason: %s", errCode, errContent.c_str());
407         dScreens_[dScreenIdx]->SetState(ENABLED);
408         return;
409     }
410 
411     dScreens_[dScreenIdx]->AddTask(std::make_shared<Task>(TaskType::TASK_CONNECT, ""));
412 }
413 } // namespace DistributedHardware
414 } // namespace OHOS