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 "screen_data_channel_impl.h"
17
18 #include <securec.h>
19
20 #include "dscreen_constants.h"
21 #include "dscreen_errcode.h"
22 #include "dscreen_hisysevent.h"
23 #include "dscreen_log.h"
24 #include "dscreen_util.h"
25 #include "dscreen_json_util.h"
26
27 namespace OHOS {
28 namespace DistributedHardware {
CreateSession(const std::shared_ptr<IScreenChannelListener> & listener)29 int32_t ScreenDataChannelImpl::CreateSession(const std::shared_ptr<IScreenChannelListener> &listener)
30 {
31 DHLOGI("%{public}s: CreateSession, peerDevId(%{public}s)", DSCREEN_LOG_TAG, GetAnonyString(peerDevId_).c_str());
32 if (listener == nullptr) {
33 DHLOGE("%{public}s: Channel listener is null", DSCREEN_LOG_TAG);
34 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
35 }
36 int32_t ret =
37 SoftbusAdapter::GetInstance().CreateSoftbusSessionServer(PKG_NAME, DATA_SESSION_NAME, peerDevId_);
38 if (ret != DH_SUCCESS) {
39 DHLOGE("%{public}s: Create data session failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
40 return ret;
41 }
42 std::shared_ptr<ISoftbusListener> softbusListener = shared_from_this();
43 ret = SoftbusAdapter::GetInstance().RegisterSoftbusListener(softbusListener, DATA_SESSION_NAME, peerDevId_);
44 if (ret != DH_SUCCESS) {
45 DHLOGE("%{public}s: Register data adapter listener failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
46 return ret;
47 }
48 if (jpegSessionFlag_ == true) {
49 ret =
50 SoftbusAdapter::GetInstance().CreateSoftbusSessionServer(PKG_NAME, JPEG_SESSION_NAME, peerDevId_);
51 if (ret != DH_SUCCESS) {
52 DHLOGE("%{public}s: Create jpeg session failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
53 return ret;
54 }
55 ret =
56 SoftbusAdapter::GetInstance().RegisterSoftbusListener(softbusListener, JPEG_SESSION_NAME, peerDevId_);
57 if (ret != DH_SUCCESS) {
58 DHLOGE("%{public}s: Register jpeg adapter listener failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
59 return ret;
60 }
61 }
62 channelListener_ = listener;
63 DHLOGI("%{public}s: Create session success", DSCREEN_LOG_TAG);
64 return DH_SUCCESS;
65 }
66
SetJpegSessionFlag(bool flag)67 void ScreenDataChannelImpl::SetJpegSessionFlag(bool flag)
68 {
69 jpegSessionFlag_ = flag;
70 }
71
ReleaseSession()72 int32_t ScreenDataChannelImpl::ReleaseSession()
73 {
74 DHLOGI("%{public}s: ReleaseSession, peerDevId(%{public}s)", DSCREEN_LOG_TAG, GetAnonyString(peerDevId_).c_str());
75 int32_t ret = SoftbusAdapter::GetInstance().RemoveSoftbusSessionServer(PKG_NAME, DATA_SESSION_NAME, peerDevId_);
76 if (ret != DH_SUCCESS) {
77 DHLOGE("%{public}s: Release data session failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
78 return ret;
79 }
80 ret = SoftbusAdapter::GetInstance().UnRegisterSoftbusListener(DATA_SESSION_NAME, peerDevId_);
81 if (ret != DH_SUCCESS) {
82 DHLOGE("%{public}s: UnRegister data adapter listener failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
83 return ret;
84 }
85
86 if (jpegSessionFlag_ == true) {
87 ret = SoftbusAdapter::GetInstance().RemoveSoftbusSessionServer(PKG_NAME, JPEG_SESSION_NAME, peerDevId_);
88 if (ret != DH_SUCCESS) {
89 DHLOGE("%{public}s: Release jpeg session failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
90 return ret;
91 }
92 ret = SoftbusAdapter::GetInstance().UnRegisterSoftbusListener(JPEG_SESSION_NAME, peerDevId_);
93 if (ret != DH_SUCCESS) {
94 DHLOGE("%{public}s: UnRegister jpeg adapter listener failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
95 return ret;
96 }
97 jpegSessionFlag_ = false;
98 }
99 DHLOGI("%{public}s: Release session success", DSCREEN_LOG_TAG);
100 return DH_SUCCESS;
101 }
102
OpenSession(const std::shared_ptr<IScreenChannelListener> listener)103 int32_t ScreenDataChannelImpl::OpenSession(const std::shared_ptr<IScreenChannelListener> listener)
104 {
105 DHLOGI("%{public}s: OpenSession, peerDevId(%{public}s)", DSCREEN_LOG_TAG, GetAnonyString(peerDevId_).c_str());
106 if (listener == nullptr) {
107 DHLOGE("%{public}s: Channel listener is null", DSCREEN_LOG_TAG);
108 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
109 }
110 channelListener_ = listener;
111 std::shared_ptr<ISoftbusListener> softbusListener = shared_from_this();
112 int32_t ret = SoftbusAdapter::GetInstance().RegisterSoftbusListener(softbusListener, DATA_SESSION_NAME, peerDevId_);
113 if (ret != DH_SUCCESS) {
114 DHLOGE("%{public}s: Register data adapter listener failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
115 return ret;
116 }
117 int32_t sessionId =
118 SoftbusAdapter::GetInstance().OpenSoftbusSession(DATA_SESSION_NAME, DATA_SESSION_NAME, peerDevId_);
119 if (sessionId < 0) {
120 DHLOGE("%{public}s: Open data session failed, ret: %{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
121 ReportOptFail(DSCREEN_OPT_FAIL, sessionId, "Open data session failed");
122 return ERR_DH_SCREEN_TRANS_ERROR;
123 }
124 sessionId_ = sessionId;
125 if (jpegSessionFlag_ == true) {
126 ret =
127 SoftbusAdapter::GetInstance().RegisterSoftbusListener(softbusListener, JPEG_SESSION_NAME, peerDevId_);
128 if (ret != DH_SUCCESS) {
129 DHLOGE("%{public}s: Register jpeg adapter listener failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
130 return ret;
131 }
132 sessionId =
133 SoftbusAdapter::GetInstance().OpenSoftbusSession(JPEG_SESSION_NAME, JPEG_SESSION_NAME, peerDevId_);
134 if (sessionId < 0) {
135 DHLOGE("%{public}s: Open jpeg session failed, ret: %{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
136 ReportOptFail(DSCREEN_OPT_FAIL, sessionId, "Open jpeg session failed");
137 return ERR_DH_SCREEN_TRANS_ERROR;
138 }
139 jpegSessionId_ = sessionId;
140 }
141 DHLOGI("%{public}s: Open screen session success, sessionId %{public}" PRId32, DSCREEN_LOG_TAG, sessionId_);
142 return DH_SUCCESS;
143 }
144
CloseSession()145 int32_t ScreenDataChannelImpl::CloseSession()
146 {
147 DHLOGI("%{public}s: CloseSession, sessionId %{public}" PRId32, DSCREEN_LOG_TAG, sessionId_);
148 if (sessionId_ == 0) {
149 DHLOGD("%{public}s: Session is not opened.", DSCREEN_LOG_TAG);
150 return ERR_DH_SCREEN_TRANS_SESSION_NOT_OPEN;
151 }
152 int32_t ret = SoftbusAdapter::GetInstance().CloseSoftbusSession(sessionId_);
153 if (ret != DH_SUCCESS) {
154 DHLOGE("%{public}s: Close screen session failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
155 return ret;
156 }
157 sessionId_ = 0;
158 if (jpegSessionFlag_ == true && jpegSessionId_ != 0) {
159 ret = SoftbusAdapter::GetInstance().CloseSoftbusSession(jpegSessionId_);
160 if (ret != DH_SUCCESS) {
161 DHLOGE("%{public}s: Close jpeg session failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
162 return ret;
163 }
164 jpegSessionId_ = 0;
165 }
166 DHLOGI("%{public}s: Close session success", DSCREEN_LOG_TAG);
167 return DH_SUCCESS;
168 }
169
SendData(const std::shared_ptr<DataBuffer> & screenData)170 int32_t ScreenDataChannelImpl::SendData(const std::shared_ptr<DataBuffer> &screenData)
171 {
172 DHLOGI("%{public}s: SendData.", DSCREEN_LOG_TAG);
173 if (screenData == nullptr || screenData->Data() == nullptr) {
174 DHLOGE("%{public}s: Screen data is null", DSCREEN_LOG_TAG);
175 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
176 }
177 uint8_t dataType = screenData->DataType();
178 if (dataType == VIDEO_PART_SCREEN_DATA) {
179 int32_t ret = SendDirtyData(screenData);
180 if (ret != DH_SUCCESS) {
181 DHLOGE("%{public}s: send dirty data failed, ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
182 return ret;
183 }
184 } else if (dataType == VIDEO_FULL_SCREEN_DATA) {
185 int32_t ret = SendFullData(screenData);
186 if (ret != DH_SUCCESS) {
187 DHLOGE("%{public}s: send full data failed, ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
188 return ret;
189 }
190 }
191 return DH_SUCCESS;
192 }
193
SendFullData(const std::shared_ptr<DataBuffer> & screenData)194 int32_t ScreenDataChannelImpl::SendFullData(const std::shared_ptr<DataBuffer> &screenData)
195 {
196 DHLOGI("%{public}s: SendFullData sessionId: %{public}" PRId32, DSCREEN_LOG_TAG, sessionId_);
197 if (screenData == nullptr) {
198 DHLOGE("%{public}s: Screen data is null", DSCREEN_LOG_TAG);
199 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
200 }
201 StreamData data = {reinterpret_cast<char *>(screenData->Data()), screenData->Capacity()};
202 StreamData ext = {0};
203 StreamFrameInfo frameInfo = {0};
204 int32_t ret = SoftbusAdapter::GetInstance().SendSoftbusStream(sessionId_, &data, &ext, &frameInfo);
205 if (ret != DH_SUCCESS) {
206 DHLOGE("%{public}s: Send full data failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
207 return ret;
208 }
209 DHLOGI("%{public}s: SendFullData success.", DSCREEN_LOG_TAG);
210 return DH_SUCCESS;
211 }
212
SendDirtyData(const std::shared_ptr<DataBuffer> & screenData)213 int32_t ScreenDataChannelImpl::SendDirtyData(const std::shared_ptr<DataBuffer> &screenData)
214 {
215 DHLOGI("%{public}s: SendDirtyData sessionId: %{public}" PRId32, DSCREEN_LOG_TAG, jpegSessionId_);
216 if (screenData == nullptr) {
217 DHLOGE("%{public}s: Screen data is null", DSCREEN_LOG_TAG);
218 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
219 }
220 nlohmann::json rectJson;
221 DirtyVecToJson(rectJson, screenData);
222 StreamData data = {reinterpret_cast<char *>(screenData->Data()), screenData->Capacity()};
223 std::string rectInfo = rectJson.dump();
224 char *dirtyInfo = new char[rectInfo.length() + 1] {0};
225 int32_t ret = memcpy_s(dirtyInfo, rectInfo.length(), rectInfo.c_str(), rectInfo.length());
226 if (ret != EOK) {
227 DHLOGE("SendDirtyData memcpy_s failed.");
228 delete [] dirtyInfo;
229 return ret;
230 }
231 StreamData ext = {dirtyInfo, rectInfo.length() + 1};
232 StreamFrameInfo frameInfo = {0};
233 ret = SoftbusAdapter::GetInstance().SendSoftbusStream(jpegSessionId_, &data, &ext, &frameInfo);
234 if (ret != DH_SUCCESS) {
235 DHLOGE("%{public}s: Send dirty data failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
236 delete [] dirtyInfo;
237 return ret;
238 }
239 delete [] dirtyInfo;
240 DHLOGI("%{public}s: SendDirtyData success.", DSCREEN_LOG_TAG);
241 return DH_SUCCESS;
242 }
243
244
OnSessionOpened(int32_t sessionId,PeerSocketInfo info)245 void ScreenDataChannelImpl::OnSessionOpened(int32_t sessionId, PeerSocketInfo info)
246 {
247 (void)info;
248 DHLOGI("%{public}s: OnScreenSessionOpened, sessionId: %{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
249 if (jpegSessionFlag_ == false) {
250 dataSessionOpened = true;
251 sessionId_ = sessionId;
252 } else {
253 if (sessionId == sessionId_) {
254 dataSessionOpened = true;
255 sessionId_ = sessionId;
256 } else if (sessionId == jpegSessionId_) {
257 jpegSessionOpened = true;
258 jpegSessionId_ = sessionId;
259 }
260 }
261 std::shared_ptr<IScreenChannelListener> listener = channelListener_.lock();
262 if (listener == nullptr) {
263 DHLOGE("%{public}s: Channel listener is null", DSCREEN_LOG_TAG);
264 return;
265 }
266 listener->OnSessionOpened();
267 }
268
OnSessionClosed(int32_t sessionId,ShutdownReason reason)269 void ScreenDataChannelImpl::OnSessionClosed(int32_t sessionId, ShutdownReason reason)
270 {
271 (void)reason;
272 DHLOGI("%{public}s: OnScreenSessionClosed, sessionId %{public}" PRId32, DSCREEN_LOG_TAG, sessionId);
273 std::shared_ptr<IScreenChannelListener> listener = channelListener_.lock();
274 if (listener == nullptr) {
275 DHLOGE("%{public}s: Channel listener is null", DSCREEN_LOG_TAG);
276 return;
277 }
278 listener->OnSessionClosed();
279 }
280
OnBytesReceived(int32_t sessionId,const void * data,uint32_t dataLen)281 void ScreenDataChannelImpl::OnBytesReceived(int32_t sessionId, const void *data, uint32_t dataLen)
282 {
283 (void) sessionId;
284 (void) data;
285 (void) dataLen;
286
287 DHLOGD("%{public}s: OnScreenBytesReceived data channel not support yet", DSCREEN_LOG_TAG);
288 }
289
OnStreamReceived(int32_t sessionId,const StreamData * data,const StreamData * ext,const StreamFrameInfo * param)290 void ScreenDataChannelImpl::OnStreamReceived(int32_t sessionId, const StreamData *data,
291 const StreamData *ext, const StreamFrameInfo *param)
292 {
293 DHLOGI("%{public}s: OnStreamReceived, receiv data from softbus.", DSCREEN_LOG_TAG);
294 if (data == nullptr) {
295 DHLOGE("%{public}s: Stream data is null", DSCREEN_LOG_TAG);
296 return;
297 }
298 auto dataBuffer = std::make_shared<DataBuffer>(data->bufLen);
299 if (ext->bufLen == 0) {
300 DHLOGI("sink received full data.");
301 ProcessDullData(data, dataBuffer);
302 return;
303 } else {
304 DHLOGI("sink received dirty data.");
305 ProcessDirtyData(data, dataBuffer, ext);
306 }
307 }
308
ProcessDullData(const StreamData * data,std::shared_ptr<DataBuffer> dataBuffer)309 void ScreenDataChannelImpl::ProcessDullData(const StreamData *data, std::shared_ptr<DataBuffer> dataBuffer)
310 {
311 DHLOGI("%{public}s: ProcessDullData.", DSCREEN_LOG_TAG);
312 std::shared_ptr<IScreenChannelListener> listener = channelListener_.lock();
313 if (listener == nullptr) {
314 DHLOGE("%{public}s: Channel listener is null.", DSCREEN_LOG_TAG);
315 return;
316 }
317 int32_t ret = memcpy_s(dataBuffer->Data(), dataBuffer->Capacity(),
318 reinterpret_cast<uint8_t*>(data->buf), data->bufLen);
319 if (ret != EOK) {
320 DHLOGE("%{public}s: Full data memcpy failed.", DSCREEN_LOG_TAG);
321 return;
322 }
323 dataBuffer->SetDataType(VIDEO_FULL_SCREEN_DATA);
324 listener->OnDataReceived(dataBuffer);
325 }
326
ProcessDirtyData(const StreamData * data,std::shared_ptr<DataBuffer> dataBuffer,const StreamData * ext)327 void ScreenDataChannelImpl::ProcessDirtyData(const StreamData *data,
328 std::shared_ptr<DataBuffer> dataBuffer, const StreamData *ext)
329 {
330 DHLOGI("%{public}s: ProcessDirtyData.", DSCREEN_LOG_TAG);
331 std::shared_ptr<IScreenChannelListener> listener = channelListener_.lock();
332 if (listener == nullptr) {
333 DHLOGE("%{public}s: Channel listener is null.", DSCREEN_LOG_TAG);
334 return;
335 }
336 int32_t ret = memcpy_s(dataBuffer->Data(), dataBuffer->Capacity(),
337 reinterpret_cast<uint8_t*>(data->buf), data->bufLen);
338 if (ret != EOK) {
339 DHLOGE("%{public}s: Dirty data memcpy_s failed.", DSCREEN_LOG_TAG);
340 return;
341 }
342 nlohmann::json rectJson = nlohmann::json::parse(ext->buf, nullptr, false);
343 if (rectJson.is_discarded()) {
344 DHLOGE("%{public}s: OnStreamReceived rectJson invalid", DSCREEN_LOG_TAG);
345 return;
346 }
347 JsonToDirtyJson(rectJson, dataBuffer);
348 listener->OnDataReceived(dataBuffer);
349 }
350
DirtyVecToJson(nlohmann::json & rectJson,const std::shared_ptr<DataBuffer> & screenData)351 void ScreenDataChannelImpl::DirtyVecToJson(nlohmann::json &rectJson, const std::shared_ptr<DataBuffer> &screenData)
352 {
353 std::vector<DirtyRect> dirtyRectVec = screenData->GetDirtyRectVec();
354 rectJson["dataType"] = screenData->DataType();
355 rectJson["dirtySize"] = dirtyRectVec.size();
356 int32_t rectIndex = 0;
357 for (auto item : dirtyRectVec) {
358 std::string tempRectIndex = std::to_string(rectIndex);
359 rectJson[tempRectIndex] = nlohmann::json {
360 {KEY_POINT_DIRTY_X, item.xPos},
361 {KEY_POINT_DIRTY_Y, item.yPos},
362 {KEY_POINT_DIRTY_W, item.width},
363 {KEY_POINT_DIRTY_H, item.height},
364 {KEY_POINT_DIRTY_SIZE, item.dirtySize}
365 };
366 rectIndex++;
367 }
368 }
369
JsonToDirtyJson(nlohmann::json & rectJson,std::shared_ptr<DataBuffer> & screenData)370 void ScreenDataChannelImpl::JsonToDirtyJson(nlohmann::json &rectJson, std::shared_ptr<DataBuffer> &screenData)
371 {
372 if (!IsInt32(rectJson, "dirtySize") || !IsInt32(rectJson, "dataType")) {
373 return;
374 }
375 int32_t dirtySize = rectJson["dirtySize"].get<int32_t>();
376 int32_t dataType = rectJson["dataType"].get<int32_t>();
377 int32_t num = 0;
378 if (dirtySize >= DIRTY_MAX_SIZE) {
379 return;
380 }
381 while (num < dirtySize) {
382 auto item = std::to_string(num);
383 if (!rectJson.contains(item)) {
384 return;
385 }
386 if (!IsInt32(rectJson[item], KEY_POINT_DIRTY_X) || !IsInt32(rectJson[item], KEY_POINT_DIRTY_Y) ||
387 !IsInt32(rectJson[item], KEY_POINT_DIRTY_W) || !IsInt32(rectJson[item], KEY_POINT_DIRTY_H) ||
388 !IsInt32(rectJson[item], KEY_POINT_DIRTY_SIZE)) {
389 DHLOGE("%{public}s: JsonToDirtyJson rectJson not contain int32", DSCREEN_LOG_TAG);
390 return;
391 }
392 int32_t X = rectJson[item][KEY_POINT_DIRTY_X].get<int32_t>();
393 int32_t Y = rectJson[item][KEY_POINT_DIRTY_Y].get<int32_t>();
394 int32_t W = rectJson[item][KEY_POINT_DIRTY_W].get<int32_t>();
395 int32_t H = rectJson[item][KEY_POINT_DIRTY_H].get<int32_t>();
396 int32_t Size = rectJson[item][KEY_POINT_DIRTY_SIZE].get<int32_t>();
397 DirtyRect rect = {X, Y, W, H, Size};
398 screenData->AddDirtyRect(rect);
399 num++;
400 }
401 screenData->SetDataType(dataType);
402 }
403 } // namespace DistributedHardware
404 } // namespace OHOS