blob: c835a081a5c2be703eeb820ef7929336db79a073 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "VelocityControl"
//#define LOG_NDEBUG 0
// Log debug messages about acceleration.
static constexpr bool DEBUG_ACCELERATION = false;
#include <math.h>
#include <limits.h>
#include <input/VelocityControl.h>
#include <utils/BitSet.h>
#include <utils/Timers.h>
namespace android {
// --- VelocityControl ---
const nsecs_t VelocityControl::STOP_TIME;
VelocityControl::VelocityControl() {
reset();
}
const VelocityControlParameters& VelocityControl::getParameters() const{
return mParameters;
}
void VelocityControl::setParameters(const VelocityControlParameters& parameters) {
mParameters = parameters;
reset();
}
void VelocityControl::reset() {
mLastMovementTime = LLONG_MIN;
mRawPositionX = 0;
mRawPositionY = 0;
mVelocityTracker.clear();
}
void VelocityControl::move(nsecs_t eventTime, float* deltaX, float* deltaY) {
if ((deltaX && *deltaX) || (deltaY && *deltaY)) {
if (eventTime >= mLastMovementTime + STOP_TIME) {
if (DEBUG_ACCELERATION && mLastMovementTime != LLONG_MIN) {
ALOGD("VelocityControl: stopped, last movement was %0.3fms ago",
(eventTime - mLastMovementTime) * 0.000001f);
}
reset();
}
mLastMovementTime = eventTime;
if (deltaX) {
mRawPositionX += *deltaX;
}
if (deltaY) {
mRawPositionY += *deltaY;
}
mVelocityTracker.addMovement(eventTime, /*pointerId=*/0, AMOTION_EVENT_AXIS_X,
mRawPositionX);
mVelocityTracker.addMovement(eventTime, /*pointerId=*/0, AMOTION_EVENT_AXIS_Y,
mRawPositionY);
std::optional<float> vx = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, 0);
std::optional<float> vy = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_Y, 0);
float scale = mParameters.scale;
if (vx && vy) {
float speed = hypotf(*vx, *vy) * scale;
if (speed >= mParameters.highThreshold) {
// Apply full acceleration above the high speed threshold.
scale *= mParameters.acceleration;
} else if (speed > mParameters.lowThreshold) {
// Linearly interpolate the acceleration to apply between the low and high
// speed thresholds.
scale *= 1 + (speed - mParameters.lowThreshold)
/ (mParameters.highThreshold - mParameters.lowThreshold)
* (mParameters.acceleration - 1);
}
if (DEBUG_ACCELERATION) {
ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): "
"vx=%0.3f, vy=%0.3f, speed=%0.3f, accel=%0.3f",
mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
mParameters.acceleration, *vx, *vy, speed, scale / mParameters.scale);
}
} else {
if (DEBUG_ACCELERATION) {
ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity",
mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold,
mParameters.acceleration);
}
}
if (deltaX) {
*deltaX *= scale;
}
if (deltaY) {
*deltaY *= scale;
}
}
}
} // namespace android