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