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