|  | /* | 
|  | * 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. | 
|  | #define DEBUG_ACCELERATION 0 | 
|  |  | 
|  | #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(); | 
|  | } | 
|  |  | 
|  | void VelocityControl::setParameters(const VelocityControlParameters& parameters) { | 
|  | mParameters = parameters; | 
|  | reset(); | 
|  | } | 
|  |  | 
|  | void VelocityControl::reset() { | 
|  | mLastMovementTime = LLONG_MIN; | 
|  | mRawPosition.x = 0; | 
|  | mRawPosition.y = 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 | 
|  | ALOGD("VelocityControl: stopped, last movement was %0.3fms ago", | 
|  | (eventTime - mLastMovementTime) * 0.000001f); | 
|  | #endif | 
|  | reset(); | 
|  | } | 
|  |  | 
|  | mLastMovementTime = eventTime; | 
|  | if (deltaX) { | 
|  | mRawPosition.x += *deltaX; | 
|  | } | 
|  | if (deltaY) { | 
|  | mRawPosition.y += *deltaY; | 
|  | } | 
|  | mVelocityTracker.addMovement(eventTime, BitSet32(BitSet32::valueForBit(0)), {mRawPosition}); | 
|  |  | 
|  | float vx, vy; | 
|  | float scale = mParameters.scale; | 
|  | if (mVelocityTracker.getVelocity(0, &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); | 
|  | #endif | 
|  | } else { | 
|  | #if DEBUG_ACCELERATION | 
|  | ALOGD("VelocityControl(%0.3f, %0.3f, %0.3f, %0.3f): unknown velocity", | 
|  | mParameters.scale, mParameters.lowThreshold, mParameters.highThreshold, | 
|  | mParameters.acceleration); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | if (deltaX) { | 
|  | *deltaX *= scale; | 
|  | } | 
|  | if (deltaY) { | 
|  | *deltaY *= scale; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | } // namespace android |