• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(); duration > expiredIntervalMS_) {
141         FI_HILOGD("Raw event expired, action:%{public}lld", 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     UpdateAggregationTimeStamp();
184     prefixRawDxSum_ = 0;
185     prefixRawDySum_ = 0;
186 }
187 
HandleTouchPadEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)188 void InputEventSampler::HandleTouchPadEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
189 {
190     std::lock_guard<std::mutex> guard(sampledEventMutex_);
191     sampledEvents_.push(pointerEvent);
192 }
193 
HandleMouseEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)194 void InputEventSampler::HandleMouseEvent(std::shared_ptr<MMI::PointerEvent> pointerEvent)
195 {
196     CHKPV(pointerEvent);
197     if (IsSpecialEvent(pointerEvent) || IsAggregationIntervalMatched() || IsDurationMatched()) {
198         AggregateRawEvents(pointerEvent);
199     } else {
200         MMI::PointerEvent::PointerItem item;
201         if (!pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), item)) {
202             FI_HILOGE("Corrupted pointerEvent, skip");
203             return;
204         }
205         prefixRawDxSum_ += item.GetRawDx();
206         prefixRawDySum_ += item.GetRawDy();
207         {
208             std::lock_guard<std::mutex> guard(rawEventMutex_);
209             rawEvents_.push({pointerEvent, std::chrono::steady_clock::now()});
210             FI_HILOGD("Raw events count:%{public}zu", rawEvents_.size());
211         }
212     }
213 }
214 
OnDownSampledEvent()215 void InputEventSampler::OnDownSampledEvent()
216 {
217     std::lock_guard<std::mutex> guard(sampledEventMutex_);
218     FI_HILOGD("Sampled events existed count:%{public}zu", sampledEvents_.size());
219     while (!sampledEvents_.empty()) {
220         auto curEvent = sampledEvents_.front();
221         sampledEvents_.pop();
222         CHKPV(pointerEventHandler_);
223         pointerEventHandler_(curEvent);
224     }
225 }
226 
ClearRawEvents()227 void InputEventSampler::ClearRawEvents()
228 {
229     std::lock_guard<std::mutex> guard(rawEventMutex_);
230     auto rawEvents = std::queue<RawEvent>();
231     rawEvents_ = rawEvents;
232 }
233 
UpdateAggregationTimeStamp()234 void InputEventSampler::UpdateAggregationTimeStamp()
235 {
236     std::lock_guard<std::mutex> guard(aggregationTimeStampMutex_);
237     aggregationTimeStamp_ = std::chrono::steady_clock::now();
238 }
239 
IsAggregationIntervalMatched()240 bool InputEventSampler::IsAggregationIntervalMatched()
241 {
242     std::lock_guard<std::mutex> guard(aggregationTimeStampMutex_);
243     if (auto duration = std::chrono::duration_cast<std::chrono::milliseconds> (
244         std::chrono::steady_clock::now() - aggregationTimeStamp_).count(); duration >= idealEventIntervalMS_) {
245         FI_HILOGD("Aggregation interval matched, duration:%{public}lld", duration);
246         return true;
247     }
248     return false;
249 }
250 
251 } // namespace Cooperate
252 } // namespace DeviceStatus
253 } // namespace Msdp
254 } // namespace OHOS