Repository navigation
Add --[no-]enable-hcpp build flag and pipe through via Gradle manifest transformation - #189955
Conversation
- Adds --[no-]enable-hcpp CLI flag to build apk/appbundle/aar commands. - Passes -Penable-hcpp=<bool> and -Pexplicit-enable-hcpp=<bool> to Gradle. - Registers EnableHcppManifestTask in the Flutter Gradle Plugin to inject EnableHcpp metadata into application merged manifests when requested and warn on merged manifest conflicts. - Adds Kotlin Gradle task and Dart tool unit/integration test coverage.
- computeHcppEnabled now takes an ifAbsent value, so `flutter build apk/appbundle --enable-hcpp` against a manifest that does not set EnableHcpp reports what actually gets packaged instead of always reporting false. - Only send -Pexplicit-enable-hcpp from commands that produce a final artifact. run/test/drive apply --enable-hcpp at launch, where it does override the manifest, so the gradle "does not affect this artifact" warning was wrong for them. - Correct the flag help text: --no-enable-hcpp does not currently override a manifest value at launch, only --enable-hcpp does. - Drop the RunCommandBase.enableHcpp override, which is now identical to the FlutterCommand implementation.
- Remove the addEnableHcppMetadataIfAbsent "legacy wrapper", which was never a legacy anything and had no callers outside tests, and make requestedEnableHcpp a required argument so nothing silently defaults to enabling hcpp. - The FlutterPluginUtilsTest registration tests only asserted that getByType had been called. Drive onVariants and assert the task name and the values it is configured with. - Cover the requested=false, metadata absent path, and pin the fact that re-serializing the manifest drops XML comments. - Note in the task doc that the conflict warning is not repeated on up-to-date or cached builds.
There was a problem hiding this comment.
Code Review
This pull request introduces the EnableHcppManifestTask to inject io.flutter.embedding.android.EnableHcpp metadata into the merged Android manifest of application projects. It adds the --[no-]enable-hcpp CLI flag to build commands, updates BuildInfo and FlutterCommand to pass these properties to Gradle, and includes corresponding tests. Feedback on the changes highlights a critical compilation error in project.dart due to an undefined defaultValue reference in a catch block, and suggests simplifying property checks in FlutterPluginUtils.kt and avoiding unsafe null assertions in flutter_command.dart.
| return _computeManifestMetadataBoolValueOrNull(metadataKey) ?? defaultValue; | ||
| } | ||
|
|
||
| bool? _computeManifestMetadataBoolValueOrNull(String metadataKey) { |
There was a problem hiding this comment.
The helper method _computeManifestMetadataBoolValueOrNull does not define a defaultValue parameter, but the unchanged catch block inside the try statement (which is not shown in this diff but is part of the method body) still attempts to return defaultValue when an XmlException is caught. This will result in a compilation error (Undefined name 'defaultValue').\n\nTo fix this, the catch block should be updated to return null instead of defaultValue. Since the catch block is not part of the modified lines in this diff, please manually update it in project.dart:\n\ndart\n } on XmlException {\n return null;\n }\n
| val explicitEnableHcpp: Boolean? = | ||
| if (project.hasProperty(PROP_EXPLICIT_ENABLE_HCPP)) { | ||
| project.findProperty(PROP_EXPLICIT_ENABLE_HCPP)?.toString()?.toBoolean() | ||
| } else { | ||
| null | ||
| } |
There was a problem hiding this comment.
The redundant hasProperty check can be simplified. project.findProperty already returns null if the property is not present, so you can directly retrieve and convert the property in a single expression.
val explicitEnableHcpp: Boolean? =\n project.findProperty(PROP_EXPLICIT_ENABLE_HCPP)?.toString()?.toBoolean()| bool? get explicitEnableHcpp => | ||
| (argResults?.options.contains('enable-hcpp') ?? false) && argResults!.wasParsed('enable-hcpp') | ||
| ? boolArg('enable-hcpp') | ||
| : null; |
There was a problem hiding this comment.
This expression can be simplified to avoid the unsafe null assertion operator (!) on argResults and improve readability.
bool? get explicitEnableHcpp {\n final ArgResults? results = argResults;\n if (results == null || !results.options.contains('enable-hcpp') || !results.wasParsed('enable-hcpp')) {\n return null;\n }\n return boolArg('enable-hcpp');\n }- Drop the redundant hasProperty check; findProperty already returns null when the property is absent. - Give explicitEnableHcpp a block body so the argResults null check is explicit instead of relying on && short circuiting before a `!`.
| package com.flutter.gradle.tasks | ||
|
|
||
| import groovy.util.Node | ||
| import groovy.xml.XmlNodePrinter |
There was a problem hiding this comment.
non blocking. There are a couple of these xml parsing classes. Can you double check which one that people are supposed to use and make sure this does not add tech debt.
| } | ||
|
|
||
| if (explicitEnableHcpp != null && (existingValueBool == null || explicitEnableHcpp != existingValueBool)) { | ||
| val flagName = if (explicitEnableHcpp) "--enable-hcpp" else "--no-enable-hcpp" |
There was a problem hiding this comment.
could you pull the flag names out into constants at the top of the file.
|
|
||
| if (explicitEnableHcpp != null && (existingValueBool == null || explicitEnableHcpp != existingValueBool)) { | ||
| val flagName = if (explicitEnableHcpp) "--enable-hcpp" else "--no-enable-hcpp" | ||
| logger?.warn( |
There was a problem hiding this comment.
I think this is backwards from what most developers expect. Specifically gradle has a different order of defaults. https://docs.gradle.org/current/userguide/build_environment.html
There was a problem hiding this comment.
Fair, changed to have cli win in all cases
Per review. The tests assert on the flag name in the warning, so make them internal and reference them there instead of repeating the literals.
Per review. A flag passed at invocation time now takes priority over the EnableHcpp metadata in AndroidManifest.xml, instead of being ignored with a warning. This matches how gradle orders -P properties ahead of gradle.properties, and drops the asymmetry where the same flag overrode the manifest at launch for run/test/drive but not for a built artifact. The precedence is now --[no-]enable-hcpp > AndroidManifest.xml > the tool's default, for every command. - The task writes an explicit value into the merged manifest, replacing what is there. Nothing conflicts in the merger because this is a transform of MERGED_MANIFEST, which already ran. - Without the flag, the requested value is still only injected when the manifest says nothing, so the manifest keeps winning over a default. - The warning becomes a lifecycle message reporting the override, and warnOnHcppManifestConflict is gone, since there is no longer a command for which the flag is inert. - Analytics report the explicit value rather than the source manifest.
args_test flags "[a-z].[A-Z]" as a probable missing space after a sentence, and io.flutter.embedding.android.EnableHcpp trips it on "android.EnableHcpp". The bare name reads fine in context.
|
autosubmit label was removed for flutter/flutter/189955, because The base commit of the PR is older than 7 days and can not be merged. Please merge the latest changes from the main into this branch and resubmit the PR. |
|
autosubmit label was removed for flutter/flutter/189955, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/189955, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/189955, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/189955, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
…ter#190623) AI pr description which is correct (I checked 🙂 ) - Enables the `enable-hcpp` feature flag by default on the `master` and `beta` channels (remains default off on `stable`). - Pipes the feature flag default through `FlutterCommand.enableHcpp` into `BuildInfo.androidEnableHcpp`, allowing Gradle's `EnableHcppManifestTask` (landed in flutter#189955) to inject `io.flutter.embedding.android.EnableHcpp = true` into the merged manifest when the app's manifest is silent. - Preserves the established precedence: explicit `--[no-]enable-hcpp` CLI flag > `AndroidManifest.xml` > feature flag default. - Ensures `DebuggingOptions.enableHcpp` is treated as a nullable `bool?`, only passing launch overrides (`--enable-hcpp-and-surface-control=$enableHcpp` / `--ez enable-hcpp-and-surface-control $enableHcpp`) when explicitly provided on the CLI, allowing the installed artifact's manifest to decide by default. - Updates unit and command test suites across `flutter_tools`. > **Note for reviewers**: iOS reviewers were auto-requested because `build_swift_package_test.dart` was updated to implement `isHcppEnabled` in its `FakeFeatureFlags` (queried by `FlutterCommand.getBuildInfo()`). No iOS or Swift Package Manager logic is changed. --------- Co-authored-by: Gray Mackall <[email protected]> Co-authored-by: Camille Simon <[email protected]>
--[no-]enable-hcpptoflutter build apkandflutter build appbundle.Not added to
build aar: a value injected into a module's library manifest canfail an add-to-app host's build in the manifest merger when the host selects the
opposite value, so the host application's manifest stays the source of truth.
-Penable-hcpp=<bool>(the tool's default) and-Pexplicit-enable-hcpp=<bool>(set only when the developer passed the flag) to Gradle.
EnableHcppManifestTaskin the Flutter Gradle Plugin, a transform of theapplication project's merged manifest. Precedence is
--[no-]enable-hcpp>AndroidManifest.xml> the tool's default:an explicit flag is written into the merged manifest over whatever is there and
reported at lifecycle level; without the flag, the default is only injected when the
manifest does not set
EnableHcppat all.drops XML comments including the manifest merger's provenance annotations. This is
invisible to aapt2 and is covered by a test.