Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: flutter/flutter
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c09109874faa
Choose a base ref
...
head repository: flutter/flutter
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5e805bfd5816
Choose a head ref
  • 15 commits
  • 26 files changed
  • 8 contributors

Commits on Oct 30, 2026

  1. Roll Skia from 4ecd22a4a1d0 to ec13cd547e98 (10 revisions) (#195647)

    https://skia.googlesource.com/skia.git/+log/4ecd22a4a1d0..ec13cd547e98
    
    2026-10-30
    recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com
    Roll recipe dependencies (trivial).
    2026-10-30
    recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com
    Roll recipe dependencies (trivial).
    2026-10-29
    recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com
    Roll recipe dependencies (trivial).
    2026-10-29
    recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com
    Roll recipe dependencies (trivial).
    2026-10-29
    recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com
    Roll recipe dependencies (trivial).
    2026-10-29 [email protected] Remove SkAvifCodec and libavif
    dependencies
    2026-10-29 [email protected] [graphite] Remove the TODO about
    passing opacity to GetBlendFormula in ShaderInfo
    2026-10-29 [email protected] gn_to_bp: Add *.sksl to
    extra_include_dir_deps
    2026-10-29 [email protected] [Ganesh] Initialize fCurrentRenderPass in
    GrVkOpsRenderPass.
    2026-10-29 [email protected] [Graphite] Treat inverse fills
    which cover the scissor as flood fill
    
    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/skia-flutter-autoroll
    Please CC [email protected],[email protected],[email protected]
    on the revert to ensure that a human
    is aware of the problem.
    
    To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry
    To file a bug in Flutter:
    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
    engine-flutter-autoroll authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    c4f78a7 View commit details
    Browse the repository at this point in the history
  2. [web] Unskip web tests that pass on CanvasKit and Skwasm: accessibili…

    …ty_inspector_test, color_filter_test (#195541)
    
    <!--
    Thanks for filing a pull request!
    Reviewers are typically assigned within a week of filing a request.
    To learn more about code review, see our documentation on Tree Hygiene:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
    -->
    
    Removes the unexplained file-level `@TestOn('!chrome')` annotations from
    two widget test files so they also run on the web:
    
    - `packages/flutter/test/widgets/accessibility_inspector_test.dart`:
    every test passes on Chrome with both CanvasKit (dart2js) and Skwasm
    (dart2wasm).
    - `packages/flutter/test/widgets/color_filter_test.dart`: four of the
    five tests pass on Chrome with both CanvasKit and Skwasm. The
    `color_filter_red.png` and `color_filter_saturation.png` goldens match
    the Linux baselines. The `Color filter - sepia` golden test is still
    skipped on web (`skip: kIsWeb`, with a comment saying why). Its `Text`
    widgets have no color set, and the web engine draws text with no color
    in black, while native draws it white, so the golden comes out
    different.
    
    Keeping the whole files skipped hid any web regressions in these tests.
    
    No tracking issue: neither `@TestOn('!chrome')` annotation pointed to an
    issue, and this is a test-only change.
    
    ## Pre-launch Checklist
    
    - [x] I read the [Contributor Guide] and followed the process outlined
    there for submitting PRs.
    - [x] I read the [AI contribution guidelines] and understand my
    responsibilities, or I am not using AI tools.
    - [x] I read the [Tree Hygiene] wiki page, which explains my
    responsibilities.
    - [x] I read and followed the [Flutter Style Guide], including [Features
    we expect every widget to implement].
    - [x] I signed the [CLA].
    - [ ] I listed at least one issue that this PR fixes in the description
    above.
    - [x] I updated/added relevant in-code documentation (doc comments with
    `///`).
    - [x] If this PR introduces a new feature or capability, I created and
    linked a website documentation issue or PR in [flutter/website] (or
    verified none is needed).
    - [x] I added new tests to check the change I am making, or this PR is
    [test-exempt].
    - [x] I followed the [breaking change policy] and added [Data Driven
    Fixes] where supported.
    - [x] All existing and new tests are passing.
    
    If you need help, consider asking for advice on the #hackers-new channel
    on [Discord].
    
    If this change needs to override an active code freeze, provide a
    comment explaining why. The code freeze workflow can be overridden by
    code reviewers. See pinned issues for any active code freezes with
    guidance.
    
    **Note**: The Flutter team is currently trialing the use of [Gemini Code
    Assist for
    GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
    Comments from the `gemini-code-assist` bot should not be taken as
    authoritative feedback from the Flutter team. If you find its comments
    useful you can update your code accordingly, but if you are unsure or
    disagree with the feedback, please feel free to wait for a Flutter team
    member's review for guidance on which automated comments should be
    addressed.
    
    <!-- Links -->
    [Contributor Guide]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
    [AI contribution guidelines]:
    https://github.com/flutter/flutter/blob/main/CONTRIBUTING.ai.md
    [Tree Hygiene]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
    [test-exempt]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
    [Flutter Style Guide]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
    [Features we expect every widget to implement]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
    [CLA]: https://cla.developers.google.com/
    [flutter/tests]: https://github.com/flutter/tests
    [flutter/website]: https://github.com/flutter/website
    [breaking change policy]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
    [Discord]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
    [Data Driven Fixes]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
    harryterkelsen authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    384f7ec View commit details
    Browse the repository at this point in the history
  3. [web_paragraph] Fix multi-span BiDi span order and region direction (#…

    …194980)
    
    Within an RTL `BidiRun`, logical spans progress from right to left, so
    `TextLayout.addLine` must iterate `paragraph.spans` in reverse logical
    order to append visual blocks from left to right.
    
    Additionally, `TextSpan._getMetrics` previously measured each span in
    isolation using the paragraph's default direction, causing leading or
    isolated neutral characters in a span following an RTL span to be
    measured as LTR (`level = 0`) instead of RTL (`level = 1` per UAX #9 N1)
    and embedded LTR spans inside an RTL paragraph to be measured as RTL.
    `WebParagraph._resolveSpans` now keeps the builder-supplied
    `_styleSpans` private, splits text spans at paragraph-level
    `bidiRegions` boundaries, and exposes only the BiDi-resolved
    `WebParagraph.spans` with each sub-span's resolved region direction so
    `extractTextClusters` and `Canvas2D` metrics match paragraph-level BiDi
    runs.
    
    ### Reviewer & AI Audit Context
    - **Core Logic Hunks**: `+75 / -9` production lines in
    `engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/paragraph.dart`
    and
    `engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/layout.dart`
    (`WebParagraph._resolveSpans()`, `TextLayout.extractBidiRuns()`,
    `TextLayout.addLine()`) and `+182 / -0` test lines in
    `engine/src/flutter/lib/web_ui/test/webparagraph/paragraph_bidi_test.dart`.
    - **C++ `SkParagraph` Parity Anchor**: Matches
    `OneLineShaper::iterateThroughShapingRegions`
    (`engine/src/flutter/third_party/skia/modules/skparagraph/src/OneLineShaper.cpp:556-578,
    697`), which intersects paragraph-level `fBidiRegions` with style
    `Block`s so each shaped run has a single UAX #9 level, and
    `TextLine::iterateThroughSingleRunByStyles`
    (`engine/src/flutter/third_party/skia/modules/skparagraph/src/TextLine.cpp:1034-1035`),
    which traverses style blocks in reverse logical order
    (`run->leftToRight() ? fBlockRange.start + index : fBlockRange.end -
    index - 1`) within RTL runs.
    - **Callers & Precondition Proofs**:
    - Exposing only the BiDi-resolved `WebParagraph.spans` (while keeping
    builder-supplied `_styleSpans` private) guarantees that `layout.dart`,
    `wrapper.dart`, and `painter.dart` cannot accidentally read unsplit
    spans.
    - Within each UAX #9 `BidiRegion` sub-span, `Canvas2D`
    `getTextClusters()` emits clusters in monotonic logical offset order
    (`engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/paragraph.dart:783`,
    Ledger `L007`), and `TextBlock` / `TextPainter` whole-block and
    per-cluster rendering translate by `spanShiftFromLineStart =
    shiftFromLineStart - shiftFromSpanStart`
    (`engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/layout.dart:381,
    1306`,
    `engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/painter.dart:356-360`),
    which handles RTL sub-spans measured in `[-spanWidth, 0]`.
    - **Cross-Phase Consumer Check (`Placeholders` / `Backgrounds` /
    `Queries`)**:
    - `PlaceholderSpan`s are preserved without `Canvas2D` text measurement
    in `_resolveSpans()` and positioned in visual left-to-right order
    alongside `TextBlock`s in `addLine()`.
    - `TextPainter` backgrounds/decorations
    (`engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/painter.dart:214,
    346`), `getBoxesForRange`
    (`engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/layout.dart:587`),
    `getPositionForOffset`
    (`engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/layout.dart:774`),
    and `getGlyphInfoAt`
    (`engine/src/flutter/lib/web_ui/lib/src/engine/web_paragraph/layout.dart:888`)
    all consume `line.visualBlocks` and `spanShiftFromLineStart`, so visual
    left-to-right block ordering and sub-span direction propagate across
    painting, selection boxes, and hit-testing.
    
    ### Tests
    -
    `engine/src/flutter/lib/web_ui/test/webparagraph/paragraph_bidi_test.dart`:
    - `Paragraph BiDi order and layout within multi-span RTL bidi run` —
    verifies left-to-right visual box ordering (`"BiDi "` -> `"שלום"` -> `"
    & "` -> `"مرحبا بالعالم"` -> `" · Emoji ..."`),
    `GlyphInfo.writingDirection` and cluster bounds, and
    `getPositionForOffset` hit-testing across a span that crosses an
    RTL->LTR boundary.
    - `Paragraph BiDi isolated neutral span between RTL spans in LTR
    paragraph` — verifies that an isolated neutral span (`" + "`) between
    two RTL spans resolves to RTL (`level = 1`) and is positioned visually
    between `"שלום"` and `"مرحبا"`.
    - `Paragraph BiDi multi-span order in RTL paragraph` — verifies that two
    RTL spans in an RTL paragraph (`"שלום "` followed by bold `"עולם"`) are
    ordered visually from right to left (`second.right == first.left`).
    - `Embedded multi-span LTR run inside RTL paragraph` — verifies that
    `_resolveSpans` overrides the RTL paragraph direction to
    `TextDirection.ltr` for an embedded multi-span LTR run (`"Hello"`, `" +
    "`, `"World"`).
    - `Multi-span RTL run with inline placeholder` — verifies that an inline
    `PlaceholderSpan` between two RTL text spans is preserved by
    `_resolveSpans` and positioned visually between them (`second` ->
    placeholder -> `first`).
    - **Full WebParagraph corpus (`--full`, `preferWebParagraph` +
    `forceTestFonts` on `40c36fffd2ec`)**:
    - Part 1 (`engine/src/flutter/lib/web_ui`): `17/17`
    `engine/src/flutter/lib/web_ui/test/webparagraph` suites (`+214 ~5 -1`,
    all 8 BiDi tests passing) + `62/62`
    `engine/src/flutter/lib/web_ui/test/ui` suites (`+196 ~0 -44`).
    - Part 2 (`packages/flutter`, `896/896` suites across `8/8` shards):
    `+16478 ~1231 -812` (`0` compile errors or unfinished shards).
    
    ## Pre-launch Checklist
    
    - [x] I read the [Contributor Guide] and followed the process outlined
    there for submitting PRs.
    - [x] I read the [Tree Hygiene] wiki page, which explains my
    responsibilities.
    - [x] I read and followed the [Flutter Style Guide], including [Features
    we expect every widget to implement].
    - [x] I signed the [CLA].
    - [ ] I listed at least one issue that this PR fixes in the description
    above.
    - [x] I updated/added relevant documentation (doc comments with `///`).
    - [x] I added new tests to check the change I am making, or this PR is
    [test-exempt].
    - [x] I followed the [breaking change policy] and added [Data Driven
    Fixes] where supported.
    - [x] All existing and new tests are passing.
    
    Assisted-by: Gemini 4 Argon (Medium)
    Rusino authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    8a72c88 View commit details
    Browse the repository at this point in the history
  4. [web] Keep semantics editing state while the text input connection is…

    … open (#195141)
    
    Fixes #194636
    
     ## Problem
    On web with semantics enabled, a focused `TextField` loses its text when
    its semantics node leaves the tree and comes back, for example after
    scrolling it out of a `ListView` and back. The framework keeps the
    connection open, but `SemanticsTextEditingStrategy.deactivate()` called
    `disable()`, which cleared connection state when the DOM `<input>` was
    disposed. The re-created element came back empty and unstyled, and its
    first `selectionchange` sent `""` to the framework as an edit.
    
    ## Fix
    `SemanticsTextEditingStrategy` now keeps the element lifecycle separate
    from the connection lifecycle. `deactivate()` only detaches the
    `<input>` through a new `_detachElement()`, and `disable()` detaches and
    then clears the connection state, which is the editing state, queued
    style, config and callbacks. A re-created element therefore gets its
    text and style back from `activate()`. `activate()` also returns early
    when no connection is open, so a field that stays focused after
    `TextInput.hide` is not attached with a null config.
    
    ## Demo
    Before: https://flutter-demo-07-before.web.app
    After: https://flutter-demo-07-after.web.app
    
    In desktop Chrome, click the text field, which holds `hello`, and
    optionally type ` world`. Scroll the list down with the mouse wheel
    until the field is off-screen, then scroll back up. Before: the field is
    empty and the bottom bar reads `controller.text = ""`. After: the field
    still shows the text and the bottom bar matches.
    flutter-zl authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    a3bcce1 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    71a3cf1 View commit details
    Browse the repository at this point in the history
  6. Roll Skia from 9f4e3117465e to 4470b8abaad6 (4 revisions) (#195658)

    https://skia.googlesource.com/skia.git/+log/9f4e3117465e..4470b8abaad6
    
    2026-10-30 [email protected] Roll Dawn
    from 432d5a4f7036 to 2e9d054d9b5b (14 revisions)
    2026-10-30 [email protected] Roll
    jsfiddle-base from 267ae6e25ccf to 3add41d53db4
    2026-10-30 [email protected] Roll
    debugger-app-base from 2ad3bc7e2843 to 33d97d296d89
    2026-10-30 [email protected] Roll
    fiddler-base from 4a9260b9789d to 3112cc649c53
    
    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/skia-flutter-autoroll
    Please CC [email protected],[email protected],[email protected]
    on the revert to ensure that a human
    is aware of the problem.
    
    To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry
    To file a bug in Flutter:
    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
    engine-flutter-autoroll authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    95fcedc View commit details
    Browse the repository at this point in the history
  7. Configuration menu
    Copy the full SHA
    00fdaae View commit details
    Browse the repository at this point in the history
  8. Configuration menu
    Copy the full SHA
    8d5617f View commit details
    Browse the repository at this point in the history
  9. Configuration menu
    Copy the full SHA
    5bc7eda View commit details
    Browse the repository at this point in the history
  10. Configuration menu
    Copy the full SHA
    a682eb3 View commit details
    Browse the repository at this point in the history
  11. Configuration menu
    Copy the full SHA
    8f3664d View commit details
    Browse the repository at this point in the history
  12. Roll Packages from 0b72e92 to 3742a4e (12 revisions) (#195686)

    flutter/packages@0b72e92...3742a4e
    
    2026-10-30 [email protected] [pigeon] Allow event channel
    unregistration (flutter/packages#13438)
    2026-10-30 [email protected] [material_ui] Fix Escape key not
    closing MenuAnchor opened by tap or click (flutter/packages#13430)
    2026-10-30 [email protected] manual roll and manual build and copy
    (flutter/packages#13495)
    2026-10-29 [email protected] [pigeon] Separate native interop Dart
    bindings into a conditionally imported companion file
    (flutter/packages#13393)
    2026-10-29 [email protected] [image_picker_ios] PR 4/5 Migrate
    the view provider, PHPicker save operation, and image utilities to Swift
    (flutter/packages#13394)
    2026-10-29 [email protected] Sync release-material_ui-1.9.0 to
    main (flutter/packages#13479)
    2026-10-29 [email protected] [material_ui]
    Unskip web tests that pass on CanvasKit and Skwasm: time_picker_test
    (flutter/packages#13471)
    2026-10-29 [email protected] [vector_graphics]
    Dispose pictures decoded after their VectorGraphic is removed
    (flutter/packages#13435)
    2026-10-29 [email protected]
    [camera_android_x] implement CameraX RecordingStats and VideoRecordEvent
    APIs (flutter/packages#13330)
    2026-10-29 [email protected] Sync release-go_router-18.1.2 to
    main (flutter/packages#13480)
    2026-10-29 [email protected] Sync release-cupertino_ui-1.1.5 to
    main (flutter/packages#13481)
    2026-10-29 [email protected]
    [vector_graphics_compiler] Fix em units in text positions
    (flutter/packages#13388)
    
    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-flutter-autoroll
    Please CC [email protected] on the revert to ensure that a
    human
    is aware of the problem.
    
    To file a bug in Flutter:
    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
    engine-flutter-autoroll authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    64042ca View commit details
    Browse the repository at this point in the history
  13. [Impeller] Minify GLSL shaders (#195240)

    For the GLSL shaders that get baked into the engine as textual source,
    this PR:
    - Removes comments and whitespace,
    - Removes needless precision from float literals
    
    This shrinks the GLSL shaders bundled into the engine by ~150KB,
    reducing the uncompressed size of libflutter.so by roughly that amount.
    This impacts the on-disk and in-memory size of the engine, but only
    reduces the in-transit apk by under 20KB since the text compresses well.
    
    Later, we can decide whether to also shorten variable names, which would
    save an additional ~40KB.
    
    ## Pre-launch Checklist
    
    - [x] I read the [Contributor Guide] and followed the process outlined
    there for submitting PRs.
    - [x] I read the [AI contribution guidelines] and understand my
    responsibilities, or I am not using AI tools.
    - [x] I read the [Tree Hygiene] wiki page, which explains my
    responsibilities.
    - [x] I read and followed the [Flutter Style Guide], including [Features
    we expect every widget to implement].
    - [x] I signed the [CLA].
    - [x] I listed at least one issue that this PR fixes in the description
    above.
    - [x] I updated/added relevant in-code documentation (doc comments with
    `///`).
    - [x] If this PR introduces a new feature or capability, I created and
    linked a website documentation issue or PR in [flutter/website] (or
    verified none is needed).
    - [x] I added new tests to check the change I am making, or this PR is
    [test-exempt].
    - [x] I followed the [breaking change policy] and added [Data Driven
    Fixes] where supported.
    - [x] All existing and new tests are passing.
    
    If you need help, consider asking for advice on the #hackers-new channel
    on [Discord].
    
    If this change needs to override an active code freeze, provide a
    comment explaining why. The code freeze workflow can be overridden by
    code reviewers. See pinned issues for any active code freezes with
    guidance.
    
    **Note**: The Flutter team is currently trialing the use of [Gemini Code
    Assist for
    GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
    Comments from the `gemini-code-assist` bot should not be taken as
    authoritative feedback from the Flutter team. If you find its comments
    useful you can update your code accordingly, but if you are unsure or
    disagree with the feedback, please feel free to wait for a Flutter team
    member's review for guidance on which automated comments should be
    addressed.
    
    <!-- Links -->
    [Contributor Guide]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
    [AI contribution guidelines]:
    https://github.com/flutter/flutter/blob/main/CONTRIBUTING.ai.md
    [Tree Hygiene]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
    [test-exempt]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
    [Flutter Style Guide]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
    [Features we expect every widget to implement]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
    [CLA]: https://cla.developers.google.com/
    [flutter/tests]: https://github.com/flutter/tests
    [flutter/website]: https://github.com/flutter/website
    [breaking change policy]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
    [Discord]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
    [Data Driven Fixes]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
    zanderso authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    cf912e3 View commit details
    Browse the repository at this point in the history
  14. [FGP] Report the real error when applying kotlin-android fails (#195080)

    When `android.builtInKotlin=false` and `android.newDsl=true`, the
    Flutter Gradle Plugin said "KGP was not found on the classpath". The
    real error from the Kotlin Gradle Plugin was hidden. The build then
    failed with an unrelated script compilation error.
    
    This change catches only the missing-plugin case, so other failures show
    the Kotlin Gradle Plugin's own message.
    
    Related to #181557 and
    #189236.
    
    <details><summary>Agent authored details</summary>
    
    `FlutterPluginUtils.detectApplyingKotlinGradlePlugin` wrapped
    `pluginManager.apply("kotlin-android")` in `catch (_: Exception)`. It
    now catches `org.gradle.api.plugins.UnknownPluginException`, which
    Gradle's `DefaultPluginManager.apply(String)` throws for an unknown
    plugin id. Failures inside the plugin's own `apply` are wrapped
    differently and now propagate.
    
    Before (AGP 9.3.1, KGP 2.4.20, template app, `builtInKotlin=false`,
    `newDsl=true`):
    ```
    Applying the Kotlin Android Plugin (KGP) was unsuccessful. KGP was not found on the classpath.
    ...
    * What went wrong:
    Script compilation errors:
      Line 41: kotlin {
    ```
    After:
    ```
    > Failed to apply plugin 'kotlin-android'.
       > ⛔ Failed to apply plugin 'org.jetbrains.kotlin.android'
         The 'org.jetbrains.kotlin.android' plugin is not compatible with AGP's 9.0 new DSL (`android.newDsl=true` is enabled by default).
         Solution: Set `android.builtInKotlin=true` in `gradle.properties` and migrate to built-in Kotlin (see https://kotl.in/gradle/agp-built-in-kotlin for guidance), or set `android.newDsl=false` in `gradle.properties` to temporarily bypass this issue.
    ```
    
    Tests: the two existing "KGP fails to apply" tests now throw
    `UnknownPluginException`. Added `propagates a KGP failure that is not a
    missing plugin`.
    
    No comments, docs or tests removed.
    
    Verification: `./gradlew test` (JDK 17) passed. ktlint 1.5.0 with the CI
    flags passed. A manual build of the template app was run before and
    after.
    
    Note: with AGP 9, KGP resolves through AGP even when
    `settings.gradle.kts` does not declare it, so the missing-plugin branch
    is hard to reach in practice.
    
    This applies cleanly to `flutter-3.50-candidate.0`;
    `FlutterPluginUtils.kt` is identical there.
    </details>
    
    ## Pre-launch Checklist
    
    - [x] I read the [Contributor Guide] and followed the process outlined
    there for submitting PRs.
    - [x] I read the [AI contribution guidelines] and understand my
    responsibilities, or I am not using AI tools.
    - [x] I read the [Tree Hygiene] wiki page, which explains my
    responsibilities.
    - [x] I read and followed the [Flutter Style Guide], including [Features
    we expect every widget to implement].
    - [x] I signed the [CLA].
    - [x] I listed at least one issue that this PR fixes in the description
    above.
    - [x] I updated/added relevant in-code documentation (doc comments with
    `///`).
    - [ ] If this PR introduces a new feature or capability, I created and
    linked a website documentation issue or PR in [flutter/website] (or
    verified none is needed).
    - [x] I added new tests to check the change I am making, or this PR is
    [test-exempt].
    - [x] I followed the [breaking change policy] and added [Data Driven
    Fixes] where supported.
    - [x] All existing and new tests are passing.
    
    If you need help, consider asking for advice on the #hackers-new channel
    on [Discord].
    
    If this change needs to override an active code freeze, provide a
    comment explaining why. The code freeze workflow can be overridden by
    code reviewers. See pinned issues for any active code freezes with
    guidance.
    
    **Note**: The Flutter team is currently trialing the use of [Gemini Code
    Assist for
    GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
    Comments from the `gemini-code-assist` bot should not be taken as
    authoritative feedback from the Flutter team. If you find its comments
    useful you can update your code accordingly, but if you are unsure or
    disagree with the feedback, please feel free to wait for a Flutter team
    member's review for guidance on which automated comments should be
    addressed.
    
    <!-- Links -->
    [Contributor Guide]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
    [AI contribution guidelines]:
    https://github.com/flutter/flutter/blob/main/CONTRIBUTING.ai.md
    [Tree Hygiene]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
    [test-exempt]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
    [Flutter Style Guide]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
    [Features we expect every widget to implement]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
    [CLA]: https://cla.developers.google.com/
    [flutter/tests]: https://github.com/flutter/tests
    [flutter/website]: https://github.com/flutter/website
    [breaking change policy]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
    [Discord]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
    [Data Driven Fixes]:
    https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
    reidbaker-agent authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    a006537 View commit details
    Browse the repository at this point in the history
  15. Fix/shared thread merger expired lease (#194200)

    Fixes #194536.
    
    ## Summary
    
    Remove expired caller lease records from `SharedThreadMerger` to prevent
    an engine from aborting when it resumes drawing while another engine
    keeps the shared raster/platform queues merged.
    
    Related to #153211. This PR addresses the `lease_term_ref > 0` assertion
    reported there, including the corresponding Android scenario. It does
    not claim to resolve the separate deadlock or backgrounding symptoms
    discussed in that issue.
    
    ## Problem
    
    Multiple `RasterThreadMerger` instances can share one
    `SharedThreadMerger`. The merged state is shared, but each caller has
    its own lease.
    
    The crash occurs in this sequence:
    
    1. Engine A merges with a lease of 1 and consumes it. The queues
    unmerge, but A's zero-valued entry remains in `lease_term_by_caller_`.
    2. Engine B merges the shared queues with an active lease.
    3. Engine A resumes drawing. The shared merger reports merged because
    B's lease is active.
    4. A calls `DecrementLease()`, finds its stale zero-valued entry, and
    aborts on `FML_CHECK(lease_term_ref > 0)`.
    
    We reproduced this defect on Android. #153211 reports the same assertion
    on iOS and includes an [Android
    report](#153211 (comment))
    involving engines in the same `FlutterEngineGroup`.
    
    The affected implementation is shared C++ code. However, the iOS
    application reproduction from #153211 has not been tested with this
    patch.
    
    ## Change
    
    - Remove the caller's map entry immediately when its lease reaches zero,
    under the existing mutex.
    - Preserve the positive-lease assertion for existing entries.
    - Allow subsequent draws from an expired caller to use the
    missing-caller path without consuming another caller's lease.
    - Use `FML_VLOG(1)` for the missing-caller path, since it can occur
    during normal rendering.
    - Combine decrement and expiration checking with `--lease_term_ref`.
    - Clarify comments describing caller lease lifetime and the shared merge
    state.
    
    The existing all-zero check handles an empty map, so the queues still
    unmerge when the final active lease expires.
    
    This is an internal Engine bug fix with no public API change or
    migration requirement.
    
    ## Production workaround
    
    In our Android return-to-bottom scenario, explicitly destroying the
    outgoing/top Flutter engine in the Activity's `finish()` method, instead
    of waiting for `onDestroy()`, avoids this crash. We have validated this
    application-level workaround in production.
    
    This changes teardown timing for the transition where the bottom
    Activity can resume drawing before the top Activity reaches
    `onDestroy()`. It is a workaround for the affected lifecycle sequence;
    the stale zero-lease record still needs to be fixed in the Engine.
    Production validation here applies to the workaround. Patched-Engine
    Android device results are documented below; iOS application validation
    remains pending.
    
    ## Tests
    
    Adds
    `RasterThreadMerger.ExpiredLeaseCanDecrementWhileAnotherCallerIsMerged`,
    covering:
    
    - Resuming drawing after a caller's lease expires while another caller
    keeps the queues merged.
    - Repeated decrements from the expired caller without consuming the
    other caller's lease.
    - Unmerging when the remaining lease expires.
    - Reacquiring and consuming a lease after unmerging.
    
    Validated locally on macOS arm64 with `host_debug_unopt_arm64`:
    
    - Built `//flutter/fml:fml_unittests`.
    - New regression test: **1 passed**.
    - All `RasterThreadMerger` tests: **17 passed**.
    - Full `fml_unittests`: **204 tests across 38 test suites passed**.
    - Ran clang-format on changed lines and `git diff --check`.
    
    A standalone reproduction using the real FML shared merger and task
    queue implementations triggers the original assertion before the fix and
    passes afterward.
    
    Patched-Engine Android device results are documented below. iOS
    application validation, upstream CI and maintainer review remain
    pending.
    
    ### Android device reproduction (unpatched Engine)
    
    Confirmed the target SIGABRT on an Android test device running Android
    17 with Flutter 3.35.3, Engine `ddf47dd3ff`, debug mode, and Impeller
    Vulkan. The demo and app-specific crash evidence are attached to
    #194536:
    
    
    -
    [lease-zero-demo-sanitized.zip](https://github.com/user-attachments/files/33544786/lease-zero-demo-sanitized.zip)
    -
    [zero-lease-crash-sanitized.zip](https://github.com/user-attachments/files/33544788/zero-lease-crash-sanitized.zip)
    
    The demo adds a hybrid-composition PlatformView to the bottom engine,
    removes it and requests 40 frames, then opens a top Activity with a
    PlatformView in another engine from the same FlutterEngineGroup. Two
    initial automated cycles did not crash; a subsequent manual cycle in the
    same process did. The observed abort occurred while opening top again,
    after top onPostResume and before the return operation. Reproduction is
    timing-dependent; no success rate is claimed.
    
    The captured abort is `shared_thread_merger.cc(59): lease_term_ref > 0`,
    with `lease_term=0`. This confirms the application-level failure on the
    unpatched Engine.
    
    ### Android device validation (patched Engine, 2026-10-16)
    
    Validated the locally built patch on **an Android test device running
    Android 17 (API 37)** in debug mode. Framework and Engine source both
    used this PR's head, `bf3e0b302cdb437b932aecc07709f266eb545597`, with
    `android_debug_unopt_arm64` and matching `host_debug_unopt_arm64`
    artifacts.
    
    - Built with `--no-enable-hcpp` to exercise legacy Hybrid Composition;
    the APK manifest explicitly sets `EnableHcpp=false`. The `finish()`
    early-destroy workaround was **not enabled**.
    - Completed **30/30 ADD -> REMOVE -> OPEN -> return cycles** across
    three independent app processes, 10 cycles each: 10 with the verbose
    Engine flag and 20 with normal logging. No zero-lease assertion, native
    fatal signal, fatal Java exception, Dart exception, or process restart
    was observed.
    - Logs record **60 legacy HC PlatformView creations** and **30 returns**
    in which bottom `onResume()` requested Dart redraw while the top engine
    was still alive, before top `onDestroy()`.
    - Verified that the installed APK SHA-256 matches the built APK, and the
    APK's `libflutter.so` Build ID matches the local Engine:
    `351451851bb71400213aa0c9764406986940c8c4`.
    - Reran the rebuilt host `RasterThreadMerger.*` suite: **17/17 passed**,
    including the new regression.
    
    
    Validation report, event sequences, per-cycle results, and binary
    identity checks:
    [engine-validation-sanitized.zip](https://github.com/user-attachments/files/33544787/engine-validation-sanitized.zip)
    
    The logs also contain 19 nonfatal `Could not make the resource context
    current.` messages; the cycles and an additional real-touch
    responsiveness check still completed. These are recorded in the attached
    report.
    
    The original unpatched device crash used Flutter 3.35.3 / Engine
    `ddf47dd3ff`. A device A/B comparison at the same framework revision
    with only this patch removed has not been run. The demo is
    timing-dependent, so these results provide bounded Android regression
    evidence. iOS application validation remains pending. The verbose Engine
    flag does not enable `FML_VLOG(1)`, so these device logs do not
    demonstrate direct coverage of the expired-caller branch; the
    deterministic C++ regression covers that behavior.
    
    ## Pre-launch Checklist
    
    - [x] I read the [Contributor Guide] and followed the process outlined
    there for submitting PRs.
    - [x] I read the [AI contribution guidelines] and understand my
    responsibilities, or I am not using AI tools.
    - [x] I read the [Tree Hygiene] wiki page, which explains my
    responsibilities.
    - [x] I read and followed the [Flutter Style Guide], including [Features
    we expect every widget to implement].
    - [x] I signed the [CLA].
    - [x] I listed at least one issue that this PR fixes in the description
    above.
    - [x] I updated/added relevant in-code documentation (doc comments with
    `///`).
    - [x] If this PR introduces a new feature or capability, I created and
    linked a website documentation issue or PR in [flutter/website] (or
    verified none is needed).
    - [x] I added new tests to check the change I am making, or this PR is
    [test-exempt].
    - [x] I followed the [breaking change policy] and added [Data Driven
    Fixes] where supported.
    - [ ] All existing and new tests are passing.
    
    The full local FML suite passes; the final test checkbox remains
    unchecked pending upstream CI.
    
    [Contributor Guide]:
    https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#overview
    [AI contribution guidelines]:
    https://github.com/flutter/flutter/blob/master/CONTRIBUTING.ai.md
    [Tree Hygiene]:
    https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md
    [Flutter Style Guide]:
    https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md
    [Features we expect every widget to implement]:
    https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
    [CLA]: https://cla.developers.google.com/
    [flutter/website]: https://github.com/flutter/website
    [test-exempt]:
    https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#tests
    [breaking change policy]:
    https://github.com/flutter/flutter/blob/master/docs/contributing/Tree-hygiene.md#handling-breaking-changes
    [Data Driven Fixes]:
    https://github.com/flutter/flutter/blob/master/docs/contributing/Data-driven-Fixes.md
    
    ---------
    
    Co-authored-by: gaaclarke <[email protected]>
    bpleekm and gaaclarke authored Oct 30, 2026
    Configuration menu
    Copy the full SHA
    5e805bf View commit details
    Browse the repository at this point in the history
Loading