1/*
2 * Copyright (c) 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 "drag_client.h"
17
18#include "default_params.h"
19#include "drag_params.h"
20#include "devicestatus_define.h"
21#include "proto.h"
22
23#undef LOG_TAG
24#define LOG_TAG "DragClient"
25
26namespace OHOS {
27namespace Msdp {
28namespace DeviceStatus {
29
30int32_t DragClient::StartDrag(ITunnelClient &tunnel,
31    const DragData &dragData, std::shared_ptr<IStartDragListener> listener)
32{
33    CALL_DEBUG_ENTER;
34    CHKPR(listener, RET_ERR);
35    if (dragData.shadowInfos.empty()) {
36        FI_HILOGE("shadowInfos is empty");
37        return ERR_INVALID_VALUE;
38    }
39    for (const auto& shadowInfo : dragData.shadowInfos) {
40        CHKPR(shadowInfo.pixelMap, RET_ERR);
41        if ((shadowInfo.x > 0) || (shadowInfo.y > 0) ||
42            (shadowInfo.x < -shadowInfo.pixelMap->GetWidth()) ||
43            (shadowInfo.y < -shadowInfo.pixelMap->GetHeight())) {
44            FI_HILOGE("Invalid parameter, shadowInfox:%{public}d, shadowInfoy:%{public}d",
45                shadowInfo.x, shadowInfo.y);
46            return RET_ERR;
47        }
48    }
49    if ((dragData.dragNum <= 0) || (dragData.buffer.size() > MAX_BUFFER_SIZE) ||
50        (dragData.displayX < 0) || (dragData.displayY < 0)) {
51        FI_HILOGE("Start drag, invalid argument, dragNum:%{public}d, bufferSize:%{public}zu, "
52            "displayX:%{public}d, displayY:%{public}d",
53            dragData.dragNum, dragData.buffer.size(), dragData.displayX, dragData.displayY);
54        return RET_ERR;
55    }
56    {
57        std::lock_guard<std::mutex> guard(mtx_);
58        startDragListener_ = listener;
59    }
60    StartDragParam param { dragData };
61    DefaultReply reply {};
62
63    int32_t ret = tunnel.Start(Intention::DRAG, param, reply);
64    if (ret != RET_OK) {
65        FI_HILOGE("ITunnelClient::Start fail");
66    }
67    return ret;
68}
69
70int32_t DragClient::StopDrag(ITunnelClient &tunnel, const DragDropResult &dropResult)
71{
72    CALL_DEBUG_ENTER;
73    StopDragParam param { dropResult };
74    DefaultReply reply;
75
76    int32_t ret = tunnel.Stop(Intention::DRAG, param, reply);
77    if (ret != RET_OK) {
78        FI_HILOGE("ITunnelClient::Start fail");
79    }
80    return ret;
81}
82
83int32_t DragClient::AddDraglistener(ITunnelClient &tunnel, DragListenerPtr listener)
84{
85    CALL_DEBUG_ENTER;
86    CHKPR(listener, RET_ERR);
87    std::lock_guard<std::mutex> guard(mtx_);
88    if (dragListeners_.find(listener) != dragListeners_.end()) {
89        return RET_OK;
90    }
91    if (!hasRegistered_) {
92        DefaultParam param {};
93        DefaultReply reply {};
94        FI_HILOGI("Start drag listening");
95
96        int32_t ret = tunnel.AddWatch(Intention::DRAG, DragRequestID::ADD_DRAG_LISTENER, param, reply);
97        if (ret != RET_OK) {
98            FI_HILOGE("ITunnelClient::AddWatch fail");
99            return ret;
100        }
101        hasRegistered_ = true;
102    }
103    dragListeners_.insert(listener);
104    return RET_OK;
105}
106
107int32_t DragClient::RemoveDraglistener(ITunnelClient &tunnel, DragListenerPtr listener)
108{
109    CALL_DEBUG_ENTER;
110    std::lock_guard<std::mutex> guard(mtx_);
111    if (listener == nullptr) {
112        dragListeners_.clear();
113    } else {
114        dragListeners_.erase(listener);
115    }
116    if (hasRegistered_ && dragListeners_.empty()) {
117        hasRegistered_ = false;
118        DefaultParam param {};
119        DefaultReply reply {};
120        FI_HILOGI("Stop drag listening");
121
122        int32_t ret = tunnel.RemoveWatch(Intention::DRAG, DragRequestID::REMOVE_DRAG_LISTENER, param, reply);
123        if (ret != RET_OK) {
124            FI_HILOGE("ITunnelClient::RemoveWatch fail");
125            return ret;
126        }
127    }
128    return RET_OK;
129}
130
131int32_t DragClient::AddSubscriptListener(ITunnelClient &tunnel, SubscriptListenerPtr listener)
132{
133    CHKPR(listener, RET_ERR);
134    std::lock_guard<std::mutex> guard(mtx_);
135    if (subscriptListeners_.find(listener) != subscriptListeners_.end()) {
136        return RET_OK;
137    }
138    if (!hasSubscriptRegistered_) {
139        DefaultParam param {};
140        DefaultReply reply {};
141        FI_HILOGI("Start subscript listening");
142
143        int32_t ret = tunnel.AddWatch(Intention::DRAG, DragRequestID::ADD_SUBSCRIPT_LISTENER, param, reply);
144        if (ret != RET_OK) {
145            FI_HILOGE("ITunnelClient::AddWatch fail");
146            return ret;
147        }
148        hasSubscriptRegistered_ = true;
149    }
150    subscriptListeners_.insert(listener);
151    return RET_OK;
152}
153
154int32_t DragClient::RemoveSubscriptListener(ITunnelClient &tunnel, SubscriptListenerPtr listener)
155{
156    std::lock_guard<std::mutex> guard(mtx_);
157    if (listener == nullptr) {
158        subscriptListeners_.clear();
159    } else {
160        subscriptListeners_.erase(listener);
161    }
162    if (hasSubscriptRegistered_ && subscriptListeners_.empty()) {
163        hasSubscriptRegistered_ = false;
164        DefaultParam param {};
165        DefaultReply reply {};
166        FI_HILOGI("Stop subscript listening");
167
168        int32_t ret = tunnel.RemoveWatch(Intention::DRAG, DragRequestID::REMOVE_SUBSCRIPT_LISTENER, param, reply);
169        if (ret != RET_OK) {
170            FI_HILOGE("ITunnelClient::RemoveWatch fail");
171            return ret;
172        }
173    }
174    return RET_OK;
175}
176
177int32_t DragClient::SetDragWindowVisible(ITunnelClient &tunnel, bool visible, bool isForce)
178{
179    SetDragWindowVisibleParam param { visible, isForce };
180    DefaultReply reply {};
181
182    int32_t ret = tunnel.SetParam(Intention::DRAG, DragRequestID::SET_DRAG_WINDOW_VISIBLE, param, reply);
183    if (ret != RET_OK) {
184        FI_HILOGE("ITunnelClient::SetParam fail");
185    }
186    return ret;
187}
188
189int32_t DragClient::UpdateDragStyle(ITunnelClient &tunnel, DragCursorStyle style)
190{
191    if ((style < DragCursorStyle::DEFAULT) || (style > DragCursorStyle::MOVE)) {
192        FI_HILOGE("Invalid style:%{public}d", static_cast<int32_t>(style));
193        return RET_ERR;
194    }
195    UpdateDragStyleParam param { style };
196    DefaultReply reply {};
197
198    int32_t ret = tunnel.SetParam(Intention::DRAG, DragRequestID::UPDATE_DRAG_STYLE, param, reply);
199    if (ret != RET_OK) {
200        FI_HILOGE("ITunnelClient::SetParam fail");
201    }
202    return ret;
203}
204
205int32_t DragClient::UpdateShadowPic(ITunnelClient &tunnel, const ShadowInfo &shadowInfo)
206{
207    CALL_DEBUG_ENTER;
208    CHKPR(shadowInfo.pixelMap, RET_ERR);
209    if ((shadowInfo.x > 0) || (shadowInfo.y > 0) ||
210        (shadowInfo.x < -shadowInfo.pixelMap->GetWidth()) ||
211        (shadowInfo.y < -shadowInfo.pixelMap->GetHeight())) {
212        FI_HILOGE("Invalid parameter, shadowInfox:%{public}d, shadowInfoy:%{public}d",
213            shadowInfo.x, shadowInfo.y);
214        return RET_ERR;
215    }
216    UpdateShadowPicParam param { shadowInfo };
217    DefaultReply reply {};
218
219    int32_t ret = tunnel.SetParam(Intention::DRAG, DragRequestID::UPDATE_SHADOW_PIC, param, reply);
220    if (ret != RET_OK) {
221        FI_HILOGE("ITunnelClient::SetParam fail");
222    }
223    return ret;
224}
225
226int32_t DragClient::GetDragTargetPid(ITunnelClient &tunnel)
227{
228    CALL_DEBUG_ENTER;
229    DefaultParam param {};
230    GetDragTargetPidReply reply {};
231
232    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_DRAG_TARGET_PID, param, reply);
233    if (ret != RET_OK) {
234        FI_HILOGE("ITunnelClient::GetParam fail");
235        return -1;
236    }
237    return reply.targetPid_;
238}
239
240int32_t DragClient::GetUdKey(ITunnelClient &tunnel, std::string &udKey)
241{
242    DefaultParam param {};
243    GetUdKeyReply reply {};
244
245    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_UDKEY, param, reply);
246    if (ret != RET_OK) {
247        FI_HILOGE("ITunnelClient::GetParam fail");
248        return ret;
249    }
250    udKey = reply.udKey_;
251    FI_HILOGI("UdKey:%{public}s", reply.udKey_.c_str());
252    return RET_OK;
253}
254
255int32_t DragClient::GetShadowOffset(ITunnelClient &tunnel, ShadowOffset &shadowOffset)
256{
257    DefaultParam param {};
258    GetShadowOffsetReply reply {};
259
260    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_SHADOW_OFFSET, param, reply);
261    if (ret != RET_OK) {
262        FI_HILOGE("ITunnelClient::GetParam fail");
263        return ret;
264    }
265    shadowOffset = reply.shadowOffset_;
266    return RET_OK;
267}
268
269int32_t DragClient::GetDragData(ITunnelClient &tunnel, DragData &dragData)
270{
271    CALL_DEBUG_ENTER;
272    DefaultParam param {};
273    GetDragDataReply reply { dragData };
274
275    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_DRAG_DATA, param, reply);
276    if (ret != RET_OK) {
277        FI_HILOGE("ITunnelClient::GetParam fail");
278    }
279    return ret;
280}
281
282int32_t DragClient::UpdatePreviewStyle(ITunnelClient &tunnel, const PreviewStyle &previewStyle)
283{
284    UpdatePreviewStyleParam param { previewStyle };
285    DefaultReply reply {};
286
287    int32_t ret = tunnel.SetParam(Intention::DRAG, DragRequestID::UPDATE_PREVIEW_STYLE, param, reply);
288    if (ret != RET_OK) {
289        FI_HILOGE("ITunnelClient::SetParam fail");
290    }
291    return ret;
292}
293
294int32_t DragClient::UpdatePreviewStyleWithAnimation(ITunnelClient &tunnel,
295    const PreviewStyle &previewStyle, const PreviewAnimation &animation)
296{
297    UpdatePreviewAnimationParam param { previewStyle, animation };
298    DefaultReply reply {};
299
300    int32_t ret = tunnel.SetParam(Intention::DRAG, DragRequestID::UPDATE_PREVIEW_STYLE_WITH_ANIMATION, param, reply);
301    if (ret != RET_OK) {
302        FI_HILOGE("ITunnelClient::SetParam fail");
303    }
304    return ret;
305}
306
307int32_t DragClient::RotateDragWindowSync(ITunnelClient &tunnel,
308    const std::shared_ptr<Rosen::RSTransaction>& rsTransaction)
309{
310    RotateDragWindowSyncParam param { rsTransaction };
311    DefaultReply reply {};
312
313    int32_t ret = tunnel.Control(Intention::DRAG, DragRequestID::ROTATE_DRAG_WINDOW_SYNC, param, reply);
314    if (ret != RET_OK) {
315        FI_HILOGE("ITunnelClient::Control fail");
316    }
317    return ret;
318}
319
320int32_t DragClient::SetDragWindowScreenId(ITunnelClient &tunnel, uint64_t displayId, uint64_t screenId)
321{
322    SetDragWindowScreenIdParam param { displayId, screenId };
323    DefaultReply reply {};
324
325    int32_t ret = tunnel.SetParam(Intention::DRAG, DragRequestID::SET_DRAG_WINDOW_SCREEN_ID, param, reply);
326    if (ret != RET_OK) {
327        FI_HILOGE("ITunnelClient::SetParam fail");
328    }
329    return ret;
330}
331
332int32_t DragClient::GetDragSummary(ITunnelClient &tunnel, std::map<std::string, int64_t> &summary)
333{
334    DefaultParam param {};
335    GetDragSummaryReply reply {};
336
337    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_DRAG_SUMMARY, param, reply);
338    if (ret != RET_OK) {
339        FI_HILOGE("ITunnelClient::GetParam fail");
340        return ret;
341    }
342    summary.swap(reply.summary_);
343    return RET_OK;
344}
345
346int32_t DragClient::GetDragState(ITunnelClient &tunnel, DragState &dragState)
347{
348    DefaultParam param {};
349    GetDragStateReply reply {};
350
351    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_DRAG_STATE, param, reply);
352    if (ret != RET_OK) {
353        FI_HILOGE("ITunnelClient::GetParam fail");
354        return ret;
355    }
356    dragState = reply.dragState_;
357    return RET_OK;
358}
359
360int32_t DragClient::EnterTextEditorArea(ITunnelClient &tunnel, bool enable)
361{
362    EnterTextEditorAreaParam param { enable };
363    DefaultReply reply {};
364
365    int32_t ret = tunnel.Control(Intention::DRAG, DragRequestID::ENTER_TEXT_EDITOR_AREA, param, reply);
366    if (ret != RET_OK) {
367        FI_HILOGE("ITunnelClient::Control fail");
368    }
369    return ret;
370}
371
372int32_t DragClient::GetDragAction(ITunnelClient &tunnel, DragAction &dragAction)
373{
374    DefaultParam param {};
375    GetDragActionReply reply {};
376
377    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_DRAG_ACTION, param, reply);
378    if (ret != RET_OK) {
379        FI_HILOGE("ITunnelClient::GetParam fail");
380        return ret;
381    }
382    dragAction = reply.dragAction_;
383    return RET_OK;
384}
385
386int32_t DragClient::GetExtraInfo(ITunnelClient &tunnel, std::string &extraInfo)
387{
388    DefaultParam param {};
389    GetExtraInfoReply reply {};
390
391    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_EXTRA_INFO, param, reply);
392    if (ret != RET_OK) {
393        FI_HILOGE("ITunnelClient::GetParam fail");
394        return ret;
395    }
396    extraInfo = std::move(reply.extraInfo_);
397    return RET_OK;
398}
399
400int32_t DragClient::AddPrivilege(ITunnelClient &tunnel)
401{
402    DefaultParam param {};
403    DefaultReply reply {};
404
405    int32_t ret = tunnel.Control(Intention::DRAG, DragRequestID::ADD_PRIVILEGE, param, reply);
406    if (ret != RET_OK) {
407        FI_HILOGE("ITunnelClient::Control fail");
408    }
409    return ret;
410}
411
412int32_t DragClient::EraseMouseIcon(ITunnelClient &tunnel)
413{
414    DefaultParam param {};
415    DefaultReply reply {};
416
417    int32_t ret = tunnel.Control(Intention::DRAG, DragRequestID::ERASE_MOUSE_ICON, param, reply);
418    if (ret != RET_OK) {
419        FI_HILOGE("ITunnelClient::Control fail");
420    }
421    return ret;
422}
423
424int32_t DragClient::AddSelectedPixelMap(ITunnelClient &tunnel, std::shared_ptr<OHOS::Media::PixelMap> pixelMap,
425    std::function<void(bool)> callback)
426{
427    CALL_DEBUG_ENTER;
428    CHKPR(pixelMap, RET_ERR);
429    CHKPR(callback, RET_ERR);
430    std::lock_guard<std::mutex> guard(mtx_);
431    addSelectedPixelMapCallback_ = callback;
432    AddSelectedPixelMapParam param { pixelMap };
433    DefaultReply reply {};
434
435    int32_t ret = tunnel.SetParam(Intention::DRAG, DragRequestID::ADD_SELECTED_PIXELMAP, param, reply);
436    if (ret != RET_OK) {
437        FI_HILOGE("ITunnelClient::SetParam fail");
438    }
439    return ret;
440}
441
442int32_t DragClient::OnAddSelectedPixelMapResult(const StreamClient &client, NetPacket &pkt)
443{
444    CALL_DEBUG_ENTER;
445    bool result = false;
446
447    pkt >> result;
448    if (pkt.ChkRWError()) {
449        FI_HILOGE("Packet read addSelectedPixelMap msg failed");
450        return RET_ERR;
451    }
452    std::lock_guard<std::mutex> guard(mtx_);
453    CHKPR(addSelectedPixelMapCallback_, RET_ERR);
454    addSelectedPixelMapCallback_(result);
455    return RET_OK;
456}
457
458int32_t DragClient::OnNotifyResult(const StreamClient &client, NetPacket &pkt)
459{
460    CALL_DEBUG_ENTER;
461    DragNotifyMsg notifyMsg;
462    int32_t result = 0;
463    int32_t dragBehavior = -1;
464    pkt >> notifyMsg.displayX >> notifyMsg.displayY >> result >> notifyMsg.targetPid >> dragBehavior;
465    if (pkt.ChkRWError()) {
466        FI_HILOGE("Packet read drag msg failed");
467        return RET_ERR;
468    }
469    if ((result < static_cast<int32_t>(DragResult::DRAG_SUCCESS)) ||
470        (result > static_cast<int32_t>(DragResult::DRAG_EXCEPTION))) {
471        FI_HILOGE("Invalid result:%{public}d", result);
472        return RET_ERR;
473    }
474    notifyMsg.result = static_cast<DragResult>(result);
475    if ((dragBehavior < static_cast<int32_t>(DragBehavior::UNKNOWN)) ||
476        (dragBehavior > static_cast<int32_t>(DragBehavior::MOVE))) {
477        FI_HILOGE("Invalid dragBehavior:%{public}d", dragBehavior);
478        return RET_ERR;
479    }
480    notifyMsg.dragBehavior = static_cast<DragBehavior>(dragBehavior);
481    std::lock_guard<std::mutex> guard(mtx_);
482    CHKPR(startDragListener_, RET_ERR);
483    startDragListener_->OnDragEndMessage(notifyMsg);
484    return RET_OK;
485}
486
487int32_t DragClient::OnNotifyHideIcon(const StreamClient& client, NetPacket& pkt)
488{
489    CALL_DEBUG_ENTER;
490    std::lock_guard<std::mutex> guard(mtx_);
491    CHKPR(startDragListener_, RET_ERR);
492    startDragListener_->OnHideIconMessage();
493    return RET_OK;
494}
495
496int32_t DragClient::OnStateChangedMessage(const StreamClient &client, NetPacket &pkt)
497{
498    CALL_DEBUG_ENTER;
499    int32_t state = 0;
500    pkt >> state;
501    if (pkt.ChkRWError()) {
502        FI_HILOGE("Packet read drag msg failed");
503        return RET_ERR;
504    }
505    std::lock_guard<std::mutex> guard(mtx_);
506    for (const auto &listener : dragListeners_) {
507        listener->OnDragMessage(static_cast<DragState>(state));
508    }
509    return RET_OK;
510}
511
512int32_t DragClient::OnDragStyleChangedMessage(const StreamClient &client, NetPacket &pkt)
513{
514    CALL_DEBUG_ENTER;
515    int32_t style = 0;
516    pkt >> style;
517    if (pkt.ChkRWError()) {
518        FI_HILOGE("Packet read drag msg failed");
519        return RET_ERR;
520    }
521    std::lock_guard<std::mutex> guard(mtx_);
522    for (const auto &listener : subscriptListeners_) {
523        listener->OnMessage(static_cast<DragCursorStyle>(style));
524    }
525    return RET_OK;
526}
527} // namespace DeviceStatus
528} // namespace Msdp
529} // namespace OHOS
530