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