Migrate the flutter-apk copy and per-ABI versionCode to the variant API - #7
Open
reidbaker-agent wants to merge 70 commits into
Open
reidbaker-agent wants to merge 70 commits into
reidbaker-agent wants to merge 70 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
…#193459) ## Description When `no-launch-chrome` is passed in platform args (e.g. during `flutter drive -d chrome`, where WebDriver launches the browser instead of Flutter), `ChromiumDevice.startApp` does not launch Chrome. As a result, `ChromiumLauncher.connectedInstance` never completes. This caused `flutter drive -d chrome` to hang: 1. `ResidentWebRunner.attach` awaited `ChromiumLauncher.connectedInstance` before signaling that the app started. Because `DriveCommand` awaits `driverService.start()` before calling `startTest()`, WebDriver was never started and the command hung indefinitely. 2. Even if `attach` was bypassed, DWDS defaulted to Chrome-based debugging for `ChromiumDevice`, whose connection provider also awaited `connectedInstance`. This PR fixes both issues by: - Only waiting on `connectedInstance` in `attach()` if the tool actually launched Chromium. - Switching DWDS to the WebSocket debug connection when `no-launch-chrome` is set, matching the `web-server` device behavior. Fixes flutter#192091 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [AI contribution guidelines] and understand my responsibilities, or I am not using AI tools. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant in-code documentation (doc comments with `///`). - [ ] If this PR introduces a new feature or capability, I created and linked a website documentation issue or PR in [flutter/website] (or verified none is needed). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [ ] 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
…193426) Unskips `Renders tab as space instead of tofu` in `engine/src/flutter/lib/web_ui/test/ui/text_test.dart` on Wimp (`chrome-dart2wasm-wimp-ui`) and strengthens the test assertions: - When `DlWimpImageFromPicture::GetImpellerTexture` was introduced in flutter#175442 (`e0f544bf620`), it constructed a temporary `impeller::AiksContext` with a `nullptr` `TypographerContext`, causing `picture.toImage()` to drop text runs and return blank images (which caused `matchImage(tabImage, tofuImage)` to fail when the `!isWimp` skip was added in flutter#183913 / `2490c22d5be`). - flutter#191747 (`87c02198123`) refactored `DlWimpImageFromPicture::GetImpellerTexture` to render via `ImpellerRenderContext` (which owns the shared `impeller::ContentContext` and `TypographerContextSkia::Make()`), restoring `.notdef` glyph rendering in `picture.toImage()`. - Removes the `!isWimp` guard so `Renders tab as space instead of tofu` runs on both Skwasm and Wimp. - Adds an assertion that unassigned non-control codepoints (`\u{0378}`) also render a `.notdef` tofu box distinct from `''`, and disposes `Paragraph`, `Picture`, and `Image` resources created inside `drawText`. Fixes flutter#183944 ## 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
… redundant casts in RenderObjectElement.update (flutter#192913) ### Description Two small, self-contained improvements in core widget element update paths that improve generated code and microbenchmark latency across both **Native AOT (`gen_snapshot` x86_64)** and **WebAssembly (`dart2wasm` `-O2`)**: 1. **`InheritedModelElement.updateDependencies` (`packages/flutter/lib/src/widgets/inherited_model.dart`)**: - **Avoid `HashSet<T>()` heap allocation on `aspect == null`**: When a widget subscribes unconditionally to all aspects (e.g., `MediaQuery.of(context)` or `InheritedModel.inheritFrom(context)` without an aspect), `updateDependencies` previously allocated a new mutable `HashSet<T>()` on the heap for every dependent element solely so `dependencies.isEmpty` would return `true` as an "unconditionally subscribed" sentinel. Replacing `HashSet<T>()` with `const <Never>{}` replaces a per-dependent heap allocation with a constant pool load (`v13 T{_ConstSet}` in Dart VM AOT; `global.get _ConstSet<Never>` in `dart2wasm`). - **Avoid redundant generic `Set<T>` casts and map writes on `aspect != null`**: Typing `dependencies` as `Set<Object?>?` and branching on `if (dependencies == null)` vs `else { dependencies.add(aspect); }` avoids loading `:type_arguments` for a parameterized `Set<T>` check on entry, skips redundant `AssertAssignable(aspect, T)` checks in release mode when `dependencies != null`, and avoids re-hashing `dependent` to overwrite `_dependents[dependent]` when the set is already stored in the map. 2. **`SingleChildRenderObjectElement.update` & `MultiChildRenderObjectElement.update` (`packages/flutter/lib/src/widgets/framework.dart`)**: - Uses the statically-typed `newWidget` parameter (`newWidget.child` and `newWidget.children`) directly instead of re-reading `this.widget` (`_widget!`) and executing runtime casts (`(widget as SingleChildRenderObjectWidget).child` and `widget as MultiChildRenderObjectWidget`) immediately after `super.update(newWidget)`. --- ### Performance & Code Generation Verification (Native AOT & WebAssembly) #### 1. Native AOT (`dart compile exe` / `gen_snapshot` x86_64 — `20,000,000` Iterations) | Target Method | Pre-Change (Native AOT) | Post-Change (Native AOT) | Absolute Delta | Relative Delta | Speedup (vs Pre-Change) | | :--- | :---: | :---: | :---: | :---: | :---: | | **`InheritedModelElement.updateDependencies (aspect == null)`** | `39.51 ns/op` (`790 ms`) | `26.08 ns/op` (`521 ms`) | `-13.43 ns/op` | **`-34.0%`** | **`1.51x` faster** | | **`InheritedModelElement.updateDependencies (aspect != null, existing Set)`** | `33.75 ns/op` (`675 ms`) | `22.51 ns/op` (`450 ms`) | `-11.24 ns/op` | **`-33.3%`** | **`1.50x` faster** | | **`SingleChildRenderObjectElement.update`** | `5.37 ns/op` (`107 ms`) | `4.80 ns/op` (`95 ms`) | `-0.57 ns/op` | **`-10.6%`** | **`1.12x` faster** | - **`SingleChildRenderObjectElement.update` Native x86_64 Disassembly (`79` → `59` instructions, `-25.3%`)**: - **Pre-Change IL**: Emits `v22 <- LoadField(v2 . _widget)` followed by a 20-instruction `AssertAssignable(v22, SingleChildRenderObjectWidget)` before loading `.child`. - **Post-Change IL**: Eliminates both `LoadField(v2 . _widget)` and `AssertAssignable`, loading `v5 <- LoadField(v3 . child)` directly from the `newWidget` register (`v3`) and reducing machine code from **79 to 59 x86_64 instructions**. - **`InheritedModelElement.updateDependencies` Native AOT IL**: - Eliminates `LoadField(v2 . :type_arguments)` on method entry (`as Set<Object?>?` uses `instantiator_type_args(null)` instead of a parameterized `Set<T>` subtype check). - Replaces `StaticCall(HashSet.<1> v7)` heap allocation with a constant pool reference (`v13 T{_ConstSet}`) when `aspect == null`. - Eliminates `StaticCall([]=<0> _dependents, dependent, dependencies)` map write when `dependencies != null`. #### 2. WebAssembly (`flutter build web --release --wasm`, Default `-O2`) - **`InheritedModelElement.updateDependencies` (`93` → `91` WAT instructions)**: - Replaces `call $_HashSet` heap allocation with `global.get _ConstSet<Never>` when `aspect == null`, and eliminates `_TypeUniverse.isObjectInterfaceSubtype1` + `_checkInstance` when adding aspects to an existing dependency set. - **`SingleChildRenderObjectElement.update` & `MultiChildRenderObjectElement.update`**: - Eliminates `call $Element.widget` and `call $"<obj> as SingleChildRenderObjectWidget"` / `call $"<obj> as MultiChildRenderObjectWidget"`, reducing `MultiChildRenderObjectElement.update (body)` from **`775` to `767` WAT instructions** and reducing sampled CPU hits in `MultiChildRenderObjectElement.update` by **`-17.6%` (`108` → `89` samples)** under heavy layout rebuild stress. ### Tests - Added `InheritedModel unconditional dependency sentinel handles aspect transitions` in `packages/flutter/test/widgets/inherited_model_test.dart`. ## 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.
…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.
Open
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.
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).