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