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 #undef LOG_TAG
17 #define LOG_TAG "InputEventSampler"
18
19 #include <chrono>
20 #include "input_event_transmission/input_event_sampler.h"
21 #include "devicestatus_define.h"
22
23 namespace OHOS {
24 namespace Msdp {
25 namespace DeviceStatus {
26 namespace Cooperate {
27
28 int32_t InputEventSampler::idealEventIntervalMS_ { 4 };
29 int32_t InputEventSampler::expiredIntervalMS_ { 24 };
30 int32_t InputEventSampler::rawDxThreshold_ { 20 };
31 int32_t InputEventSampler::rawDyThreshold_ { 20 };
32 std::unordered_set<int32_t> InputEventSampler::filterPointerActions_ {
33 MMI::PointerEvent::POINTER_ACTION_ENTER_WINDOW,
34 MMI::PointerEvent::POINTER_ACTION_LEAVE_WINDOW,
35 MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW,
36 MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW,
37 };
38
InputEventSampler()39 InputEventSampler::InputEventSampler() { }
40
OnPointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)41 void InputEventSampler::OnPointerEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
42 {
43 if (IsSkipNeeded(pointerEvent)) {
44 return;
45 }
46 if (IsRawEventsExpired()) {
47 ClearRawEvents();
48 }
49 if (IsTouchPadEvent(pointerEvent)) {
50 HandleTouchPadEvent(pointerEvent);
51 } else {
52 HandleMouseEvent(pointerEvent);
53 }
54 OnDownSampledEvent();
55 }
56
SetPointerEventHandler(PointerEventHandler pointerEventHandler)57 void InputEventSampler::SetPointerEventHandler(PointerEventHandler pointerEventHandler)
58 {
59 pointerEventHandler_ = pointerEventHandler;
60 }
61
IsTouchPadEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)62 bool InputEventSampler::IsTouchPadEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
63 {
64 if (pointerEvent == nullptr) {
65 FI_HILOGW("Null pointerEvent, skip");
66 return false;
67 }
68 MMI::PointerEvent::PointerItem item;
69 if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
70 FI_HILOGE("Corrupted pointerEvent, skip");
71 return false;
72 }
73 FI_HILOGD("Current toolType:%{public}d", item.GetToolType());
74 return (item.GetToolType() == MMI::PointerEvent::TOOL_TYPE_TOUCHPAD);
75 }
76
IsSpecialEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)77 bool InputEventSampler::IsSpecialEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
78 {
79 if (pointerEvent == nullptr) {
80 FI_HILOGW("Null pointerEvent, skip");
81 return false;
82 }
83 if (auto pointerAction = pointerEvent->GetPointerAction();
84 pointerAction != MMI::PointerEvent::POINTER_ACTION_MOVE &&
85 pointerAction != MMI::PointerEvent::POINTER_ACTION_PULL_MOVE) {
86 FI_HILOGI("Special event, action:%{public}d", pointerAction);
87 return true;
88 }
89 return false;
90 }
91
IsDurationMatched()92 bool InputEventSampler::IsDurationMatched()
93 {
94 std::lock_guard<std::mutex> guard(rawEventMutex_);
95 auto currentTimeStamp = std::chrono::steady_clock::now();
96 if (rawEvents_.empty()) {
97 return false;
98 }
99 auto headEvent = rawEvents_.front();
100 if (auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
101 currentTimeStamp - headEvent.rcvdTimeStamp).count(); duration >= idealEventIntervalMS_) {
102 FI_HILOGD("Current timeSpan:%{public}lld, matched condition", duration);
103 return true;
104 }
105 return false;
106 }
107
IsOffsetMatched(std::shared_ptr<MMI::PointerEvent> pointerEvent)108 bool InputEventSampler::IsOffsetMatched(std::shared_ptr<MMI::PointerEvent> pointerEvent)
109 {
110 MMI::PointerEvent::PointerItem item;
111 if (pointerEvent == nullptr) {
112 return false;
113 }
114 if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
115 FI_HILOGE("Corrupted pointerEvent, skip");
116 return false;
117 }
118 auto rawDxSum = prefixRawDxSum_ + item.GetRawDx();
119 auto rawDySum = prefixRawDySum_ + item.GetRawDy();
120 if (abs(rawDxSum) >= rawDxThreshold_ || abs(rawDySum) >= rawDyThreshold_) {
121 FI_HILOGD("Current rawDxSum:%{public}d, rawDySum:%{public}d, match offset condition", rawDxSum, rawDySum);
122 return true;
123 }
124 return false;
125 }
126
IsRawEventsExpired()127 bool InputEventSampler::IsRawEventsExpired()
128 {
129 std::lock_guard<std::mutex> guard(rawEventMutex_);
130 if (rawEvents_.empty()) {
131 FI_HILOGD("Raw event expired,skip");
132 return false;
133 }
134 auto lastEvent = rawEvents_.back();
135 if (lastEvent.pointerEvent == nullptr) {
136 return false;
137 }
138 auto currentTimeStamp = std::chrono::steady_clock::now();
139 if (auto duration = std::chrono::duration_cast<std::chrono::milliseconds> (
140 currentTimeStamp - lastEvent.rcvdTimeStamp).count() > expiredIntervalMS_) {
141 FI_HILOGD("Raw event expired, action:%{public}d", duration);
142 return true;
143 }
144 return false;
145 }
146
IsSkipNeeded(std::shared_ptr<MMI::PointerEvent> pointerEvent)147 bool InputEventSampler::IsSkipNeeded(std::shared_ptr<MMI::PointerEvent> pointerEvent)
148 {
149 if (pointerEvent == nullptr) {
150 FI_HILOGW("Null pointerEvent, skip");
151 return true;
152 }
153 if (auto pointerAction = pointerEvent->GetPointerAction();
154 filterPointerActions_.find(pointerAction) != filterPointerActions_.end()) {
155 FI_HILOGI("Unexpected pointerEvent, action:%{public}d, skip", pointerAction);
156 return true;
157 }
158 return false;
159 }
160
AggregateRawEvents(std::shared_ptr<MMI::PointerEvent> pointerEvent)161 void InputEventSampler::AggregateRawEvents(std::shared_ptr<MMI::PointerEvent> pointerEvent)
162 {
163 MMI::PointerEvent::PointerItem item;
164 CHKPV(pointerEvent);
165 if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
166 FI_HILOGW("Corrupted pointerEvent, skip");
167 return;
168 }
169 auto pointerId = item.GetPointerId();
170 auto sampledRawDx = prefixRawDxSum_ + item.GetRawDx();
171 auto sampledRawDy = prefixRawDySum_ + item.GetRawDy();
172
173 MMI::PointerEvent::PointerItem aggregatedItem = item;
174 aggregatedItem.SetRawDx(sampledRawDx);
175 aggregatedItem.SetRawDy(sampledRawDy);
176
177 pointerEvent->UpdatePointerItem(pointerId, aggregatedItem);
178 {
179 std::lock_guard<std::mutex> guard(sampledEventMutex_);
180 sampledEvents_.push(pointerEvent);
181 }
182 ClearRawEvents();
183 prefixRawDxSum_ = 0;
184 prefixRawDySum_ = 0;
185 }
186
HandleTouchPadEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)187 void InputEventSampler::HandleTouchPadEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
188 {
189 std::lock_guard<std::mutex> guard(sampledEventMutex_);
190 sampledEvents_.push(pointerEvent);
191 }
192
HandleMouseEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)193 void InputEventSampler::HandleMouseEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
194 {
195 CHKPV(pointerEvent);
196 if (IsSpecialEvent(pointerEvent) || IsDurationMatched()) {
197 AggregateRawEvents(pointerEvent);
198 } else {
199 MMI::PointerEvent::PointerItem item;
200 if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
201 FI_HILOGE("Corrupted pointerEvent, skip");
202 return;
203 }
204 prefixRawDxSum_ += item.GetRawDx();
205 prefixRawDySum_ += item.GetRawDy();
206 {
207 std::lock_guard<std::mutex> guard(rawEventMutex_);
208 rawEvents_.push({pointerEvent, std::chrono::steady_clock::now()});
209 FI_HILOGD("Raw events count:%{public}zu", rawEvents_.size());
210 }
211 }
212 }
213
OnDownSampledEvent()214 void InputEventSampler::OnDownSampledEvent()
215 {
216 std::lock_guard<std::mutex> guard(sampledEventMutex_);
217 FI_HILOGD("Sampled events existed count:%{public}zu", sampledEvents_.size());
218 while (!sampledEvents_.empty()) {
219 auto curEvent = sampledEvents_.front();
220 sampledEvents_.pop();
221 CHKPV(pointerEventHandler_);
222 pointerEventHandler_(curEvent);
223 }
224 }
225
ClearRawEvents()226 void InputEventSampler::ClearRawEvents()
227 {
228 std::lock_guard<std::mutex> guard(rawEventMutex_);
229 auto rawEvents = std::queue<RawEvent>();
230 rawEvents_ = rawEvents;
231 }
232 } // namespace Cooperate
233 } // namespace DeviceStatus
234 } // namespace Msdp
235 } // namespace OHOS