Add last orientation and tilt axes to predictions

The motion prediction API will not contain information about the
orientation and tilt axes; we should be predicting it, but until
the prediction library is optimized, we will just put the last
information that was seen.

Bug: 262009288
Test: used in the sample app, saw the tilt and orientation
Change-Id: I610bfee7029386ecb708cced296fafe2004b76ae
diff --git a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/MultiPointerPredictor.java b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/MultiPointerPredictor.java
index 415e2da..b630652 100644
--- a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/MultiPointerPredictor.java
+++ b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/MultiPointerPredictor.java
@@ -75,14 +75,15 @@
     @Override
     public boolean onTouchEvent(@NonNull MotionEvent event) {
         int action = event.getActionMasked();
-        int pointerId = event.getPointerId(event.getActionIndex());
+        int actionIndex = event.getActionIndex();
+        int pointerId = event.getPointerId(actionIndex);
         if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) {
             SinglePointerPredictor predictor = new SinglePointerPredictor();
             predictor.setPredictionTarget(mPredictionTargetMs);
             if (mReportRateMs > 0) {
                 predictor.setReportRate(mReportRateMs);
             }
-            predictor.initStrokePrediction(pointerId);
+            predictor.initStrokePrediction(pointerId, event.getToolType(actionIndex));
             predictor.onTouchEvent(event);
             mPredictorMap.put(pointerId, predictor);
         } else if (action == MotionEvent.ACTION_UP) {
diff --git a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/SinglePointerPredictor.java b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/SinglePointerPredictor.java
index db4ba103..b1fecae 100644
--- a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/SinglePointerPredictor.java
+++ b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/SinglePointerPredictor.java
@@ -80,10 +80,15 @@
     private final DVector2 mAcceleration = new DVector2();
     private final DVector2 mJank = new DVector2();
 
-    /* pointer of the gesture that require prediction */
+    /* pointer of the gesture that requires prediction */
     private int mPointerId = 0;
 
+    /* tool type of the gesture that requires prediction */
+    private int mToolType = MotionEvent.TOOL_TYPE_UNKNOWN;
+
     private double mPressure = 0;
+    private double mLastOrientation = 0;
+    private double mLastTilt = 0;
 
     /**
      * Kalman based predictor, predicting the location of the pen `predictionTarget`
@@ -98,13 +103,15 @@
         mPrevEventTime = 0;
     }
 
-    void initStrokePrediction(int pointerId) {
+    void initStrokePrediction(int pointerId, int toolType) {
         mKalman.reset();
         mPrevEventTime = 0;
         mPointerId = pointerId;
+        mToolType = toolType;
     }
 
-    private void update(float x, float y, float pressure, long eventTime) {
+    private void update(float x, float y, float pressure, float orientation,
+            float tilt, long eventTime) {
         if (x == mLastPosition.a1
                 && y == mLastPosition.a2
                 && (eventTime <= (mPrevEventTime + EVENT_TIME_IGNORED_THRESHOLD_MS))) {
@@ -121,6 +128,8 @@
         mKalman.update(x, y, pressure);
         mLastPosition.a1 = x;
         mLastPosition.a2 = y;
+        mLastOrientation = orientation;
+        mLastTilt = tilt;
 
         // Calculate average report rate over the first 20 samples. Most sensors will not
         // provide reliable timestamps and do not report at an even interval, so this is just
@@ -176,6 +185,7 @@
             return false;
         }
         int pointerIndex = event.findPointerIndex(mPointerId);
+
         if (pointerIndex == -1) {
             Log.i(
                     TAG,
@@ -188,7 +198,9 @@
         }
         for (BatchedMotionEvent ev : BatchedMotionEvent.iterate(event)) {
             MotionEvent.PointerCoords pointerCoords = ev.coords[pointerIndex];
-            update(pointerCoords.x, pointerCoords.y, pointerCoords.pressure, ev.timeMs);
+            update(pointerCoords.x, pointerCoords.y, pointerCoords.pressure,
+                    pointerCoords.orientation,
+                    pointerCoords.getAxisValue(MotionEvent.AXIS_TILT), ev.timeMs);
         }
         return true;
     }
@@ -221,6 +233,7 @@
                 new MotionEvent.PointerProperties[1];
         pointerProperties[0] = new MotionEvent.PointerProperties();
         pointerProperties[0].id = mPointerId;
+        pointerProperties[0].toolType = mToolType;
 
         // Project physical state of the pen into the future.
         int predictionTargetInSamples =
@@ -253,6 +266,8 @@
             coords[0].x = (float) mPosition.a1;
             coords[0].y = (float) mPosition.a2;
             coords[0].pressure = (float) mPressure;
+            coords[0].orientation = (float) mLastOrientation;
+            coords[0].setAxisValue(MotionEvent.AXIS_TILT, (float) mLastTilt);
             if (predictedEvent == null) {
                 predictedEvent =
                         MotionEvent.obtain(
@@ -301,6 +316,7 @@
                         new MotionEvent.PointerProperties[1];
                 pointerProperties[0] = new MotionEvent.PointerProperties();
                 pointerProperties[0].id = mPointerId;
+                pointerProperties[0].toolType = mToolType;
                 predictedEvent =
                         MotionEvent.obtain(
                                 0 /* downTime */,