Merge "Revert "Conform to 1D VelocityTracker""
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index a52fc75..2d4da2c 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -180,9 +180,9 @@
     private static native void nativeClear(long ptr);
     private static native void nativeAddMovement(long ptr, MotionEvent event);
     private static native void nativeComputeCurrentVelocity(long ptr, int units, float maxVelocity);
-    private static native float nativeGetVelocity(long ptr, int axis, int id);
-    private static native boolean nativeGetEstimator(
-            long ptr, int axis, int id, Estimator outEstimator);
+    private static native float nativeGetXVelocity(long ptr, int id);
+    private static native float nativeGetYVelocity(long ptr, int id);
+    private static native boolean nativeGetEstimator(long ptr, int id, Estimator outEstimator);
 
     static {
         // Strategy string and IDs mapping lookup.
@@ -361,7 +361,7 @@
      * @return The previously computed X velocity.
      */
     public float getXVelocity() {
-        return getXVelocity(ACTIVE_POINTER_ID);
+        return nativeGetXVelocity(mPtr, ACTIVE_POINTER_ID);
     }
 
     /**
@@ -371,7 +371,7 @@
      * @return The previously computed Y velocity.
      */
     public float getYVelocity() {
-        return getYVelocity(ACTIVE_POINTER_ID);
+        return nativeGetYVelocity(mPtr, ACTIVE_POINTER_ID);
     }
 
     /**
@@ -382,7 +382,7 @@
      * @return The previously computed X velocity.
      */
     public float getXVelocity(int id) {
-        return nativeGetVelocity(mPtr, MotionEvent.AXIS_X, id);
+        return nativeGetXVelocity(mPtr, id);
     }
 
     /**
@@ -393,7 +393,7 @@
      * @return The previously computed Y velocity.
      */
     public float getYVelocity(int id) {
-        return nativeGetVelocity(mPtr, MotionEvent.AXIS_Y, id);
+        return nativeGetYVelocity(mPtr, id);
     }
 
     /**
@@ -403,8 +403,6 @@
      * It is not necessary to call {@link #computeCurrentVelocity(int)} before calling
      * this method.
      *
-     * @param axis Which axis's velocity to return.
-     *             Should be one of the axes defined in {@link MotionEvent}.
      * @param id Which pointer's velocity to return.
      * @param outEstimator The estimator to populate.
      * @return True if an estimator was obtained, false if there is no information
@@ -412,11 +410,11 @@
      *
      * @hide For internal use only.  Not a final API.
      */
-    public boolean getEstimator(int axis, int id, Estimator outEstimator) {
+    public boolean getEstimator(int id, Estimator outEstimator) {
         if (outEstimator == null) {
             throw new IllegalArgumentException("outEstimator must not be null");
         }
-        return nativeGetEstimator(mPtr, axis, id, outEstimator);
+        return nativeGetEstimator(mPtr, id, outEstimator);
     }
 
     /**
@@ -436,9 +434,16 @@
         private static final int MAX_DEGREE = 4;
 
         /**
-         * Polynomial coefficients describing motion.
+         * Polynomial coefficients describing motion in X.
          */
-        public final float[] coeff = new float[MAX_DEGREE + 1];
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public final float[] xCoeff = new float[MAX_DEGREE + 1];
+
+        /**
+         * Polynomial coefficients describing motion in Y.
+         */
+        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+        public final float[] yCoeff = new float[MAX_DEGREE + 1];
 
         /**
          * Polynomial degree, or zero if only position information is available.
@@ -453,21 +458,39 @@
         public float confidence;
 
         /**
-         * Gets an estimate of the position of the pointer at the specified time point.
+         * Gets an estimate of the X position of the pointer at the specified time point.
          * @param time The time point in seconds, 0 is the last recorded time.
-         * @return The estimated axis value.
+         * @return The estimated X coordinate.
          */
-        public float estimate(float time) {
-            return estimate(time, coeff);
+        public float estimateX(float time) {
+            return estimate(time, xCoeff);
         }
 
         /**
-         * Gets the coefficient with the specified index.
-         * @param index The index of the coefficient to return.
-         * @return The coefficient, or 0 if the index is greater than the degree.
+         * Gets an estimate of the Y position of the pointer at the specified time point.
+         * @param time The time point in seconds, 0 is the last recorded time.
+         * @return The estimated Y coordinate.
          */
-        public float getCoeff(int index) {
-            return index <= degree ? coeff[index] : 0;
+        public float estimateY(float time) {
+            return estimate(time, yCoeff);
+        }
+
+        /**
+         * Gets the X coefficient with the specified index.
+         * @param index The index of the coefficient to return.
+         * @return The X coefficient, or 0 if the index is greater than the degree.
+         */
+        public float getXCoeff(int index) {
+            return index <= degree ? xCoeff[index] : 0;
+        }
+
+        /**
+         * Gets the Y coefficient with the specified index.
+         * @param index The index of the coefficient to return.
+         * @return The Y coefficient, or 0 if the index is greater than the degree.
+         */
+        public float getYCoeff(int index) {
+            return index <= degree ? yCoeff[index] : 0;
         }
 
         private float estimate(float time, float[] c) {
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 80d50ff..9ee9b82 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -90,10 +90,8 @@
         private float mBoundingBottom;
 
         // Position estimator.
-        private VelocityTracker.Estimator mEstimatorX = new VelocityTracker.Estimator();
-        private VelocityTracker.Estimator mAltEstimatorX = new VelocityTracker.Estimator();
-        private VelocityTracker.Estimator mEstimatorY = new VelocityTracker.Estimator();
-        private VelocityTracker.Estimator mAltEstimatorY = new VelocityTracker.Estimator();
+        private VelocityTracker.Estimator mEstimator = new VelocityTracker.Estimator();
+        private VelocityTracker.Estimator mAltEstimator = new VelocityTracker.Estimator();
 
         @UnsupportedAppUsage
         public PointerState() {
@@ -681,13 +679,11 @@
                 ps.addTrace(coords.x, coords.y, true);
                 ps.mXVelocity = mVelocity.getXVelocity(id);
                 ps.mYVelocity = mVelocity.getYVelocity(id);
-                mVelocity.getEstimator(MotionEvent.AXIS_X, id, ps.mEstimatorX);
-                mVelocity.getEstimator(MotionEvent.AXIS_Y, id, ps.mEstimatorY);
+                mVelocity.getEstimator(id, ps.mEstimator);
                 if (mAltVelocity != null) {
                     ps.mAltXVelocity = mAltVelocity.getXVelocity(id);
                     ps.mAltYVelocity = mAltVelocity.getYVelocity(id);
-                    mAltVelocity.getEstimator(MotionEvent.AXIS_X, id, ps.mAltEstimatorX);
-                    mAltVelocity.getEstimator(MotionEvent.AXIS_Y, id, ps.mAltEstimatorY);
+                    mAltVelocity.getEstimator(id, ps.mAltEstimator);
                 }
                 ps.mToolType = event.getToolType(i);
 
diff --git a/core/jni/android_view_VelocityTracker.cpp b/core/jni/android_view_VelocityTracker.cpp
index 50688af..46bd682 100644
--- a/core/jni/android_view_VelocityTracker.cpp
+++ b/core/jni/android_view_VelocityTracker.cpp
@@ -32,7 +32,8 @@
 static const int ACTIVE_POINTER_ID = -1;
 
 static struct {
-    jfieldID coeff;
+    jfieldID xCoeff;
+    jfieldID yCoeff;
     jfieldID degree;
     jfieldID confidence;
 } gEstimatorClassInfo;
@@ -46,22 +47,28 @@
 
     void clear();
     void addMovement(const MotionEvent* event);
-    // TODO(b/32830165): consider supporting an overload that supports computing velocity only for
-    // a subset of the supported axes.
     void computeCurrentVelocity(int32_t units, float maxVelocity);
-    float getVelocity(int32_t axis, int32_t id);
-    bool getEstimator(int32_t axis, int32_t id, VelocityTracker::Estimator* outEstimator);
+    void getVelocity(int32_t id, float* outVx, float* outVy);
+    bool getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator);
 
 private:
+    struct Velocity {
+        float vx, vy;
+    };
+
     VelocityTracker mVelocityTracker;
-    VelocityTracker::ComputedVelocity mComputedVelocity;
+    int32_t mActivePointerId;
+    BitSet32 mCalculatedIdBits;
+    Velocity mCalculatedVelocity[MAX_POINTERS];
 };
 
 VelocityTrackerState::VelocityTrackerState(const VelocityTracker::Strategy strategy)
-      : mVelocityTracker(strategy) {}
+      : mVelocityTracker(strategy), mActivePointerId(-1) {}
 
 void VelocityTrackerState::clear() {
     mVelocityTracker.clear();
+    mActivePointerId = -1;
+    mCalculatedIdBits.clear();
 }
 
 void VelocityTrackerState::addMovement(const MotionEvent* event) {
@@ -69,20 +76,61 @@
 }
 
 void VelocityTrackerState::computeCurrentVelocity(int32_t units, float maxVelocity) {
-    mVelocityTracker.populateComputedVelocity(mComputedVelocity, units, maxVelocity);
+    BitSet32 idBits(mVelocityTracker.getCurrentPointerIdBits());
+    mCalculatedIdBits = idBits;
+
+    for (uint32_t index = 0; !idBits.isEmpty(); index++) {
+        uint32_t id = idBits.clearFirstMarkedBit();
+
+        float vx, vy;
+        mVelocityTracker.getVelocity(id, &vx, &vy);
+
+        vx = vx * units / 1000;
+        vy = vy * units / 1000;
+
+        if (vx > maxVelocity) {
+            vx = maxVelocity;
+        } else if (vx < -maxVelocity) {
+            vx = -maxVelocity;
+        }
+        if (vy > maxVelocity) {
+            vy = maxVelocity;
+        } else if (vy < -maxVelocity) {
+            vy = -maxVelocity;
+        }
+
+        Velocity& velocity = mCalculatedVelocity[index];
+        velocity.vx = vx;
+        velocity.vy = vy;
+    }
 }
 
-float VelocityTrackerState::getVelocity(int32_t axis, int32_t id) {
+void VelocityTrackerState::getVelocity(int32_t id, float* outVx, float* outVy) {
     if (id == ACTIVE_POINTER_ID) {
         id = mVelocityTracker.getActivePointerId();
     }
 
-    return mComputedVelocity.getVelocity(axis, id).value_or(0);
+    float vx, vy;
+    if (id >= 0 && id <= MAX_POINTER_ID && mCalculatedIdBits.hasBit(id)) {
+        uint32_t index = mCalculatedIdBits.getIndexOfBit(id);
+        const Velocity& velocity = mCalculatedVelocity[index];
+        vx = velocity.vx;
+        vy = velocity.vy;
+    } else {
+        vx = 0;
+        vy = 0;
+    }
+
+    if (outVx) {
+        *outVx = vx;
+    }
+    if (outVy) {
+        *outVy = vy;
+    }
 }
 
-bool VelocityTrackerState::getEstimator(int32_t axis, int32_t id,
-                                        VelocityTracker::Estimator* outEstimator) {
-    return mVelocityTracker.getEstimator(axis, id, outEstimator);
+bool VelocityTrackerState::getEstimator(int32_t id, VelocityTracker::Estimator* outEstimator) {
+    return mVelocityTracker.getEstimator(id, outEstimator);
 }
 
 // Return a strategy enum from integer value.
@@ -129,25 +177,37 @@
     state->computeCurrentVelocity(units, maxVelocity);
 }
 
-static jfloat android_view_VelocityTracker_nativeGetVelocity(JNIEnv* env, jclass clazz, jlong ptr,
-                                                             jint axis, jint id) {
+static jfloat android_view_VelocityTracker_nativeGetXVelocity(JNIEnv* env, jclass clazz,
+        jlong ptr, jint id) {
     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
-    return state->getVelocity(axis, id);
+    float vx;
+    state->getVelocity(id, &vx, NULL);
+    return vx;
+}
+
+static jfloat android_view_VelocityTracker_nativeGetYVelocity(JNIEnv* env, jclass clazz,
+        jlong ptr, jint id) {
+    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
+    float vy;
+    state->getVelocity(id, NULL, &vy);
+    return vy;
 }
 
 static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
-                                                                jlong ptr, jint axis, jint id,
-                                                                jobject outEstimatorObj) {
+        jlong ptr, jint id, jobject outEstimatorObj) {
     VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
     VelocityTracker::Estimator estimator;
+    bool result = state->getEstimator(id, &estimator);
 
-    bool result = state->getEstimator(axis, id, &estimator);
+    jfloatArray xCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
+            gEstimatorClassInfo.xCoeff));
+    jfloatArray yCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
+            gEstimatorClassInfo.yCoeff));
 
-    jfloatArray coeffObj =
-            jfloatArray(env->GetObjectField(outEstimatorObj, gEstimatorClassInfo.coeff));
-
-    env->SetFloatArrayRegion(coeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
-                             estimator.coeff);
+    env->SetFloatArrayRegion(xCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
+            estimator.xCoeff);
+    env->SetFloatArrayRegion(yCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
+            estimator.yCoeff);
     env->SetIntField(outEstimatorObj, gEstimatorClassInfo.degree, estimator.degree);
     env->SetFloatField(outEstimatorObj, gEstimatorClassInfo.confidence, estimator.confidence);
     return result;
@@ -164,8 +224,9 @@
          (void*)android_view_VelocityTracker_nativeAddMovement},
         {"nativeComputeCurrentVelocity", "(JIF)V",
          (void*)android_view_VelocityTracker_nativeComputeCurrentVelocity},
-        {"nativeGetVelocity", "(JII)F", (void*)android_view_VelocityTracker_nativeGetVelocity},
-        {"nativeGetEstimator", "(JIILandroid/view/VelocityTracker$Estimator;)Z",
+        {"nativeGetXVelocity", "(JI)F", (void*)android_view_VelocityTracker_nativeGetXVelocity},
+        {"nativeGetYVelocity", "(JI)F", (void*)android_view_VelocityTracker_nativeGetYVelocity},
+        {"nativeGetEstimator", "(JILandroid/view/VelocityTracker$Estimator;)Z",
          (void*)android_view_VelocityTracker_nativeGetEstimator},
 };
 
@@ -175,7 +236,8 @@
 
     jclass clazz = FindClassOrDie(env, "android/view/VelocityTracker$Estimator");
 
-    gEstimatorClassInfo.coeff = GetFieldIDOrDie(env, clazz, "coeff", "[F");
+    gEstimatorClassInfo.xCoeff = GetFieldIDOrDie(env, clazz, "xCoeff", "[F");
+    gEstimatorClassInfo.yCoeff = GetFieldIDOrDie(env, clazz, "yCoeff", "[F");
     gEstimatorClassInfo.degree = GetFieldIDOrDie(env, clazz, "degree", "I");
     gEstimatorClassInfo.confidence = GetFieldIDOrDie(env, clazz, "confidence", "F");