• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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