1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.input.motionprediction;
18 
19 import android.content.Context;
20 import android.os.Build;
21 import android.view.MotionEvent;
22 import android.view.View;
23 
24 import androidx.annotation.NonNull;
25 import androidx.annotation.Nullable;
26 import androidx.input.motionprediction.common.Configuration;
27 import androidx.input.motionprediction.kalman.KalmanMotionEventPredictor;
28 import androidx.input.motionprediction.system.SystemMotionEventPredictor;
29 
30 /**
31  * There is a gap between the time a user touches the screen and that information is reported to the
32  * app; a motion predictor is a utility that provides predicted {@link android.view.MotionEvent}
33  * based on the previously received ones. Obtain a new predictor instance using
34  * {@link #newInstance(android.view.View)}; put the motion events you receive into it with
35  * {@link #record(android.view.MotionEvent)}, and call {@link #predict()} to retrieve the
36  * predicted  {@link android.view.MotionEvent} that would occur at the moment the next frame is
37  * rendered on the display.
38  */
39 public interface MotionEventPredictor {
40     /**
41      * Record a user's movement to the predictor. You should call this for every
42      * {@link android.view.MotionEvent} that is received by the associated
43      * {@link android.view.View}.
44      *
45      * @param event the {@link android.view.MotionEvent} the associated view received and that
46      *              needs to be recorded.
47      * @throws IllegalArgumentException if an inconsistent MotionEvent stream is sent.
48      */
record(@onNull MotionEvent event)49     void record(@NonNull MotionEvent event);
50 
51     /**
52      * Compute a prediction
53      *
54      * @return the predicted {@link android.view.MotionEvent}, or null if not possible to make a
55      * prediction.
56      */
57     @Nullable
predict()58     MotionEvent predict();
59 
60     /**
61      * Create a new motion predictor associated to a specific {@link android.view.View}.
62      *
63      * For devices running Android versions before U, the predicions are provided by a library based
64      * on a Kalman filter; from Android U, a system API is available, but predictions may not be
65      * supported for all strokes (for instance, it may be limited to stylus events). In these cases,
66      * the Kalman filter library will be used; to determine if a `MotionEvent` will be handled by
67      * the system prediction, use {@link android.view.MotionPredictor#isPredictionAvailable}.
68      *
69      * @param view the view to associated to this predictor
70      * @return the new predictor instance
71      */
72     @NonNull
newInstance(@onNull View view)73     static MotionEventPredictor newInstance(@NonNull View view) {
74         Context context = view.getContext();
75         Configuration configuration = Configuration.getInstance();
76         if (Build.VERSION.SDK_INT >= 34
77                 && configuration.preferSystemPrediction()) {
78             return SystemMotionEventPredictor.newInstance(
79                     context,
80                     configuration.predictionStrategy());
81         } else {
82             return new KalmanMotionEventPredictor(context, configuration.predictionStrategy());
83         }
84     }
85 }
86