Skip to content

Commit

Permalink
Android Platform Views support Verified Input Events
Browse files Browse the repository at this point in the history
Android Platform Views process MotionEvents in a complicated way:

1. MotionEvent is processed by the `AndroidTouchProcessor` and transmitted
to the engine for delivery to the framework.
2. Framework processes the MotionEvent as a PointerEvent.
3. Eventually the PointerEvent is transmitted back to Android and a new
MotionEvent is synthesized.
4. The MotionEvent is delivered to the platform view.

After step (3) the MotionEvent will fail Verification
(`android.hardware.input.InputManager.verifyInputEvent`).

The fix requires that in step (3) we use the original motion event delivered
in step (1) instead of synthesizing a new instance.
  • Loading branch information
johnmccutchan committed Dec 20, 2023
1 parent e70d1ad commit babac33
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

/** Sends touch information from Android to Flutter in a format that Flutter understands. */
public class AndroidTouchProcessor {

private static final String TAG = "AndroidTouchProcessor";
// Must match the PointerChange enum in pointer.dart.
@IntDef({
PointerChange.CANCEL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

/** Tracks the motion events received by the FlutterView. */
public final class MotionEventTracker {

private static final String TAG = "MotionEventTracker";
/** Represents a unique identifier corresponding to a motion event. */
public static class MotionEventId {
private static final AtomicLong ID_COUNTER = new AtomicLong(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,10 @@ public MotionEvent toMotionEvent(
MotionEventTracker.MotionEventId.from(touch.motionEventId);
MotionEvent trackedEvent = motionEventTracker.pop(motionEventId);

if (!usingVirtualDiplay && trackedEvent != null) {
return trackedEvent;
}

// Pointer coordinates in the tracked events are global to FlutterView
// framework converts them to be local to a widget, given that
// motion events operate on local coords, we need to replace these in the tracked
Expand All @@ -688,24 +692,6 @@ public MotionEvent toMotionEvent(
parsePointerCoordsList(touch.rawPointerCoords, density)
.toArray(new PointerCoords[touch.pointerCount]);

if (!usingVirtualDiplay && trackedEvent != null) {
return MotionEvent.obtain(
trackedEvent.getDownTime(),
trackedEvent.getEventTime(),
trackedEvent.getAction(),
trackedEvent.getPointerCount(),
pointerProperties,
pointerCoords,
trackedEvent.getMetaState(),
trackedEvent.getButtonState(),
trackedEvent.getXPrecision(),
trackedEvent.getYPrecision(),
trackedEvent.getDeviceId(),
trackedEvent.getEdgeFlags(),
trackedEvent.getSource(),
trackedEvent.getFlags());
}

// TODO (kaushikiska) : warn that we are potentially using an untracked
// event in the platform views.
return MotionEvent.obtain(
Expand Down

0 comments on commit babac33

Please sign in to comment.