Sitelet https://github.com/flutter/flutter/pull/192259
Skip to content

Request unbuffered dispatch for platform view motion events after _PlatformViewGestureRecognizer rejects gesture - #192259

Merged
auto-submit[bot] merged 18 commits into
flutter:masterfrom
gmackall:arena-scoped-unbuffered
Sep 14, 2026
Merged

auto-submit[bot] merged 18 commits into
flutter:masterfrom
gmackall:arena-scoped-unbuffered

Conversation

@gmackall

@gmackall gmackall commented Sep 3, 2026 •

Copy link
Copy Markdown
Member

Changes platform view touch input for all modes to request the unbuffered stream for the given event when the GestureArena determines the platform view has bowed out of ownership of that event, via View.requestUnbufferedDispatch(). Flutter content itself makes this request, but currently platform views don't.

This greatly improves platform view scrolling smoothness, while having no breaking change or impact on platform views performing gesture handling (because the GestureArena has determined that they don't own the input event).

Problem & Invariant

Under high-load or scrolling scenarios, buffered touch dispatch causes visible jank and input lag. Flutter requests unbuffered dispatch for its own rendering, but platform views continue using buffered streams unless requested. Simply requesting unbuffered dispatch unconditionally can cause issues if gestures are still competing or owned by the platform view. Scoping unbuffered dispatch to gestures that Flutter has won ensures that platform views receive fast, unbuffered dispatch specifically during Flutter gestures (like scrolling).

Architecture & Gesture Correlation (embedderId)

Previous iterations attempted to correlate gestures across the channel by matching synthetic downTime timestamps packed into PointerDownEvent.timeStamp. However, resamplers or clock drift can alter event timestamps.

Instead, this PR uses Flutter's canonical embedderId mechanism:

  1. Android Touch Processor: When an Android MotionEvent arrives, AndroidTouchProcessor tracks it using MotionEventTracker.track(event) and populates packet.putLong(motionEventId), which the framework receives as PointerEvent.embedderId.
  2. Framework Arena Resolution: _PlatformViewGestureRecognizer records the embedderId of the pointer-down event. When Flutter wins the arena and calls rejectGesture(pointer), the framework sends gestureId (set to embedderId) over the flutter/platform_views system channel.
  3. Engine Correlation (MotionEventTracker.peek):
    • PlatformViewsController and PlatformViewsController2 handle onRejectGesture(viewId, gestureId).
    • The controllers query motionEventTracker.peek(MotionEventId.from(gestureId)) to look up the native MotionEvent without consuming it from the tracker.
    • From this MotionEvent, the native downTime is retrieved and passed to FlutterMutatorView and PlatformViewWrapper.
    • PlatformViewGestureTracker marks flutterWonGesture = true if the downTime matches the current active gesture stream, and keeps calling requestUnbufferedDispatch() for all remaining events in the gesture until ACTION_UP or ACTION_CANCEL.
  4. Graceful Degradation / Fails Closed:
    • If peek() returns null (e.g. if the event was already popped or on non-Android embedders), or if gestureId is 0 or unmatched, the optimization degrades gracefully to standard buffered touch dispatch without breaking input handling.

Tests

  • Framework tests: packages/flutter/test/rendering/platform_view_test.dart
    • Verifies rejectGesture passes the pointer's embedderId as gestureId.
    • Verifies multi-touch gestures correctly pass individual embedderIds.
    • Verifies no channel call is dispatched when embedderId is 0.
  • Engine Robolectric tests:
    • PlatformViewsControllerTest: Verifies rejectGesture with valid gestureId looks up tracked MotionEvent and enables unbuffered dispatch; verifies mismatched or missing IDs do not enable it.
    • PlatformViewsController2Test: Verifies same behavior on the modern hybrid composition pipeline.
    • FlutterMutatorViewTest and PlatformViewWrapperTest: Verifies gesture tracking across ACTION_DOWN, ACTION_MOVE sequences, and resetting on ACTION_UP/ACTION_CANCEL.

Supersedes #192249

Pre-launch Checklist


Generated with Gemini / AI assistance.

@github-actions github-actions Bot added platform-android Android applications specifically framework flutter/packages/flutter repository. See also f: labels. engine flutter/engine related. See also e: labels. team-android Owned by Android platform team labels Sep 3, 2026
@gmackall gmackall added the CICD Run CI/CD label Sep 3, 2026
@gmackall gmackall changed the title Arena scoped unbuffered Request unbuffered dispatch for platform view motion events after _PlatformViewGestureRecognizer rejects gesture Sep 3, 2026
…re matching downTime

- Pass gesture downTime timestamp (gestureId) from _PlatformViewGestureRecognizer through PlatformViewController to the Android platform views channel.
- In PlatformViewWrapper and FlutterMutatorView, track isGestureActive and currentDownTime.
- Only honor onFlutterWonGesture when a gesture is currently active and the gestureId matches currentDownTime.
- Add comprehensive unit tests verifying matching, mismatched, and post-touch rejection scenarios.
gmackall added a commit to gmackall/flutter that referenced this pull request Sep 3, 2026
@gmackall
gmackall force-pushed the arena-scoped-unbuffered branch from 227b8d7 to ded4972 Compare September 3, 2026 23:28
@github-actions github-actions Bot added the f: scrolling Viewports, list views, slivers, etc. label Sep 4, 2026
gmackall added a commit to gmackall/flutter that referenced this pull request Sep 4, 2026
@gmackall
gmackall force-pushed the arena-scoped-unbuffered branch 4 times, most recently from 7e7ad80 to f2b4df6 Compare September 4, 2026 05:12
gmackall added a commit to gmackall/flutter that referenced this pull request Sep 4, 2026
- Fix multi-touch gestureId tracking in _PlatformViewGestureRecognizer by not clearing _downTimes on acceptGesture, preserving the initial gesture downTime.
- Document cross-language downTime invariant in Dart, AndroidTouchProcessor, and PlatformViewsChannel.
- Guard gestureId != null before calling rejectGesture and use .ignore().
- Deduplicate gesture tracking between FlutterMutatorView and PlatformViewWrapper into PlatformViewGestureTracker with sentinel downTime (-1).
- Restore final on channelHandler in PlatformViewsController and PlatformViewsController2, using constructor injection in PlatformViewsControllerDelegator for testing.
- Reduce test-only visibility surface to package-private where applicable.
- Remove redundant AndroidViewController.rejectGesture override and clarify PlatformViewController.rejectGesture documentation.
- Add multi-touch unit test in platform_view_test.dart and comprehensive tests in PlatformViewGestureTrackerTest.
@gmackall
gmackall force-pushed the arena-scoped-unbuffered branch from 48f22ef to 67204fd Compare September 4, 2026 17:00
@github-actions github-actions Bot removed the f: scrolling Viewports, list views, slivers, etc. label Sep 4, 2026
… constructors

Null-guard platformViewsController and platformViewsController2 when
passing their channelHandler instances to the delegator constructor,
preventing NullPointerExceptions in tests and environments where only one
controller is provided.
…t overload

- Correct comment in platform_view.dart and AndroidTouchProcessor.java
  regarding PointerEventResampler, noting that when resampling is enabled
  PointerDownEvent.timeStamp is resampled to sampleTime and safely degrades
  to buffered dispatch.
- Drop unused onTouchEvent(MotionEvent, View) overload and unused View
  import in PlatformViewGestureTracker.
…ator

PlatformViewsControllerDelegator delegates between two controllers and
cannot function if either controller is null. Mark parameters @nonnull
and remove the unused dead delegator instantiation in
PlatformViewsControllerTest.
@gmackall
gmackall marked this pull request as ready for review September 4, 2026 22:47
@auto-submit

auto-submit Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/192259, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@gmackall gmackall added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 11, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 11, 2026
@auto-submit

auto-submit Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/192259, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@gmackall gmackall added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 11, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 11, 2026
@auto-submit

auto-submit Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/192259, because - The status or check suite Mac_arm64_verify_binaries has failed. Please fix the issues identified (or deflake) before re-applying this label.

@gmackall gmackall added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 11, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 11, 2026
@auto-submit

auto-submit Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/192259, because - The status or check suite Google testing has failed. Please fix the issues identified (or deflake) before re-applying this label.

@gmackall gmackall added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 14, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 14, 2026
@auto-submit

auto-submit Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/192259, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label.

@gmackall gmackall added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 14, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Sep 14, 2026
Merged via the queue into flutter:master with commit c5ddcd2 Sep 14, 2026
29 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 14, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Sep 16, 2026
flutter/flutter@8b3e8f5...27fec0e

2026-09-14 ttankkeo112@gmail.com Add dedicated rubber band spring for overscroll recovery in BouncingScrollPhysics (flutter/flutter#187568)
2026-09-14 engine-flutter-autoroll@skia.org Roll Skia from 83c984a6daf5 to 59904977fcbb (8 revisions) (flutter/flutter#192767)
2026-09-14 34871572+gmackall@users.noreply.github.com Request unbuffered dispatch for platform view motion events after `_PlatformViewGestureRecognizer` rejects gesture (flutter/flutter#192259)
2026-09-14 engine-flutter-autoroll@skia.org Roll Fuchsia GN SDK from ZsxUUK2SfA-TrNvb8... to PDJz3b3CL31uoLOkD... (flutter/flutter#192440)
2026-09-14 codefu@google.com ci(bringup): cleanup some bringup (flutter/flutter#192752)
2026-09-14 kevmoo@users.noreply.github.com Warn users on potential removal of dart:html in dry run (flutter/flutter#192710)
2026-09-14 codefu@google.com docs: migrate design document guidance to flutter/rfc (flutter/flutter#192648)
2026-09-14 154381524+flutteractionsbot@users.noreply.github.com Sync CHANGELOG.md from stable (flutter/flutter#192499)
2026-09-14 engine-flutter-autoroll@skia.org Roll Skia from 7a6fd7ff72d5 to 83c984a6daf5 (1 revision) (flutter/flutter#192745)
2026-09-14 1961493+harryterkelsen@users.noreply.github.com RELAND: [devicelab] Clean up Chrome profile directories and trap abort signals in web benchmarks (flutter/flutter#192655)
2026-09-14 kevmoo@users.noreply.github.com fix(web): hide --web-content-hash until content hashing is complete (flutter/flutter#192663)
2026-09-14 engine-flutter-autoroll@skia.org Roll Skia from 527751088719 to 7a6fd7ff72d5 (2 revisions) (flutter/flutter#192725)
2026-09-14 engine-flutter-autoroll@skia.org Roll Skia from eaf9f82813eb to 527751088719 (1 revision) (flutter/flutter#192722)
2026-09-14 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from AQu85JoTHCMET3Q8G... to 7R1l5MhSZZUr1Q6D1... (flutter/flutter#192719)
2026-09-14 robert.ancell@canonical.com [Linux] Clear the frame when there is nothing to render (flutter/flutter#192461)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com,tarrinneal@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels. framework flutter/packages/flutter repository. See also f: labels. platform-android Android applications specifically team-android Owned by Android platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants