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 "1.0/include/screenregionmgr.h"
17
18 #include "display_manager.h"
19 #include "if_system_ability_manager.h"
20 #include "iservice_registry.h"
21 #include "nlohmann/json.hpp"
22
23 #include "dscreen_constants.h"
24 #include "dscreen_errcode.h"
25 #include "dscreen_fwkkit.h"
26 #include "dscreen_json_util.h"
27 #include "dscreen_log.h"
28 #include "dscreen_maprelation.h"
29 #include "dscreen_util.h"
30 #include "idscreen_source.h"
31 #include "screen_client.h"
32 #include "screen_client_common.h"
33
34 using json = nlohmann::json;
35
36 namespace OHOS {
37 namespace DistributedHardware {
38 namespace V1_0 {
39 IMPLEMENT_SINGLE_INSTANCE(ScreenRegionManager);
ScreenRegionManager()40 ScreenRegionManager::ScreenRegionManager()
41 {
42 DHLOGI("ScreenRegionManager");
43 }
44
~ScreenRegionManager()45 ScreenRegionManager::~ScreenRegionManager()
46 {
47 DHLOGI("~ScreenRegionManager");
48 }
49
ReleaseAllRegions()50 int32_t ScreenRegionManager::ReleaseAllRegions()
51 {
52 DHLOGI("ScreenRegionManager::ReleaseAllRegion");
53 std::lock_guard<std::mutex> lock(screenRegionsMtx_);
54 for (const auto &item : screenRegions_) {
55 std::shared_ptr<ScreenRegion> screenRegion = item.second;
56 if (screenRegion == nullptr) {
57 continue;
58 }
59 int32_t ret = screenRegion->Stop();
60 if (ret != DH_SUCCESS) {
61 DHLOGE("Release region failed, remoteDevId: %s, err: %" PRId32,
62 GetAnonyString(screenRegion->GetRemoteDevId()).c_str(), ret);
63 }
64 }
65 screenRegions_.clear();
66 return DH_SUCCESS;
67 }
68
HandleDScreenNotify(const std::string & remoteDevId,int32_t eventCode,const std::string & eventContent)69 void ScreenRegionManager::HandleDScreenNotify(const std::string &remoteDevId, int32_t eventCode,
70 const std::string &eventContent)
71 {
72 DHLOGI("HandleDScreenNotify, remoteDevId: %s, eventCode: %" PRId32, GetAnonyString(remoteDevId).c_str(), eventCode);
73 if (eventCode == NOTIFY_SINK_SETUP) {
74 HandleNotifySetUp(remoteDevId, eventContent);
75 return;
76 }
77 DHLOGE("invalid event.");
78 }
79
GetScreenDumpInfo(std::string & result)80 void ScreenRegionManager::GetScreenDumpInfo(std::string &result)
81 {
82 DHLOGI("GetScreenDumpInfo.");
83 result.clear();
84 result.append("screenRegion OnLine:\n[\n");
85 if (screenRegions_.size() == 0) {
86 result.append("]");
87 DHLOGD("no screenRegion");
88 return;
89 }
90
91 for (const auto &iter : screenRegions_) {
92 result.append(" {\n");
93 std::shared_ptr<ScreenRegion> screenRegion = iter.second;
94 if (screenRegion == nullptr) {
95 continue;
96 }
97 uint64_t screenId = screenRegion->GetScreenId();
98 std::string remoteDevId = screenRegion->GetRemoteDevId();
99 std::shared_ptr<VideoParam> videoParam = screenRegion->GetVideoParam();
100 if (videoParam == nullptr) {
101 continue;
102 }
103 uint32_t screenHeight = videoParam->GetScreenHeight();
104 uint32_t screenWidth = videoParam->GetScreenWidth();
105 int32_t windowId = screenRegion->GetWindowId();
106 std::string screenInfo = " \"clientWindowId\" : \"" + std::to_string(windowId) + "\",\n" +
107 " \"remoteScreenId\" : \"" + std::to_string(screenId) + "\",\n" +
108 " \"localDevId\" : \"" + GetAnonyString(localDevId_) + "\",\n" +
109 " \"remoteDevId\" : \"" + GetAnonyString(remoteDevId) + "\",\n" +
110 " \"screenWidth\" : \"" + std::to_string(screenWidth) + "\",\n" +
111 " \"screenHeight\" : \"" + std::to_string(screenHeight) + "\"\n";
112 result.append(screenInfo);
113 }
114 result.append(" }\n]");
115 }
116
CheckContentJson(json & eventContentJson)117 bool ScreenRegionManager::CheckContentJson(json &eventContentJson)
118 {
119 if (!IsUInt64(eventContentJson, KEY_SCREEN_ID)) {
120 return false;
121 }
122 if (!IsString(eventContentJson, KEY_DH_ID)) {
123 return false;
124 }
125 if (eventContentJson.contains(KEY_VERSION) && !IsString(eventContentJson, KEY_VERSION)) {
126 return false;
127 }
128 return true;
129 }
130
HandleNotifySetUp(const std::string & remoteDevId,const std::string & eventContent)131 void ScreenRegionManager::HandleNotifySetUp(const std::string &remoteDevId, const std::string &eventContent)
132 {
133 DHLOGI("HandleNotifySetUp, remoteDevId: %s", GetAnonyString(remoteDevId).c_str());
134 json eventContentJson = json::parse(eventContent, nullptr, false);
135 if (eventContentJson.is_discarded()||!CheckContentJson(eventContentJson) ||
136 !eventContentJson.contains(KEY_VIDEO_PARAM) || !eventContentJson.contains(KEY_MAPRELATION)) {
137 NotifyRemoteSourceSetUpResult(remoteDevId, "", ERR_DH_SCREEN_SA_SCREENREGION_SETUP_FAIL, "");
138 return;
139 }
140 std::string version = "1.0";
141 if (IsString(eventContentJson, KEY_VERSION)) {
142 version = eventContentJson[KEY_VERSION].get<std::string>();
143 }
144 uint64_t screenId = eventContentJson[KEY_SCREEN_ID].get<uint64_t>();
145 std::string dhId = eventContentJson[KEY_DH_ID].get<std::string>();
146
147 std::shared_ptr<VideoParam> videoParam =
148 std::make_shared<VideoParam>(eventContentJson[KEY_VIDEO_PARAM].get<VideoParam>());
149 std::shared_ptr<DScreenMapRelation> mapRelation =
150 std::make_shared<DScreenMapRelation>(eventContentJson[KEY_MAPRELATION].get<DScreenMapRelation>());
151
152 uint64_t displayId = Rosen::DisplayManager::GetInstance().GetDefaultDisplayId();
153 std::shared_ptr<ScreenRegion> screenRegion = std::make_shared<ScreenRegion>(remoteDevId, screenId, displayId);
154 screenRegion->SetVideoParam(videoParam);
155 screenRegion->SetMapRelation(mapRelation);
156
157 int32_t ret = DH_SUCCESS;
158 {
159 std::lock_guard<std::mutex> lock(screenRegionsMtx_);
160 if (screenRegions_.count(remoteDevId) != 0) {
161 ret = screenRegions_[remoteDevId]->Stop();
162 }
163
164 if (ret != DH_SUCCESS) {
165 DHLOGE("screenRegion stop failed, remoteDevId: %s, err: %" PRId32,
166 GetAnonyString(screenRegions_[remoteDevId]->GetRemoteDevId()).c_str(), ret);
167 NotifyRemoteSourceSetUpResult(remoteDevId, dhId, ERR_DH_SCREEN_SA_SCREENREGION_SETUP_FAIL, "");
168 return;
169 }
170 screenRegions_[remoteDevId] = screenRegion;
171 }
172 ret = screenRegion->SetUp(version);
173 if (ret != DH_SUCCESS) {
174 NotifyRemoteSourceSetUpResult(remoteDevId, dhId, ERR_DH_SCREEN_SA_SCREENREGION_SETUP_FAIL, "");
175 return;
176 }
177
178 ret = screenRegion->Start();
179 if (ret != DH_SUCCESS) {
180 NotifyRemoteSourceSetUpResult(remoteDevId, dhId, ERR_DH_SCREEN_SA_SCREENREGION_START_FAIL, "");
181 return;
182 }
183
184 PublishMessage(DHTopic::TOPIC_SINK_PROJECT_WINDOW_INFO, screenId, remoteDevId, screenRegion->GetWindowId(),
185 screenRegion->GetWindowProperty());
186 NotifyRemoteSourceSetUpResult(remoteDevId, dhId, DH_SUCCESS, "");
187 }
188
NotifyRemoteSourceSetUpResult(const std::string & remoteDevId,const std::string & dhId,int32_t errCode,const std::string & errContent)189 void ScreenRegionManager::NotifyRemoteSourceSetUpResult(const std::string &remoteDevId, const std::string &dhId,
190 int32_t errCode, const std::string &errContent)
191 {
192 DHLOGI("NotifyRemoteSourceSetUpResult, sourceDevId: %s, dhId: %s, errCode: %" PRId32,
193 GetAnonyString(remoteDevId).c_str(), GetAnonyString(dhId).c_str(), errCode);
194 int32_t eventCode = NOTIFY_SOURCE_SETUP_RESULT;
195
196 json eventContentJson;
197 eventContentJson[KEY_DH_ID] = dhId;
198 eventContentJson[KEY_ERR_CODE] = errCode;
199 eventContentJson[KEY_ERR_CONTENT] = errContent;
200
201 std::string eventContent = eventContentJson.dump();
202
203 NotifyRemoteScreenService(remoteDevId, dhId, eventCode, eventContent);
204 }
205
NotifyRemoteScreenService(const std::string & remoteDevId,const std::string & dhId,int32_t eventCode,const std::string & eventContent)206 int32_t ScreenRegionManager::NotifyRemoteScreenService(const std::string &remoteDevId, const std::string &dhId,
207 int32_t eventCode, const std::string &eventContent)
208 {
209 DHLOGI("Notify remote source screen service, remote devId: %s, eventCode: %" PRId32,
210 GetAnonyString(remoteDevId).c_str(), eventCode);
211 sptr<IDScreenSource> remoteSourceSA = GetDScreenSourceSA(remoteDevId);
212 if (remoteSourceSA == nullptr) {
213 DHLOGE("get remote source sa failed.");
214 return ERR_DH_SCREEN_SA_GET_REMOTE_SOURCE_SERVICE_FAIL;
215 }
216 std::string localDevId;
217 int32_t ret = GetLocalDeviceNetworkId(localDevId);
218 if (ret != DH_SUCCESS) {
219 DHLOGE("notify remote screen service failed, cannot get local device id");
220 return ret;
221 }
222 localDevId_ = localDevId;
223 remoteSourceSA->DScreenNotify(localDevId, eventCode, eventContent);
224 return DH_SUCCESS;
225 }
226
GetDScreenSourceSA(const std::string & devId)227 sptr<IDScreenSource> ScreenRegionManager::GetDScreenSourceSA(const std::string &devId)
228 {
229 DHLOGI("GetDScreenSourceSA, devId: %s", GetAnonyString(devId).c_str());
230 sptr<ISystemAbilityManager> samgr =
231 SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
232 if (samgr == nullptr) {
233 DHLOGE("Failed to get system ability mgr.");
234 return nullptr;
235 }
236 auto remoteObject = samgr->GetSystemAbility(DISTRIBUTED_HARDWARE_SCREEN_SOURCE_SA_ID, devId);
237 if (remoteObject == nullptr) {
238 DHLOGE("remoteObject is null");
239 return nullptr;
240 }
241
242 sptr<IDScreenSource> remoteSourceSA = iface_cast<IDScreenSource>(remoteObject);
243 if (remoteSourceSA == nullptr) {
244 DHLOGE("Failed to get remote dscreen source sa");
245 return nullptr;
246 }
247 return remoteSourceSA;
248 }
249
PublishMessage(const DHTopic topic,const uint64_t & screenId,const std::string & remoteDevId,const int32_t & windowId,std::shared_ptr<WindowProperty> windowProperty)250 void ScreenRegionManager::PublishMessage(const DHTopic topic, const uint64_t &screenId,
251 const std::string &remoteDevId, const int32_t &windowId, std::shared_ptr<WindowProperty> windowProperty)
252 {
253 DHLOGI("ScreenRegionManager PublishMessage");
254 if (DScreenFwkKit::GetInstance().GetDHFwkKit() == nullptr) {
255 DHLOGE("GetDHFwkKit fail.");
256 return;
257 }
258
259 json messageJosn;
260 std::string message;
261 messageJosn[SOURCE_WIN_ID] = screenId;
262 messageJosn[SOURCE_DEV_ID] = remoteDevId;
263 messageJosn[SINK_SHOW_WIN_ID] = windowId;
264 messageJosn[SINK_PROJ_SHOW_WIDTH] = windowProperty->width;
265 messageJosn[SINK_PROJ_SHOW_HEIGHT] = windowProperty->height;
266 messageJosn[SINK_WIN_SHOW_X] = windowProperty->startX;
267 messageJosn[SINK_WIN_SHOW_Y] = windowProperty->startY;
268 message = messageJosn.dump();
269
270 DScreenFwkKit::GetInstance().GetDHFwkKit()->PublishMessage(topic, message);
271 }
272 } // namespace V1_0
273 } // namespace DistributedHardware
274 } // namespace OHOS