Do not resample when frameTime is not available
LegacyResampler still resamples MotionEvents even when requestedFrameTime is
std::nullopt. The problem is that if the parameter requestedFrameTime
is std::nullopt, it is reassigned inside consumeBatchedInputEvents to
std::numeric_limits<nsecs_t>::max(). In spite of using max() as a
placeholder to indicate that everything should be consumed, it is still a valid time, and resampler uses it to resample MotionEvent. To fix this issue, having a valid requestedFrameTime should also be a condition to resample MotionEvents.
Bug: 374375203
Flag: EXEMPT refactor
Test: TEST=libinput_tests; m $TEST && $ANDROID_HOST_OUT/nativetest64/$TEST/$TEST
Change-Id: I6e53bdd0a35d359da8b50f10dd4aad9bddc8aa3f
diff --git a/libs/input/InputConsumerNoResampling.cpp b/libs/input/InputConsumerNoResampling.cpp
index 9665de7..d3653cf 100644
--- a/libs/input/InputConsumerNoResampling.cpp
+++ b/libs/input/InputConsumerNoResampling.cpp
@@ -357,7 +357,8 @@
mBatches[deviceId].emplace(msg);
} else {
// consume all pending batches for this device immediately
- consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/std::nullopt);
+ consumeBatchedInputEvents(deviceId, /*requestedFrameTime=*/
+ std::numeric_limits<nsecs_t>::max());
if (canResample &&
(action == AMOTION_EVENT_ACTION_UP || action == AMOTION_EVENT_ACTION_CANCEL)) {
LOG_IF(INFO, mResamplers.erase(deviceId) == 0)
@@ -480,7 +481,7 @@
}
std::pair<std::unique_ptr<MotionEvent>, std::optional<uint32_t>>
-InputConsumerNoResampling::createBatchedMotionEvent(const nsecs_t requestedFrameTime,
+InputConsumerNoResampling::createBatchedMotionEvent(const std::optional<nsecs_t> requestedFrameTime,
std::queue<InputMessage>& messages) {
std::unique_ptr<MotionEvent> motionEvent;
std::optional<uint32_t> firstSeqForBatch;
@@ -491,7 +492,11 @@
const nanoseconds resampleLatency = (resampler != mResamplers.cend())
? resampler->second->getResampleLatency()
: nanoseconds{0};
- const nanoseconds adjustedFrameTime = nanoseconds{requestedFrameTime} - resampleLatency;
+ // When batching is not enabled, we want to consume all events. That's equivalent to having an
+ // infinite requestedFrameTime.
+ const nanoseconds adjustedFrameTime = (requestedFrameTime.has_value())
+ ? (nanoseconds{*requestedFrameTime} - resampleLatency)
+ : nanoseconds{std::numeric_limits<nsecs_t>::max()};
while (!messages.empty() &&
(messages.front().body.motion.eventTime <= adjustedFrameTime.count())) {
@@ -513,8 +518,9 @@
if (!messages.empty()) {
futureSample = &messages.front();
}
- if ((motionEvent != nullptr) && (resampler != mResamplers.cend())) {
- resampler->second->resampleMotionEvent(nanoseconds{requestedFrameTime}, *motionEvent,
+ if ((motionEvent != nullptr) && (resampler != mResamplers.cend()) &&
+ (requestedFrameTime.has_value())) {
+ resampler->second->resampleMotionEvent(nanoseconds{*requestedFrameTime}, *motionEvent,
futureSample);
}
@@ -524,16 +530,13 @@
bool InputConsumerNoResampling::consumeBatchedInputEvents(
std::optional<DeviceId> deviceId, std::optional<nsecs_t> requestedFrameTime) {
ensureCalledOnLooperThread(__func__);
- // When batching is not enabled, we want to consume all events. That's equivalent to having an
- // infinite requestedFrameTime.
- requestedFrameTime = requestedFrameTime.value_or(std::numeric_limits<nsecs_t>::max());
bool producedEvents = false;
for (auto deviceIdIter = (deviceId.has_value()) ? (mBatches.find(*deviceId))
: (mBatches.begin());
deviceIdIter != mBatches.cend(); ++deviceIdIter) {
std::queue<InputMessage>& messages = deviceIdIter->second;
- auto [motion, firstSeqForBatch] = createBatchedMotionEvent(*requestedFrameTime, messages);
+ auto [motion, firstSeqForBatch] = createBatchedMotionEvent(requestedFrameTime, messages);
if (motion != nullptr) {
LOG_ALWAYS_FATAL_IF(!firstSeqForBatch.has_value());
mCallbacks.onMotionEvent(std::move(motion), *firstSeqForBatch);