Sitelet https://github.com/reidbaker-agent/flutter/pull/6
Skip to content

Register the Flutter compile task lazily from the variant API for app projects - #6

Open
reidbaker-agent wants to merge 449 commits into
agp-ndk-fallbackfrom
agp-assets-onvariants
Open

reidbaker-agent wants to merge 449 commits into
agp-ndk-fallbackfrom
agp-assets-onvariants

Conversation

@reidbaker-agent

@reidbaker-agent reidbaker-agent commented Jul 22, 2026 •

Copy link
Copy Markdown
Owner

Phase 6 of 11 of the AGP public-API migration; stacked on #5.

Phase P5, commit 1 of 2 (P5a), of the AGP public-API migration
(flutter#180137, flutter#166550):

  • For application projects, compileFlutterBuild<Variant> (FlutterTask)
    is now registered inside the consolidated androidComponents.onVariants
    block as a lazy TaskProvider, configured entirely from the public
    variant API: minSdk from Variant.minSdk.apiLevel, flavor from
    Variant.flavorName, and the Flutter build mode from
    buildModeFor(variant.buildType, variant.debuggable) so custom
    debuggable build types keep mapping to debug engine artifacts.
    Registration is gated by shouldConfigureFlutterTask on the computed
    assemble task name (new name-based overload), mirroring the legacy
    callback's gating.
  • addFlutterDeps is split: addFlutterDepsForApp (per-ABI versionCode,
    legacy assets copy into the merged-assets dir, processResources hook)
    looks the compile task up by name instead of registering it;
    addFlutterDepsForModule keeps the full legacy path for add-to-app
    module projects until that path migrates. The always-null
    packageAssets/isUsedAsSubproject dead code and the duplicated
    processResources hook in the application variant callback are
    removed.

No behavior change intended for what gets built; the assets delivery
mechanism changes in the next commit (P5b).

Verification note: FGP unit tests could not run in this sandbox (network
policy blocks dl.google.com); run 'gradle test' (both AGP axes) in CI.

Revert-safe (with P5b) until P6 lands.

CI must run the FGP unit tests (the Kotlin suite in packages/flutter_tools/gradle could not run in the delivery sandbox: dl.google.com returns 403, so AGP artifacts do not resolve).

@reidbaker-agent
reidbaker-agent force-pushed the agp-assets-onvariants branch from 1c1b7f1 to 8dbebbb Compare July 22, 2026 15:54
@reidbaker-agent
reidbaker-agent force-pushed the agp-ndk-fallback branch 2 times, most recently from 7e60b17 to 106779a Compare July 28, 2026 13:35
@reidbaker-agent
reidbaker-agent force-pushed the agp-assets-onvariants branch from 8dbebbb to b7ca673 Compare July 28, 2026 13:35
@reidbaker-agent
reidbaker-agent force-pushed the agp-assets-onvariants branch from b7ca673 to 34cd183 Compare July 28, 2026 13:37
@reidbaker-agent
reidbaker-agent force-pushed the agp-assets-onvariants branch from 34cd183 to bd722f5 Compare July 29, 2026 20:21
@reidbaker-agent
reidbaker-agent force-pushed the agp-assets-onvariants branch 2 times, most recently from 78c25d5 to ad24137 Compare July 30, 2026 21:59
@reidbaker
reidbaker force-pushed the agp-assets-onvariants branch from ad24137 to 2654136 Compare July 31, 2026 18:07
@reidbaker
reidbaker force-pushed the agp-assets-onvariants branch from 2654136 to bd2c850 Compare August 6, 2026 14:37
pull Bot pushed a commit to Little-Star888/flutter that referenced this pull request Aug 12, 2026
…on documentation (flutter#190842)

There are 2 files in this pr. One is a document the ai used to keep
track of work. More importantly it acts kind of like issues so it
references the items in future prs. The second is user facing website
documentation. I do not know if we will use it verbatim but for the set
of prs lets treat that md doc as human understandable documentation that
we must understand before landing the next pr.

Reviewers: When the pr is out of draft and your comments are fully
addressed please prioritize this pr over other work. The review bar is
higher, the number of reviews has more people and the work for the next
pr is already done.
 - @reidbaker 
---
Standard review context for this pr stack

This is PR is part of an 11 pr stack to migrate the "newdsl"
`gradle-api` specifically in agp 9.1.0.
The complete stack has pass pre submits, post submits and customer
tests.
https://flutter-dashboard.appspot.com/#/build?repo=flutter&branch=experimental/agp-gradle-api

All of the code was LLM authored. A mix of manual prompting, automatic
prompting, several models and adversarial review. The combined sessions
are enough that I cannot include relevant prompts like I have been doing
on other prs.

If you want to review the pr stack you can find it here. These prs will
be abandoned/closed as prs land into flutter/flutter.
1. reidbaker-agent#1 (branch:
agp-api-doc)
2. reidbaker-agent#2 (branch:
agp-internal-utils)
3. reidbaker-agent#3 (branch:
agp-buildmode-deps)
4. reidbaker-agent#4 (branch:
agp-plugin-buildtypes)
5. reidbaker-agent#5 (branch:
agp-ndk-fallback)
6. reidbaker-agent#6 (branch:
agp-assets-onvariants)
7. reidbaker-agent#7 (branch:
agp-apk-copy-versioncode)
8. reidbaker-agent#8 (branch:
agp-add-to-app)
9. reidbaker-agent#9 (branch:
agp-aar-script)
10. reidbaker-agent#10 (branch:
agp-newdsl-flip)
11. reidbaker-agent#11 (branch:
agp-gradle-api)

Follow up work is tracked in
flutter#190964

This work is urgent in the sense that we are worried that android will
publish agp 10 with no opt out but not so urgent that we are willing to
break flutter users because we didn't review or understand the code
because we were in a rush.

Breaking changes are expected as part of this work. There are patterns
the android team explicitly does not want apps to use and apis that have
no equivalent.

As part of the effort to ensure this work does not slip into ai slop,
prs from this stack will be reviewed by me (@reidbaker) before asking
for review. Then we will have 2 android expert reviewers also review the
every pr.

---
Agent authored pr description
This is PR 1 of 11 in the AGP 9.1.0 / public `gradle-api` migration
stack.

It adds the contributor-facing and website draft documentation for the
Flutter Gradle Plugin's migration to the Android Gradle Plugin public
Variant API, which unblocks building Flutter Android apps with AGP's
`newDsl=true` enabled.

Part of flutter#180137 and flutter#166550.

## 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 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.

---------

Co-authored-by: reidbaker-agent <reidbaker@google.com>
okorohelijah pushed a commit to okorohelijah/flutter that referenced this pull request Aug 17, 2026
…90957)

This is PR 2 of 11 in the AGP 9.1.0 / public `gradle-api`/ newdls
migration stack.

This PR extracts some common utilities used in the Flutter Gradle Plugin
to internal functions, to be used in upcoming PRs in this stack. It also
introduces a typesafe CompileSdkVersion that handles comparisons between
api versions and preview versions which are strings.

First attempt was here flutter#190949
this pr includes my feedback from that first review. The first attempt
did not follow the pattern of having the agent account open the pr
because of rebase shenanigans that ended up touching freeze.yml.

---
Standard review context for this pr stack

This is PR is part of an 11 pr stack to migrate the "newdsl"
`gradle-api` specifically in agp 9.1.0.
The complete stack has pass pre submits, post submits and customer
tests.
https://flutter-dashboard.appspot.com/#/build?repo=flutter&branch=experimental/agp-gradle-api

All of the code was LLM authored. A mix of manual prompting, automatic
prompting, several models and adversarial review. The combined sessions
are enough that I cannot include relevant prompts like I have been doing
on other prs.

If you want to review the pr stack you can find it here. These prs will
be abandoned/closed as prs land into flutter/flutter.
1. reidbaker-agent#1 (branch:
agp-api-doc)
2. reidbaker-agent#2 (branch:
agp-internal-utils)
3. reidbaker-agent#3 (branch:
agp-buildmode-deps)
4. reidbaker-agent#4 (branch:
agp-plugin-buildtypes)
5. reidbaker-agent#5 (branch:
agp-ndk-fallback)
6. reidbaker-agent#6 (branch:
agp-assets-onvariants)
7. reidbaker-agent#7 (branch:
agp-apk-copy-versioncode)
8. reidbaker-agent#8 (branch:
agp-add-to-app)
9. reidbaker-agent#9 (branch:
agp-aar-script)
10. reidbaker-agent#10 (branch:
agp-newdsl-flip)
11. reidbaker-agent#11 (branch:
agp-gradle-api)

This work is urgent in the sense that we are worried that android will
publish agp 10 with no opt out but not so urgent that we are willing to
break flutter users because we didn't review or understand the code
because we were in a rush.

Breaking changes are expected as part of this work. There are patterns
the android team explicitly does not want apps to use and apis that have
no equivalent.

As part of the effort to ensure this work does not slip into ai slop,
prs from this stack will be reviewed by me (@reidbaker) before asking
for review. Then we will have 2 android expert reviewers also review the
every pr.

--- 
Agent authored description. 
This is PR 2 of 11 in the AGP 9.1.0 / public `gradle-api` migration
stack.

This PR extracts some common utilities used in the Flutter Gradle Plugin
to internal functions, to be used in upcoming PRs in this stack.

## 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 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.

---------

Co-authored-by: reidbaker-agent <reidbaker@google.com>
Co-authored-by: Reid Baker <1063596+reidbaker@users.noreply.github.com>
pull Bot pushed a commit to TheRakeshPurohit/flutter that referenced this pull request Aug 24, 2026
…dependencies through the new DSL (flutter#191218)

This is PR 3 of 11 in the AGP 9.1.0 / public `gradle-api`/ newdsl
migration stack.

* It migrates many (but not all) usages of getLegacyAndroidExtension. 
* Introduces consistency in renaming of imports. 
* Adds a test to ensure we are not adding internal apis (thanks
@mboetger from pr1)
* builds the ability to run our gradle tests with multiple AGP versions
(see packages/flutter_tools/gradle/build.gradle.kts)

Between PR 3 and PR 8, an Add-to-app host app embedding a Flutter module
with a custom build type (for example "staging") gets release engine
artifacts. That means hot reload, debugger attach, and DevTools do not
operate in that build.
We can't move the work in PR 8 up but I would not want to cut a release
between this pr and 8 landing. If we keep reviewing one pr a day then
that is not a risk.

Apps impacted by this change can use matchingFallbacks to avoid this
problem (see code below).

In pr 8 we change when we look for "isDebuggable" to much later in the
gradle lifeycle when all the variants have been created which then lets
us use a new api to understand if the variant is intended to be
debuggable.

Kotlin 
```kotlin
// host app build.gradle.kts
android {
    buildTypes {
        create("staging") {
            isDebuggable = true
            applicationIdSuffix = ".staging"
            matchingFallbacks += "debug" /// This line. 
        }
    }
}
```
Groovy 
```groovy
// host app build.gradle
android {
    buildTypes {
        staging {
            debuggable true
            applicationIdSuffix ".staging"
            matchingFallbacks = ['debug'] /// This line. 
        }
    }
}
```

Depends on flutter#190957 (PR 2).
- @reidbaker 


---
Standard review context for this pr stack

This is PR is part of an 11 pr stack to migrate the "newdsl"
`gradle-api` specifically in agp 9.1.0.
The complete stack has passed presubmits, postsubmits, and customer
tests:
https://flutter-dashboard.appspot.com/#/build?repo=flutter&branch=experimental/agp-gradle-api

All of the code was LLM authored. A mix of manual prompting, automatic
prompting, several models and adversarial review. The combined sessions
are enough that I cannot include relevant prompts like I have been doing
on other prs.

If you want to review the pr stack you can find it here. These prs will
be abandoned/closed as prs land into flutter/flutter.
1. reidbaker-agent#1 (branch:
agp-api-doc)
2. reidbaker-agent#2 (branch:
agp-internal-utils)
3. reidbaker-agent#3 (branch:
agp-buildmode-deps)
4. reidbaker-agent#4 (branch:
agp-plugin-buildtypes)
5. reidbaker-agent#5 (branch:
agp-ndk-fallback)
6. reidbaker-agent#6 (branch:
agp-assets-onvariants)
7. reidbaker-agent#7 (branch:
agp-apk-copy-versioncode)
8. reidbaker-agent#8 (branch:
agp-add-to-app)
9. reidbaker-agent#9 (branch:
agp-aar-script)
10. reidbaker-agent#10 (branch:
agp-newdsl-flip)
11. reidbaker-agent#11 (branch:
agp-gradle-api)

This work is urgent in the sense that we are worried that android will
publish agp 10 with no opt out but not so urgent that we are willing to
break flutter users because we didn't review or understand the code
because we were in a rush.

Breaking changes are expected as part of this work. There are patterns
the android team explicitly does not want apps to use and apis that have
no equivalent.

As part of the effort to ensure this work does not slip into ai slop,
prs from this stack will be reviewed by me (@reidbaker) before asking
for review. Then we will have 2 android expert reviewers also review
every pr.

--- 
Agent authored description. 
This is PR 3 of 11 in the AGP 9.1.0 / public `gradle-api` migration
stack (flutter#180137, flutter#166550).

### Key Changes
- **DSL Build Mode Overloads**: Adds `buildModeFor` overloads accepting
`ApplicationBuildType`, `DynamicFeatureBuildType`, and
`LibraryBuildType` DSL types alongside the `(buildTypeName,
isDebuggable)` core overload.
- **Robust CompileSdkVersion Domain Model**: Extracts
`CompileSdkVersion` with constructor invariant validation (`init {
require(...) }`) enforcing mutual exclusivity between `apiLevel` and
`previewCodename`.
- **Namespaced Multi-AGP Build Property**: Namespaces the AGP version
property in `packages/flutter_tools/gradle/build.gradle.kts` as
`flutter.internal.agpVersion` (defaulting to `8.11.1`) to prevent user
app properties from leaking into the included build during app
compilation.
- **Standardized Type Aliasing**: Applies non-temporal type aliasing
(`import com.android.build.api.dsl.BuildType as DslBuildType`) across
`FlutterPlugin.kt` and `PluginHandler.kt`.
- **Public DSL Extension Access**: Updates `addFlutterDependencies` and
`PluginHandler` to iterate `AgpCommonExtensionWrapper.buildTypes`.
- **Build & Bytecode Validation**: Adds the
`:validateNoCommonExtensionInBytecode` task in `build.gradle.kts` to
prevent compiled main classes from referencing binary-incompatible
`CommonExtension`, and adds `BytecodeValidatorTest.kt` verifying the
binary pattern-matching and class scanning logic.
- **Comprehensive Unit Tests**: Adds full 4-way dispatch test coverage
in `AgpCommonExtensionWrapperTest`, dependency wiring tests in
`FlutterPluginTest`, and decomposes `PluginHandlerTest` mock fixtures
into focused helpers with positive assertions.

### Add-to-App & DSL Scope Context
`LibraryBuildType` does not expose `isDebuggable` at DSL scope. In PR 3,
custom build types on library projects (e.g. host app 'staging') fall
back to `"release"` at DSL scope. In PR 8 ("Unify add-to-app module
wiring on the variant API"), module wiring will be unified on
`Component.debuggable` at variant scope.

## 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 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.

---------

Co-authored-by: reidbaker-agent <reidbaker@google.com>
Co-authored-by: Reid Baker <1063596+reidbaker@users.noreply.github.com>
NikhilKukreja26 pushed a commit to NikhilKukreja26/flutter that referenced this pull request Aug 28, 2026
…nitWith on public DSL (flutter#191606)

This is PR 4 of 11 in the AGP 9.1.0 / public `gradle-api` / newdsl
migration stack.

There are no breaking changes expected in this pr. Only internal logic
is impacted.

I will be honest I also found the tests hard to review. I had the agent
pull out shared mocking logic but I am not sure that actually made
review easier.

Depends on flutter#191218 (PR 3).
- @reidbaker

---
Standard review context for this pr stack

This is PR is part of an 11 pr stack to migrate the "newdsl"
`gradle-api` specifically in agp 9.1.0.

All of the code was LLM authored. A mix of manual prompting, automatic
prompting, several models and adversarial review. The combined sessions
are enough that I cannot include relevant prompts like I have been doing
on other prs.

If you want to review the pr stack you can find it here. These prs will
be abandoned/closed as prs land into flutter/flutter.
1. reidbaker-agent#1 (branch:
agp-api-doc)
2. reidbaker-agent#2 (branch:
agp-internal-utils)
3. reidbaker-agent#3 (branch:
agp-buildmode-deps)
4. reidbaker-agent#4 (branch:
agp-plugin-buildtypes)
5. reidbaker-agent#5 (branch:
agp-ndk-fallback)
6. reidbaker-agent#6 (branch:
agp-assets-onvariants)
7. reidbaker-agent#7 (branch:
agp-apk-copy-versioncode)
8. reidbaker-agent#8 (branch:
agp-add-to-app)
9. reidbaker-agent#9 (branch:
agp-aar-script)
10. reidbaker-agent#10 (branch:
agp-newdsl-flip)
11. reidbaker-agent#11 (branch:
agp-gradle-api)

This work is urgent in the sense that we are worried that android will
publish agp 10 with no opt out but not so urgent that we are willing to
break flutter users because we didn't review or understand the code
because we were in a rush.

Breaking changes are expected as part of this work. There are patterns
the android team explicitly does not want apps to use and apis that have
no equivalent.

As part of the effort to ensure this work does not slip into ai slop,
prs from this stack will be reviewed by me (@reidbaker) before asking
for review. Then we will have 2 android expert reviewers also review
every pr.

---
Agent authored description.
This is PR 4 of 11 in the AGP 9.1.0 / public `gradle-api` migration
stack (flutter#180137, flutter#166550).

### Key Changes
- **Public DSL `initWith` Copy**: Replaces the legacy
`getLegacyAndroidExtension` build-type copy in `PluginHandler` with
`initWith` on the public DSL (`AgpCommonExtensionWrapper.buildTypes`).
Missing build types on the plugin project are created with
`initWith(appBuildType)`, and `isDebuggable` is copied when both sides
are `ApplicationBuildType`.
- **Zero AGP Internals in Production Sources**: Removes the last
remaining `com.android.build.gradle.internal` imports from production
code (`src/main`).
- **Internal AGP Import Guard**: Adds `InternalAgpApiImportTest` to
continuously enforce that production sources do not introduce
`com.android.build.gradle.internal.*` imports.
- **Decomposed & Robust Unit Tests**: Replaces legacy mock-only tests in
`PluginHandlerTest` with tests that execute `configurePlugins` and
verify `initWith` copying for both library and application plugin
projects, mapping custom debuggable build types to debug engine
artifacts, and verifying that pre-existing plugin build types are
skipped.
- **Migration Documentation Update**: Adds details for the P3 pre-spike
and `finalizeDsl` fallback in
`Migrating-Flutter-Gradle-Plugin-to-AGP-public-API.md`.

## 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 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.
@reidbaker
reidbaker force-pushed the agp-ndk-fallback branch 2 times, most recently from 30452db to 6360b6d Compare September 1, 2026 16:09
gaaclarke and others added 28 commits September 26, 2026 02:13
…d framebufferfetch (flutter#193306)

My fork of flutter#193178 to avoid OP's
open PR limit.

Coauthored with @krll-kov 

Fixes flutter#192918

## 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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

---------

Co-authored-by: Kyrylo K. <63228361+krll-kov@users.noreply.github.com>
…92632)

Preemptively fixes static analysis warnings reported by newer Dart SDK
builds under `specify_nonobvious_local_variable_types`.

Adds explicit types to pattern variable declarations in:
- `dev/integration_tests/record_use_test_package/hook/link.dart`
- `packages/flutter/lib/src/widgets/actions.dart`
- `packages/flutter/lib/src/widgets/selectable_region.dart`
-
`packages/flutter_tools/lib/src/widget_preview/preview_code_generator.dart`
Unskips the `TextPainter.getWordBoundary works` test in
`packages/flutter/test/painting/text_painter_test.dart`. It was skipped
on web (`skip: isBrowser`) for
flutter#61017 and now passes on
Chrome, both with the default compiler and with `--wasm`.

This removes the last web skip that references
flutter#61017.

The other web skip in this file (invalid UTF-16 handling,
flutter#87544) is unchanged because
that test still fails on web.

Related issues:
- flutter#61017

## 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.

<!-- 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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
…ine arguments via `Intent`s (flutter#190249)

> [!WARNING]
> This is a breaking change. Though the motivation for this change is
the security of our users and migration to accommodate this change is
critical, I looked at some top plugins that _might_ have been impacted
to ensure they won't be broken: All 1P plugins,
[`firebase_messaging`](https://pub.dev/packages/firebase_messaging)
v16.5.0,
[`flutter_local_notifications`](https://pub.dev/packages/flutter_local_notifications)
v22.3.0,
[`awesome_notifications`](https://pub.dev/packages/awesome_notifications)
v0.12.1,
[`android_alarm_manager_plus`](https://pub.dev/packages/android_alarm_manager_plus)
v5.1.1,
[`receive_sharing_intent`](https://pub.dev/packages/receive_sharing_intent)
v1.9.0,
[`onesignal_flutter`](https://pub.dev/packages/onesignal_flutter),
[`workmanager`](https://pub.dev/packages/workmanager) v0.10.7
[`flutter_background_service`](https://pub.dev/packages/flutter_background_service)
v5.1.0, [`app_links`](https://pub.dev/packages/app_links) v7.2.1,
[`uni_links`](https://pub.dev/packages/uni_links) v0.5.1


Changes the embedding to only allow setting app launch entry-point and
cached engine related arguments via `Intent`s in debug/profile mode or
when the `Intent` sender is verifiably the app itself. This hardens the
embedding against arbitrary argument injection by a malicious actor,
preventing unauthorized access to sensitive app routes and engine
controls. Below Android 13, it is impossible to verify the `Intent`
sender is verifiably the app itself in all cases, so apps/plugins that
do not migrate and run on those versions will be impacted.

In debug/profile modes, if an unverified `Intent` attempts to set these
arguments, the embedding now logs a detailed warning containing the
target component, the intent details, and the specific `Intent` extra
keys that triggered the verification failure. It also links to the
breaking changes migration guide for help on migrating:
flutter/website#13645

For deep links, the `Intent` is compared against the app's `Intent`
filters to ensure the app should allow that link. This is standard for
the OS; see [Android's Intents and Intent Filters
documentation](https://developer.android.com/guide/components/intents-filters)
for more information on that.

Fixes flutter#190452 and fixes
flutter#190450.

## 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 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.
- [ ] 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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
[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

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
…flutter#193180)

Ensures that when an application opts into WebAssembly on Firefox or
Safari via `wasmAllowList` in JS/JSON bootstrap configuration,
`FlutterLoader` strictly enforces `supportsDart2Wasm()` capability
checks and browser version guards before selecting any `dart2wasm`
build:

- **Firefox `< 147` WasmGC Version Guard**: Guards `supportsDart2Wasm()`
in `browser_environment.js` so Firefox `< 147` falls back to `dart2js`
even if `wasmAllowList: { gecko: true }` is configured.
- **Unify `enableWasm` Gating Across All `dart2wasm` Targets**: Moves
the `!enableWasm` check in `loader.js` from
`rendererIncompatibilityReason('skwasm')` into
`buildIncompatibilityReason` for `build.compileTarget === 'dart2wasm'`,
preventing `dart2wasm` + `canvaskit` builds from bypassing
`wasmAllowList` opt-outs.
- **Explicit Opt-In Fallback Test**: Adds test coverage in
`fallbacks_test.dart` verifying that `flutter.loader.load()` with
`wasmAllowList` explicitly enabled for all engines still rejects
`dart2wasm` builds when `supportsDart2Wasm` is false.

Part of flutter#143603
…nd its tests (flutter#193334)

Adds `@docImport 'package:flutter/material.dart'` /
`'package:flutter/cupertino.dart'` for doc references that currently
resolve only through dartdoc's global lookup. This is an interim fix;
these (and the existing) doc imports will need to change once the
long-term solution in flutter#181288
is decided.

Note: Widget tests are checked for Material and Cupertino imports
(`dev/bots/check_tests_cross_imports.dart`), but the check does not
cover doc imports. If you'd rather not doc import Material in widget
tests, I can put the names in backticks instead.

Towards flutter#192870 — enabling the
`comment_references` lint.
…ter#193283)

Follow-up to flutter#192734, flutter#193087 and flutter#193216, covering the references
inside `lib/src/material` and `lib/src/cupertino`. Doc comment changes
only.

The changes fall into four kinds:
- missing `@docImport` directives
- qualified member references, e.g. `[value]` →
`[MaterialStatesController.value]`
- a constructor parameter in backticks instead of brackets
(`liveRegion`)
- references to names that do not exist, reworded (`child`, `enabled` in
`cupertino/menu_anchor.dart`)

Towards flutter#192870 — enabling the
`comment_references` lint.
This PR was generated by `flutter update-packages --force-upgrade`.
…mpty (flutter#193434)

When `flutterManifest.isEmpty` (for example, a `pubspec.yaml` without a
`flutter:` section), `ManifestAssetBundle.build` previously returned
early with an empty `AssetManifest.bin`, ignoring any data assets
produced by build/link hooks (`flutterHookResult.dataAssets`).

Bug:

* flutter#146264

### Changes
- Only short-circuit with an empty manifest in
`ManifestAssetBundle.build` when both `flutterManifest.isEmpty` and
`flutterHookResult?.dataAssets.isEmpty ?? true`.
- Skip `computeTransitiveDependencies` when `flutterManifest.isEmpty`.
- Add a unit test in `asset_bundle_test.dart` verifying that data assets
from hooks are bundled when `pubspec.yaml` is empty.

### PR Stack
| # | PR | Branch | Commit |
| :-: | :--- | :--- | :--- |
| **1** | **👉 flutter#193434 (this PR)**
| `data-assets-empty-pubspec` |
flutter@62199c4
|
| 2 | flutter#193435 |
`data-assets-flutter-test` |
flutter@25be1ab
|
| 3 | flutter#193436 |
`data-assets-dev-dependencies-release-test` |
flutter@79abad9
|
| 4 | flutter#193437 |
`data-assets-widget-preview` |
flutter@98f1001
|

## 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.
This PR was generated by `flutter update-packages --force-upgrade`.
…utterDevice.create (flutter#192830)

## Summary

Part 22a of the modular dependency injection migration.

* Migrates `FlutterDevice` and `FlutterDevice.create` to accept a
required `ToolContext` and destructure its dependencies (`artifacts`,
`config`, `fs`, `logger`, `platform`, `processManager`,
`shutdownHooks`):
  ```dart
  static Future<FlutterDevice> create(
    Device device, {
    required BuildInfo buildInfo,
    required String? target,
    required ToolContext toolContext,
    ResidentCompilerFactory? residentCompilerFactory,
    TargetModel? targetModelOverride,
    String? userIdentifier,
  })
  ```
* Requires non-nullable `ToolContext` on `AttachCommand`,
`DriveCommand`, `FlutterDriverFactory`, `WebDriverService`, and
`Daemon`, eliminating duplicate individual service constructor
parameters (`fileSystem`, `logger`, `platform`, `processInfo`,
`signals`, `stdio`, `terminal`, `outputPreferences`, `processUtils`) and
`toolContext!` null-assertions.
* Updates `FakeFlutterDevice` test doubles in `hot_shared.dart` and
`resident_runner_helpers.dart`, and unit tests across
`attach_test.dart`, `drive_test.dart`, `web_driver_service_test.dart`,
`resident_runner_test.dart`, `cold_test.dart`, and `hot_test.dart`.

Fork diff:
bkonyi/flutter@master...di/22a-flutter-device

Part of flutter#188471
…r#193450)

flutter/packages@e55e7ac...ba0364a

2026-09-26 stuartmorgan@google.com [google_maps_flutter] Indicate that
default iOS impl is discoraged (flutter/packages#12872)
2026-09-26 36861262+QuncCccccc@users.noreply.github.com [material_ui]
Add Material 3 Expressive IconButton (flutter/packages#12832)
2026-09-25 jessiewong401@gmail.com Plugin example apps to 9.3.1
(flutter/packages#13019)
2026-09-25 36861262+QuncCccccc@users.noreply.github.com [material_ui]
Don't clip MenuItemButton.leadingIcon (flutter/packages#12986)
2026-09-25 36861262+QuncCccccc@users.noreply.github.com [material_ui]
Migrate M3 ExpansionTile template to use new gen_defaults
(flutter/packages#12920)
2026-09-25 149176071+m1roxx@users.noreply.github.com
[two_dimensional_scrollables] Exclude trailing pinned spans from the
non-pinned range (flutter/packages#12666)
2026-09-25 36861262+QuncCccccc@users.noreply.github.com [material_ui]
Migrate M3 Drawer template to use new gen_defaults
(flutter/packages#12916)
2026-09-25 36861262+QuncCccccc@users.noreply.github.com [material_ui]
Migrate M3 Divider template to use new gen_defaults
(flutter/packages#12915)
2026-09-25 instantni.med@gmail.com [google_maps_flutter_web] Fix
AdvancedMarker anchors on web (flutter/packages#11966)

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 flutter-ecosystem@google.com 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
…v/benchmarks (flutter#193433)

Fixes doc comment references in `dev/integration_tests` and
`dev/benchmarks` that don't resolve in Dart scope, mostly by adding doc
imports; parameters and locals go in backticks.

Towards flutter#192870 — enabling the
`comment_references` lint.
…erRecorder (flutter#193260)

Splits out the
`dev/benchmarks/macrobenchmarks/lib/src/web/recorder.dart` fix from
flutter#193135 per review discussion
(flutter#193135 (comment)).

Previously, `SceneBuilderRecorder.onDrawFrame` nested
`_profile!.recordAsync('windowRenderDuration', ...)` inside synchronous
`_profile!.record('sceneBuildDuration', ...)` without awaiting
`recordAsync`, which both triggered `unawaited_futures` and caused
`sceneBuildDuration` to include the synchronous portion of
`windowRenderDuration`. This PR un-nests the two recordings and makes
`onDrawFrame` `async` so `sceneBuildDuration` only measures
`sceneBuilder.build()` and `windowRenderDuration` is properly awaited.
This PR was generated by `flutter update-packages --force-upgrade`.
…... (flutter#193454)

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/fuchsia-linux-sdk-flutter
Please CC bensonluk@google.com,zra@google.com 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
This PR automates the synchronization of `CHANGELOG.md` from the
`stable` branch to the `master` branch.

Co-authored-by: Jackson Gardner <jacksongardner@google.com>
…93360)

Reverts: [Reland: Only render views that need to be rendered
](flutter#192128)

Initiated by: @elliette

Reason for reverting: broke flutter -> packages autoroller

Original PR Author: @knopp

Reviewed By: @loic-sharma

The original PR description is provided below:

This relands flutter#179874, reverted in
flutter#191252.

The reason for revert was stalled web benchmarks
(flutter#191251). Stalling was caused
by `_autoUpdateBenchmarkPhase` inside
`macrobenchmarks/lib/src/web/recorder.dart` expecting certain number of
`preroll_frame` and `apply_frame` events. These events are only
published for frames that are composited (ui.Scene being rendered), but
some of the web benchmarks request frame without making any render
objects dirty, which after
flutter#191252 did not result on view
being composited.

The fix is to force view composition on every frame when the benchmarks
are running.

cc @yjbanov regarding the changes in `recorder.dart`.

## 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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

Co-authored-by: Elliott Brooks <21270878+elliette@users.noreply.github.com>
This PR fixes cross imports in navigator_test.dart, except for one test
that is a regression test with TabBarView/TabController. (That test will
need to be moved first, and the old test be deleted, rewritten after it
was moved)

It also cleans up some bits around test routes.

Part of flutter#177415

*If you had to change anything in the [flutter/tests] repo, include a
link to the migration guide as per the [breaking change policy].*

## 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 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.

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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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
[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
Replace the two existing DDC sdk.js build targets:
```
flutter/web_sdk:flutter_dartdevc_canvaskit_kernel_sdk_amd
flutter/web_sdk:flutter_dartdevc_canvaskit_kernel_sdk_ddcLibraryBundle
```
with new variants:
```
flutter/web_sdk:flutter_ddc_canary_sdk
flutter/web_sdk:flutter_ddc_stable_sdk
```

This removes the dart_sdk.js artifact built with the AMD module system
flags. It is no longer supported and inaccessible from the flutter_tools
CLI. Other PRs are in flight to delete the remaining test references to
this module system that are no longer running.

This also prepares for the eventual flip of the DDC `--canary` flag
default back to `false`. We are now building a dart_sdk.js artifact with
the flag disabled.

Issue: flutter#142060

## 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.

<!-- 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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

---------

Co-authored-by: Ben Konyi <bkonyi@google.com>
Part of flutter#192568

The following tests are kept on 15 due to failing testing. We will fix
once we have macOS 26 bots in the try pool:
* Mac framework_tests_libraries
* Mac framework_tests_impeller
* Mac framework_tests_widgets
* Mac_build_test flutter_gallery__transition_perf_e2e_ios
* Mac mac_unopt < ci/mac_release_arm64_tests
* Linux linux_web_engine_tests < Mac run safari suites

## 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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

---------

Co-authored-by: Jackson Gardner <jacksongardner@google.com>
…me (flutter#193113)

Fixes flutter#85831

While working on webp encoder for `image` package i noticed that flutter
does not render some animated webp and gifs with following exception:
```
======== Exception caught by image resource service ================================================
The following _Exception was thrown resolving an image frame:
Exception: Could not getPixels for frame 1

When the exception was thrown, this was the stack: 
Path: \\Mac\Downloads\gif\200w.webp
====================================================================================================
```
<details>
<summary>Code sample and visual demo with the files used, since the
issue has no screenshots and author did not provide his code
sample:</summary>

<img width="1491" height="819" alt="image" src="/sitelet?url=https%3A%2F%2Fgithub.com%2Freidbaker-agent%2Fflutter%2Fpull%2F%253Ca%2520href%3D"/sitelet?url=https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F04e7dc17-bc7f-453f-ba28-5621d47c3f23">https://github.com/user-attachments/assets/04e7dc17-bc7f-453f-ba28-5621d47c3f23"
/>

```dart
import 'dart:io';

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @OverRide
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: Scaffold(
        appBar: AppBar(title: Text('Material App Bar')),
        body: Center(child: Column(children: <Widget>[
          Image.file(File(r'\\Mac\Downloads\gif\200w.gif'), height: 100,),
          Image.file(File(r'\\Mac\Downloads\gif\200w.webp'), height: 100,),

          Image.file(File(r'\\Mac\Downloads\gif\giphy.gif'), height: 100,),
          Image.file(File(r'\\Mac\Downloads\gif\giphy.webp'), height: 100,),

          Image.file(File(r'\\Mac\Downloads\gif\opaque_first_frame_bug.gif'), height: 100,),
        ])),
      ),
    );
  }
}
```

<details>
<summary>Webp and gif Images used for this sample:</summary>

<img width="200" height="356" alt="200w" src="/sitelet?url=https%3A%2F%2Fgithub.com%2Freidbaker-agent%2Fflutter%2Fpull%2F%253Ca%2520href%3D"/sitelet?url=https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2Fabcbdd6e-d4d0-4e23-b88d-04c0e3d4a79e">https://github.com/user-attachments/assets/abcbdd6e-d4d0-4e23-b88d-04c0e3d4a79e"
/>
<img width="56" height="100" alt="200w" src="/sitelet?url=https%3A%2F%2Fgithub.com%2Freidbaker-agent%2Fflutter%2Fpull%2F%253Ca%2520href%3D"/sitelet?url=https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F8df4d356-1297-4aad-af85-a2b4bd23b606">https://github.com/user-attachments/assets/8df4d356-1297-4aad-af85-a2b4bd23b606"
/>

<img width="480" height="480" alt="giphy" src="/sitelet?url=https%3A%2F%2Fgithub.com%2Freidbaker-agent%2Fflutter%2Fpull%2F%253Ca%2520href%3D"/sitelet?url=https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F13b6952e-1bf9-49ec-b58f-52c5caf6fa04">https://github.com/user-attachments/assets/13b6952e-1bf9-49ec-b58f-52c5caf6fa04"
/>
<img width="100" height="100" alt="giphy" src="/sitelet?url=https%3A%2F%2Fgithub.com%2Freidbaker-agent%2Fflutter%2Fpull%2F%253Ca%2520href%3D"/sitelet?url=https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F4d3bb3dc-0f8c-4384-9b1d-86e3a4474206">https://github.com/user-attachments/assets/4d3bb3dc-0f8c-4384-9b1d-86e3a4474206"
/>
<img width="200" height="200" alt="opaque_first_frame_bug" src="/sitelet?url=https%3A%2F%2Fgithub.com%2Freidbaker-agent%2Fflutter%2Fpull%2F%253Ca%2520href%3D"/sitelet?url=https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F5e41e321-04f4-4ad5-a9cd-90c0164e4c6a">https://github.com/user-attachments/assets/5e41e321-04f4-4ad5-a9cd-90c0164e4c6a"
/>
</details>

</details>

It appears that this is an old issue in how Flutter uses Skia, because
for animated WebP and GIF, Skia's SkCodec::getInfo() reports the alpha
type of the first frame only, and its documentation doesn't mention that
(or at least i did not find it). Flutter allocates every frame's bitmap
from that info without checking getFrameInfo(i).fAlphaType, so Skia
rejects any later frame with alpha after an opaque first frame with
kInvalidConversion.

Tested on an engine built from master (e619960, Windows x64 release)
with an app that decodes every frame through `ui.instantiateImageCodec`:

| file | without the change | with the change |
|---|---|---|
| WebP, 59 frames, frames 46 and 53 have alpha | frames 46, 53 fail |
all decode |
| 3 WebP files, 15 frames each, frames 1-14 have alpha (lossy and
lossless) | frames 1-14 fail | all decode |
| GIF, opaque frame 0, frame 1 with transparency, disposal to background
| frame 1 fails | all decode |
| the same WebP frames with one alpha pixel in frame 0, and a GIF with
disposal none | all decode | all decode |

Fix: when `SkCodec::getInfo()` reports `kOpaque_SkAlphaType` for an
animation, `BuiltinSkiaCodecImageGenerator` now reports
`kPremul_SkAlphaType` if any later frame reports a non-opaque
`SkCodec::FrameInfo::fAlphaType`. Animations whose later frames all
report `kOpaque_SkAlphaType` stay opaque. APNG is decoded by
APNGImageGenerator, which this change doesn't touch.

The new tests in `testing/dart/codec_test.dart` use a 140-byte WebP and
a 70-byte GIF fixture. I ran `codec_test.dart` with `flutter_tester`
from a `host_debug_unopt_x64` build (Windows x64) with the Skia and
Impeller Vulkan backends, single and multithreaded: all 16 tests pass.
Without the change the two new tests fail with `Could not getPixels for
frame 1`. The Impeller OpenGL ES tests were not tested locally.

<details>
<summary>Screenshot after the fix, both with impeller enabled and
disabled:</summary>
<img width="1329" height="760" alt="image" src="/sitelet?url=https%3A%2F%2Fgithub.com%2Freidbaker-agent%2Fflutter%2Fpull%2F%253Ca%2520href%3D"/sitelet?url=https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2Fa01da7d8-3c40-49a1-a312-4941d23128a2">https://github.com/user-attachments/assets/a01da7d8-3c40-49a1-a312-4941d23128a2"
/>
</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.
- [ ] 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].
- [ ] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.

<!-- 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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/website]: https://github.com/flutter/website
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Upgrade flutter/flutter to Roblectric 4.17. Includes all neccessary
engine updates too. This is the latest and only version of Robolectric
that supports SDK 37.

Added a bunch of flags because JDK 17+ blocks reflective access to JDK
internals by default. Starting with 4.17, Robolectric's test environment
setup reflects into `jdk.internal.access`, so these are required. This
is the flag set
recommended by Robolectric, see
https://robolectric.org/getting-started/#running-with-java-17-and-higher.

Partially Addresses flutter#189518

## 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.

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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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
…r#193125)

Enables the `unawaited_futures` lint rule in
`analysis_options_common.yaml` across the Flutter repository.

Closes flutter#168555

## 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].
- [x] 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.
In flutter#191841, we replaced `Shell::WaitForFirstFrame` with
`Shell::AddFirstFrameCallback` but didn't update the test names to match
the new API.

In particular, `WaitForFirstFrameTimeout` no longer tested that any
caller-visible timeout fired, since the new API manages the timeout
internally. The test now just verifies the first frame callback doesn't
fire when no frame has rendered.

Just naming changes, no semantic changes.

Issue: b/521830222


## 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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
reidbaker self-requested a review as a code owner September 29, 2026 16:27
reidbaker added a commit that referenced this pull request Oct 2, 2026
… source directory on the app path (flutter#192488)

## Description

This is PR 6 of 11 in the AGP 9.1.0 / public `gradle-api` migration
stack ([flutter#180137](flutter#180137),
[flutter#166550](flutter#166550)).

Before turning an agent to this stack of prs this migration was the one
I was the most worried about getting right. I added a test we were
missing to help prevent regressions. Add to app is a future pr (I think
the next one).

- @reidbaker

<details> 
<summary>Agent authored details</summary> 
### Changes

1. **App asset delivery via the modern variant API**
- Registers `copyFlutterAssets<Variant>` inside the consolidated
`onVariants` block as a lazy `TaskProvider<CopyFlutterAssetsTask>`.
- Wires it to AGP with
`variant.sources.assets.addGeneratedSourceDirectory(copyFlutterAssetsTaskProvider,
CopyFlutterAssetsTask::destinationDir)`, so AGP merges Flutter's assets
as a generated asset source directory instead of us mutating the task
graph.
2. **`CopyFlutterAssetsTask`**
- Uses injected `FileSystemOperations.sync` so stale assets are pruned
on rebuild.
- Forces owner read+write on staged assets, avoiding read-only files
inherited from the pub cache.
- `@InputDirectory` + `@PathSensitive(RELATIVE)`, `@OutputDirectory`,
and `@DisableCachingByDefault`.
3. **Compile option extraction** — adds a `FlutterCompileOptions` data
class to remove duplicated property reads between the app path and
`addFlutterDepsForModule`.
4. **Task graph cleanup** — deletes the legacy app-path copy into
`mergeAssets.outputDir`, the `processResources` / `cleanMergeAssets`
surgery, and the manual `compress<Variant>Assets` `dependsOn` wiring.
Add-to-app module paths are intentionally untouched until PR 8.
5. **Tests** — new unit tests for `onVariants` wiring and
`CopyFlutterAssetsTask` execution, plus a new Android integration test
that inspects the built APK.

---

### Asset type coverage

Two different levels of verification are relevant here, and it is worth
separating them:

- **Bundle-level** — does the asset end up in the `flutter_assets`
bundle that `flutter assemble` produces? Covered by unit tests in
`general.shard`.
- **APK-level** — does it end up inside the built `.apk` / `.aab`?
Covered by integration tests that unzip the artifact.

This distinction matters because `CopyFlutterAssetsTask` performs a
single opaque `sync` of the whole `flutter_assets/**` tree with one
top-level `include` and no per-type filtering, renaming, or
special-casing. Nothing inside that directory is treated differently by
the Android build. So for Flutter-side asset types, the APK-level risk
is not "does this asset type survive" but "does the directory arrive at
all" — which the new tests in this PR cover directly.

Tests added in this PR are in
`packages/flutter_tools/test/integration.shard/android_gradle_asset_merging_test.dart`,
abbreviated below as **`asset_merging`**.

| Asset type | How it's specified | Bundle-level coverage | APK-level
coverage | Assessment |
| :--- | :--- | :--- | :--- | :--- |
| Standard `assets:` entry | [Flutter: assets and
images](https://docs.flutter.dev/ui/assets/assets-and-images) |
[`asset_bundle_test.dart`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/general.shard/asset_bundle_test.dart)
→ `'nonempty'` | **`asset_merging`** → `'Flutter assets, directory
assets, resolution variants, and native Android assets coexist in APK'`
| Covered at both levels. |
| Directory / wildcard assets | [Flutter: asset
variants](https://docs.flutter.dev/ui/assets/assets-and-images#asset-variants)
|
[`asset_bundle_test.dart`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/general.shard/asset_bundle_test.dart)
→ `'wildcard directories do not include subdirectories'` |
**`asset_merging`** → same test as above | Covered at both levels. |
| Resolution-aware variants (`2.0x/`, `3.0x/`) | [Flutter:
resolution-aware
images](https://docs.flutter.dev/ui/assets/assets-and-images#resolution-aware)
|
[`asset_bundle_variant_test.dart`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/general.shard/asset_bundle_variant_test.dart)
→ group `'AssetBundle asset variants (with Unix-style paths)'` |
**`asset_merging`** → same test as above | Covered at both levels. |
| Fonts (`fonts:`) | [Flutter: custom
fonts](https://docs.flutter.dev/cookbook/design/fonts) |
[`asset_bundle_package_fonts_test.dart`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/general.shard/asset_bundle_package_fonts_test.dart)
→ `'App includes neither font manifest nor fonts when no defines fonts'`
| None | No new test recommended. Fonts are ordinary files inside
`flutter_assets` and receive no special handling from
`CopyFlutterAssetsTask` or AGP. Bundle-level coverage plus this PR's
directory-arrival coverage is sufficient. |
| Package assets (`packages/<pkg>/...`) | [Flutter: assets from
packages](https://docs.flutter.dev/ui/assets/assets-and-images#from-packages)
|
[`asset_bundle_package_test.dart:530`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/general.shard/asset_bundle_package_test.dart#L530)
→ `'One asset is bundled when the app depends on a package, ...'` | None
| No new test recommended. Same rationale — these are plain files under
`flutter_assets`. |
| `NOTICES` / license aggregation | [Flutter:
licenses](https://docs.flutter.dev/ui/assets/assets-and-images) |
[`asset_bundle_test.dart#L131`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/general.shard/asset_bundle_test.dart#L131)
— `NOTICES.Z` is asserted in the expected bundle output of most tests in
the file | None | No new test recommended. Same rationale. |
| Shaders (`shaders:`) | [Flutter: fragment
shaders](https://docs.flutter.dev/ui/design/graphics/fragment-shaders) |
[`asset_bundle_test.dart#L918`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/general.shard/asset_bundle_test.dart#L918)
→ `'Including a shader triggers the shader compiler'` | None | No new
test recommended. Compiled shaders land in `flutter_assets` as opaque
files. |
| Deferred-component assets | [Flutter: deferred
components](https://docs.flutter.dev/perf/deferred-components) |
[`asset_bundle_test.dart`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/general.shard/asset_bundle_test.dart)
→ `'deferred assets are parsed'` |
[`deferred_components_assets_reproduce_test.dart`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/integration.shard/deferred_components_assets_reproduce_test.dart)
→ `'deferred components assets are not missing on clean build'`;
[`deferred_components_test.dart`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/integration.shard/deferred_components_test.dart)
→ `'simple build appbundle android-arm64 target succeeds'` | Covered at
both levels. These are the only pre-existing tests that unzip an
artifact and assert on asset entries. |
| Obfuscation / split debug info | [Flutter:
obfuscation](https://docs.flutter.dev/deployment/obfuscate) | n/a |
[`android_obfuscate_test.dart`](https://github.com/flutter/flutter/blob/master/packages/flutter_tools/test/integration.shard/android_obfuscate_test.dart)
→ `'Dart identifiers are obfuscated with build apk --obfuscate'` | Not
an asset path. That test asserts on `libapp.so`, and the symbol file is
emitted out-of-band to the host disk rather than packaged. Listed only
to preempt the question. |
| `src/main/assets/` | [Android: app
resources](https://developer.android.com/guide/topics/resources/providing-resources)
| n/a | **`asset_merging`** → `'Flutter assets, directory assets,
resolution variants, and native Android assets coexist in APK'` |
Covered. Also covered on collision: **`asset_merging`** → `'generated
Flutter assets take precedence over static src/main/assets on path
collision without build failure'`. |
| Per-flavor `src/<flavor>/assets/` | [Android: build
variants](https://developer.android.com/build/build-variants) | n/a |
**`asset_merging`** → `'flavor-specific and buildType-specific native
assets are packaged into the matching variant APK'` | Covered, including
the negative case that the non-selected flavor does not contribute. |
| Per-buildType `src/<buildType>/assets/` | [Android: build
variants](https://developer.android.com/build/build-variants) | n/a |
**`asset_merging`** → same test as above | Covered. Added in response to
review; folded into the existing flavor test so it reuses that build and
costs no additional CI time. |
| Library / AAR assets from dependencies | [Android: create a
library](https://developer.android.com/studio/projects/android-library)
| n/a | None | No new test recommended. Likely common in the wild, but
merging AAR assets is core AGP behavior that this PR does not touch — we
add a generated source directory and otherwise leave the merger alone.
Testing it would be testing AGP, not Flutter. |
| `androidResources.noCompress` | [Android:
AaptOptions](https://developer.android.com/reference/tools/gradle-api/current/com/android/build/api/dsl/AndroidResources)
| n/a | None | No new test recommended. Rare, and handled entirely by
AGP's packaging step downstream of anything this PR changes. |

**Gap summary.** The only Android-side gap this PR chose not to close is
library/AAR asset merging, on the grounds that it is AGP behavior we do
not modify. If we later want it, the natural home is
`android_gradle_asset_merging_test.dart` — add a `flutter create
--template=plugin` dependency carrying an asset and assert the entry
appears in the app's APK.

</details>

### Behavioral and compatibility notes

1. **`copyFlutterAssets<Variant>` is no longer a Gradle `Copy`.** Build
scripts that reached in and cast it to `org.gradle.api.tasks.Copy` will
now get a `ClassCastException` and must use `CopyFlutterAssetsTask` or
plain `Task`.
2. **`processResources` no longer depends on `flutter assemble`.**
Java/Kotlin resource processing is now independent of Flutter
compilation.
3. **Stale asset pruning moved.** It is handled by
`FileSystemOperations.sync` in the task's own output directory rather
than by mutating `cleanMergeAssets`.
4. **Collision precedence is contractual, not incidental.** Per the AGP
`SourceDirectories` API docs, `addGeneratedSourceDirectory` places the
directory in the "Variant" overlay and it "will have the highest
priority" during merge. Generated Flutter assets therefore win over
`src/main/assets`. This is asserted by test, and the contract is quoted
in a comment above that test.

---

## 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.

<!-- 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/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[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

---------

Co-authored-by: Reid Baker <1063596+reidbaker@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.