Repository navigation
[Android] Guard PlatformViewsController2.onEndFrame against a detached FlutterView - #190612
Merged
auto-submit[bot] merged 3 commits intoAug 19, 2026
Merged
Conversation
…d FlutterView onEndFrame() runs on the platform thread but is posted from the raster thread by AndroidExternalViewEmbedder2::SubmitFlutterView, on every frame including frames with no platform layers. By the time it runs the FlutterView may have been detached from the controller, or detached from its window -- and View.getRootSurfaceControl() returns null when the view is not attached to a window. Neither case was guarded. The resulting NullPointerException is not merely logged: the JNI caller, onEndFrame2(), ends with FML_CHECK(fml::jni::CheckException(env)), which turns any pending Java exception into abort(). There is no Dart-side recovery, so this takes down the process. Null-check both, and close the merged transaction on the early return so it does not leak.
Contributor
There was a problem hiding this comment.
Code Review
This pull request updates PlatformViewsController2.java to prevent potential crashes during onEndFrame() when the FlutterView is detached or its root surface control is null. It introduces null checks for flutterView and its root surface control, closing the transaction and returning early if either is null. Additionally, corresponding unit tests are added in PlatformViewsController2Test.java to verify this behavior. I have no further feedback to provide.
gmackall
approved these changes
Aug 18, 2026
gmackall
left a comment
Member
There was a problem hiding this comment.
lgtm, thanks for the pr and investigation
mboetger
approved these changes
Aug 18, 2026
This was referenced Aug 19, 2026
MylioScott
pushed a commit
to mylollc/flutter
that referenced
this pull request
Oct 14, 2026
…d FlutterView (flutter#190612) `PlatformViewsController2.onEndFrame()` dereferenced `flutterView` and the result of `flutterView.getRootSurfaceControl()` without checking either for null. `AndroidExternalViewEmbedder2::SubmitFlutterView()` posts `onEndFrame2()` from the raster thread to the platform thread on every frame, including frames with no platform layers. By the time the task runs, the `FlutterView` may have been detached from the controller, in which case `detachFromView()` has set `flutterView` to null, or detached from its window, in which case `View.getRootSurfaceControl()` returns null. The resulting `NullPointerException` is not merely logged. The JNI call ends with `FML_CHECK(fml::jni::CheckException(env))`, which converts the pending Java exception into an `abort()`. This change guards both nullable values and closes the merged `SurfaceControl.Transaction` before returning early so that it is not leaked. It also moves `flutterView.invalidate()` below the guard. Fixes flutter#190609 (cherry picked from commit 8bcda46) Cherry-pick note: the import hunk was placed by hand because this branch does not carry flutter#184732 (rect clipping for surface views); nothing else changed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PlatformViewsController2.onEndFrame()dereferencedflutterViewand the result offlutterView.getRootSurfaceControl()without checking either for null.AndroidExternalViewEmbedder2::SubmitFlutterView()postsonEndFrame2()from the raster thread tothe platform thread on every frame, including frames with no platform layers. By the time the task
runs, the
FlutterViewmay have been detached from the controller, in which casedetachFromView()has setflutterViewto null, or detached from its window, in which caseView.getRootSurfaceControl()returns null.The resulting
NullPointerExceptionis not merely logged. The JNI call ends withFML_CHECK(fml::jni::CheckException(env)), which converts the pending Java exception into anabort(). This terminates the process with no Dart-side recovery or application-level workaroundother than disabling HCPP.
This change guards both nullable values and closes the merged
SurfaceControl.Transactionbeforereturning early so that it is not leaked. It also moves
flutterView.invalidate()below the guard,because that call was itself unsafe when
flutterViewwas null.The issue reproduces on every warm teardown when an HCPP platform view is visible and the
FlutterEngineoutlives its activity. In a 10-launch loop, the unpatched embedding produced fiveaborts because every abort killed the process and made the following launch a cold start.
Verified locally on an Android 16 emulator by compiling the patched class into the prebuilt
embedding JAR: 0 aborts across 12 teardowns. Platform-view rendering continued to work after
reattaching the engine. The reproduction app and full before-and-after logs are included in the
linked issue.
Fixes #190609
Pre-launch Checklist
///).