1c29fa5a6Sopenharmony_ci/* 2c29fa5a6Sopenharmony_ci * Copyright (c) 2021-2024 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#include "event_resample.h" 17c29fa5a6Sopenharmony_ci 18c29fa5a6Sopenharmony_ci#include "event_log_helper.h" 19c29fa5a6Sopenharmony_ci#include "input_device_manager.h" 20c29fa5a6Sopenharmony_ci#include "i_input_windows_manager.h" 21c29fa5a6Sopenharmony_ci#include "mmi_log.h" 22c29fa5a6Sopenharmony_ci#include "util.h" 23c29fa5a6Sopenharmony_ci 24c29fa5a6Sopenharmony_ci#undef MMI_LOG_DOMAIN 25c29fa5a6Sopenharmony_ci#define MMI_LOG_DOMAIN MMI_LOG_SERVER 26c29fa5a6Sopenharmony_ci#undef MMI_LOG_TAG 27c29fa5a6Sopenharmony_ci#define MMI_LOG_TAG "EventResample" 28c29fa5a6Sopenharmony_ci 29c29fa5a6Sopenharmony_cinamespace OHOS { 30c29fa5a6Sopenharmony_cinamespace MMI { 31c29fa5a6Sopenharmony_ciEventResample::EventResample(){}; 32c29fa5a6Sopenharmony_ciEventResample::~EventResample(){}; 33c29fa5a6Sopenharmony_ci 34c29fa5a6Sopenharmony_cistd::shared_ptr<PointerEvent> EventResample::OnEventConsume(std::shared_ptr<PointerEvent> pointerEvent, 35c29fa5a6Sopenharmony_ci int64_t frameTime, ErrCode &status) 36c29fa5a6Sopenharmony_ci{ 37c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 38c29fa5a6Sopenharmony_ci MotionEvent* outEvent = nullptr; 39c29fa5a6Sopenharmony_ci ErrCode result = ERR_OK; 40c29fa5a6Sopenharmony_ci 41c29fa5a6Sopenharmony_ci status = ERR_OK; 42c29fa5a6Sopenharmony_ci if (ERR_OK != InitializeInputEvent(pointerEvent, frameTime)) { 43c29fa5a6Sopenharmony_ci status = ERR_WOULD_BLOCK; 44c29fa5a6Sopenharmony_ci return pointerEvent; 45c29fa5a6Sopenharmony_ci } 46c29fa5a6Sopenharmony_ci 47c29fa5a6Sopenharmony_ci do { 48c29fa5a6Sopenharmony_ci // All events are dispathed so consume batches 49c29fa5a6Sopenharmony_ci if (PointerEvent::POINTER_ACTION_UNKNOWN == inputEvent_.pointerAction) { 50c29fa5a6Sopenharmony_ci result = ConsumeBatch(frameTime_, &outEvent); 51c29fa5a6Sopenharmony_ci frameTime_ = 0; 52c29fa5a6Sopenharmony_ci if ((ERR_OK == result) && (nullptr != outEvent)) { 53c29fa5a6Sopenharmony_ci status = result; 54c29fa5a6Sopenharmony_ci break; 55c29fa5a6Sopenharmony_ci } else { 56c29fa5a6Sopenharmony_ci status = result; 57c29fa5a6Sopenharmony_ci return nullptr; 58c29fa5a6Sopenharmony_ci } 59c29fa5a6Sopenharmony_ci } 60c29fa5a6Sopenharmony_ci 61c29fa5a6Sopenharmony_ci // Add event into batch 62c29fa5a6Sopenharmony_ci if (UpdateBatch(&outEvent, result)) { 63c29fa5a6Sopenharmony_ci break; 64c29fa5a6Sopenharmony_ci } 65c29fa5a6Sopenharmony_ci 66c29fa5a6Sopenharmony_ci // Update touch state object 67c29fa5a6Sopenharmony_ci EventDump("UpdateTouchState", inputEvent_); 68c29fa5a6Sopenharmony_ci EventLogHelper::PrintEventData(pointerEvent_, MMI_LOG_HEADER); 69c29fa5a6Sopenharmony_ci PrintfDeviceName(); 70c29fa5a6Sopenharmony_ci UpdateTouchState(inputEvent_); 71c29fa5a6Sopenharmony_ci return pointerEvent_; 72c29fa5a6Sopenharmony_ci } while (0); 73c29fa5a6Sopenharmony_ci 74c29fa5a6Sopenharmony_ci if ((ERR_OK == result) && (nullptr != outEvent)) { 75c29fa5a6Sopenharmony_ci // Update pointer event 76c29fa5a6Sopenharmony_ci UpdatePointerEvent(outEvent); 77c29fa5a6Sopenharmony_ci EventLogHelper::PrintEventData(pointerEvent_, MMI_LOG_HEADER); 78c29fa5a6Sopenharmony_ci PrintfDeviceName(); 79c29fa5a6Sopenharmony_ci return pointerEvent_; 80c29fa5a6Sopenharmony_ci } 81c29fa5a6Sopenharmony_ci 82c29fa5a6Sopenharmony_ci return nullptr; 83c29fa5a6Sopenharmony_ci} 84c29fa5a6Sopenharmony_ci 85c29fa5a6Sopenharmony_cistd::shared_ptr<PointerEvent> EventResample::GetPointerEvent() 86c29fa5a6Sopenharmony_ci{ 87c29fa5a6Sopenharmony_ci return pointerEvent_; 88c29fa5a6Sopenharmony_ci} 89c29fa5a6Sopenharmony_ci 90c29fa5a6Sopenharmony_civoid EventResample::EventDump(const char *msg, MotionEvent &event) 91c29fa5a6Sopenharmony_ci{ 92c29fa5a6Sopenharmony_ci MMI_HILOGD("%{public}s: pointerAction:%{public}d, actionTime:%{public}" PRId64 ", pointerCount:%{public}d," 93c29fa5a6Sopenharmony_ci "sourceType:%{public}d, deviceId:%{public}d, eventId:%{public}d", 94c29fa5a6Sopenharmony_ci msg, event.pointerAction, event.actionTime, event.pointerCount, 95c29fa5a6Sopenharmony_ci event.sourceType, event.deviceId, event.eventId); 96c29fa5a6Sopenharmony_ci for (auto &it : event.pointers) { 97c29fa5a6Sopenharmony_ci MMI_HILOGD("ID:%{public}d, coordX:%d, coordY:%d, toolType:%{public}d", 98c29fa5a6Sopenharmony_ci it.second.id, it.second.coordX, it.second.coordY, it.second.toolType); 99c29fa5a6Sopenharmony_ci } 100c29fa5a6Sopenharmony_ci} 101c29fa5a6Sopenharmony_ci 102c29fa5a6Sopenharmony_ciErrCode EventResample::InitializeInputEvent(std::shared_ptr<PointerEvent> pointerEvent, int64_t frameTime) 103c29fa5a6Sopenharmony_ci{ 104c29fa5a6Sopenharmony_ci int32_t pointerAction = PointerEvent::POINTER_ACTION_UNKNOWN; 105c29fa5a6Sopenharmony_ci 106c29fa5a6Sopenharmony_ci if (pointerEvent != nullptr) { 107c29fa5a6Sopenharmony_ci pointerEvent_ = pointerEvent; 108c29fa5a6Sopenharmony_ci } 109c29fa5a6Sopenharmony_ci 110c29fa5a6Sopenharmony_ci if (frameTime_ <= 0) { 111c29fa5a6Sopenharmony_ci if (0 != frameTime) { 112c29fa5a6Sopenharmony_ci frameTime_ = frameTime; 113c29fa5a6Sopenharmony_ci } else if (nullptr != pointerEvent) { 114c29fa5a6Sopenharmony_ci frameTime_ = GetSysClockTime(); 115c29fa5a6Sopenharmony_ci } else { 116c29fa5a6Sopenharmony_ci frameTime_ = 0; 117c29fa5a6Sopenharmony_ci } 118c29fa5a6Sopenharmony_ci } 119c29fa5a6Sopenharmony_ci 120c29fa5a6Sopenharmony_ci // Check that event can be consumed and initialize motion event. 121c29fa5a6Sopenharmony_ci if (nullptr != pointerEvent) { 122c29fa5a6Sopenharmony_ci EventLogHelper::PrintEventData(pointerEvent_, MMI_LOG_HEADER); 123c29fa5a6Sopenharmony_ci PrintfDeviceName(); 124c29fa5a6Sopenharmony_ci pointerAction = pointerEvent->GetPointerAction(); 125c29fa5a6Sopenharmony_ci MMI_HILOGD("pointerAction:%{public}d, actionTime:%{public}" PRId64 " frameTime_:%{public}" PRId64, 126c29fa5a6Sopenharmony_ci pointerAction, pointerEvent->GetActionTime(), frameTime_); 127c29fa5a6Sopenharmony_ci switch (pointerAction) { 128c29fa5a6Sopenharmony_ci case PointerEvent::POINTER_ACTION_DOWN: 129c29fa5a6Sopenharmony_ci case PointerEvent::POINTER_ACTION_MOVE: 130c29fa5a6Sopenharmony_ci case PointerEvent::POINTER_ACTION_UP: 131c29fa5a6Sopenharmony_ci break; 132c29fa5a6Sopenharmony_ci default: { 133c29fa5a6Sopenharmony_ci MotionEvent event; 134c29fa5a6Sopenharmony_ci event.InitializeFrom(pointerEvent); 135c29fa5a6Sopenharmony_ci UpdateTouchState(event); 136c29fa5a6Sopenharmony_ci return ERR_WOULD_BLOCK; 137c29fa5a6Sopenharmony_ci } 138c29fa5a6Sopenharmony_ci } 139c29fa5a6Sopenharmony_ci inputEvent_.Reset(); 140c29fa5a6Sopenharmony_ci inputEvent_.InitializeFrom(pointerEvent); 141c29fa5a6Sopenharmony_ci 142c29fa5a6Sopenharmony_ci EventDump("Input Event", inputEvent_); 143c29fa5a6Sopenharmony_ci } else { 144c29fa5a6Sopenharmony_ci inputEvent_.Reset(); 145c29fa5a6Sopenharmony_ci } 146c29fa5a6Sopenharmony_ci 147c29fa5a6Sopenharmony_ci return ERR_OK; 148c29fa5a6Sopenharmony_ci} 149c29fa5a6Sopenharmony_ci 150c29fa5a6Sopenharmony_cibool EventResample::UpdateBatch(MotionEvent** outEvent, ErrCode &result) 151c29fa5a6Sopenharmony_ci{ 152c29fa5a6Sopenharmony_ci ssize_t batchIndex = FindBatch(inputEvent_.deviceId, inputEvent_.sourceType); 153c29fa5a6Sopenharmony_ci if (batchIndex >= 0) { 154c29fa5a6Sopenharmony_ci Batch& batch = batches_.at(batchIndex); 155c29fa5a6Sopenharmony_ci if (CanAddSample(batch, inputEvent_)) { 156c29fa5a6Sopenharmony_ci batch.samples.push_back(inputEvent_); 157c29fa5a6Sopenharmony_ci MMI_HILOGD("Event added to batch, deviceId:%{public}d, sourceType:%{public}d, pointerAction:%{public}d", 158c29fa5a6Sopenharmony_ci inputEvent_.deviceId, inputEvent_.sourceType, inputEvent_.pointerAction); 159c29fa5a6Sopenharmony_ci return true; 160c29fa5a6Sopenharmony_ci } 161c29fa5a6Sopenharmony_ci } 162c29fa5a6Sopenharmony_ci 163c29fa5a6Sopenharmony_ci // Start a new batch 164c29fa5a6Sopenharmony_ci if (PointerEvent::POINTER_ACTION_MOVE == inputEvent_.pointerAction) { 165c29fa5a6Sopenharmony_ci Batch batch; 166c29fa5a6Sopenharmony_ci batch.samples.push_back(inputEvent_); 167c29fa5a6Sopenharmony_ci batches_.push_back(std::move(batch)); 168c29fa5a6Sopenharmony_ci return true; 169c29fa5a6Sopenharmony_ci } 170c29fa5a6Sopenharmony_ci 171c29fa5a6Sopenharmony_ci return false; 172c29fa5a6Sopenharmony_ci} 173c29fa5a6Sopenharmony_ci 174c29fa5a6Sopenharmony_civoid EventResample::UpdatePointerEvent(MotionEvent* outEvent) 175c29fa5a6Sopenharmony_ci{ 176c29fa5a6Sopenharmony_ci EventDump("Output Event", *outEvent); 177c29fa5a6Sopenharmony_ci pointerEvent_->SetActionTime(outEvent->actionTime); 178c29fa5a6Sopenharmony_ci pointerEvent_->SetPointerAction(outEvent->pointerAction); 179c29fa5a6Sopenharmony_ci pointerEvent_->SetActionTime(outEvent->actionTime); 180c29fa5a6Sopenharmony_ci pointerEvent_->SetId(outEvent->eventId); 181c29fa5a6Sopenharmony_ci 182c29fa5a6Sopenharmony_ci for (auto &it : outEvent->pointers) { 183c29fa5a6Sopenharmony_ci PointerEvent::PointerItem item; 184c29fa5a6Sopenharmony_ci if (pointerEvent_->GetPointerItem(it.first, item)) { 185c29fa5a6Sopenharmony_ci int32_t toolWindowX = item.GetToolWindowX(); 186c29fa5a6Sopenharmony_ci int32_t toolWindowY = item.GetToolWindowY(); 187c29fa5a6Sopenharmony_ci if (EventLogHelper::IsBetaVersion() && !pointerEvent_->HasFlag(InputEvent::EVENT_FLAG_PRIVACY_MODE)) { 188c29fa5a6Sopenharmony_ci MMI_HILOGD("Output event: toolWindowX:%{public}d, toolWindowY:%{public}d", toolWindowX, toolWindowY); 189c29fa5a6Sopenharmony_ci } else { 190c29fa5a6Sopenharmony_ci MMI_HILOGD("Output event: toolWindowX:%d, toolWindowY:%d", toolWindowX, toolWindowY); 191c29fa5a6Sopenharmony_ci } 192c29fa5a6Sopenharmony_ci auto logicX = it.second.coordX; 193c29fa5a6Sopenharmony_ci auto logicY = it.second.coordY; 194c29fa5a6Sopenharmony_ci item.SetDisplayX(logicX); 195c29fa5a6Sopenharmony_ci item.SetDisplayY(logicY); 196c29fa5a6Sopenharmony_ci 197c29fa5a6Sopenharmony_ci auto windowXY = TransformSampleWindowXY(pointerEvent_, item, logicX, logicY); 198c29fa5a6Sopenharmony_ci item.SetWindowX(windowXY.first); 199c29fa5a6Sopenharmony_ci item.SetWindowY(windowXY.second); 200c29fa5a6Sopenharmony_ci 201c29fa5a6Sopenharmony_ci if (PointerEvent::POINTER_ACTION_MOVE == outEvent->pointerAction) { 202c29fa5a6Sopenharmony_ci item.SetPressed(true); 203c29fa5a6Sopenharmony_ci } else if (PointerEvent::POINTER_ACTION_UP == outEvent->pointerAction) { 204c29fa5a6Sopenharmony_ci item.SetPressed(false); 205c29fa5a6Sopenharmony_ci } else { 206c29fa5a6Sopenharmony_ci MMI_HILOGD("Output event:Pointer action:%{public}d", outEvent->pointerAction); 207c29fa5a6Sopenharmony_ci } 208c29fa5a6Sopenharmony_ci pointerEvent_->UpdatePointerItem(it.first, item); 209c29fa5a6Sopenharmony_ci } 210c29fa5a6Sopenharmony_ci } 211c29fa5a6Sopenharmony_ci} 212c29fa5a6Sopenharmony_ci 213c29fa5a6Sopenharmony_cistd::pair<int32_t, int32_t> EventResample::TransformSampleWindowXY(std::shared_ptr<PointerEvent> pointerEvent, 214c29fa5a6Sopenharmony_ci PointerEvent::PointerItem &item, int32_t logicX, int32_t logicY) 215c29fa5a6Sopenharmony_ci{ 216c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 217c29fa5a6Sopenharmony_ci if (pointerEvent == nullptr) { 218c29fa5a6Sopenharmony_ci return {logicX + item.GetToolWindowX(), logicY + item.GetToolWindowY()}; 219c29fa5a6Sopenharmony_ci } 220c29fa5a6Sopenharmony_ci auto windows = WIN_MGR->GetWindowGroupInfoByDisplayId(pointerEvent->GetTargetDisplayId()); 221c29fa5a6Sopenharmony_ci for (const auto &window : windows) { 222c29fa5a6Sopenharmony_ci if (pointerEvent->GetTargetWindowId() == window.id) { 223c29fa5a6Sopenharmony_ci if (window.transform.empty()) { 224c29fa5a6Sopenharmony_ci return {logicX + item.GetToolWindowX(), logicY + item.GetToolWindowY()}; 225c29fa5a6Sopenharmony_ci } 226c29fa5a6Sopenharmony_ci auto windowXY = WIN_MGR->TransformWindowXY(window, logicX, logicY); 227c29fa5a6Sopenharmony_ci auto windowX = static_cast<int32_t>(windowXY.first); 228c29fa5a6Sopenharmony_ci auto windowY = static_cast<int32_t>(windowXY.second); 229c29fa5a6Sopenharmony_ci return {windowX, windowY}; 230c29fa5a6Sopenharmony_ci } 231c29fa5a6Sopenharmony_ci } 232c29fa5a6Sopenharmony_ci return {logicX, logicY}; 233c29fa5a6Sopenharmony_ci} 234c29fa5a6Sopenharmony_ci 235c29fa5a6Sopenharmony_ciErrCode EventResample::ConsumeBatch(int64_t frameTime, MotionEvent** outEvent) 236c29fa5a6Sopenharmony_ci{ 237c29fa5a6Sopenharmony_ci int32_t result = 0; 238c29fa5a6Sopenharmony_ci for (size_t i = batches_.size(); i > 0;) { 239c29fa5a6Sopenharmony_ci i--; 240c29fa5a6Sopenharmony_ci Batch& batch = batches_.at(i); 241c29fa5a6Sopenharmony_ci if (frameTime < 0) { 242c29fa5a6Sopenharmony_ci result = ConsumeSamples(batch, batch.samples.size(), outEvent); 243c29fa5a6Sopenharmony_ci batches_.erase(batches_.begin() + i); 244c29fa5a6Sopenharmony_ci return result; 245c29fa5a6Sopenharmony_ci } 246c29fa5a6Sopenharmony_ci 247c29fa5a6Sopenharmony_ci int64_t sampleTime = frameTime; 248c29fa5a6Sopenharmony_ci if (resampleTouch_) { 249c29fa5a6Sopenharmony_ci sampleTime -= RESAMPLE_LATENCY; 250c29fa5a6Sopenharmony_ci } 251c29fa5a6Sopenharmony_ci ssize_t split = FindSampleNoLaterThan(batch, sampleTime); 252c29fa5a6Sopenharmony_ci if (split < 0) { 253c29fa5a6Sopenharmony_ci continue; 254c29fa5a6Sopenharmony_ci } 255c29fa5a6Sopenharmony_ci 256c29fa5a6Sopenharmony_ci result = ConsumeSamples(batch, split + 1, outEvent); 257c29fa5a6Sopenharmony_ci const MotionEvent* next; 258c29fa5a6Sopenharmony_ci if (batch.samples.empty()) { 259c29fa5a6Sopenharmony_ci batches_.erase(batches_.begin() + i); 260c29fa5a6Sopenharmony_ci next = NULL; 261c29fa5a6Sopenharmony_ci } else { 262c29fa5a6Sopenharmony_ci next = &batch.samples.at(0); 263c29fa5a6Sopenharmony_ci } 264c29fa5a6Sopenharmony_ci if (!result && resampleTouch_) { 265c29fa5a6Sopenharmony_ci ResampleTouchState(sampleTime, static_cast<MotionEvent*>(*outEvent), next); 266c29fa5a6Sopenharmony_ci } 267c29fa5a6Sopenharmony_ci return result; 268c29fa5a6Sopenharmony_ci } 269c29fa5a6Sopenharmony_ci 270c29fa5a6Sopenharmony_ci return ERR_WOULD_BLOCK; 271c29fa5a6Sopenharmony_ci} 272c29fa5a6Sopenharmony_ci 273c29fa5a6Sopenharmony_ciErrCode EventResample::ConsumeSamples(Batch& batch, size_t count, MotionEvent** outEvent) 274c29fa5a6Sopenharmony_ci{ 275c29fa5a6Sopenharmony_ci outputEvent_.Reset(); 276c29fa5a6Sopenharmony_ci 277c29fa5a6Sopenharmony_ci for (size_t i = 0; i < count; i++) { 278c29fa5a6Sopenharmony_ci MotionEvent& event = batch.samples.at(i); 279c29fa5a6Sopenharmony_ci UpdateTouchState(event); 280c29fa5a6Sopenharmony_ci if (i > 0) { 281c29fa5a6Sopenharmony_ci AddSample(&outputEvent_, &event); 282c29fa5a6Sopenharmony_ci } else { 283c29fa5a6Sopenharmony_ci outputEvent_.InitializeFrom(event); 284c29fa5a6Sopenharmony_ci } 285c29fa5a6Sopenharmony_ci } 286c29fa5a6Sopenharmony_ci batch.samples.erase(batch.samples.begin(), batch.samples.begin() + count); 287c29fa5a6Sopenharmony_ci 288c29fa5a6Sopenharmony_ci *outEvent = &outputEvent_; 289c29fa5a6Sopenharmony_ci 290c29fa5a6Sopenharmony_ci return ERR_OK; 291c29fa5a6Sopenharmony_ci} 292c29fa5a6Sopenharmony_ci 293c29fa5a6Sopenharmony_civoid EventResample::AddSample(MotionEvent* outEvent, const MotionEvent* event) 294c29fa5a6Sopenharmony_ci{ 295c29fa5a6Sopenharmony_ci outEvent->actionTime = event->actionTime; 296c29fa5a6Sopenharmony_ci for (auto &it : event->pointers) { 297c29fa5a6Sopenharmony_ci outEvent->pointers[it.first] = it.second; 298c29fa5a6Sopenharmony_ci } 299c29fa5a6Sopenharmony_ci} 300c29fa5a6Sopenharmony_ci 301c29fa5a6Sopenharmony_civoid EventResample::UpdateTouchState(MotionEvent &event) 302c29fa5a6Sopenharmony_ci{ 303c29fa5a6Sopenharmony_ci int32_t deviceId = event.deviceId; 304c29fa5a6Sopenharmony_ci int32_t source = event.sourceType; 305c29fa5a6Sopenharmony_ci 306c29fa5a6Sopenharmony_ci switch (event.pointerAction) { 307c29fa5a6Sopenharmony_ci case PointerEvent::POINTER_ACTION_DOWN: { 308c29fa5a6Sopenharmony_ci ssize_t idx = FindTouchState(deviceId, source); 309c29fa5a6Sopenharmony_ci if (idx < 0) { 310c29fa5a6Sopenharmony_ci TouchState newState; 311c29fa5a6Sopenharmony_ci touchStates_.push_back(newState); 312c29fa5a6Sopenharmony_ci idx = static_cast<ssize_t>(touchStates_.size()) - 1; 313c29fa5a6Sopenharmony_ci } 314c29fa5a6Sopenharmony_ci TouchState& touchState = touchStates_.at(idx); 315c29fa5a6Sopenharmony_ci touchState.Initialize(deviceId, source); 316c29fa5a6Sopenharmony_ci touchState.AddHistory(event); 317c29fa5a6Sopenharmony_ci break; 318c29fa5a6Sopenharmony_ci } 319c29fa5a6Sopenharmony_ci case PointerEvent::POINTER_ACTION_MOVE: { 320c29fa5a6Sopenharmony_ci ssize_t idx = FindTouchState(deviceId, source); 321c29fa5a6Sopenharmony_ci if (idx >= 0) { 322c29fa5a6Sopenharmony_ci TouchState& touchState = touchStates_.at(idx); 323c29fa5a6Sopenharmony_ci touchState.AddHistory(event); 324c29fa5a6Sopenharmony_ci RewriteMessage(touchState, event); 325c29fa5a6Sopenharmony_ci } 326c29fa5a6Sopenharmony_ci break; 327c29fa5a6Sopenharmony_ci } 328c29fa5a6Sopenharmony_ci case PointerEvent::POINTER_ACTION_UP: 329c29fa5a6Sopenharmony_ci default: { 330c29fa5a6Sopenharmony_ci ssize_t idx = FindTouchState(deviceId, source); 331c29fa5a6Sopenharmony_ci if (idx >= 0) { 332c29fa5a6Sopenharmony_ci TouchState& touchState = touchStates_.at(idx); 333c29fa5a6Sopenharmony_ci RewriteMessage(touchState, event); 334c29fa5a6Sopenharmony_ci touchStates_.erase(touchStates_.begin() + idx); 335c29fa5a6Sopenharmony_ci } 336c29fa5a6Sopenharmony_ci frameTime_ = 0; 337c29fa5a6Sopenharmony_ci idx = FindBatch(deviceId, source); 338c29fa5a6Sopenharmony_ci if (idx >= 0) { 339c29fa5a6Sopenharmony_ci batches_.erase(batches_.begin() + idx); 340c29fa5a6Sopenharmony_ci } 341c29fa5a6Sopenharmony_ci break; 342c29fa5a6Sopenharmony_ci } 343c29fa5a6Sopenharmony_ci } 344c29fa5a6Sopenharmony_ci} 345c29fa5a6Sopenharmony_ci 346c29fa5a6Sopenharmony_civoid EventResample::ResampleTouchState(int64_t sampleTime, MotionEvent* event, const MotionEvent* next) 347c29fa5a6Sopenharmony_ci{ 348c29fa5a6Sopenharmony_ci if (!resampleTouch_ || (PointerEvent::SOURCE_TYPE_TOUCHSCREEN != event->sourceType) 349c29fa5a6Sopenharmony_ci || (PointerEvent::POINTER_ACTION_MOVE != event->pointerAction)) { 350c29fa5a6Sopenharmony_ci return; 351c29fa5a6Sopenharmony_ci } 352c29fa5a6Sopenharmony_ci 353c29fa5a6Sopenharmony_ci ssize_t idx = FindTouchState(event->deviceId, event->sourceType); 354c29fa5a6Sopenharmony_ci if (idx < 0) { 355c29fa5a6Sopenharmony_ci return; 356c29fa5a6Sopenharmony_ci } 357c29fa5a6Sopenharmony_ci 358c29fa5a6Sopenharmony_ci TouchState &touchState = touchStates_.at(idx); 359c29fa5a6Sopenharmony_ci if (touchState.historySize < 1) { 360c29fa5a6Sopenharmony_ci return; 361c29fa5a6Sopenharmony_ci } 362c29fa5a6Sopenharmony_ci 363c29fa5a6Sopenharmony_ci // Ensure that the current sample has all of the pointers that need to be reported. 364c29fa5a6Sopenharmony_ci const History* current = touchState.GetHistory(0); 365c29fa5a6Sopenharmony_ci for (auto &it : event->pointers) { 366c29fa5a6Sopenharmony_ci if (!current->HasPointerId(it.first)) { 367c29fa5a6Sopenharmony_ci return; 368c29fa5a6Sopenharmony_ci } 369c29fa5a6Sopenharmony_ci } 370c29fa5a6Sopenharmony_ci 371c29fa5a6Sopenharmony_ci // Find the data to use for resampling. 372c29fa5a6Sopenharmony_ci const History* other; 373c29fa5a6Sopenharmony_ci History future; 374c29fa5a6Sopenharmony_ci float alpha; 375c29fa5a6Sopenharmony_ci if (next) { 376c29fa5a6Sopenharmony_ci // Interpolate between current sample and future sample. 377c29fa5a6Sopenharmony_ci // So current->actionTime <= sampleTime <= future.actionTime. 378c29fa5a6Sopenharmony_ci future.InitializeFrom(*next); 379c29fa5a6Sopenharmony_ci other = &future; 380c29fa5a6Sopenharmony_ci int64_t delta = future.actionTime - current->actionTime; 381c29fa5a6Sopenharmony_ci if (delta < RESAMPLE_MIN_DELTA) { 382c29fa5a6Sopenharmony_ci return; 383c29fa5a6Sopenharmony_ci } 384c29fa5a6Sopenharmony_ci alpha = static_cast<float>(sampleTime - current->actionTime) / delta; 385c29fa5a6Sopenharmony_ci } else if (touchState.historySize >= HISTORY_SIZE_MAX) { 386c29fa5a6Sopenharmony_ci // Extrapolate future sample using current sample and past sample. 387c29fa5a6Sopenharmony_ci // So other->actionTime <= current->actionTime <= sampleTime. 388c29fa5a6Sopenharmony_ci other = touchState.GetHistory(1); 389c29fa5a6Sopenharmony_ci int64_t delta = current->actionTime - other->actionTime; 390c29fa5a6Sopenharmony_ci if (delta < RESAMPLE_MIN_DELTA) { 391c29fa5a6Sopenharmony_ci return; 392c29fa5a6Sopenharmony_ci } else if (delta > RESAMPLE_MAX_DELTA) { 393c29fa5a6Sopenharmony_ci return; 394c29fa5a6Sopenharmony_ci } 395c29fa5a6Sopenharmony_ci int64_t maxPredict = current->actionTime + std::min(delta / 2, RESAMPLE_MAX_PREDICTION); 396c29fa5a6Sopenharmony_ci if (sampleTime > maxPredict) { 397c29fa5a6Sopenharmony_ci sampleTime = maxPredict; 398c29fa5a6Sopenharmony_ci } 399c29fa5a6Sopenharmony_ci alpha = static_cast<float>(current->actionTime - sampleTime) / delta; 400c29fa5a6Sopenharmony_ci } else { 401c29fa5a6Sopenharmony_ci return; 402c29fa5a6Sopenharmony_ci } 403c29fa5a6Sopenharmony_ci 404c29fa5a6Sopenharmony_ci // Resample touch coordinates. 405c29fa5a6Sopenharmony_ci ResampleCoordinates(sampleTime, event, touchState, current, other, alpha); 406c29fa5a6Sopenharmony_ci} 407c29fa5a6Sopenharmony_ci 408c29fa5a6Sopenharmony_civoid EventResample::ResampleCoordinates(int64_t sampleTime, MotionEvent* event, TouchState &touchState, 409c29fa5a6Sopenharmony_ci const History* current, const History* other, float alpha) 410c29fa5a6Sopenharmony_ci{ 411c29fa5a6Sopenharmony_ci History oldLastResample; 412c29fa5a6Sopenharmony_ci oldLastResample.InitializeFrom(touchState.lastResample); 413c29fa5a6Sopenharmony_ci touchState.lastResample.actionTime = sampleTime; 414c29fa5a6Sopenharmony_ci 415c29fa5a6Sopenharmony_ci for (auto &it : event->pointers) { 416c29fa5a6Sopenharmony_ci uint32_t id = it.first; 417c29fa5a6Sopenharmony_ci if (oldLastResample.HasPointerId(id) && touchState.RecentCoordinatesAreIdentical(id)) { 418c29fa5a6Sopenharmony_ci auto lastItem = touchState.lastResample.pointers.find(id); 419c29fa5a6Sopenharmony_ci if (lastItem != touchState.lastResample.pointers.end()) { 420c29fa5a6Sopenharmony_ci auto oldLastItem = oldLastResample.pointers.find(id); 421c29fa5a6Sopenharmony_ci lastItem->second.CopyFrom(oldLastItem->second); 422c29fa5a6Sopenharmony_ci } 423c29fa5a6Sopenharmony_ci continue; 424c29fa5a6Sopenharmony_ci } 425c29fa5a6Sopenharmony_ci 426c29fa5a6Sopenharmony_ci Pointer resampledCoords; 427c29fa5a6Sopenharmony_ci const Pointer& currentCoords = current->GetPointerById(id); 428c29fa5a6Sopenharmony_ci resampledCoords.CopyFrom(currentCoords); 429c29fa5a6Sopenharmony_ci auto item = event->pointers.find(id); 430c29fa5a6Sopenharmony_ci if (item == event->pointers.end()) { 431c29fa5a6Sopenharmony_ci return; 432c29fa5a6Sopenharmony_ci } 433c29fa5a6Sopenharmony_ci if (other->HasPointerId(id) && ShouldResampleTool(item->second.toolType)) { 434c29fa5a6Sopenharmony_ci const Pointer& otherCoords = other->GetPointerById(id); 435c29fa5a6Sopenharmony_ci resampledCoords.coordX = CalcCoord(currentCoords.coordX, otherCoords.coordX, alpha); 436c29fa5a6Sopenharmony_ci resampledCoords.coordY = CalcCoord(currentCoords.coordY, otherCoords.coordY, alpha); 437c29fa5a6Sopenharmony_ci } 438c29fa5a6Sopenharmony_ci item->second.CopyFrom(resampledCoords); 439c29fa5a6Sopenharmony_ci event->actionTime = sampleTime; 440c29fa5a6Sopenharmony_ci } 441c29fa5a6Sopenharmony_ci} 442c29fa5a6Sopenharmony_ci 443c29fa5a6Sopenharmony_cissize_t EventResample::FindBatch(int32_t deviceId, int32_t source) const 444c29fa5a6Sopenharmony_ci{ 445c29fa5a6Sopenharmony_ci ssize_t idx = 0; 446c29fa5a6Sopenharmony_ci for (auto it = batches_.begin(); it < batches_.end(); ++it, ++idx) { 447c29fa5a6Sopenharmony_ci const MotionEvent& head = it->samples.at(0); 448c29fa5a6Sopenharmony_ci if ((head.deviceId == deviceId) && (head.sourceType == source)) { 449c29fa5a6Sopenharmony_ci return idx; 450c29fa5a6Sopenharmony_ci } 451c29fa5a6Sopenharmony_ci } 452c29fa5a6Sopenharmony_ci return -1; 453c29fa5a6Sopenharmony_ci} 454c29fa5a6Sopenharmony_ci 455c29fa5a6Sopenharmony_cissize_t EventResample::FindTouchState(int32_t deviceId, int32_t source) const 456c29fa5a6Sopenharmony_ci{ 457c29fa5a6Sopenharmony_ci ssize_t idx = 0; 458c29fa5a6Sopenharmony_ci for (auto it = touchStates_.begin(); it < touchStates_.end(); ++it, ++idx) { 459c29fa5a6Sopenharmony_ci if ((it->deviceId == deviceId) && (it->source == source)) { 460c29fa5a6Sopenharmony_ci return idx; 461c29fa5a6Sopenharmony_ci } 462c29fa5a6Sopenharmony_ci } 463c29fa5a6Sopenharmony_ci return -1; 464c29fa5a6Sopenharmony_ci} 465c29fa5a6Sopenharmony_ci 466c29fa5a6Sopenharmony_cibool EventResample::CanAddSample(const Batch &batch, MotionEvent &event) 467c29fa5a6Sopenharmony_ci{ 468c29fa5a6Sopenharmony_ci const MotionEvent& head = batch.samples.at(0); 469c29fa5a6Sopenharmony_ci uint32_t pointerCount = event.pointerCount; 470c29fa5a6Sopenharmony_ci int32_t pointerAction = event.pointerAction; 471c29fa5a6Sopenharmony_ci if ((head.pointerCount != pointerCount) || (head.pointerAction != pointerAction)) { 472c29fa5a6Sopenharmony_ci return false; 473c29fa5a6Sopenharmony_ci } 474c29fa5a6Sopenharmony_ci 475c29fa5a6Sopenharmony_ci return true; 476c29fa5a6Sopenharmony_ci} 477c29fa5a6Sopenharmony_ci 478c29fa5a6Sopenharmony_civoid EventResample::RewriteMessage(TouchState& state, MotionEvent &event) 479c29fa5a6Sopenharmony_ci{ 480c29fa5a6Sopenharmony_ci for (auto &it : event.pointers) { 481c29fa5a6Sopenharmony_ci uint32_t id = it.first; 482c29fa5a6Sopenharmony_ci if (state.lastResample.HasPointerId(id)) { 483c29fa5a6Sopenharmony_ci if ((event.actionTime < state.lastResample.actionTime) || state.RecentCoordinatesAreIdentical(id)) { 484c29fa5a6Sopenharmony_ci Pointer& msgCoords = it.second; 485c29fa5a6Sopenharmony_ci const Pointer& resampleCoords = state.lastResample.GetPointerById(id); 486c29fa5a6Sopenharmony_ci msgCoords.CopyFrom(resampleCoords); 487c29fa5a6Sopenharmony_ci } else { 488c29fa5a6Sopenharmony_ci state.lastResample.pointers.erase(id); 489c29fa5a6Sopenharmony_ci } 490c29fa5a6Sopenharmony_ci } 491c29fa5a6Sopenharmony_ci } 492c29fa5a6Sopenharmony_ci} 493c29fa5a6Sopenharmony_ci 494c29fa5a6Sopenharmony_cissize_t EventResample::FindSampleNoLaterThan(const Batch& batch, int64_t time) 495c29fa5a6Sopenharmony_ci{ 496c29fa5a6Sopenharmony_ci size_t numSamples = batch.samples.size(); 497c29fa5a6Sopenharmony_ci size_t idx = 0; 498c29fa5a6Sopenharmony_ci while ((idx < numSamples) && (batch.samples.at(idx).actionTime <= time)) { 499c29fa5a6Sopenharmony_ci idx += 1; 500c29fa5a6Sopenharmony_ci } 501c29fa5a6Sopenharmony_ci return ssize_t(idx) - 1; 502c29fa5a6Sopenharmony_ci} 503c29fa5a6Sopenharmony_ci 504c29fa5a6Sopenharmony_cibool EventResample::ShouldResampleTool(int32_t toolType) 505c29fa5a6Sopenharmony_ci{ 506c29fa5a6Sopenharmony_ci switch (toolType) { 507c29fa5a6Sopenharmony_ci case PointerEvent::TOOL_TYPE_FINGER: 508c29fa5a6Sopenharmony_ci case PointerEvent::TOOL_TYPE_PEN: 509c29fa5a6Sopenharmony_ci return true; 510c29fa5a6Sopenharmony_ci default: 511c29fa5a6Sopenharmony_ci return false; 512c29fa5a6Sopenharmony_ci } 513c29fa5a6Sopenharmony_ci} 514c29fa5a6Sopenharmony_ci 515c29fa5a6Sopenharmony_civoid EventResample::PrintfDeviceName() 516c29fa5a6Sopenharmony_ci{ 517c29fa5a6Sopenharmony_ci auto device = INPUT_DEV_MGR->GetInputDevice(pointerEvent_->GetDeviceId()); 518c29fa5a6Sopenharmony_ci CHKPV(device); 519c29fa5a6Sopenharmony_ci MMI_HILOGI("InputTracking id:%{public}d event created by:%{public}s", pointerEvent_->GetId(), 520c29fa5a6Sopenharmony_ci device->GetName().c_str()); 521c29fa5a6Sopenharmony_ci} 522c29fa5a6Sopenharmony_ci 523c29fa5a6Sopenharmony_ci} // namespace MMI 524c29fa5a6Sopenharmony_ci} // namespace OHOS 525