| /* |
| * 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 |