1 /*
2  * Copyright (c) 2024 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 "hot_area.h"
17 #include "devicestatus_define.h"
18 
19 #undef LOG_TAG
20 #define LOG_TAG "HotArea"
21 
22 namespace OHOS {
23 namespace Msdp {
24 namespace DeviceStatus {
25 namespace Cooperate {
26 namespace {
27 constexpr int32_t HOT_AREA_WIDTH { 100 };
28 constexpr int32_t HOT_AREA_MARGIN { 200 };
29 }; // namespace
30 
AddListener(const RegisterHotareaListenerEvent & event)31 void HotArea::AddListener(const RegisterHotareaListenerEvent &event)
32 {
33     CALL_DEBUG_ENTER;
34     std::lock_guard guard(lock_);
35     HotAreaInfo info {
36         .pid = event.pid,
37         .msgId = MessageId::HOT_AREA_ADD_LISTENER,
38     };
39     auto [iter, isOk] = callbacks_.emplace(info);
40     if (!isOk) {
41         callbacks_.erase(iter);
42         callbacks_.emplace(info);
43     }
44 }
45 
RemoveListener(const UnregisterHotareaListenerEvent & event)46 void HotArea::RemoveListener(const UnregisterHotareaListenerEvent &event)
47 {
48     CALL_DEBUG_ENTER;
49     std::lock_guard guard(lock_);
50     callbacks_.erase(HotAreaInfo { .pid = event.pid });
51 }
52 
EnableCooperate(const EnableCooperateEvent & event)53 void HotArea::EnableCooperate(const EnableCooperateEvent &event)
54 {
55     CALL_DEBUG_ENTER;
56     std::lock_guard guard(lock_);
57     auto display = Rosen::DisplayManager::GetInstance().GetDefaultDisplay();
58     CHKPV(display);
59     width_ = display->GetWidth();
60     height_ = display->GetHeight();
61 }
62 
ProcessData(std::shared_ptr<MMI::PointerEvent> pointerEvent)63 int32_t HotArea::ProcessData(std::shared_ptr<MMI::PointerEvent> pointerEvent)
64 {
65     CALL_DEBUG_ENTER;
66     std::lock_guard guard(lock_);
67     CHKPR(pointerEvent, RET_ERR);
68     MMI::PointerEvent::PointerItem pointerItem;
69     if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointerItem)) {
70         FI_HILOGE("Corrupted pointer event");
71         return RET_ERR;
72     }
73     displayX_ = pointerItem.GetDisplayX();
74     displayY_ = pointerItem.GetDisplayY();
75     deltaX_ = pointerItem.GetRawDx();
76     deltaY_ = pointerItem.GetRawDy();
77     CheckInHotArea();
78     CheckPointerToEdge(type_);
79     NotifyMessage();
80     return RET_OK;
81 }
82 
CheckInHotArea()83 void HotArea::CheckInHotArea()
84 {
85     CALL_DEBUG_ENTER;
86     if (displayX_ <= HOT_AREA_WIDTH && displayY_ >= HOT_AREA_MARGIN &&
87         displayY_ <= (height_ - HOT_AREA_MARGIN)) {
88         type_ = HotAreaType::AREA_LEFT;
89     } else if (displayX_ >= (width_ - HOT_AREA_WIDTH) && displayY_ >= HOT_AREA_MARGIN &&
90         displayY_ <= (height_ - HOT_AREA_MARGIN)) {
91         type_ = HotAreaType::AREA_RIGHT;
92     } else if (displayY_ <= HOT_AREA_WIDTH && displayX_ >= HOT_AREA_MARGIN &&
93         displayX_ <= (width_ - HOT_AREA_MARGIN)) {
94         type_ = HotAreaType::AREA_TOP;
95     } else if (displayY_ >= (height_ - HOT_AREA_WIDTH) && displayX_ >= HOT_AREA_MARGIN &&
96         displayX_ <= (width_ - HOT_AREA_MARGIN)) {
97         type_ = HotAreaType::AREA_BOTTOM;
98     } else {
99         type_ = HotAreaType::AREA_NONE;
100     }
101 }
102 
CheckPointerToEdge(HotAreaType type)103 void HotArea::CheckPointerToEdge(HotAreaType type)
104 {
105     CALL_DEBUG_ENTER;
106     if (type == HotAreaType::AREA_LEFT) {
107         isEdge_ = displayX_ <= 0 && deltaX_ < 0;
108     } else if (type == HotAreaType::AREA_RIGHT) {
109         isEdge_ = displayX_ >= (width_ - 1) && deltaX_ > 0;
110     } else if (type == HotAreaType::AREA_TOP) {
111         isEdge_ = displayY_ <= 0 && deltaY_ < 0;
112     } else if (type == HotAreaType::AREA_BOTTOM) {
113         isEdge_ = displayY_ >= (height_ - 1) && deltaY_ > 0;
114     } else {
115         isEdge_ = false;
116     }
117 }
118 
NotifyMessage()119 void HotArea::NotifyMessage()
120 {
121     CALL_DEBUG_ENTER;
122     OnHotAreaMessage(type_, isEdge_);
123 }
124 
OnHotAreaMessage(HotAreaType msg,bool isEdge)125 void HotArea::OnHotAreaMessage(HotAreaType msg, bool isEdge)
126 {
127     CALL_DEBUG_ENTER;
128     for (const auto &callback : callbacks_) {
129         NotifyHotAreaMessage(callback.pid, callback.msgId, msg, isEdge);
130     }
131 }
132 
OnClientDied(const ClientDiedEvent & event)133 void HotArea::OnClientDied(const ClientDiedEvent &event)
134 {
135     FI_HILOGI("Remove client died listener, pid: %{public}d", event.pid);
136     callbacks_.erase(HotAreaInfo { .pid = event.pid });
137 }
138 
NotifyHotAreaMessage(int32_t pid,MessageId msgId,HotAreaType msg,bool isEdge)139 void HotArea::NotifyHotAreaMessage(int32_t pid, MessageId msgId, HotAreaType msg, bool isEdge)
140 {
141     CALL_DEBUG_ENTER;
142     CHKPV(env_);
143     auto session = env_->GetSocketSessionManager().FindSessionByPid(pid);
144     CHKPV(session);
145     NetPacket pkt(msgId);
146 
147     pkt << displayX_ << displayY_ << static_cast<int32_t>(msg) << isEdge;
148     if (pkt.ChkRWError()) {
149         FI_HILOGE("Packet write data failed");
150         return;
151     }
152     if (!session->SendMsg(pkt)) {
153         FI_HILOGE("Sending failed");
154         return;
155     }
156 }
157 } // namespace Cooperate
158 } // namespace DeviceStatus
159 } // namespace Msdp
160 } // namespace OHOS