19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.view;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganovimport android.util.Pools.SynchronizedPool;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper for tracking the velocity of touch events, for implementing
232ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * flinging and other such gestures.
242ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown *
252ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * Use {@link #obtain} to retrieve a new instance of the class when you are going
262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * to begin tracking.  Put the motion events you receive into it with
272ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * {@link #addMovement(MotionEvent)}.  When you want to determine the velocity call
282ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown * {@link #computeCurrentVelocity(int)} and then call {@link #getXVelocity(int)}
29185b8256f570dfe620789130bb3861bdeecfffddGilles Debunne * and {@link #getYVelocity(int)} to retrieve the velocity for each pointer id.
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
31abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganovpublic final class VelocityTracker {
32abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov    private static final SynchronizedPool<VelocityTracker> sPool =
33abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov            new SynchronizedPool<VelocityTracker>(2);
34d928d6837dee4df30b06529164326722075da063Romain Guy
352ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    private static final int ACTIVE_POINTER_ID = -1;
362ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
3796804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private long mPtr;
389eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown    private final String mStrategy;
399eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown
4096804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private static native long nativeInitialize(String strategy);
4196804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private static native void nativeDispose(long ptr);
4296804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private static native void nativeClear(long ptr);
4396804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private static native void nativeAddMovement(long ptr, MotionEvent event);
4496804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private static native void nativeComputeCurrentVelocity(long ptr, int units, float maxVelocity);
4596804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private static native float nativeGetXVelocity(long ptr, int id);
4696804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private static native float nativeGetYVelocity(long ptr, int id);
4796804bc8fb3d6b2de11e3b9779c976e7b0e96ee8Ashok Bhat    private static native boolean nativeGetEstimator(long ptr, int id, Estimator outEstimator);
482ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve a new VelocityTracker object to watch the velocity of a
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * motion.  Be sure to call {@link #recycle} when done.  You should
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * generally only maintain an active object while tracking a movement,
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * so that the VelocityTracker can be re-used elsewhere.
54d928d6837dee4df30b06529164326722075da063Romain Guy     *
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns a new VelocityTracker.
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static public VelocityTracker obtain() {
58abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov        VelocityTracker instance = sPool.acquire();
59abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov        return (instance != null) ? instance : new VelocityTracker(null);
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
61d928d6837dee4df30b06529164326722075da063Romain Guy
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
639eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown     * Obtains a velocity tracker with the specified strategy.
649eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown     * For testing and comparison purposes only.
659eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown     *
669eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown     * @param strategy The strategy, or null to use the default.
679eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown     * @return The velocity tracker.
689eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown     *
699eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown     * @hide
709eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown     */
719eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown    public static VelocityTracker obtain(String strategy) {
729eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown        if (strategy == null) {
739eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown            return obtain();
749eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown        }
759eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown        return new VelocityTracker(strategy);
769eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown    }
779eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown
789eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown    /**
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Return a VelocityTracker object back to be re-used by others.  You must
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * not touch the object after calling this function.
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void recycle() {
839eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown        if (mStrategy == null) {
84abae2a1b891772d36d8f781adfcc8969e551691fSvetoslav Ganov            clear();
859eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown            sPool.release(this);
869eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown        }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
88d928d6837dee4df30b06529164326722075da063Romain Guy
899eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown    private VelocityTracker(String strategy) {
909eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown        mPtr = nativeInitialize(strategy);
919eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown        mStrategy = strategy;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
932ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
942ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    @Override
952ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    protected void finalize() throws Throwable {
962ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        try {
972ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            if (mPtr != 0) {
982ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown                nativeDispose(mPtr);
992ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown                mPtr = 0;
1002ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            }
1012ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        } finally {
1022ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            super.finalize();
1032ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        }
1042ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    }
1052ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Reset the velocity tracker back to its initial state.
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clear() {
1102ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        nativeClear(mPtr);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Add a user's movement to the tracker.  You should call this for the
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * initial {@link MotionEvent#ACTION_DOWN}, the following
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link MotionEvent#ACTION_MOVE} events that you receive, and the
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * final {@link MotionEvent#ACTION_UP}.  You can, however, call this
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for whichever events you desire.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1202ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown     * @param event The MotionEvent you received and would like to track.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1222ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown    public void addMovement(MotionEvent event) {
1232ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        if (event == null) {
1242ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown            throw new IllegalArgumentException("event must not be null");
12588cf2fca38066e75f9349950c8e6255a91350d97Jeff Brown        }
1262ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        nativeAddMovement(mPtr, event);
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1284296fc4d326447875c26a925f12b3935632f13bbRomain Guy
1294296fc4d326447875c26a925f12b3935632f13bbRomain Guy    /**
1304296fc4d326447875c26a925f12b3935632f13bbRomain Guy     * Equivalent to invoking {@link #computeCurrentVelocity(int, float)} with a maximum
1314296fc4d326447875c26a925f12b3935632f13bbRomain Guy     * velocity of Float.MAX_VALUE.
1324296fc4d326447875c26a925f12b3935632f13bbRomain Guy     *
1334296fc4d326447875c26a925f12b3935632f13bbRomain Guy     * @see #computeCurrentVelocity(int, float)
1344296fc4d326447875c26a925f12b3935632f13bbRomain Guy     */
1354296fc4d326447875c26a925f12b3935632f13bbRomain Guy    public void computeCurrentVelocity(int units) {
1362ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        nativeComputeCurrentVelocity(mPtr, units, Float.MAX_VALUE);
1374296fc4d326447875c26a925f12b3935632f13bbRomain Guy    }
1384296fc4d326447875c26a925f12b3935632f13bbRomain Guy
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Compute the current velocity based on the points that have been
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * collected.  Only call this when you actually want to retrieve velocity
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * information, as it is relatively expensive.  You can then retrieve
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the velocity with {@link #getXVelocity()} and
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #getYVelocity()}.
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param units The units you would like the velocity in.  A value of 1
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * provides pixels per millisecond, 1000 provides pixels per second, etc.
1484296fc4d326447875c26a925f12b3935632f13bbRomain Guy     * @param maxVelocity The maximum velocity that can be computed by this method.
1494296fc4d326447875c26a925f12b3935632f13bbRomain Guy     * This value must be declared in the same unit as the units parameter. This value
1504296fc4d326447875c26a925f12b3935632f13bbRomain Guy     * must be positive.
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1524296fc4d326447875c26a925f12b3935632f13bbRomain Guy    public void computeCurrentVelocity(int units, float maxVelocity) {
1532ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        nativeComputeCurrentVelocity(mPtr, units, maxVelocity);
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve the last computed X velocity.  You must first call
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #computeCurrentVelocity(int)} before calling this function.
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The previously computed X velocity.
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public float getXVelocity() {
1632ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        return nativeGetXVelocity(mPtr, ACTIVE_POINTER_ID);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve the last computed Y velocity.  You must first call
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #computeCurrentVelocity(int)} before calling this function.
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The previously computed Y velocity.
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public float getYVelocity() {
1732ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        return nativeGetYVelocity(mPtr, ACTIVE_POINTER_ID);
1748acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell    }
1758acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell
1768acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell    /**
1778acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     * Retrieve the last computed X velocity.  You must first call
1788acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     * {@link #computeCurrentVelocity(int)} before calling this function.
1798acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     *
18073d8fca6ba1991dbcbcd4686212d087a5ae8de2dAdam Powell     * @param id Which pointer's velocity to return.
1818acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     * @return The previously computed X velocity.
1828acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     */
18373d8fca6ba1991dbcbcd4686212d087a5ae8de2dAdam Powell    public float getXVelocity(int id) {
1842ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        return nativeGetXVelocity(mPtr, id);
1858acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell    }
1868acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell
1878acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell    /**
1888acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     * Retrieve the last computed Y velocity.  You must first call
1898acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     * {@link #computeCurrentVelocity(int)} before calling this function.
1908acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     *
19173d8fca6ba1991dbcbcd4686212d087a5ae8de2dAdam Powell     * @param id Which pointer's velocity to return.
1928acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     * @return The previously computed Y velocity.
1938acdb201bdad2cd03c07ebad9cda29f7971ed164Adam Powell     */
19473d8fca6ba1991dbcbcd4686212d087a5ae8de2dAdam Powell    public float getYVelocity(int id) {
1952ed2462aa29c564f5231f317c27b3188da875e52Jeff Brown        return nativeGetYVelocity(mPtr, id);
19688cf2fca38066e75f9349950c8e6255a91350d97Jeff Brown    }
197b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
198b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    /**
199b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * Get an estimator for the movements of a pointer using past movements of the
200b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * pointer to predict future movements.
201b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     *
202b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * It is not necessary to call {@link #computeCurrentVelocity(int)} before calling
203b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * this method.
204b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     *
205b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * @param id Which pointer's velocity to return.
206b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * @param outEstimator The estimator to populate.
207b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * @return True if an estimator was obtained, false if there is no information
208b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * available about the pointer.
209b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     *
210b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * @hide For internal use only.  Not a final API.
211b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     */
21285bd0d62830a098c1bdc720dfdcf4fe1b18b657cJeff Brown    public boolean getEstimator(int id, Estimator outEstimator) {
213b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        if (outEstimator == null) {
214b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            throw new IllegalArgumentException("outEstimator must not be null");
215b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
21685bd0d62830a098c1bdc720dfdcf4fe1b18b657cJeff Brown        return nativeGetEstimator(mPtr, id, outEstimator);
217b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
218b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
219b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    /**
220b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * An estimator for the movements of a pointer based on a polynomial model.
221b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     *
222b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * The last recorded position of the pointer is at time zero seconds.
223b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * Past estimated positions are at negative times and future estimated positions
224b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * are at positive times.
225b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     *
226b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * First coefficient is position (in pixels), second is velocity (in pixels per second),
227b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * third is acceleration (in pixels per second squared).
228b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     *
229b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     * @hide For internal use only.  Not a final API.
230b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown     */
231b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    public static final class Estimator {
232b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        // Must match VelocityTracker::Estimator::MAX_DEGREE
2339eb7d86181729c3eb769d71123c4ce9ffc868f08Jeff Brown        private static final int MAX_DEGREE = 4;
234b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
235b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        /**
236b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * Polynomial coefficients describing motion in X.
237b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         */
238b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        public final float[] xCoeff = new float[MAX_DEGREE + 1];
239b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
240b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        /**
241b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * Polynomial coefficients describing motion in Y.
242b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         */
243b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        public final float[] yCoeff = new float[MAX_DEGREE + 1];
244b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
245b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        /**
246b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * Polynomial degree, or zero if only position information is available.
247b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         */
248b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        public int degree;
249b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
250b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        /**
251b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit).
252b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         */
253b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        public float confidence;
254b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
255b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        /**
256b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * Gets an estimate of the X position of the pointer at the specified time point.
257b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * @param time The time point in seconds, 0 is the last recorded time.
258b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * @return The estimated X coordinate.
259b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         */
260b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        public float estimateX(float time) {
261b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            return estimate(time, xCoeff);
262b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
263b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
264b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        /**
265b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * Gets an estimate of the Y position of the pointer at the specified time point.
266b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * @param time The time point in seconds, 0 is the last recorded time.
267b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         * @return The estimated Y coordinate.
268b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown         */
269b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        public float estimateY(float time) {
270b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            return estimate(time, yCoeff);
271b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
272b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown
2738a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        /**
2748a90e6e3174083f274538567d851f98478fc83e9Jeff Brown         * Gets the X coefficient with the specified index.
2758a90e6e3174083f274538567d851f98478fc83e9Jeff Brown         * @param index The index of the coefficient to return.
2768a90e6e3174083f274538567d851f98478fc83e9Jeff Brown         * @return The X coefficient, or 0 if the index is greater than the degree.
2778a90e6e3174083f274538567d851f98478fc83e9Jeff Brown         */
2788a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        public float getXCoeff(int index) {
2798a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            return index <= degree ? xCoeff[index] : 0;
2808a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        }
2818a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
2828a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        /**
2838a90e6e3174083f274538567d851f98478fc83e9Jeff Brown         * Gets the Y coefficient with the specified index.
2848a90e6e3174083f274538567d851f98478fc83e9Jeff Brown         * @param index The index of the coefficient to return.
2858a90e6e3174083f274538567d851f98478fc83e9Jeff Brown         * @return The Y coefficient, or 0 if the index is greater than the degree.
2868a90e6e3174083f274538567d851f98478fc83e9Jeff Brown         */
2878a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        public float getYCoeff(int index) {
2888a90e6e3174083f274538567d851f98478fc83e9Jeff Brown            return index <= degree ? yCoeff[index] : 0;
2898a90e6e3174083f274538567d851f98478fc83e9Jeff Brown        }
2908a90e6e3174083f274538567d851f98478fc83e9Jeff Brown
291b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        private float estimate(float time, float[] c) {
292b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            float a = 0;
293b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            float scale = 1;
294b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            for (int i = 0; i <= degree; i++) {
295b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                a += c[i] * scale;
296b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown                scale *= time;
297b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            }
298b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown            return a;
299b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown        }
300b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown    }
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
302