Repository navigation
Migrate the flutter-apk copy and per-ABI versionCode to the variant API - #7
Open
reidbaker-agent wants to merge 71 commits into
Open
reidbaker-agent wants to merge 71 commits into
reidbaker-agent wants to merge 71 commits into
Conversation
reidbaker-agent
force-pushed
the
agp-assets-onvariants
branch
from
July 22, 2026 15:54
1c1b7f1 to
8dbebbb
Compare
reidbaker-agent
force-pushed
the
agp-apk-copy-versioncode
branch
from
July 22, 2026 15:54
c051ed0 to
1d44353
Compare
reidbaker-agent
force-pushed
the
agp-assets-onvariants
branch
from
July 28, 2026 13:35
8dbebbb to
b7ca673
Compare
reidbaker-agent
force-pushed
the
agp-apk-copy-versioncode
branch
from
July 28, 2026 13:36
1d44353 to
f3d2a31
Compare
reidbaker-agent
force-pushed
the
agp-assets-onvariants
branch
from
July 28, 2026 13:37
b7ca673 to
34cd183
Compare
reidbaker-agent
force-pushed
the
agp-apk-copy-versioncode
branch
from
July 28, 2026 13:37
f3d2a31 to
91f0814
Compare
reidbaker-agent
force-pushed
the
agp-assets-onvariants
branch
from
July 29, 2026 20:21
34cd183 to
bd722f5
Compare
reidbaker-agent
force-pushed
the
agp-apk-copy-versioncode
branch
from
July 29, 2026 20:21
91f0814 to
45e5dea
Compare
reidbaker-agent
force-pushed
the
agp-assets-onvariants
branch
from
July 29, 2026 20:43
bd722f5 to
78c25d5
Compare
reidbaker-agent
force-pushed
the
agp-apk-copy-versioncode
branch
3 times, most recently
from
July 31, 2026 16:16
e34a92a to
b7a23f7
Compare
reidbaker
force-pushed
the
agp-apk-copy-versioncode
branch
from
July 31, 2026 18:07
b7a23f7 to
53bcc7f
Compare
reidbaker
force-pushed
the
agp-assets-onvariants
branch
from
August 6, 2026 14:37
2654136 to
bd2c850
Compare
reidbaker
force-pushed
the
agp-apk-copy-versioncode
branch
from
August 6, 2026 14:37
53bcc7f to
910cd5d
Compare
This was referenced Aug 10, 2026
10 tasks done
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>
10 tasks done
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>
10 tasks done
10 tasks done
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.
10 tasks done
bkonyi
pushed a commit
to bkonyi/flutter
that referenced
this pull request
Sep 4, 2026
… NDK fallback to public DSL (flutter#192116) This is PR 5 of 11 in the AGP 9.1.0 / public `gradle-api` / newdsl migration stack. Add externalNativeBuild to the shared type. Extracted some shared mocking logic to a utility. No external visible changes expected. Also improved the README.md so that the test file for multiple agp versions was a markdown link. - @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 5 of 11 in the AGP 9.1.0 / public `gradle-api` migration stack (flutter#180137, flutter#166550). ### Key Changes - **Public DSL Wrapper `externalNativeBuild`**: Exposes `val externalNativeBuild: ExternalNativeBuild` in `AgpCommonExtensionWrapper.kt` dispatching across `ApplicationExtension`, `LibraryExtension`, `DynamicFeatureExtension`, and `TestExtension` without referencing `CommonExtension` (bypassing AGP binary incompatibility). - **Zero Legacy `BaseExtension` in Production Sources**: Deletes `getLegacyAndroidExtension(project: Project): BaseExtension` and removes the `com.android.build.gradle.BaseExtension` import from `FlutterPluginUtils.kt`. - **Public DSL NDK Fallback Configuration**: Migrates `forceNdkDownload` and `configureSyntheticExternalNativeBuildFallback` in `FlutterPluginUtils.kt` to `getAndroidExtension(gradleProject)` using `externalNativeBuild.cmake` / `externalNativeBuild.ndkBuild`. Sets `cmake.path = File(...)`, `cmake.buildStagingDirectory = ...`, and `buildType.externalNativeBuild.cmake.arguments += ...` through the public DSL while preserving the upstream PR flutter#187201 `ndkBuild.path` check. - **Unit Test Public DSL Mocking & Cleanup**: Migrates unit tests in `FlutterPluginUtilsTest.kt` to mock public DSL types (`ApplicationExtension`, `Cmake`, `NdkBuild`), asserts CMake arguments by list content, deletes obsolete tests asserting `ApplicationExtension`-vs-`BaseExtension` `ndkVersion` preference, and removes unused `import io.mockk.called` as well as all legacy `com.android.build.gradle.internal.*` imports. ## 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
force-pushed
the
agp-assets-onvariants
branch
from
September 9, 2026 15:26
bd2c850 to
1625350
Compare
11 tasks done
…3621) https://skia.googlesource.com/skia.git/+log/0575a37d0619..f2d68e0b8863 2026-10-01 recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com Roll recipe dependencies (trivial). 2026-10-01 skia-autoroll@skia-public.iam.gserviceaccount.com Roll vulkan-deps from 3f513ae95e49 to 251e97a55bd3 (9 revisions) 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 awolff@google.com,egdaniel@google.com,kjlubick@google.com 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
…vIf... (flutter#193640) 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-test-scripts-flutter Please CC awolff@google.com,chrome-fuchsia-engprod@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
…ts (flutter#193512) Removes or narrows 5 web skips across 5 framework test files: - `packages/flutter/test/gestures/gesture_binding_resample_event_test.dart`: removes the `skip: isBrowser` from the shared `testResampleEvent` helper. Pointer event resampling under `fakeAsync` now works on web, so every resample test in the file runs on web. - `packages/flutter/test/widgets/binding_test.dart`: narrows the skip on `defaultStackFilter elides framework Element mounting stacks` from `kIsWeb` to `kIsWasm`. It passes with CanvasKit but still fails with Skwasm, which flutter#87875 continues to track. - `packages/flutter/test/widgets/keep_alive_test.dart`: unskips `KeepAlive render tree description`. The test only failed because the expected `RenderView` description used `Platform.operatingSystem`. `RenderView.debugFillProperties` prints `Web` on web (`kIsWeb ? 'Web' : Platform.operatingSystem`), so the two expected strings now match that logic. - `packages/flutter/test/widgets/app_overrides_test.dart`: unskips `showPerformanceOverlayOverride true`. The test only checks that a `PerformanceOverlay` widget is inserted into the tree, which works on web. It does not depend on the overlay rendering stats, which is what flutter#52258 tracks. - `packages/flutter/test/services/scribe_test.dart`: unskips `when receiving an unsupported message`, which checks that an unsupported `flutter/scribe` platform message returns a `null` response (the `MissingPluginException` is caught). Platform message handling behaves the same on web, so the `[intended]` skip is unnecessary. The other `[intended]` web skips in this file are unchanged. Fixes flutter#87067 Fixes flutter#87876 ## 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
…trap.js (flutter#193271) Synchronizes Flutter Web's Wasm feature detection with the Dart SDK's `dart2wasm` compiler output (`main.dart.support.js`) and automates keeping `supportsDart2Wasm()` in sync during Dart SDK rolls. Follows up on flutter#193090. ### Background When `dart2wasm` compiles a Wasm module (`pkg/dart2wasm/lib/compile.dart`), it emits `<output>.support.js` (`main.dart.support.js` in Flutter Web builds), containing a JavaScript boolean expression that checks whether the current browser supports all WebAssembly features required by the compiled module (WasmGC, relaxed/standard SIMD, `js-string` builtins, `try_table`, and conditional `requiresMultiMemory`). Previously, `engine/src/flutter/lib/web_ui/flutter_js/src/browser_environment.js` maintained a manual copy of this byte array check inside `supportsDart2Wasm()`. Whenever `dart2wasm` added or modified a required Wasm feature probe in the Dart SDK, `flutter_js` had to be manually updated in a separate PR. Additionally, `main.dart.support.js` emitted by `dart2wasm` during `flutter build web --wasm` was never read by `flutter_tools`. ### Changes 1. **Consume `main.dart.support.js` in `flutter_tools` bootstrap generation**: - `generateFlutterBootstrapScript` reads `main.dart.support.js` when present in the build output directory and emits `_flutter.supportsDart2Wasm = <expr>;` immediately after `_flutter.buildConfig = ...;` (preserving strict JSON parsing in `--web-content-hash`). - `supportsDart2Wasm()` in `browser_environment.js` evaluates `window._flutter?.supportsDart2Wasm ?? defaultSupportsDart2Wasm()` after enforcing the Firefox `< 147` guard, so standard `flutter build web --wasm` apps use the exact feature probe emitted by the active `dart2wasm` compiler (including conditional flags such as `--extra-compiler-option=--import-shared-memory`), while custom HTML embeddings using standalone `flutter.js` fall back to `defaultSupportsDart2Wasm()` from `supports_dart2wasm.js`. 2. **Automate `supports_dart2wasm.js` generation during Dart SDK rolls**: - Moves the default `supportsDart2Wasm` probe into a standalone generated module `engine/src/flutter/lib/web_ui/flutter_js/src/supports_dart2wasm.js` imported by `browser_environment.js`. - `engine/src/tools/dart/create_updated_flutter_deps.py` (`SyncSupportsDart2WasmJs`) parses `_generateSupportJs` from `pkg/dart2wasm/lib/compile.dart` (from local `third_party/dart` or `dart.googlesource.com` when `--dart_revision` is specified) and generates `supports_dart2wasm.js`. - `.github/workflows/roll-dart-dependencies.yml` stages `engine/src/flutter/lib/web_ui/flutter_js/src/supports_dart2wasm.js` alongside `DEPS` when rolling Dart dependencies. 3. **CI Parity Guard**: - `engine/src/tools/dart/create_updated_flutter_deps_tests.py` verifies `ExtractDart2WasmSupportExpression` across historical `dart2wasm` epochs and asserts that `supports_dart2wasm.js` matches `third_party/dart/pkg/dart2wasm/lib/compile.dart` whenever `third_party/dart` is present. ## 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] All existing and new tests are passing.
Follow-up to flutter#188571, which removed the `download_jdk` gclient var from DEPS and the builder JSONs under `ci/builders/`. Two references were outside that path and got missed: - `engine/src/flutter/.ci.yaml`: the Linux, Mac and Windows `builder_cache` targets still pass `"download_jdk": "true"`. DEPS no longer declares the var, so gclient drops the override and the line does nothing. - `lib/web_ui/dev/generate_builder_json.dart` still emits `'download_jdk': false`. On master today, `felt generate-builder-json` adds three `"download_jdk": false` lines back to `linux_web_engine_test.json`. With this change it regenerates the checked-in file with no diff. No behavior change. After this, `git grep download_jdk` is empty. Part of flutter#187627. ## 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). - [ ] 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/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 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…193407) ### Rationale In `engine/src/flutter/tools/gn`, `to_gn_args()` checks `if args.target_os == 'wasm' or args.web:`, delegates to `to_gn_wasm_args()`, and returns early before reaching the line `gn_args['flutter_runtime_mode'] = runtime_mode`. Because `to_gn_wasm_args()` never mapped the argument back into `gn_args`, `flutter_runtime_mode` falls back to `"debug"` during GN evaluation for all `--web` engine targets. This evaluates `impeller_debug = true` (`IMPELLER_DEBUG=1` macro) globally in C++ for Web Impeller release builds. This defect was driving 50+ synchronous `glCheckFramebufferStatus()` calls per frame on `bouncy@128` (and 500+ calls per frame on multi-pass blur/filter workloads) during Web Impeller benchmarking. ### Summary of Changes - Propagates `args.runtime_mode` into `gn_args['flutter_runtime_mode']` inside `to_gn_wasm_args()` in `tools/gn`. - Adds explicit unit tests in `tools/gn_test.py` (`test_get_out_dir` and `test_to_gn_args`) verifying `flutter_runtime_mode` and output directories across `debug`, `profile`, and `release` for `--web` and `--target-os=wasm`. ### Verification & Empirical Performance Delta (`wimp.wasm` `wasm_release`) - Executed `tools/gn_test.py` with 100% pass on all 5 test cases. - Built `wimp.wasm` (`wasm_release`) locally before and after this change and benchmarked both single-pass and multi-pass offscreen workloads (`?effects=multipass`, wrapping each leaf node in `ColorFiltered` + `ClipRect` + `BackdropFilter` 5px Gaussian blur + `Opacity`): | Workload & Metric | Before (`IMPELLER_DEBUG=1`) | After (`IMPELLER_DEBUG=0`) | Delta | Speedup | | :--- | :---: | :---: | :---: | :---: | | **`wimp.wasm` Uncompressed / Gzipped Size** | `3,608,411 B` / `1,463,726 B` | `3,599,401 B` / `1,457,944 B` | `-9,010 B` / `-5,782 B` | `-0.25%` / `-0.40%` | | **`bouncy@128` (single-pass) `glCheckFramebufferStatus` / frame** | `58` (`2.83%` worker CPU) | `0` | **`-100.0%`** | Eliminated | | **`bouncy_multipass@16` (`wimp_st`) `glCheckFramebufferStatus` / frame** | `148` | `0` | **`-100.0%`** | Eliminated | | **`bouncy_multipass@16` (`wimp_st`) Raster Time (`ms/frame`)** | `273.40 ms` | `210.28 ms` | **`-63.12 ms` (`-23.1%`)** | **`1.30x` faster** | | **`bouncy_multipass@32` (`wimp_st`) `glCheckFramebufferStatus` / frame** | `268` | `0` | **`-100.0%`** | Eliminated | | **`bouncy_multipass@32` (`wimp_st`) Raster Time (`ms/frame`)** | `286.61 ms` | `203.44 ms` | **`-83.16 ms` (`-29.0%`)** | **`1.41x` faster** | | **`bouncy_multipass@64` (`wimp_st`) `glCheckFramebufferStatus` / frame** | `502` | `0` | **`-100.0%`** | Eliminated | | **`bouncy_multipass@64` (`wimp_st`) Raster Time (`ms/frame`)** | `364.64 ms` | `246.61 ms` | **`-118.03 ms` (`-32.4%`)** | **`1.48x` faster** | | **`bouncy_multipass@64` (`wimp_mt`) `glCheckFramebufferStatus` / frame** | `503` | `0` | **`-100.0%`** | Eliminated | | **`bouncy_multipass@64` (`wimp_mt`) Raster Time (`ms/frame`)** | `380.41 ms` | `256.95 ms` | **`-123.46 ms` (`-32.5%`)** | **`1.48x` faster** | | **`bouncy_multipass@64` (`--disable-gl-drawing-for-tests`, `wimp_st`)** | `228.21 ms` | `42.31 ms` | **`-185.90 ms` (`-81.5%`)** | **`5.39x` faster** | Fixes flutter#193406 ## 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
…193524) ## Summary Migrates `DeviceManager` (`FlutterDeviceManager`) initialization out of `context_runner.dart` and into `ToolDependencies.bootstrap` in `tool_dependencies.dart`, exposing `deviceManager` on `ToolDependencies`. * Bootstraps `AndroidWorkflow`, `MacOSWorkflow`, `WindowsWorkflow`, and `FlutterDeviceManager` in `ToolDependencies.bootstrap`. * Removes the `DeviceManager` fallback from `context_runner.dart` and binds `DeviceManager: () => toolDeps.deviceManager` in `runner.dart` after bootstrapping so unmigrated callers accessing `globals.deviceManager` resolve the bootstrapped instance. * Wires `toolDependencies.deviceManager` into `DaemonCommand` and `DevicesCommand` in `executable.dart`. * Adds unit test coverage in `packages/flutter_tools/test/general.shard/context/dependency_injection_test.dart`. Part of flutter#188471 ## 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
…eb-content-hash (flutter#193614) ## Description Fixes a content-hash mismatch when combining `--web-content-hash` and `--source-maps` in `flutter build web`: - **Hash and rename `sourceMapFile` before rewriting `sourceMappingURL` (`_hashAndRenameWebOutput`)**: - Previously, `_hashAndRenameWebOutput` (`packages/flutter_tools/lib/src/build_system/targets/web.dart`) hashed `main.dart.js` *before* rewriting its trailing `//# sourceMappingURL=main.dart.js.map` comment in-place (and stripped the trailing newline because `\s*$` matched `\n` before EOF). - When `updatePrecacheManifest` (`packages/flutter_tools/lib/src/web/content_hash.dart`) later hashed the final `build/web/main.dart.<hash>.js` bytes on disk, the rewritten `sourceMappingURL` comment produced a different SHA-256 prefix, causing `precache_manifest.json` to emit `"urlHashed": false` and a mismatched `"hash"` for `main.dart.<hash>.js`. - `_hashAndRenameWebOutput` now hashes `sourceMapFile` first (`mapHash`), renames it via `computeHashedBasename(oldMapBasename, mapHash, file.fileSystem)` (`main.dart.<mapHash>.js.map`, `main.dart.<mapHash>.mjs.map`, `worker.<mapHash>.js.map`), rewrites `//# sourceMappingURL=<newMapBasename>` in the code file using a positive lookahead `(?=\s*$)` so trailing newlines are preserved, and then hashes and renames the code file (`contentHash`) so its filename hash matches its final on-disk bytes. - **Resolve hashed source map basenames in `Dart2JSTarget.buildFiles` and `Dart2WasmTarget.buildFiles`**: - Uses `_resolveHashedBasename(environment.buildDir, _mainJsMapRegex, 'main.dart.js.map')` and `_resolveHashedBasename(environment.buildDir, _mainMjsMapRegex, 'main.dart.mjs.map')` when `compilerConfig.webContentHash` is enabled so `WebReleaseBundle` copies the independently content-hashed `.map` files to `build/web/`. ## Related Issues - Fixes flutter#193601 - Part of flutter#149031 ## Tests - Updated source map hashing unit tests in `packages/flutter_tools/test/general.shard/build_system/targets/web_test.dart` to verify independent map and code content hashes and trailing newline preservation. - Added a regression test (`hashAndRenameWebOutput with sourceMapFile produces matching hash and urlHashed: true in updatePrecacheManifest`) verifying end-to-end parity between `_hashAndRenameWebOutput` and `updatePrecacheManifest`.
…ter#193661) Manual roll requested by jjosh@google.com https://chromium.googlesource.com/chromium/deps/icu.git/+log/6ebb40c59477..5aa526207171 2026-09-24 tkent@chromium.org Update TZDB to 2024d 2026-09-03 kojii@chromium.org Add kojii to `OWNERS` 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/icu-sdk-flutter Please CC awolff@google.com,fuchsia-ui-discuss@google.com,jjosh@google.com on the revert to ensure that a human is aware of the problem. To file a bug in ICU: https://github.com/unicode-org/icu 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
…or DI (flutter#193542) Migrates `DaemonCommand`, `DaemonServer`, `Daemon`, `DaemonDomain`, `AppDomain`, `DeviceDomain`, `EmulatorDomain`, and `ProxyDomain` to explicit constructor dependency injection via `ToolContext`, `AndroidContext`, `Analytics`, `FeatureFlags`, and `DeviceManager`, and makes `DelegatingToolContext` `const` in `test/src/fakes.dart`. Note: in `--listen-on-tcp-port` mode, per-connection domain errors now route through `NotifyingLogger` to connected clients rather than the server's stderr (`DaemonServer.logger` continues to log general server-level errors). Fork diff: bkonyi/flutter@master...di/22b-1-daemon Part of flutter#188471 ## 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.
…zation order (flutter#191591) Fixes flutter#99153 ## Summary # Flutter Issue Investigation: flutter#99153 **Issue**: [flutter#99153 - Use dependency graph to determine plugin initialization order](flutter#99153) **Status**: Resolved **Scope**: `packages/flutter_tools` --- ## 1. Overview and Problem Statement When Flutter generates native plugin registrants (such as `GeneratedPluginRegistrant.java`, `GeneratedPluginRegistrant.m`, `generated_plugin_registrant.cc`, `web_plugin_registrant.dart`) and plugin dependency files (`.flutter-plugins-dependencies`), plugins were previously sorted purely alphabetically by plugin name (`left.name.compareTo(right.name)`). While alphabetical sorting ensured deterministic registrant generation, it did not take into account dependencies between plugins. If `plugin_a` depended on `plugin_z`, `plugin_a` would be registered and initialized before `plugin_z`, leading to potential initialization order bugs when a plugin depends on services or state initialized by another plugin. --- ## 2. Root Cause Analysis 1. **`findPlugins` & `refreshPluginsList`**: - `findPlugins` collected plugins in arbitrary traversal order from `computeTransitiveDependencies`. - `refreshPluginsList` sorted `plugins` alphabetically (`plugins.sort((Plugin left, Plugin right) => left.name.compareTo(right.name));`). 2. **`_resolvePluginImplementationsByPlatform`**: - Platform implementation candidate resolution re-sorted the platform-specific plugins alphabetically (`pluginImplementations.sort((Plugin left, Plugin right) => left.name.compareTo(right.name));`), overriding any topological order. 3. **`_writeFlutterPluginsList` and Registrant Generators**: - Iterated over the sorted lists and wrote registrations directly to disk. --- ## 3. Solution & Architecture ### Topological Sort (`sortByDependencies`) Implemented `sortByDependencies(Iterable<Plugin> plugins)` in `packages/flutter_tools/lib/src/flutter_plugins.dart`: - Uses Kahn's algorithm for topological sorting: 1. Computes in-degree for all plugins within the set of active plugins based on `plugin.dependencies`. Non-plugin dependencies (e.g., `flutter`, `meta`, external packages) are filtered out. 2. Seeds available queue with plugins having 0 in-degree, sorted alphabetically. 3. Dequeues plugins and decrements dependent plugins' in-degrees. When in-degree reaches 0, dependent plugins are added to the available queue (alphabetically sorted). 4. If a dependency cycle occurs, the algorithm breaks cycles deterministically by selecting the unplaced plugin with the smallest in-degree, breaking ties alphabetically. 5. For independent plugins with no dependency relationships, preserves alphabetical sorting. ### Call Site Updates - Updated `findPlugins` to return `sortByDependencies(plugins)`. - Updated `_resolvePluginImplementationsByPlatform` to sort platform implementations using `sortByDependencies(pluginResolution.values)`. - Removed redundant `plugins.sort` in `refreshPluginsList` and `packages/flutter_tools/lib/src/commands/build_swift_package.dart`. --- ## 4. Automated Testing and Verification ### Regression & Unit Tests Added - **`Refreshing the plugin list sorts plugins by dependency order`** in `packages/flutter_tools/test/general.shard/plugins_test.dart`. - **`group('sortByDependencies')`** in `plugins_test.dart`: - `returns empty list when input is empty` - `returns single element list as-is` - `sorts independent plugins alphabetically` - `sorts direct dependency before dependent plugin` - `sorts multi-level linear dependency chain` - `sorts diamond dependency graph` - `ignores non-plugin dependencies` - `handles dependency cycle deterministically without throwing or hanging` - **Registrant Injection Tests**: - `Generated Linux plugin files sorts by dependency order` - `Generated Windows plugin files sorts by dependency order` ### Verification Results - `dart format` cleanly applied across all modified files. - `dart analyze --fatal-infos packages/flutter_tools`: Passed with **0 errors, 0 warnings, 0 infos**. - `dart test packages/flutter_tools/test/general.shard/plugins_test.dart`: All **97 tests passing**. ## Verification - Regression test included and verified.
… green (flutter#193580) ## 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. - [ ] 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). - [ ] 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. - [x] All existing and new tests are passing.
… 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>
Issue: flutter#193579. This is a fix for the following error: ``` Processing /Volumes/Work/s/w/ir/x/w/flutter/bin/cache/pkg/tests/registry/flutter_cocoon.test... Unhandled exception: ProcessException: No such file or directory Command: ./test_utilities/bin/flutter_test_runner.sh dashboard #0 _ProcessImpl._start (dart:io-patch/process_patch.dart:411:33) #1 Process.start (dart:io-patch/process_patch.dart:42:20) #2 shell (file:///Volumes/Work/s/w/ir/x/w/flutter/dev/customer_testing/lib/runner.dart:236:29) #3 runTests (file:///Volumes/Work/s/w/ir/x/w/flutter/dev/customer_testing/lib/runner.dart:172:31) <asynchronous suspension> #4 main (file:///Volumes/Work/s/w/ir/x/w/flutter/dev/customer_testing/run_tests.dart:15:8) <asynchronous suspension> ```
This PR automates the synchronization of `CHANGELOG.md` from the `stable` branch to the `master` branch.
Enables `xvfb: "1"` in `.ci.yaml` for `Linux windowing_test` to provide a virtual display on CI bots, and starts an `openbox` window manager in `dev/devicelab/bin/tasks/windowing_test_linux.dart` (matching the engine xvfb.py test), which is required for fullscreen and maximized window testing. Part of stack #193534.
<!-- 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 --> The app has been moved to https://github.com/flutter/packages/tree/main/packages/material_ui/test_apps/a11y_assessments ## Pre-launch Checklist - [ ] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [ ] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [ ] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [ ] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [ ] I signed the [CLA]. - [ ] 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). - [ ] 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. 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
…93676) https://skia.googlesource.com/skia.git/+log/f2d68e0b8863..7b7326917e77 2026-10-01 alexisdavidc@google.com [Raster] Update BilerpBench to include 1080p-4k upscaling 2026-10-01 recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com Roll recipe dependencies (trivial). 2026-10-01 elliotsisteron@google.com Run RustPNGAndroid tests on the CQ for Rust PNG changes 2026-10-01 recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com Roll recipe dependencies (trivial). 2026-10-01 alexisdavidc@google.com [Docs] Add comment for ThreadLocalStrikeCache 2026-10-01 elliotsisteron@google.com Reject zero denominator or gamma in SkGainmapInfo 2026-10-01 skia-autoroll@skia-public.iam.gserviceaccount.com Manual roll Dawn from db1e07651072 to 395c66d29124 (7 revisions) 2026-10-01 thomsmit@google.com [sksl] Track SPIR-V capabilities in a set instead of a bitmask 2026-10-01 thomsmit@google.com [graphite] Disable some ComputeTests on protected contexts 2026-10-01 skia-autoroll@skia-public.iam.gserviceaccount.com Roll vulkan-deps from 251e97a55bd3 to 955345963155 (2 revisions) 2026-10-01 skia-autoroll@skia-public.iam.gserviceaccount.com Manual roll ANGLE from bae3c5d66a8d to de3b57c0e726 (7 revisions) 2026-10-01 elizarovv@google.com Gate the GrProcessor pool lock on SK_ASSUME_SINGLE_GANESH_CONTEXT 2026-10-01 skia-autoroll@skia-public.iam.gserviceaccount.com Roll ANGLE from 67691470653a to bae3c5d66a8d (7 revisions) 2026-10-01 skia-autoroll@skia-public.iam.gserviceaccount.com Roll Skia Infra from dff238600166 to b3423e5ca35c (11 revisions) 2026-10-01 skia-autoroll@skia-public.iam.gserviceaccount.com Roll Dawn from 4e3776803c08 to db1e07651072 (9 revisions) 2026-10-01 skia-autoroll@skia-public.iam.gserviceaccount.com Roll debugger-app-base from fd26511d445a to b69748450f35 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 awolff@google.com,egdaniel@google.com,kjlubick@google.com 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
Deduplicates redundant OpenGL ES state transitions across draw commands
within `RenderPassGLES` (`EncodeCommandsInReactor`):
1. **Per-Pass Orthogonal GLES State Tracking (`RenderPassStateCache`)**:
- Encapsulates pass-scoped GL state tracking inside
`RenderPassStateCache` (`BlendStateCache`, `StencilFaceStateCache`,
`StencilStateCache`, and `DepthStateCache` in an anonymous namespace in
`render_pass_gles.cc`), tracking enabled/disabled state (`GL_BLEND`,
`GL_STENCIL_TEST`, `GL_DEPTH_TEST`, `GL_SCISSOR_TEST`), active program
handle (`std::optional<HandleGLES>` via `HandleGLES::Equal{}` so
pipeline variants sharing a compiled `UniqueHandleGLES` skip redundant
program binds and `_impeller_y_flip` uniform updates), color mask, blend
equations/factors, depth compare function and write mask, front/back
stencil functions/operations/write masks, viewport, scissor rect, cull
mode, and winding order across draw calls within
`EncodeCommandsInReactor`.
- `ResetGLState` initializes the tracked state once at pass entry before
`glClear`, eliminating the redundant pass-exit `ResetGLState` call while
ensuring no state leaks across passes, `ReactorGLES` handle operations,
or `BlitPassGLES` commands.
### WebGL 2.0 Call Count & CPU Command-Encoding Reduction (Web Impeller
/ WIMP)
| Workload (`1280x720`, `wimp_st`) | Metric | Before | After | Delta |
| :--- | :--- | :---: | :---: | :---: |
| **`bouncy` (`128` nodes, `441` draws)** | Total WebGL2 calls / frame |
`13,234` | `7,983` | **`-39.7%` (`-5,251` calls)** |
| | `glBlendEquationSeparate` + `glBlendFuncSeparate` / frame | `802` |
`4` | **`-99.5%`** |
| | `glStencilFuncSeparate` + `Op` + `Mask` / frame | `1,327` | `9` |
**`-99.3%`** |
| | `glColorMask` / frame | `443` | `3` | **`-99.3%`** |
| | `glEnable` + `glDisable` / frame | `1,506` | `225` | **`-85.1%`** |
| | `glDepthFunc` + `glDepthMask` / frame | `884` | `161` | **`-81.8%`**
|
| | `glUseProgram` / frame | `441` | `105` | **`-76.2%`** |
| | `glUniform1fv` (`_impeller_y_flip`) / frame | `441` | `105` |
**`-76.2%`** |
| | `glScissor` / frame | `175` | `117` | **`-33.1%`** |
| | CPU command-encoding raster time (`--disable-gl-drawing-for-tests`)
| `13.41 ms` | `12.47 ms` | **`-7.0%` (`-0.94 ms`, `1.08x` faster)** |
| **`grid` (`1000` nodes, `5,908` draws)** | Total WebGL2 calls / frame
| `154,521` | `94,517` | **`-38.8%` (`-60,004` calls)** |
| | `glBlendEquationSeparate` + `glBlendFuncSeparate` / frame | `9,474`
| `338` | **`-96.4%`** |
| | `glStencilFuncSeparate` + `Op` + `Mask` / frame | `17,726` | `844` |
**`-95.2%`** |
| | `glColorMask` / frame | `5,909` | `337` | **`-94.3%`** |
| | `glEnable` + `glDisable` / frame | `18,071` | `2,691` | **`-85.1%`**
|
| | `glUseProgram` / frame | `5,908` | `2,197` | **`-62.8%`** |
| | `glUniform1fv` (`_impeller_y_flip`) / frame | `5,908` | `2,197` |
**`-62.8%`** |
| | `glDepthFunc` + `glDepthMask` / frame | `11,817` | `6,051` |
**`-48.8%`** |
| | CPU command-encoding raster time (`--disable-gl-drawing-for-tests`)
| `60.86 ms` | `56.13 ms` | **`-7.8%` (`-4.73 ms`, `1.08x` faster)** |
Fixes flutter#192147
## 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
reidbaker
force-pushed
the
agp-apk-copy-versioncode
branch
from
October 2, 2026 01:06
910cd5d to
79ef973
Compare
11 tasks done
The application path of the Flutter Gradle Plugin no longer uses the deprecated BaseVariant API (applicationVariants / ApkVariantOutput): - CopyFlutterApksTask copies the variant's SingleArtifact.APK outputs, read through BuiltArtifactsLoader, into build/outputs/flutter-apk under the unchanged names app[-abi][-flavor]-<mode>.apk. assemble<Variant> depends on it. The task has no Project or variant fields and uses an injected FileSystemOperations. - A single naming function in the task produces both the declared @OutputFiles and the copied file names. Its inputs are the ABIs of the variant's outputs (what AGP builds), the flavor, and the build mode. The task fails if AGP built an APK for an ABI that was not declared. - Per-ABI versionCode for --split-per-abi is a read-then-set on VariantOutput.versionCode in onVariants. This is a documented exception to the no-configuration-time-get rule, because the lazy form is circular. The read relies on AGP's compatibility mode (android.compatibility.enableLegacyApi, on by default through 9.x). - The applicationVariants.configureEach block and its @Suppress("DEPRECATION") markers are deleted. The add-to-app module path keeps using libraryVariants until the next phase. Behavior change: Flutter's onVariants callback runs before an app's own androidComponents.onVariants block, while ApkVariantOutput's versionCodeOverride was applied after it. Apps that transform output.versionCode there transform Flutter's offset value (for example arm64-v8a, build 42, x10000: 422000 -> 20420000). The migration doc and the breaking-change page draft describe this and give a recipe that keeps the 422000-style numbers. No divergence warning is emitted, because it would fire on the onVariants pattern that AGP recommends. Part of flutter#166550.
reidbaker
force-pushed
the
agp-apk-copy-versioncode
branch
from
October 2, 2026 01:38
79ef973 to
e15544b
Compare
…ures - Take the per-ABI versionCode base from a finalizeDsl snapshot of the DSL versionCodes (DslVersionCodes) instead of reading output.versionCode, which AGP rejects during configuration when android.compatibility.enableLegacyApi=false. Warn and skip when the DSL declares no versionCode. - Add a strict-mode (enableLegacyApi=false) case to flutter_build_apk_split_per_abi_test. - CopyFlutterApksTask: use Gradle's Copy/Sync caching annotation and reason; explain when the metadata can be missing and when the ABI check can fail; point both errors at the plugin that transforms SingleArtifact.APK instead of asking for a Flutter issue. - Document what an APK transform must keep in website-page-draft.md. - Link the website-page-draft.md references to tracking issue flutter#193713. - Remove temporal wording from KDoc and docs.
Merged
11 tasks done
…er comments - CopyFlutterApksTask: state why caching is disabled (local copy; a cache entry would duplicate the APKs) and build both errors through one transformedApkError helper. - Trim comments and KDoc added by this PR to what the code does not already say.
The flutter tool runs Gradle with -q, which hides logger.warn. Log the warning with logger.error, as the plugin's other user-facing warnings do, and state the consequence (Google Play needs a distinct versionCode per APK) and the fix.
reidbaker-agent
added a commit
that referenced
this pull request
Oct 9, 2026
…sionCode to the variant API (flutter#193693) ## Description This is PR 7 of 11 in the AGP 9.1.0 / public `gradle-api` migration stack ([flutter#180137](flutter#180137), [flutter#166550](flutter#166550)). This pr changes the way splitting by api version codes work. This can be a surprising change but I have not found a work around. PR 8 adds add-to-app support and as a result deletes a bunch of code that exists to bridge the partial migration. See flutter#19371 specifically https://github.com/flutter/flutter/pull/193717/changes/f668780fd47caca13c03828f49d21572074825d6..a6be16034c8a1a4a0456cd35194b5973cfd4dc75#r4185414230 which is a subset of changes. <details> <summary>Agent authored details</summary> ### Changes 1. **flutter-apk copy on the variant API.** `CopyFlutterApksTask` (`copyFlutterApks<Variant>`) copies the variant's `SingleArtifact.APK` outputs, read through `BuiltArtifactsLoader`, into `build/app/outputs/flutter-apk/`. The names are `app[-abi][-flavor]-<mode>.apk`, the format `listApkPaths` in `lib/src/android/gradle.dart` expects. `assemble<Variant>` depends on the task. - The task has no `Project` or variant fields. It uses injected `FileSystemOperations` and `@InputDirectory @PathSensitive(RELATIVE)`. - It is annotated `@DisableCachingByDefault(because = "Not worth caching")`, the annotation and reason Gradle uses on its own `Copy` and `Sync` tasks. - Its declared outputs are the individual APK files (`@OutputFiles`). The shared `flutter-apk` directory is not declared, because it would overlap between variants. - One naming function, `CopyFlutterApksTask.apkFileName`, produces both the declared outputs and the copied files. Its inputs are the ABIs of the variant's outputs, the flavor, and the build mode. 2. **Per-ABI versionCode without reading `output.versionCode`.** For `--split-per-abi`, the plugin sets `output.versionCode = ABI_VERSION[abi] * 1000 + base` on each `ApplicationVariant` output with an ABI filter. It never reads the property, because AGP rejects that read during configuration when `android.compatibility.enableLegacyApi=false`. - `DslVersionCodes` takes a snapshot of `defaultConfig.versionCode` and each product flavor's `versionCode` in `androidComponents.finalizeDsl`. - `forVariant(variant.productFlavors)` resolves the base the way AGP merges it: the first flavor, in dimension order, that sets a versionCode, otherwise `defaultConfig`. - If the DSL declares no versionCode, Flutter logs a warning and leaves the variant's versionCodes unchanged. 3. **APK transform errors point at the transform.** The copy fails in two cases. Both can happen only if another plugin or build script transforms `SingleArtifact.APK`: - the APK directory has no `output-metadata.json`; - an APK has an ABI filter that none of the variant's outputs declares. Both error messages name `SingleArtifact.APK` and tell the user to contact the maintainer of the plugin that does the transform. They do not ask for a Flutter issue. The task KDoc and `website-page-draft.md` say what a transform must keep. Plugins Flutter developers commonly use (Walle, VasDolly, packer-ng, AndResGuard, Sentry, Firebase App Distribution, Gradle Play Publisher) do not trigger either error; the evidence is in [this review reply](flutter#193693 (comment)). 4. **Deleted** the app-path `applicationVariants.configureEach` block and `configureAbiVersionCodeOverride`, together with their two `@Suppress("DEPRECATION")` markers and the unsafe `as ApkVariantOutput` cast. The add-to-app module path (`addFlutterDepsForModule`, `libraryVariants`) is left for PR 8. 5. **Structure follows the PR 6 review** (@mboetger's point that `registerFlutterAssetTasks` should not register the compile task). `onVariants` calls `configureSplitPerAbiVersionCodes` and `registerCopyFlutterApksTask` after `registerFlutterAssetTasks`, under the same `isApplicationProject && shouldCompileFlutterForVariant` gate. Each helper does one job, and no helper takes a parameter only to pass it on. 6. **Docs:** - `Migrating-Flutter-Gradle-Plugin-to-AGP-public-API.md`: decision record 4, the replacement map, and items 2 and 3 of "Features that must break". - `website-page-draft.md`: versionCode recipes that do not read `output.versionCode`, and the rules for APK transforms. - Links to the draft carry a TODO for [flutter#193713](flutter#193713), which tracks publishing it on docs.flutter.dev. 7. **Tests:** - `CopyFlutterApksTaskTest` (new, 5 tests). - `DslVersionCodesTest` (new, 5 tests). - 8 new `FlutterPluginTest` cases: defaultConfig and flavor offsets, the no-versionCode warning, no split, the force flag, copy wiring, profile/custom build type naming, and assemble wiring. The mocked `VariantOutput.versionCode` stubs only `set`, so any read fails the test. - `flutter_build_apk_split_per_abi_test.dart`: a fourth test builds with `android.compatibility.enableLegacyApi=false`, and every test asserts each per-ABI APK is in `flutter-apk`. ### Review response (commit `33f39876b92`) | Comment | Change | | --- | --- | | Caching annotation: "How do I know this is true?" | Uses Gradle's own `Copy`/`Sync` annotation and reason (checked with `javap`). | | Why would `load` return null? / How would ABIs mismatch? | Comments say exactly when each can happen. Errors point at the plugin that transforms the APK. | | Other places that build APK names | FGP has one. The tool's three reading sites are listed in the reply (ratchet: not changed here). | | Custom variants, and proof the copy works | Build-mode rule matches the deleted code. Results of a flavor and custom build type scratch app are in the reply. | | Temporal wording | Removed from KDoc and docs. | | Link to the website docs | TODO tied to flutter#193713 until the page is published. | | Reading `output.versionCode` depends on compatibility mode | No read. `finalizeDsl` snapshot instead, with a compatibility-mode-off integration test. | | Why ×10000, and can the earlier numbers be kept? | Explained in the replies. Keeping them requires reading the value the app set, which AGP rejects with compatibility mode off. | ### Why removing the deleted code is safe The deleted code used `AbstractAppExtension.applicationVariants`, `ApkVariantOutput.versionCodeOverride`/`getFilter`, and `packageApplicationProvider`. AGP deprecated these, and they are not available with AGP 9's `android.newDsl=true`. The replacements (`ApplicationVariant.outputs`, `VariantOutput.versionCode`/`filters`, `SingleArtifact.APK`, `BuiltArtifactsLoader`, `DslLifecycle.finalizeDsl`) are public `com.android.build.api` APIs available at the stack's AGP 8.11.1 floor. ### Behavioral and compatibility notes 1. **versionCode for apps that transform it in their own `onVariants` (breaking).** Flutter registers its `onVariants` callback when the plugin is applied, so AGP runs it before an app's `androidComponents.onVariants` block. `versionCodeOverride` was applied after that block. Apps that set `versionCode` only in the `android {}` DSL see no change. An app that multiplies by 10000 (compatibility mode on), built with `--build-number 42`: | ABI (offset) | `versionCodeOverride` | This PR | | --- | --- | --- | | `armeabi-v7a` (1) | 421000 | 10420000 | | `arm64-v8a` (2) | 422000 | 20420000 | | `x86_64` (4) | 424000 | 40420000 | Values stay distinct, keep ABI order, and only go up, so Play upgrades keep working. With compatibility mode off, apps can't read `output.versionCode` either. For that case the docs give a recipe that sets an absolute value in the app's `onVariants`, which replaces Flutter's: `offset * 1000 + flutter.versionCode * 10000`. 2. **A versionCode declared only in the manifest is not offset.** The DSL snapshot can't see it, so Flutter logs a warning and leaves the variant's versionCodes unchanged. 3. **A `finalizeDsl` callback registered after Flutter's that changes versionCode is not seen.** This is documented in the `DslVersionCodes` KDoc and the migration doc. 4. **`copyFlutterApks<Variant>` tasks appear in `gradlew tasks`** and can be UP-TO-DATE. 5. **Two build types that map to the same Flutter mode share a file name.** For example, `debug` and a debuggable `staging` both write `app-debug.apk`; the deleted code had the same clash. Running both assembles in one `./gradlew` invocation makes the two copy tasks alternate. The `flutter` tool builds one variant per invocation, so it is unaffected. ### Integration test coverage of the changed paths | Path | Tests | | --- | --- | | Per-ABI versionCode: default, build number, app `onVariants` transform, compatibility mode off | `flutter_build_apk_split_per_abi_test.dart` (4 tests; checks versionCodes with `apkanalyzer` and the per-ABI files in `flutter-apk`) | | flutter-apk copy, default and flavored | `android_gradle_asset_merging_test.dart`, `gradle_libapp_so_packaging_test.dart` (incl. flavors), `android_plugin_example_app_build_test.dart`, `isolated/native_assets_flutter_build_test.dart`; devicelab `flavors_test`, `gradle_desugar_classes_test` | | Plugin unit tests on AGP 8.11.1 and AGP 9 | `android_run_flutter_gradle_plugin_tests_test.dart` | ### Tests run locally - `./gradlew test` in `packages/flutter_tools/gradle` (JDK 17): pass (33 suites, 0 failures). - ktlint 1.5.0 with the CI `.editorconfig` and baseline: clean. - `dart format` / `dart analyze --fatal-infos` on the changed Dart test: clean. - `flutter_build_apk_split_per_abi_test` on `33f39876b92`: 4/4 pass. - On the review changes before the final edits to comments and error messages: `android_gradle_asset_merging_test` (4), `gradle_libapp_so_packaging_test` (4), `android_run_flutter_gradle_plugin_tests_test` (2) all pass. - Manual build with `enableLegacyApi=false` (AGP 9.3.1): versionCodes 1042/2042/4042. A negative control that re-adds the read fails with "configuration of project ':app' has not completed yet". - Scratch app with `free`/`paid` flavors and a custom `staging` build type: APK names and versionCodes match the deleted code. </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 `///`). - [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
EricApostal
pushed a commit
to EricApostal/flutter
that referenced
this pull request
Oct 12, 2026
… variant API (flutter#193717) PR 7 ([flutter#193693](flutter#193693)) merged to `master` as `ecd1ab06865`, and `23ddd6b74e6` merges `master` into this branch, so the [Files changed](https://github.com/flutter/flutter/pull/193717/files) tab shows only PR 8's changes. PR 8 commits: - `8c9a54d8297` Unify add-to-app module wiring on the variant API - `2c28d8f8245` Merge PR 7 head `f668780fd47` (conflicts resolved to PR 7's wording where PR 8 does not change the code) - `a6be16034c8` Trim comments added by PR 8 - `b8cd39bcf81` Address review: clarify the variant gate and task registration comments - `2efbd345505` Address review: check the add-to-app module in module_host_with_custom_build_test - `d8f869ec468` Address review: share task registration stubs in FlutterPluginTest - `798ac295725` Address review: take ApplicationVariant in configureApplicationOutputs - `1366874099e` Address review: drop android.compatibility.enableLegacyApi from the qa section - `eb20bbd43de` Merge PR 7 head `25550b3fc49` (no conflicts) - `23ddd6b74e6` Merge `master` at `ecd1ab06865` (PR 7 squash-merged). `FlutterPlugin.kt`, `FlutterPluginUtils.kt` and `FlutterPluginTest.kt` conflicted only because the squash commit is not an ancestor; `master`'s copies are identical to `25550b3fc49`, already merged by `eb20bbd43de`, so this branch's side was kept. ## Description This is PR 8 of 11 in the AGP 9.1.0 / public `gradle-api` migration stack ([flutter#180137](flutter#180137), [flutter#166550](flutter#166550)). An add-to-app module (an Android library) is wired through the same `androidComponents.onVariants` path as an app. The module adds Flutter's assets and native libraries to its own variants, and the host app consumes them like any Android library. Flutter does not look up or configure the host project. With this PR, a host app with AGP 9's `android.newDsl=true` builds a Flutter module from source; on `33f39876b92` it fails with `Check failed.` while configuring `:app`. **Breaking:** `flutter.hostAppProjectName` has no effect. Setting it logs a warning. **Base:** `master`. PR 7 (flutter#193693) merged as `ecd1ab06865`. <details> <summary>Agent authored details</summary> ### Changes 1. **Module variants on `onVariants`** (`FlutterPlugin.kt` `addFlutterTasks`). For every variant, app or library, `onVariants` calls `registerFlutterCompileTask`, `registerFlutterAssetTasks` and `registerFlutterJniLibsTask`. Only application variants then call the new `configureApplicationOutputs` (per-ABI versionCodes and the flutter-apk copy), which takes an `ApplicationVariant`. There is no mid-lambda `return@onVariants`. 2. **Every module variant is configured.** `shouldCompileFlutterForVariant` returns true for a `LibraryVariant`. The command-line check (`shouldConfigureFlutterTask`, flutter#109560) compares the command line with the project's own `assemble<Variant>` names, and a host task such as `:app:assembleDemoStaging` never matches the module variant it consumes (`debug`, via `matchingFallbacks`). A module has three variants: the template's `debug` and `release`, plus the `profile` build type the plugin creates. It declares no flavors (`templates/module/android/library_new_embedding/Flutter.tmpl/build.gradle.tmpl`). The tasks are registered lazily, so a build runs only the module variant the host consumes. `--dry-run` on a host with flavor `demo` and build types `staging` (falls back to `debug`) and `prod` (falls back to `release`): | Host task | Module Flutter tasks in the task graph | | --- | --- | | `app:assembleDemoDebug`, `app:assembleDemoStaging` | `compileFlutterBuildDebug`, `copyFlutterAssetsDebug`, `copyJniLibsflutterBuildDebug` | | `app:assembleDemoRelease`, `app:assembleDemoProd` | `compileFlutterBuildRelease`, `copyFlutterAssetsRelease`, `copyJniLibsflutterBuildRelease` | 3. **Build mode from the module variant.** `registerFlutterCompileTask` reads the library variant's `buildType` and public `Component.debuggable`, so the mode follows the module variant the host consumes. 4. **jniLibs wired from the compile task provider.** `registerFlutterJniLibsTask` takes `compileTaskProvider` and sets `intermediateDir` from `compileTaskProvider.map { it.outputDirectory }`. The `tasks.matching { it.name == … }` dependency and the `findByName` provider are gone. Both copy tasks are registered only together with their compile task, so `intermediateDir` is required (not `@Optional`) in `CopyFlutterJniLibsTask` and `CopyFlutterAssetsTask`, and their `isPresent` branches are removed. 5. **`flutter.hostAppProjectName`.** `warnIfHostAppProjectNameIsSet` reads `project.providers.gradleProperty(…)` (not `rootProject.hasProperty`) and logs `Warning: The Gradle property 'flutter.hostAppProjectName' has no effect. Remove it from gradle.properties.` The `flutter.hostAppProjectName=SampleApp` line is removed from `dev/integration_tests/pure_android_host_apps/android_custom_host_app/gradle.properties`, so devicelab `module_custom_host_app_name_test` (host project `:SampleApp`) checks that a host not named `app` builds without the property. 6. **Deleted:** - From `FlutterPlugin.kt`: the host-project lookup, the `appProject.afterEvaluate` × `libraryVariants.all` × `applicationVariants.all` loop, the `merge<HostVariant>Assets.dependsOn` edge, `addFlutterDepsForModule` and `addCopyFlutterAssetsDependency`. - From `FlutterPluginUtils.kt`: `shouldConfigureFlutterTask(Project, Task)` and `buildModeFor(com.android.builder.model.BuildType)`. Both lost their last caller. 7. **Docs.** - `Migrating-Flutter-Gradle-Plugin-to-AGP-public-API.md`: decision record 5 and "Features that must break" item 6 are rewritten. - [`website-page-draft.md`](https://github.com/flutter/flutter/blob/master/docs/platforms/android/website-page-draft.md) (publishing tracked in [flutter#193713](flutter#193713)): the add-to-app section is rewritten. - The text these replace said that the warning names a removal milestone (it does not), and that a host `staging` debuggable build type gets debug artifacts (the module variant decides). It also said that `tasks.getByPath(":flutter:copyFlutterAssetsDebug")` fails with "Task with path … not found". That is false: in the scratch host below it returns a `CopyFlutterAssetsTask`. 8. **Tests.** - New `FlutterPluginTest` cases: - jniLibs wiring from the compile task provider, with no name lookups; - a module variant configured for a single unrelated command-line task, with no APK wiring; - the module build mode for `debug`, `profile` and `release`; - the `hostAppProjectName` warning, with no host lookup, and no warning when it is unset. - The skip test also checks that no jniLibs task is registered. - The new tests share stub helpers (`stubTaskRegistration`, `captureTaskConfiguration`, `setCommandLineTasks`). - devicelab `module_host_with_custom_build_test` gets a final section. The host fixture adds a build type `qa` (debuggable, falls back to `release`). The section runs `app:assembleDemoQa` with `android.newDsl=true` and `flutter.hostAppProjectName=app`. It checks that the output has the warning, and that `app-demo-qa.apk` has the Flutter assets and `libapp.so` for arm64-v8a and armeabi-v7a, and no debug assets. The existing sections already check `app:assembleDemoStaging` (debug artifacts). ### Audit resolution [PR 8 draft audit](reidbaker-agent#8 (comment)): | Item | Resolution | | --- | --- | | 1. String-based compile task lookup for jniLibs | Provider wiring, `FlutterPlugin.kt:549-553`. Unit test `onVariants wires the jniLibs copy to the output of the variant's compile task`. | | 2. Mid-block `return@onVariants` | None. `onVariants` (`:329-350`) calls helpers; app-only wiring is in `configureApplicationOutputs` (`:647`). | | 3. Redundant `dependsOn` | None on the assets copy (`:497-530`) or the jniLibs copy (`:536-560`). | | 4. Dead overload; `rootProject` read; fixture property | `shouldConfigureFlutterTask(Project, Task)` deleted. `providers.gradleProperty` at `:665`. Fixture line removed. | [PR 7 draft audit](reidbaker-agent#7 (comment)): its four items were resolved in flutter#193693. The stale "registered in `applicationVariants`" KDoc it named has no counterpart here; the `registerFlutterCompileTask` KDoc names no project type. ### Why removing the deleted code is safe - The deleted module path used `com.android.build.gradle.LibraryExtension.libraryVariants`, `AbstractAppExtension.applicationVariants`, `BaseVariant.mergeAssetsProvider` and `BaseVariantOutput.processResourcesProvider`. AGP does not register those extensions with `android.newDsl=true`, which is why `33f39876b92` fails with `Check failed.` in the host `afterEvaluate` block that looks up `LibraryExtension`. Its replacements (`LibraryVariant`, `Component.debuggable`, `Sources.assets`/`jniLibs.addGeneratedSourceDirectory`) are public `com.android.build.api` APIs. FGP compiles against AGP 9.1.1, the minimum on `master` (flutter#193813), and `Component.getDebuggable` also exists in gradle-api 8.11.1 (checked with `javap`). - Remaining `hostAppProjectName` users: none. `git grep hostAppProjectName` hits only this PR's code, tests and docs, plus an unrelated iOS `XcodeProject.hostAppProjectName` in the tool. The templates, `include_flutter.groovy`, `module_plugin_loader.gradle` and devicelab do not read it. devicelab `module_custom_host_app_name_test` (host project `:SampleApp`) passes without the fixture property. - `com.android.builder.model.BuildType` and `shouldConfigureFlutterTask(Project, Task)` have no remaining references. ### Removed comments, docstrings and tests | Removed | Reason | | --- | --- | | KDoc and two `TODO(gmackall)` comments (flutter#166550) on `addFlutterDepsForModule`; KDoc on `addCopyFlutterAssetsDependency` | Functions deleted. flutter#166550 stays open for the rest of the stack. | | The "host app build variant → Flutter variant" table comment in the module block | The mapping is gone; the module variant decides the mode. | | KDoc of `shouldConfigureFlutterTask(Project, Task)` and `buildModeFor(ModelBuildType)` | Functions deleted. | | `flutterCompileTaskName` KDoc | Nothing references the task by name, and the one-line name builder needs no doc. | | flutter#188785 comment in `registerFlutterJniLibsTask`, and the `@Optional` KDoc and "no Flutter build" comment in `CopyFlutterJniLibsTask` | The jniLibs task is registered only with its compile task. `gradle_libapp_so_packaging_test` "app:assembleAndroidTest builds when no Flutter compile task is configured" still passes. | | `@Optional` KDoc on `CopyFlutterAssetsTask.intermediateDir` (it kept `@Optional` for the module migration) | The migration is this PR. | | `FlutterPluginUtilsTest`: `buildModeFor returns profile if the BuildType has name profile`, `buildModeFor returns debug if the BuildType is debuggable`, `buildModeFor returns release if the BuildType is not debuggable and not named profile` | Overload deleted. `buildModeFor with a name and debuggable flag prefers the profile name over debuggability` covers the same cases. | | `FlutterPluginUtilsTest`: four `shouldConfigureFlutterTask` tests used a mocked `Task` | Kept with the same names and inputs, calling the `String` overload. | | `CopyFlutterAssetsTaskTest`: `clears the destination directory when there is no flutter build for the variant` | The input is required, so that case cannot happen. Replaced by `removes staged assets that the flutter build does not produce`, which keeps the stale-file check. | | Comments trimmed per review (`a6be16034c8`): the `PROP_HOST_APP_PROJECT_NAME` KDoc; the `registerFlutterJniLibsTask` KDoc sentence naming its compile task; the "An application project only has application variants." comment above the `check`; restatements in the KDoc of `shouldCompileFlutterForVariant` (PR 7's paragraph restored verbatim), `registerFlutterCompileTask`, `configureApplicationOutputs`, `warnIfHostAppProjectNameIsSet` and both `intermediateDir`s; test helper KDocs and integration test comments; migration doc item 6 | Each restated the code. What remains is why library variants are ungated, why the inputs are required, and the test intent. Added code-comment lines vs `f668780fd47`: 85 → 39. | | `packages/flutter_tools/test/integration.shard/android_add_to_app_module_test.dart` (added by this PR, then deleted per review, `2efbd345505`) | Its `qa` check moved into devicelab `module_host_with_custom_build_test`, which builds the same fixture. Its `staging` check duplicated the devicelab staging section, except for `android.newDsl=true`. The devicelab task runs presubmit on Linux, Mac and Windows (`.ci.yaml`), like the deleted test. | | Rewritten per review (`b8cd39bcf81`): the library paragraph of the `shouldCompileFlutterForVariant` KDoc, the assets `GradleException` comment, the `registerFlutterCompileTask` and `configureApplicationOutputs` KDocs | They explained too little ("What does this mean?") or restated the code. | | The `check(variant is ApplicationVariant)` that PR 7 added in the app `onVariants` path, moved by this PR into `configureApplicationOutputs` (`798ac295725`) | The call site branches on `variant is ApplicationVariant`, and the function takes an `ApplicationVariant`, so the compiler enforces the type. In an application project every variant is an `ApplicationVariant`, so the APK wiring runs for the same variants. | | `-Pandroid.compatibility.enableLegacyApi=false` in the devicelab `qa` section (`1366874099e`) | AGP 9.1.0, 9.1.1 and 9.3.1 mark the option `Deprecated(VERSION_10_0)`. Its consumers back the variant API that `android.newDsl=true` removes. | ### Behavioral and compatibility notes 1. **`flutter.hostAppProjectName` has no effect (breaking).** It logs a warning and names no removal milestone. Its only use was the host lookup. 2. **The Flutter build mode follows the module variant the host consumes.** A host `debug`/`profile`/`release` consumes the module variant of the same name. A custom host build type gets the module variant its `matchingFallbacks` select. With a debuggable `qa` that falls back to `release`, built as the only task, the APKs contain: | Build | `flutter_assets` | `libapp.so` | Flutter tasks run | | --- | --- | --- | --- | | `33f39876b92` (`newDsl=false`) | no | no | `compileFlutterBuildDebug` (not packaged) | | This PR | yes | yes | `compileFlutterBuildRelease` | 3. **A host `assemble<Variant>AndroidTest` run on its own runs the module's `flutter assemble` for that variant.** `--dry-run` of `:app:assembleDemoDebugAndroidTest` lists `:flutter:compileFlutterBuildDebug` with this PR, and only `copyJniLibsflutterBuildDebug` on `33f39876b92`. This is a cost, accepted because the module cannot map host task names to its own variants. 4. **Module assets are a generated assets source directory.** The deleted code copied them into the module's merged-assets output after `mergeAssets`, and made every build re-run `clean<MergeAssetsTask>`. Collisions resolve by source-set priority, as for apps since PR 6. 5. **`copyFlutterAssets<V>` in a module is a `CopyFlutterAssetsTask`, not a `Copy`.** Lookups by name still work; lookups typed as `Copy` fail. 6. Related open work: [flutter#191703](flutter#191703) reports an NPE in `getLegacyAndroidExtension` with `newDsl=true`. That function was removed earlier in the stack, and this PR removes the next failure on that path. A module with plugins on `newDsl=true` is not tested here. No conflict with [flutter#193682](flutter#193682) or [flutter#193610](flutter#193610) (`gradle_errors.dart`); this PR changes no message that the tool matches. [flutter#184409](flutter#184409) asks for separate library and app logic in `addFlutterTasks`; this PR shares `onVariants` and splits only the app outputs. ### Integration test coverage of the changed paths | Path | Tests | | --- | --- | | Module from source, `newDsl=true`, debuggable custom build type on `release`, `hostAppProjectName` warning | devicelab `module_host_with_custom_build_test`, `app:assembleDemoQa` section | | Module from source, flavor and custom build types, debug and release | devicelab `module_host_with_custom_build_test` (other sections; `app:assembleDemoStaging` needs the ungated `LibraryVariant`), `build_android_host_app_with_module_source` | | Host project not named `app`, without `hostAppProjectName` | devicelab `module_custom_host_app_name_test` | | Module AAR (`flutter build aar`) and AAR host | devicelab `build_aar_module_test`, `build_android_host_app_with_module_aar`; `android_obfuscate_test`, `android_plugin_new_output_dir_test` | | App path | `gradle_libapp_so_packaging_test`, `flutter_build_apk_split_per_abi_test`, `android_gradle_asset_merging_test`, `android_run_flutter_gradle_plugin_tests_test` | ### Tests run locally (macOS, JDK 17) On the head after merging `master` (`23ddd6b74e6`; FGP compiles and tests against AGP 9.1.1): - `./gradlew test --rerun-tasks` in `packages/flutter_tools/gradle`: 33 suites, 277 tests, 0 failures. - ktlint 1.5.0 with the CI `.editorconfig` and baseline: clean. - `dart format` and `dart analyze --fatal-infos` on `module_host_with_custom_build_test.dart` and `gradle_libapp_so_packaging_test.dart`: clean. - `gradle_libapp_so_packaging_test`: 4 tests pass. - devicelab, all `success`: `module_host_with_custom_build_test`, `module_custom_host_app_name_test`, `build_android_host_app_with_module_source`. On `1366874099e`: - `./gradlew test --rerun-tasks` in `packages/flutter_tools/gradle`: 33 suites, 274 tests, 0 failures. - ktlint 1.5.0 with the CI `.editorconfig` and baseline: clean. - `dart format` and `dart analyze --fatal-infos` on `module_host_with_custom_build_test.dart`: clean. - devicelab `module_host_with_custom_build_test`: `success`. The `app:assembleDemoQa` section ran `./gradlew app:assembleDemoQa -Pandroid.newDsl=true -Pflutter.hostAppProjectName=app` and logged the `flutter.hostAppProjectName` warning. On `d8f869ec468`: - `./gradlew test --rerun-tasks` in `packages/flutter_tools/gradle`: 33 suites, 274 tests, 0 failures. - ktlint 1.5.0 with the CI `.editorconfig` and baseline: clean. - `dart format` and `dart analyze --fatal-infos` on `module_host_with_custom_build_test.dart`: clean. - devicelab `module_host_with_custom_build_test`: `success`. The `app:assembleDemoQa` section logged the `flutter.hostAppProjectName` warning. On `a6be16034c8` (the merge and the trim): - `./gradlew test` in `packages/flutter_tools/gradle`: 33 suites, 274 tests, 0 failures. - ktlint 1.5.0 with the CI `.editorconfig` and baseline: clean. - `dart format` and `dart analyze --fatal-infos` on the changed Dart files: clean. - `android_add_to_app_module_test` (deleted in `2efbd345505`): passes. - devicelab `module_custom_host_app_name_test` (fixture without `flutter.hostAppProjectName`): `success`, and the log has no `hostAppProjectName` warning. On `8c9a54d8297` (before the merge of PR 7's review changes and the comment trim): - Integration tests, one at a time, all pass: `android_add_to_app_module_test` (1), `android_obfuscate_test` (2), `android_plugin_new_output_dir_test` (1), `gradle_libapp_so_packaging_test` (4), `flutter_build_apk_split_per_abi_test` (4), `android_gradle_asset_merging_test` (4), `android_run_flutter_gradle_plugin_tests_test` (2). - `android_add_to_app_module_test` on `33f39876b92`: fails with `Check failed.`. With `variant is LibraryVariant ||` removed: fails with "does not contain 'assets/flutter_assets/AssetManifest.bin'". - devicelab via `bin/test_runner.dart test --exit`, all `success`: `module_host_with_custom_build_test`, `module_custom_host_app_name_test`, `build_android_host_app_with_module_source`, `build_aar_module_test`, `build_android_host_app_with_module_aar`. - Scratch module plus the devicelab host fixture (AGP 9.3.1, Gradle 9.5.0): - Defaults: `assembleDemoStaging` has `kernel_blob.bin` and no `libapp.so`; `assembleDemoRelease` has `libapp.so` for arm64-v8a, armeabi-v7a and x86_64. - Same with `android.compatibility.enableLegacyApi=false`, and with `android.newDsl=true` added. </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 `///`). - [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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 7 of 11 of the AGP public-API migration; stacked on #6.
Phase P6 of the AGP public-API migration (flutter#180137,
flutter#166550). The application path no longer uses the legacy
variant API at all:
directory contents (via BuiltArtifactsLoader) into
build/outputs/flutter-apk under the unchanged names
app[-abi][-flavor]-<build-mode>.apk. It is attached as a finalizer of
assemble<Variant> (matched by name, with a projectsEvaluated
assertion that fails loudly if the assemble task was never created,
instead of silently leaving flutter run/build without APKs). The task
declares individual predictable @OutputFiles - computed from target
platforms, flavor, and build mode - rather than the shared
flutter-apk directory, so it is UP-TO-DATE-capable without
overlapping outputs between variants; it replaces the old
assemble.doLast copy.
on VariantOutput.versionCode inside onVariants (the output is seeded
with AGP's merged value, which covers flavor-defined versionCodes),
replacing versionCodeOverride on the legacy ApkVariantOutput. When
the built APK's versionCode differs from what Flutter configured
(e.g. an afterEvaluate mutation), CopyFlutterApksTask logs a warning
pointing at androidComponents.onVariants.
helpers are deleted; AbstractAppExtension remains only in the
add-to-app module path, which migrates next.
Verification (CI): split-per-abi + apkanalyzer per-ABI versionCode
assertions including the flavor-defined-versionCode case; flavor
filename check; flutter run / hot restart / attach; Windows-runner
smoke for the copy tasks; android_e2e_api_test; gradle unit tests on
both AGP axes.
Revert-safe until P7 lands (mutually tolerant with P7 until P10).
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).