/* * 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 #include #include #include #include namespace android { // --- VelocityControl --- const nsecs_t VelocityControl::STOP_TIME; VelocityControl::VelocityControl() { reset(); } VelocityControlParameters& VelocityControl::getParameters() { 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 vx = mVelocityTracker.getVelocity(AMOTION_EVENT_AXIS_X, 0); std::optional 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