1c29fa5a6Sopenharmony_ci/* 2c29fa5a6Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License. 5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at 6c29fa5a6Sopenharmony_ci * 7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8c29fa5a6Sopenharmony_ci * 9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and 13c29fa5a6Sopenharmony_ci * limitations under the License. 14c29fa5a6Sopenharmony_ci */ 15c29fa5a6Sopenharmony_ci 16c29fa5a6Sopenharmony_ci#ifndef EVENT_RESAMPLE_H 17c29fa5a6Sopenharmony_ci#define EVENT_RESAMPLE_H 18c29fa5a6Sopenharmony_ci 19c29fa5a6Sopenharmony_ci#include <vector> 20c29fa5a6Sopenharmony_ci#include <map> 21c29fa5a6Sopenharmony_ci#include <list> 22c29fa5a6Sopenharmony_ci 23c29fa5a6Sopenharmony_ci#include "proto.h" 24c29fa5a6Sopenharmony_ci#include "singleton.h" 25c29fa5a6Sopenharmony_ci#include "nocopyable.h" 26c29fa5a6Sopenharmony_ci#include "error_multimodal.h" 27c29fa5a6Sopenharmony_ci#include "pointer_event.h" 28c29fa5a6Sopenharmony_ci 29c29fa5a6Sopenharmony_cinamespace OHOS { 30c29fa5a6Sopenharmony_cinamespace MMI { 31c29fa5a6Sopenharmony_ciclass EventResample final { 32c29fa5a6Sopenharmony_ci DECLARE_DELAYED_SINGLETON(EventResample); 33c29fa5a6Sopenharmony_ci 34c29fa5a6Sopenharmony_cipublic: 35c29fa5a6Sopenharmony_ci DISALLOW_COPY_AND_MOVE(EventResample); 36c29fa5a6Sopenharmony_ci std::shared_ptr<PointerEvent> OnEventConsume(std::shared_ptr<PointerEvent> pointerEvent, 37c29fa5a6Sopenharmony_ci int64_t frameTime, ErrCode &status); 38c29fa5a6Sopenharmony_ci std::shared_ptr<PointerEvent> GetPointerEvent(); 39c29fa5a6Sopenharmony_ci 40c29fa5a6Sopenharmony_ci void PrintfDeviceName(); 41c29fa5a6Sopenharmony_ci 42c29fa5a6Sopenharmony_ci // Microseconds per milliseconds. 43c29fa5a6Sopenharmony_ci static constexpr int64_t US_PER_MS = 1000; 44c29fa5a6Sopenharmony_ci 45c29fa5a6Sopenharmony_ci // Latency added during resampling. A few milliseconds doesn't hurt much but 46c29fa5a6Sopenharmony_ci // reduces the impact of mispredicted touch positions. 47c29fa5a6Sopenharmony_ci static constexpr int64_t RESAMPLE_LATENCY = 5 * US_PER_MS; 48c29fa5a6Sopenharmony_ci 49c29fa5a6Sopenharmony_ci // Minimum time difference between consecutive samples before attempting to resample. 50c29fa5a6Sopenharmony_ci static constexpr int64_t RESAMPLE_MIN_DELTA = 2 * US_PER_MS; 51c29fa5a6Sopenharmony_ci 52c29fa5a6Sopenharmony_ci // Maximum time difference between consecutive samples before attempting to resample 53c29fa5a6Sopenharmony_ci // by extrapolation. 54c29fa5a6Sopenharmony_ci static constexpr int64_t RESAMPLE_MAX_DELTA = 20 * US_PER_MS; 55c29fa5a6Sopenharmony_ci 56c29fa5a6Sopenharmony_ci // Maximum time to predict forward from the last known state, to avoid predicting too 57c29fa5a6Sopenharmony_ci // far into the future. This time is further bounded by 50% of the last time delta. 58c29fa5a6Sopenharmony_ci static constexpr int64_t RESAMPLE_MAX_PREDICTION = 4 * US_PER_MS; 59c29fa5a6Sopenharmony_ci 60c29fa5a6Sopenharmony_ci // Maximum history size to store samples 61c29fa5a6Sopenharmony_ci static constexpr size_t HISTORY_SIZE_MAX = 2; 62c29fa5a6Sopenharmony_ci 63c29fa5a6Sopenharmony_ciprivate: 64c29fa5a6Sopenharmony_ci 65c29fa5a6Sopenharmony_ci struct Pointer { 66c29fa5a6Sopenharmony_ci int32_t coordX; 67c29fa5a6Sopenharmony_ci int32_t coordY; 68c29fa5a6Sopenharmony_ci int32_t toolType; 69c29fa5a6Sopenharmony_ci int32_t id; 70c29fa5a6Sopenharmony_ci 71c29fa5a6Sopenharmony_ci void CopyFrom(const Pointer& other) 72c29fa5a6Sopenharmony_ci { 73c29fa5a6Sopenharmony_ci coordX = other.coordX; 74c29fa5a6Sopenharmony_ci coordY = other.coordY; 75c29fa5a6Sopenharmony_ci toolType = other.toolType; 76c29fa5a6Sopenharmony_ci id = other.id; 77c29fa5a6Sopenharmony_ci } 78c29fa5a6Sopenharmony_ci 79c29fa5a6Sopenharmony_ci void Reset() 80c29fa5a6Sopenharmony_ci { 81c29fa5a6Sopenharmony_ci coordX = 0; 82c29fa5a6Sopenharmony_ci coordY = 0; 83c29fa5a6Sopenharmony_ci toolType = 0; 84c29fa5a6Sopenharmony_ci id = 0; 85c29fa5a6Sopenharmony_ci } 86c29fa5a6Sopenharmony_ci }; 87c29fa5a6Sopenharmony_ci 88c29fa5a6Sopenharmony_ci struct MotionEvent { 89c29fa5a6Sopenharmony_ci std::map<uint32_t, Pointer> pointers; 90c29fa5a6Sopenharmony_ci int64_t actionTime { 0 }; 91c29fa5a6Sopenharmony_ci uint32_t pointerCount { 0 }; 92c29fa5a6Sopenharmony_ci int32_t sourceType { PointerEvent::SOURCE_TYPE_UNKNOWN }; 93c29fa5a6Sopenharmony_ci int32_t pointerAction { PointerEvent::POINTER_ACTION_UNKNOWN }; 94c29fa5a6Sopenharmony_ci int32_t deviceId { 0 }; 95c29fa5a6Sopenharmony_ci int32_t eventId { 0 }; 96c29fa5a6Sopenharmony_ci 97c29fa5a6Sopenharmony_ci void Reset() 98c29fa5a6Sopenharmony_ci { 99c29fa5a6Sopenharmony_ci pointers.clear(); 100c29fa5a6Sopenharmony_ci actionTime = 0; 101c29fa5a6Sopenharmony_ci pointerCount = 0; 102c29fa5a6Sopenharmony_ci sourceType = PointerEvent::SOURCE_TYPE_UNKNOWN; 103c29fa5a6Sopenharmony_ci pointerAction = PointerEvent::POINTER_ACTION_UNKNOWN; 104c29fa5a6Sopenharmony_ci deviceId = 0; 105c29fa5a6Sopenharmony_ci eventId = 0; 106c29fa5a6Sopenharmony_ci } 107c29fa5a6Sopenharmony_ci 108c29fa5a6Sopenharmony_ci void InitializeFrom(MotionEvent& other) 109c29fa5a6Sopenharmony_ci { 110c29fa5a6Sopenharmony_ci for (auto &it : other.pointers) { 111c29fa5a6Sopenharmony_ci pointers[it.first] = it.second; 112c29fa5a6Sopenharmony_ci } 113c29fa5a6Sopenharmony_ci actionTime = other.actionTime; 114c29fa5a6Sopenharmony_ci pointerCount = other.pointerCount; 115c29fa5a6Sopenharmony_ci deviceId = other.deviceId; 116c29fa5a6Sopenharmony_ci sourceType = other.sourceType; 117c29fa5a6Sopenharmony_ci pointerAction = other.pointerAction; 118c29fa5a6Sopenharmony_ci eventId = other.eventId; 119c29fa5a6Sopenharmony_ci } 120c29fa5a6Sopenharmony_ci 121c29fa5a6Sopenharmony_ci void InitializeFrom(std::shared_ptr<PointerEvent> event) 122c29fa5a6Sopenharmony_ci { 123c29fa5a6Sopenharmony_ci actionTime = event->GetActionTime(); 124c29fa5a6Sopenharmony_ci deviceId = event->GetDeviceId(); 125c29fa5a6Sopenharmony_ci sourceType = event->GetSourceType(); 126c29fa5a6Sopenharmony_ci pointerAction = event->GetPointerAction(); 127c29fa5a6Sopenharmony_ci eventId = event->GetId(); 128c29fa5a6Sopenharmony_ci 129c29fa5a6Sopenharmony_ci std::vector<int32_t> pointerIds = event->GetPointerIds(); 130c29fa5a6Sopenharmony_ci pointerCount = 0; 131c29fa5a6Sopenharmony_ci for (auto &it : pointerIds) { 132c29fa5a6Sopenharmony_ci PointerEvent::PointerItem item; 133c29fa5a6Sopenharmony_ci if (event->GetPointerItem(it, item)) { 134c29fa5a6Sopenharmony_ci Pointer pointer; 135c29fa5a6Sopenharmony_ci pointer.coordX = item.GetDisplayX(); 136c29fa5a6Sopenharmony_ci pointer.coordY = item.GetDisplayY(); 137c29fa5a6Sopenharmony_ci pointer.toolType = item.GetToolType(); 138c29fa5a6Sopenharmony_ci pointer.id = item.GetPointerId(); 139c29fa5a6Sopenharmony_ci pointers[pointer.id] = pointer; 140c29fa5a6Sopenharmony_ci pointerCount++; 141c29fa5a6Sopenharmony_ci } 142c29fa5a6Sopenharmony_ci } 143c29fa5a6Sopenharmony_ci } 144c29fa5a6Sopenharmony_ci }; 145c29fa5a6Sopenharmony_ci 146c29fa5a6Sopenharmony_ci struct Batch { 147c29fa5a6Sopenharmony_ci std::vector<MotionEvent> samples; 148c29fa5a6Sopenharmony_ci }; 149c29fa5a6Sopenharmony_ci std::vector<Batch> batches_; 150c29fa5a6Sopenharmony_ci 151c29fa5a6Sopenharmony_ci struct History { 152c29fa5a6Sopenharmony_ci std::map<uint32_t, Pointer> pointers; 153c29fa5a6Sopenharmony_ci int64_t actionTime { 0 }; 154c29fa5a6Sopenharmony_ci 155c29fa5a6Sopenharmony_ci void InitializeFrom(const MotionEvent &event) 156c29fa5a6Sopenharmony_ci { 157c29fa5a6Sopenharmony_ci actionTime = event.actionTime; 158c29fa5a6Sopenharmony_ci for (auto &it : event.pointers) { 159c29fa5a6Sopenharmony_ci pointers[it.first] = it.second; 160c29fa5a6Sopenharmony_ci } 161c29fa5a6Sopenharmony_ci } 162c29fa5a6Sopenharmony_ci 163c29fa5a6Sopenharmony_ci void InitializeFrom(const History &other) 164c29fa5a6Sopenharmony_ci { 165c29fa5a6Sopenharmony_ci actionTime = other.actionTime; 166c29fa5a6Sopenharmony_ci for (auto &it : other.pointers) { 167c29fa5a6Sopenharmony_ci pointers[it.first] = it.second; 168c29fa5a6Sopenharmony_ci } 169c29fa5a6Sopenharmony_ci } 170c29fa5a6Sopenharmony_ci 171c29fa5a6Sopenharmony_ci const Pointer& GetPointerById(uint32_t id) const 172c29fa5a6Sopenharmony_ci { 173c29fa5a6Sopenharmony_ci auto item = pointers.find(id); 174c29fa5a6Sopenharmony_ci return item->second; 175c29fa5a6Sopenharmony_ci } 176c29fa5a6Sopenharmony_ci 177c29fa5a6Sopenharmony_ci bool HasPointerId(uint32_t id) const 178c29fa5a6Sopenharmony_ci { 179c29fa5a6Sopenharmony_ci auto item = pointers.find(id); 180c29fa5a6Sopenharmony_ci if (item != pointers.end()) { 181c29fa5a6Sopenharmony_ci return true; 182c29fa5a6Sopenharmony_ci } else { 183c29fa5a6Sopenharmony_ci return false; 184c29fa5a6Sopenharmony_ci } 185c29fa5a6Sopenharmony_ci } 186c29fa5a6Sopenharmony_ci }; 187c29fa5a6Sopenharmony_ci 188c29fa5a6Sopenharmony_ci struct TouchState { 189c29fa5a6Sopenharmony_ci int32_t deviceId; 190c29fa5a6Sopenharmony_ci int32_t source; 191c29fa5a6Sopenharmony_ci size_t historyCurrent; 192c29fa5a6Sopenharmony_ci size_t historySize; 193c29fa5a6Sopenharmony_ci History history[HISTORY_SIZE_MAX]; 194c29fa5a6Sopenharmony_ci History lastResample; 195c29fa5a6Sopenharmony_ci 196c29fa5a6Sopenharmony_ci void Initialize(int32_t deviceId, int32_t source) 197c29fa5a6Sopenharmony_ci { 198c29fa5a6Sopenharmony_ci this->deviceId = deviceId; 199c29fa5a6Sopenharmony_ci this->source = source; 200c29fa5a6Sopenharmony_ci historyCurrent = 0; 201c29fa5a6Sopenharmony_ci historySize = 0; 202c29fa5a6Sopenharmony_ci lastResample.actionTime = 0; 203c29fa5a6Sopenharmony_ci } 204c29fa5a6Sopenharmony_ci 205c29fa5a6Sopenharmony_ci void AddHistory(const MotionEvent &event) 206c29fa5a6Sopenharmony_ci { 207c29fa5a6Sopenharmony_ci historyCurrent ^= 1; 208c29fa5a6Sopenharmony_ci if (historySize < HISTORY_SIZE_MAX) { 209c29fa5a6Sopenharmony_ci historySize += 1; 210c29fa5a6Sopenharmony_ci } 211c29fa5a6Sopenharmony_ci history[historyCurrent].InitializeFrom(event); 212c29fa5a6Sopenharmony_ci } 213c29fa5a6Sopenharmony_ci 214c29fa5a6Sopenharmony_ci const History* GetHistory(size_t idx) const 215c29fa5a6Sopenharmony_ci { 216c29fa5a6Sopenharmony_ci return &history[(historyCurrent + idx) & 1]; 217c29fa5a6Sopenharmony_ci } 218c29fa5a6Sopenharmony_ci 219c29fa5a6Sopenharmony_ci bool RecentCoordinatesAreIdentical(uint32_t id) const 220c29fa5a6Sopenharmony_ci { 221c29fa5a6Sopenharmony_ci // Return true if the two most recently received "raw" coordinates are identical 222c29fa5a6Sopenharmony_ci if (historySize < HISTORY_SIZE_MAX) { 223c29fa5a6Sopenharmony_ci return false; 224c29fa5a6Sopenharmony_ci } 225c29fa5a6Sopenharmony_ci if (!GetHistory(0)->HasPointerId(id) || !GetHistory(1)->HasPointerId(id)) { 226c29fa5a6Sopenharmony_ci return false; 227c29fa5a6Sopenharmony_ci } 228c29fa5a6Sopenharmony_ci float currentX = GetHistory(0)->GetPointerById(id).coordX; 229c29fa5a6Sopenharmony_ci float currentY = GetHistory(0)->GetPointerById(id).coordY; 230c29fa5a6Sopenharmony_ci float previousX = GetHistory(1)->GetPointerById(id).coordX; 231c29fa5a6Sopenharmony_ci float previousY = GetHistory(1)->GetPointerById(id).coordY; 232c29fa5a6Sopenharmony_ci if (currentX == previousX && currentY == previousY) { 233c29fa5a6Sopenharmony_ci return true; 234c29fa5a6Sopenharmony_ci } 235c29fa5a6Sopenharmony_ci return false; 236c29fa5a6Sopenharmony_ci } 237c29fa5a6Sopenharmony_ci }; 238c29fa5a6Sopenharmony_ci std::vector<TouchState> touchStates_; 239c29fa5a6Sopenharmony_ci 240c29fa5a6Sopenharmony_ci MotionEvent inputEvent_; 241c29fa5a6Sopenharmony_ci MotionEvent outputEvent_; 242c29fa5a6Sopenharmony_ci int64_t frameTime_ {-1}; 243c29fa5a6Sopenharmony_ci bool resampleTouch_ {true}; 244c29fa5a6Sopenharmony_ci std::shared_ptr<PointerEvent> pointerEvent_ {nullptr}; 245c29fa5a6Sopenharmony_ci 246c29fa5a6Sopenharmony_ci void EventDump(const char *msg, MotionEvent &event); 247c29fa5a6Sopenharmony_ci ErrCode InitializeInputEvent(std::shared_ptr<PointerEvent> pointerEvent, int64_t frameTime); 248c29fa5a6Sopenharmony_ci bool UpdateBatch(MotionEvent** outEvent, ErrCode &result); 249c29fa5a6Sopenharmony_ci void UpdatePointerEvent(MotionEvent* outEvent); 250c29fa5a6Sopenharmony_ci ErrCode ConsumeBatch(int64_t frameTime, MotionEvent** outEvent); 251c29fa5a6Sopenharmony_ci ErrCode ConsumeSamples(Batch& batch, size_t count, MotionEvent** outEvent); 252c29fa5a6Sopenharmony_ci void AddSample(MotionEvent* outEvent, const MotionEvent* event); 253c29fa5a6Sopenharmony_ci void UpdateTouchState(MotionEvent &event); 254c29fa5a6Sopenharmony_ci void ResampleTouchState(int64_t sampleTime, MotionEvent* event, const MotionEvent* next); 255c29fa5a6Sopenharmony_ci void ResampleCoordinates(int64_t sampleTime, MotionEvent* event, TouchState &touchState, 256c29fa5a6Sopenharmony_ci const History* current, const History* other, float alpha); 257c29fa5a6Sopenharmony_ci ssize_t FindBatch(int32_t deviceId, int32_t source) const; 258c29fa5a6Sopenharmony_ci ssize_t FindTouchState(int32_t deviceId, int32_t source) const; 259c29fa5a6Sopenharmony_ci bool CanAddSample(const Batch &batch, MotionEvent &event); 260c29fa5a6Sopenharmony_ci void RewriteMessage(TouchState& state, MotionEvent &event); 261c29fa5a6Sopenharmony_ci ssize_t FindSampleNoLaterThan(const Batch& batch, int64_t time); 262c29fa5a6Sopenharmony_ci bool ShouldResampleTool(int32_t toolType); 263c29fa5a6Sopenharmony_ci std::pair<int32_t, int32_t> TransformSampleWindowXY(std::shared_ptr<PointerEvent> pointerEvent, 264c29fa5a6Sopenharmony_ci PointerEvent::PointerItem &item, int32_t logicX, int32_t logicY); 265c29fa5a6Sopenharmony_ci}; 266c29fa5a6Sopenharmony_ci 267c29fa5a6Sopenharmony_ciinline static float CalcCoord(float a, float b, float alpha) 268c29fa5a6Sopenharmony_ci{ 269c29fa5a6Sopenharmony_ci return a + alpha * (b - a); 270c29fa5a6Sopenharmony_ci} 271c29fa5a6Sopenharmony_ci 272c29fa5a6Sopenharmony_ci#define EventResampleHdr ::OHOS::DelayedSingleton<EventResample>::GetInstance() 273c29fa5a6Sopenharmony_ci} // namespace MMI 274c29fa5a6Sopenharmony_ci} // namespace OHOS 275c29fa5a6Sopenharmony_ci#endif // EVENT_RESAMPLE_H 276