[CP-beta]Fix Android license detection for cmdline-tools 23.0+ - #192132
Conversation
## Description Fixes flutter#191487 Android SDK cmdline-tools 23.0 deprecated `sdkmanager --licenses` in favor of the new `android` CLI. Running `sdkmanager --licenses` now only prints a deprecation warning instead of the parseable license summary Flutter previously relied on: ``` WARNING: The SDK Manager CLI tool (sdkmanager) is deprecated. Android CLI will be used instead. The 'android' binary can also be found in the cmdline-tools directory, and 'android sdk' is the replacement for 'sdkmanager'. To learn more about the Android CLI and how to use it, see the documentation (https://d.android.com/tools/agents/android-cli) Warning: The --licenses option is no longer needed. ``` None of the existing regexes in `licensesAccepted` match this output, so `flutter doctor` incorrectly reports `Android license status unknown` even when licenses are actually accepted. ## Approach I initially considered treating the new deprecation message as `LicensesAccepted.all`, but testing against a real cmdline-tools 23.0 install showed this message prints identically whether or not the licenses directory exists — so it can't be trusted as a signal of actual license state. I verified this by temporarily renaming my `<sdk>/licenses` directory and re-running `sdkmanager --licenses`; the output was byte-for-byte identical either way. I also checked the new `android` CLI's `--help` output (`sdk`, `sdk install`, `info`) — there's no license-status subcommand or flag exposed in this version, so there's no better structured signal to query instead. Since the SDK's actual license acceptance state is still tracked on disk under `<sdk>/licenses/` (this is presumably what Gradle checks directly, since Gradle builds still succeed after this cmdline-tools update), this PR adds a narrow, additive fallback: - When `sdkmanager`'s output matches the specific new-CLI deprecation message (and only then — not for arbitrary unparseable/garbage output), `licensesAccepted` checks the `licenses/` directory on disk directly instead of trusting stdout. - All existing regex-based parsing for older `sdkmanager` versions is untouched. ## Known limitation This fallback can only distinguish "some license files are present and non-empty" (→ `all`) from "no license files at all" (→ `none`). It cannot reproduce the previous `LicensesAccepted.some` state for the new CLI, since that information is no longer exposed by the tool in any form I could find. Happy to adjust the approach if maintainers have a preference here. ## Tests Added two regression tests reproducing the exact real-world output captured from a Windows machine running cmdline-tools 23.0: - `licensesAccepted falls back to the licenses directory when sdkmanager output is unparseable (new Android CLI, licenses present)` - `licensesAccepted falls back to none when sdkmanager output is unparseable and no licenses are present (new Android CLI, licenses missing)` All existing tests in `android_workflow_test.dart` continue to pass (35/35). Also manually verified end-to-end: `flutter doctor -v` on the affected machine now correctly reports `All Android licenses accepted.` instead of `Android license status unknown.` --------- Co-authored-by: Gray Mackall <34871572+gmackall@users.noreply.github.com>
|
@gmackall please fill out the PR description above, afterwards the release team will review this request. |
|
This pull request was opened from and to a release candidate branch. This should only be done as part of the official Flutter release process. If you are attempting to make a regular contribution to the Flutter project, please close this PR and follow the instructions at Tree Hygiene for detailed instructions on contributing to Flutter. Reviewers: Use caution before merging pull requests to release branches. Ensure the proper procedure has been followed. |
There was a problem hiding this comment.
Code Review
This pull request implements a fallback license check from disk when the Android sdkmanager output is unparseable due to deprecation warnings from newer Android CLI tools, and adds corresponding unit tests. The review feedback suggests catching FileSystemException on individual files within the licenses directory to prevent a single file error from failing the entire validation process.
| final bool hasAcceptedLicense = licensesDir.listSync().whereType<File>().any( | ||
| (File file) => !file.basename.startsWith('.') && file.lengthSync() > 0, | ||
| ); |
There was a problem hiding this comment.
If any individual file in the licenses directory throws a FileSystemException during file.lengthSync() (for example, due to a broken symlink or permission issues on a specific file), the exception will propagate out of any and cause the entire method to return LicensesAccepted.unknown. This happens even if there are other valid, accepted license files in the directory.
To make this check more robust, we can catch FileSystemException individually for each file inside the any block.
| final bool hasAcceptedLicense = licensesDir.listSync().whereType<File>().any( | |
| (File file) => !file.basename.startsWith('.') && file.lengthSync() > 0, | |
| ); | |
| final bool hasAcceptedLicense = licensesDir.listSync().whereType<File>().any( | |
| (File file) { | |
| if (file.basename.startsWith('.')) { | |
| return false; | |
| } | |
| try { | |
| return file.lengthSync() > 0; | |
| } on FileSystemException { | |
| return false; | |
| } | |
| }, | |
| ); |
e3005e3
into
flutter:flutter-3.48-candidate.0
This pull request is created by automatic cherry pick workflow
Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request.
Issue Link:
#191487
Impact Description:
Android SDK Command-line Tools 23.0 deprecated
sdkmanager --licensesin favor of the newandroidCLI. When invoked,sdkmanager --licensesnow only outputs a deprecation notice (Warning: The --licenses option is no longer needed.) rather than the parseable license summaryflutter doctorpreviously depended on.As a result,
flutter doctorfails to parse license status and reports✗ Android license status unknown.while prompting users to runflutter doctor --android-licenses, which fails to resolve the issue.Changelog Description:
[flutter/191487] When using Android SDK Command-line Tools 23.0+ for Android, flutter doctor incorrectly reports "Android license status unknown".
Workaround:
<Android-SDK>/licenses/, Android Gradle builds still succeed and theflutter doctorwarning can be safely ignored (if the user knows to ignore).Risk:
What is the risk level of this cherry-pick?
Test Coverage:
Are you confident that your fix is well-tested by automated tests?
Validation Steps:
$ANDROID_HOME/cmdline-tools/latest/source.propertiesthatPkg.Revision=23.0).flutter doctor -v.Android toolchain, it reports• All Android licenses accepted.instead of✗ Android license status unknown.$ANDROID_HOME/licensesdirectory, runflutter doctor -v, and verify it reportsAndroid licenses not accepted. Restore the directory.