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:%{private}d, shadowInfoy:%{private}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:%{private}d, displayY:%{private}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, bool isJsCaller)
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        AddDraglistenerParam param { isJsCaller };
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, bool isJsCaller)
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        RemoveDraglistenerParam param { isJsCaller };
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, int32_t eventId)
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, eventId };
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:%{private}d, shadowInfoy:%{private}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    bool isJsCaller)
334{
335    GetDragSummaryParam param { isJsCaller };
336    GetDragSummaryReply reply {};
337
338    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_DRAG_SUMMARY, param, reply);
339    if (ret != RET_OK) {
340        FI_HILOGE("ITunnelClient::GetParam fail");
341        return ret;
342    }
343    summary.swap(reply.summary_);
344    return RET_OK;
345}
346
347int32_t DragClient::GetDragState(ITunnelClient &tunnel, DragState &dragState)
348{
349    DefaultParam param {};
350    GetDragStateReply reply {};
351
352    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_DRAG_STATE, param, reply);
353    if (ret != RET_OK) {
354        FI_HILOGE("ITunnelClient::GetParam fail");
355        return ret;
356    }
357    dragState = reply.dragState_;
358    return RET_OK;
359}
360
361int32_t DragClient::EnableUpperCenterMode(ITunnelClient &tunnel, bool enable)
362{
363    EnterTextEditorAreaParam param { enable };
364    DefaultReply reply {};
365
366    int32_t ret = tunnel.Control(Intention::DRAG, DragRequestID::ENTER_TEXT_EDITOR_AREA, param, reply);
367    if (ret != RET_OK) {
368        FI_HILOGE("ITunnelClient::Control fail");
369    }
370    return ret;
371}
372
373int32_t DragClient::GetDragAction(ITunnelClient &tunnel, DragAction &dragAction)
374{
375    DefaultParam param {};
376    GetDragActionReply reply {};
377
378    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_DRAG_ACTION, param, reply);
379    if (ret != RET_OK) {
380        FI_HILOGE("ITunnelClient::GetParam fail");
381        return ret;
382    }
383    dragAction = reply.dragAction_;
384    return RET_OK;
385}
386
387int32_t DragClient::GetExtraInfo(ITunnelClient &tunnel, std::string &extraInfo)
388{
389    DefaultParam param {};
390    GetExtraInfoReply reply {};
391
392    int32_t ret = tunnel.GetParam(Intention::DRAG, DragRequestID::GET_EXTRA_INFO, param, reply);
393    if (ret != RET_OK) {
394        FI_HILOGE("ITunnelClient::GetParam fail");
395        return ret;
396    }
397    extraInfo = std::move(reply.extraInfo_);
398    return RET_OK;
399}
400
401int32_t DragClient::AddPrivilege(ITunnelClient &tunnel)
402{
403    DefaultParam param {};
404    DefaultReply reply {};
405
406    int32_t ret = tunnel.Control(Intention::DRAG, DragRequestID::ADD_PRIVILEGE, param, reply);
407    if (ret != RET_OK) {
408        FI_HILOGE("ITunnelClient::Control fail");
409    }
410    return ret;
411}
412
413int32_t DragClient::EraseMouseIcon(ITunnelClient &tunnel)
414{
415    DefaultParam param {};
416    DefaultReply reply {};
417
418    int32_t ret = tunnel.Control(Intention::DRAG, DragRequestID::ERASE_MOUSE_ICON, param, reply);
419    if (ret != RET_OK) {
420        FI_HILOGE("ITunnelClient::Control fail");
421    }
422    return ret;
423}
424
425int32_t DragClient::SetMouseDragMonitorState(ITunnelClient &tunnel, bool state)
426{
427    SetMouseDragMonitorStateParam param { state };
428    DefaultReply reply {};
429
430    int32_t ret = tunnel.Control(Intention::DRAG, DragRequestID::SET_MOUSE_DRAG_MONITOR_STATE, param, reply);
431    if (ret != RET_OK) {
432        FI_HILOGE("ITunnelClient::Control fail");
433    }
434    return ret;
435}
436
437int32_t DragClient::AddSelectedPixelMap(ITunnelClient &tunnel, std::shared_ptr<OHOS::Media::PixelMap> pixelMap,
438    std::function<void(bool)> callback)
439{
440    CALL_DEBUG_ENTER;
441    CHKPR(pixelMap, RET_ERR);
442    CHKPR(callback, RET_ERR);
443    std::lock_guard<std::mutex> guard(mtx_);
444    addSelectedPixelMapCallback_ = callback;
445    AddSelectedPixelMapParam param { pixelMap };
446    DefaultReply reply {};
447
448    int32_t ret = tunnel.SetParam(Intention::DRAG, DragRequestID::ADD_SELECTED_PIXELMAP, param, reply);
449    if (ret != RET_OK) {
450        FI_HILOGE("ITunnelClient::SetParam fail");
451    }
452    return ret;
453}
454
455int32_t DragClient::OnAddSelectedPixelMapResult(const StreamClient &client, NetPacket &pkt)
456{
457    CALL_DEBUG_ENTER;
458    bool result = false;
459
460    pkt >> result;
461    if (pkt.ChkRWError()) {
462        FI_HILOGE("Packet read addSelectedPixelMap msg failed");
463        return RET_ERR;
464    }
465    std::lock_guard<std::mutex> guard(mtx_);
466    CHKPR(addSelectedPixelMapCallback_, RET_ERR);
467    addSelectedPixelMapCallback_(result);
468    return RET_OK;
469}
470
471int32_t DragClient::OnNotifyResult(const StreamClient &client, NetPacket &pkt)
472{
473    CALL_DEBUG_ENTER;
474    DragNotifyMsg notifyMsg;
475    int32_t result = 0;
476    int32_t dragBehavior = -1;
477    pkt >> notifyMsg.displayX >> notifyMsg.displayY >> result >> notifyMsg.targetPid >> dragBehavior;
478    if (pkt.ChkRWError()) {
479        FI_HILOGE("Packet read drag msg failed");
480        return RET_ERR;
481    }
482    if ((result < static_cast<int32_t>(DragResult::DRAG_SUCCESS)) ||
483        (result > static_cast<int32_t>(DragResult::DRAG_EXCEPTION))) {
484        FI_HILOGE("Invalid result:%{public}d", result);
485        return RET_ERR;
486    }
487    notifyMsg.result = static_cast<DragResult>(result);
488    if ((dragBehavior < static_cast<int32_t>(DragBehavior::UNKNOWN)) ||
489        (dragBehavior > static_cast<int32_t>(DragBehavior::MOVE))) {
490        FI_HILOGE("Invalid dragBehavior:%{public}d", dragBehavior);
491        return RET_ERR;
492    }
493    notifyMsg.dragBehavior = static_cast<DragBehavior>(dragBehavior);
494    std::lock_guard<std::mutex> guard(mtx_);
495    CHKPR(startDragListener_, RET_ERR);
496    startDragListener_->OnDragEndMessage(notifyMsg);
497    return RET_OK;
498}
499
500int32_t DragClient::OnNotifyHideIcon(const StreamClient& client, NetPacket& pkt)
501{
502    CALL_DEBUG_ENTER;
503    std::lock_guard<std::mutex> guard(mtx_);
504    CHKPR(startDragListener_, RET_ERR);
505    startDragListener_->OnHideIconMessage();
506    return RET_OK;
507}
508
509int32_t DragClient::OnStateChangedMessage(const StreamClient &client, NetPacket &pkt)
510{
511    CALL_DEBUG_ENTER;
512    int32_t state = 0;
513    pkt >> state;
514    if (pkt.ChkRWError()) {
515        FI_HILOGE("Packet read drag msg failed");
516        return RET_ERR;
517    }
518    std::lock_guard<std::mutex> guard(mtx_);
519    for (const auto &listener : dragListeners_) {
520        listener->OnDragMessage(static_cast<DragState>(state));
521    }
522    return RET_OK;
523}
524
525int32_t DragClient::OnDragStyleChangedMessage(const StreamClient &client, NetPacket &pkt)
526{
527    CALL_DEBUG_ENTER;
528    int32_t style = 0;
529    pkt >> style;
530    if (pkt.ChkRWError()) {
531        FI_HILOGE("Packet read drag msg failed");
532        return RET_ERR;
533    }
534    std::lock_guard<std::mutex> guard(mtx_);
535    for (const auto &listener : subscriptListeners_) {
536        listener->OnMessage(static_cast<DragCursorStyle>(style));
537    }
538    return RET_OK;
539}
540
541void DragClient::OnConnected(ITunnelClient &tunnel)
542{
543    CALL_INFO_TRACE;
544    if (connectedDragListeners_.empty()) {
545        FI_HILOGE("The connect drag listener set is empty");
546        return;
547    }
548    for (const auto &listener : connectedDragListeners_) {
549        if (AddDraglistener(tunnel, listener) != RET_OK) {
550            FI_HILOGW("AddDraglistener failed");
551        }
552    }
553    connectedDragListeners_.clear();
554}
555
556void DragClient::OnDisconnected(ITunnelClient &tunnel)
557{
558    CALL_INFO_TRACE;
559    std::lock_guard<std::mutex> guard(mtx_);
560    if (dragListeners_.empty()) {
561        FI_HILOGE("The drag listener set is empty");
562        return;
563    }
564    connectedDragListeners_ = dragListeners_;
565    dragListeners_.clear();
566    hasRegistered_ = false;
567}
568} // namespace DeviceStatus
569} // namespace Msdp
570} // namespace OHOS
571