Add amount of prediction to the predict call
This is an internal change for the MotionPrediction API. Instead of having
a fixed amount of prediction, the Kalman library consumer will be able to
specify the desired amount of prediction.
Bug: 232941452
Test: tested on sample app, confirmed that prediction works as expected
Change-Id: I8f887ebca3288d4b4dbe21e2f0b4dcaf918f8de7
diff --git a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanMotionEventPredictor.java b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanMotionEventPredictor.java
index 91bec15..7a7ab0f 100644
--- a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanMotionEventPredictor.java
+++ b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanMotionEventPredictor.java
@@ -32,11 +32,6 @@
private MultiPointerPredictor mMultiPointerPredictor = new MultiPointerPredictor();
public KalmanMotionEventPredictor() {
- // 1 may seem arbitrary, but this basically tells the predictor to
- // just predict the next MotionEvent.
- // This will need to change as we want to build a prediction depending
- // on the expected time that the frame will arrive to the screen.
- mMultiPointerPredictor.setPredictionTarget(1);
}
@Override
@@ -53,7 +48,7 @@
if (mMultiPointerPredictor == null) {
return null;
}
- return mMultiPointerPredictor.predict();
+ return mMultiPointerPredictor.predict(1);
}
@Override
diff --git a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanPredictor.java b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanPredictor.java
index 87a35e6..3a8ff60 100644
--- a/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanPredictor.java
+++ b/input/input-motionprediction/src/main/java/androidx/input/motionprediction/kalman/KalmanPredictor.java
@@ -30,13 +30,6 @@
*/
@RestrictTo(LIBRARY)
public interface KalmanPredictor {
-
- /** Gets the current prediction target */
- int getPredictionTarget();
-
- /** Sets the current prediction target */
- void setPredictionTarget(int predictionTargetMillis);
-
/** Sets the report rate */
void setReportRate(int reportRateMs);
@@ -45,5 +38,5 @@
/** @return null if not possible to make a prediction. */
@Nullable
- MotionEvent predict();
+ MotionEvent predict(int predictionTargetMillis);
}
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 cb6c3a9..3f02764 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
@@ -36,29 +36,11 @@
private static final boolean DEBUG_PREDICTION = Log.isLoggable(TAG, Log.DEBUG);
private final SparseArray<SinglePointerPredictor> mPredictorMap = new SparseArray<>();
- private int mPredictionTargetMs = 0;
private int mReportRateMs = 0;
public MultiPointerPredictor() {}
@Override
- public int getPredictionTarget() {
- return mPredictionTargetMs;
- }
-
- @Override
- public void setPredictionTarget(int predictionTargetMillis) {
- if (predictionTargetMillis < 0) {
- predictionTargetMillis = 0;
- }
- mPredictionTargetMs = predictionTargetMillis;
-
- for (int i = 0; i < mPredictorMap.size(); ++i) {
- mPredictorMap.valueAt(i).setPredictionTarget(predictionTargetMillis);
- }
- }
-
- @Override
public void setReportRate(int reportRateMs) {
if (reportRateMs <= 0) {
throw new IllegalArgumentException(
@@ -78,7 +60,6 @@
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);
}
@@ -113,7 +94,7 @@
/** Support eventTime */
@Override
- public @Nullable MotionEvent predict() {
+ public @Nullable MotionEvent predict(int predictionTargetMs) {
final int pointerCount = mPredictorMap.size();
// Shortcut for likely case where only zero or one pointer is on the screen
// this logic exists only to make sure logic when one pointer is on screen then
@@ -128,7 +109,7 @@
}
if (pointerCount == 1) {
SinglePointerPredictor predictor = mPredictorMap.valueAt(0);
- MotionEvent predictedEv = predictor.predict();
+ MotionEvent predictedEv = predictor.predict(predictionTargetMs);
if (DEBUG_PREDICTION) {
Log.d(TAG, "predict() -> MotionEvent: " + predictedEv);
}
@@ -141,7 +122,7 @@
for (int i = 0; i < pointerCount; ++i) {
pointerIds[i] = mPredictorMap.keyAt(i);
SinglePointerPredictor predictor = mPredictorMap.valueAt(i);
- singlePointerEvents[i] = predictor.predict();
+ singlePointerEvents[i] = predictor.predict(predictionTargetMs);
// If predictor consumer expect more sample, generate sample where position and
// pressure are constant
singlePointerEvents[i] = predictor.appendPredictedEvent(singlePointerEvents[i]);
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 0ba5bc6..74dfc7c 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
@@ -60,9 +60,6 @@
// Minimum number of Kalman filter samples needed for predicting the next point
private static final int MIN_KALMAN_FILTER_ITERATIONS = 4;
- // Target time in milliseconds to predict.
- private float mPredictionTargetMs = 0.0f;
-
// The Kalman filter is tuned to smooth noise while maintaining fast reaction to direction
// changes. The stronger the filter, the smoother the prediction result will be, at the
// cost of possible prediction errors.
@@ -148,23 +145,6 @@
}
@Override
- public int getPredictionTarget() {
- // Prediction target should always be an int, so no precision lost in the cast
- return (int) mPredictionTargetMs;
- }
-
- @Override
- public void setPredictionTarget(int predictionTargetMillis) {
- if (predictionTargetMillis < 0) {
- predictionTargetMillis = 0;
- }
- mPredictionTargetMs = predictionTargetMillis;
- if (mReportRates == null) {
- mExpectedPredictionSampleSize = (int) Math.ceil(mPredictionTargetMs / mReportRateMs);
- }
- }
-
- @Override
public void setReportRate(int reportRateMs) {
if (reportRateMs <= 0) {
throw new IllegalArgumentException(
@@ -172,8 +152,6 @@
}
mReportRateMs = reportRateMs;
mReportRates = null;
-
- mExpectedPredictionSampleSize = (int) Math.ceil(mPredictionTargetMs / mReportRateMs);
}
@Override
@@ -205,7 +183,11 @@
}
@Override
- public @Nullable MotionEvent predict() {
+ public @Nullable MotionEvent predict(int predictionTargetMs) {
+ if (mReportRates == null) {
+ mExpectedPredictionSampleSize = (int) Math.ceil(predictionTargetMs / mReportRateMs);
+ }
+
if (mExpectedPredictionSampleSize == -1
&& mKalman.getNumIterations() < MIN_KALMAN_FILTER_ITERATIONS) {
return null;
@@ -236,7 +218,7 @@
// Project physical state of the pen into the future.
int predictionTargetInSamples =
- (int) Math.ceil(mPredictionTargetMs / mReportRateMs * confidenceFactor);
+ (int) Math.ceil(predictionTargetMs / mReportRateMs * confidenceFactor);
// Normally this should always be false as confidenceFactor should be less than 1.0
if (mExpectedPredictionSampleSize != -1