Repository navigation
Fix Android license detection for cmdline-tools 23.0+ - #191554
Conversation
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 ('Warning: The --licenses option is no longer needed.') instead of the parseable license summary Flutter previously relied on, so none of the existing regexes match and flutter doctor incorrectly reports Android license status as unknown.
This adds a narrow fallback: when sdkmanager's output is recognized as this specific new-CLI deprecation message (and only then, not for arbitrary unparseable output), licensesAccepted checks the SDK's licenses directory on disk directly instead. This was verified against a real cmdline-tools 23.0 install, including confirming that the deprecation warning is printed identically regardless of whether licenses are actually accepted, which is why the fallback checks the licenses directory rather than trusting the warning text itself.
Note: this fallback can only distinguish 'some license files are present' from 'no license files at all', so it cannot reproduce the previous LicensesAccepted.some state for the new CLI.
Fixes flutter#191487
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
There was a problem hiding this comment.
Code Review
This pull request introduces a fallback mechanism for checking Android SDK licenses when the sdkmanager --licenses output is unparseable due to deprecation warnings in newer Android CLI tools. If the warning is detected, the validator checks the licenses directory on disk to determine if licenses have been accepted. Tests have been added to verify this fallback behavior. Feedback was provided to handle potential FileSystemException errors when calling listSync() on the licenses directory to prevent crashes.
| final Directory licensesDir = _androidSdk.directory.childDirectory('licenses'); | ||
| final bool hasAcceptedLicense = licensesDir.listSync().whereType<File>().any( | ||
| (File file) => file.lengthSync() > 0, | ||
| ); | ||
| return hasAcceptedLicense ? LicensesAccepted.all : LicensesAccepted.none; |
There was a problem hiding this comment.
Calling listSync() on a directory can throw a FileSystemException if the directory does not exist, is actually a file, or if there are permission issues. To prevent potential crashes in flutter doctor, we should check if the directory exists and handle any FileSystemException gracefully.
final Directory licensesDir = _androidSdk.directory.childDirectory('licenses');
if (!licensesDir.existsSync()) {
return LicensesAccepted.none;
}
try {
final bool hasAcceptedLicense = licensesDir.listSync().whereType<File>().any(
(File file) => file.lengthSync() > 0,
);
return hasAcceptedLicense ? LicensesAccepted.all : LicensesAccepted.none;
} on FileSystemException {
return LicensesAccepted.none;
}Addresses review feedback: listSync() on the licenses directory can throw a FileSystemException if the directory doesn't exist, is actually a file, or there are permission issues (e.g. a race between the licensesAvailable check and use). Wrap the disk check in a try/on FileSystemException and return LicensesAccepted.unknown in that case instead of letting flutter doctor crash. Added a regression test simulating this scenario.
|
Whoops we closed this a little fast, that's addressed in the description:
Huh that's really unfortunate. |
|
An existing Git SHA, To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with |
flutter/flutter@8d8c1aa...c978386 2026-08-30 [email protected] Roll Skia from ce359c7fbfe6 to 588b550a4dd8 (1 revision) (flutter/flutter#192040) 2026-08-30 [email protected] Roll Skia from 3ae8e3d1e335 to ce359c7fbfe6 (1 revision) (flutter/flutter#192037) 2026-08-30 [email protected] Roll Fuchsia Linux SDK from J123CwfDPYyVDpkMl... to o9DikEfRoFyVK3LKD... (flutter/flutter#192031) 2026-08-29 [email protected] Make the AbsorbPointer sample show the difference from IgnorePointer (flutter/flutter#188940) 2026-08-29 [email protected] Roll Dart SDK from 391ff83cd1d3 to 76abdf94faa8 (1 revision) (flutter/flutter#192021) 2026-08-29 [email protected] Roll Skia from b392fb672d13 to 3ae8e3d1e335 (1 revision) (flutter/flutter#192020) 2026-08-29 [email protected] Roll Skia from 0b4249b26b38 to b392fb672d13 (6 revisions) (flutter/flutter#192016) 2026-08-29 [email protected] Fixes for texture-backed gradients (flutter/flutter#191925) 2026-08-29 [email protected] Roll Dart SDK from ae63a6eca3f1 to 391ff83cd1d3 (3 revisions) (flutter/flutter#192010) 2026-08-29 [email protected] Fix Android license detection for cmdline-tools 23.0+ (flutter/flutter#191554) 2026-08-29 [email protected] [flutter_tools] Pause web server requests until initial compilation finishes (flutter/flutter#191990) 2026-08-28 [email protected] fix(workflow): Mac Verify Binaries needs `Linux mac_android_aot_engine` (flutter/flutter#191999) 2026-08-28 [email protected] Roll Fuchsia Linux SDK from dDxH8G5cDBP602eyG... to J123CwfDPYyVDpkMl... (flutter/flutter#191984) 2026-08-28 [email protected] Update scheduled workflow for more tasks, add goldctl update (flutter/flutter#191991) 2026-08-28 [email protected] Update no-main-prs to leave a comment (flutter/flutter#191973) 2026-08-28 [email protected] [AGP 9.1.0 Migration #4] Replace plugin build-type copy with initWith on public DSL (flutter/flutter#191606) 2026-08-28 [email protected] Roll Skia from fe0b9a5261f9 to 0b4249b26b38 (1 revision) (flutter/flutter#191974) 2026-08-28 [email protected] [UIScene] Migrate dev/benchmarks/macrobenchmarks to UIScene lifecycle (flutter/flutter#191648) 2026-08-28 [email protected] Uiscene migrate remaining apps (flutter/flutter#191652) 2026-08-28 [email protected] [tool] Migrate SymbolizeCommand to modular dependency injection (flutter/flutter#190744) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: 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
…r#12693) flutter/flutter@8d8c1aa...c978386 2026-08-30 [email protected] Roll Skia from ce359c7fbfe6 to 588b550a4dd8 (1 revision) (flutter/flutter#192040) 2026-08-30 [email protected] Roll Skia from 3ae8e3d1e335 to ce359c7fbfe6 (1 revision) (flutter/flutter#192037) 2026-08-30 [email protected] Roll Fuchsia Linux SDK from J123CwfDPYyVDpkMl... to o9DikEfRoFyVK3LKD... (flutter/flutter#192031) 2026-08-29 [email protected] Make the AbsorbPointer sample show the difference from IgnorePointer (flutter/flutter#188940) 2026-08-29 [email protected] Roll Dart SDK from 391ff83cd1d3 to 76abdf94faa8 (1 revision) (flutter/flutter#192021) 2026-08-29 [email protected] Roll Skia from b392fb672d13 to 3ae8e3d1e335 (1 revision) (flutter/flutter#192020) 2026-08-29 [email protected] Roll Skia from 0b4249b26b38 to b392fb672d13 (6 revisions) (flutter/flutter#192016) 2026-08-29 [email protected] Fixes for texture-backed gradients (flutter/flutter#191925) 2026-08-29 [email protected] Roll Dart SDK from ae63a6eca3f1 to 391ff83cd1d3 (3 revisions) (flutter/flutter#192010) 2026-08-29 [email protected] Fix Android license detection for cmdline-tools 23.0+ (flutter/flutter#191554) 2026-08-29 [email protected] [flutter_tools] Pause web server requests until initial compilation finishes (flutter/flutter#191990) 2026-08-28 [email protected] fix(workflow): Mac Verify Binaries needs `Linux mac_android_aot_engine` (flutter/flutter#191999) 2026-08-28 [email protected] Roll Fuchsia Linux SDK from dDxH8G5cDBP602eyG... to J123CwfDPYyVDpkMl... (flutter/flutter#191984) 2026-08-28 [email protected] Update scheduled workflow for more tasks, add goldctl update (flutter/flutter#191991) 2026-08-28 [email protected] Update no-main-prs to leave a comment (flutter/flutter#191973) 2026-08-28 [email protected] [AGP 9.1.0 Migration flutter#4] Replace plugin build-type copy with initWith on public DSL (flutter/flutter#191606) 2026-08-28 [email protected] Roll Skia from fe0b9a5261f9 to 0b4249b26b38 (1 revision) (flutter/flutter#191974) 2026-08-28 [email protected] [UIScene] Migrate dev/benchmarks/macrobenchmarks to UIScene lifecycle (flutter/flutter#191648) 2026-08-28 [email protected] Uiscene migrate remaining apps (flutter/flutter#191652) 2026-08-28 [email protected] [tool] Migrate SymbolizeCommand to modular dependency injection (flutter/flutter#190744) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: 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
…r#12693) flutter/flutter@8d8c1aa...c978386 2026-08-30 [email protected] Roll Skia from ce359c7fbfe6 to 588b550a4dd8 (1 revision) (flutter/flutter#192040) 2026-08-30 [email protected] Roll Skia from 3ae8e3d1e335 to ce359c7fbfe6 (1 revision) (flutter/flutter#192037) 2026-08-30 [email protected] Roll Fuchsia Linux SDK from J123CwfDPYyVDpkMl... to o9DikEfRoFyVK3LKD... (flutter/flutter#192031) 2026-08-29 [email protected] Make the AbsorbPointer sample show the difference from IgnorePointer (flutter/flutter#188940) 2026-08-29 [email protected] Roll Dart SDK from 391ff83cd1d3 to 76abdf94faa8 (1 revision) (flutter/flutter#192021) 2026-08-29 [email protected] Roll Skia from b392fb672d13 to 3ae8e3d1e335 (1 revision) (flutter/flutter#192020) 2026-08-29 [email protected] Roll Skia from 0b4249b26b38 to b392fb672d13 (6 revisions) (flutter/flutter#192016) 2026-08-29 [email protected] Fixes for texture-backed gradients (flutter/flutter#191925) 2026-08-29 [email protected] Roll Dart SDK from ae63a6eca3f1 to 391ff83cd1d3 (3 revisions) (flutter/flutter#192010) 2026-08-29 [email protected] Fix Android license detection for cmdline-tools 23.0+ (flutter/flutter#191554) 2026-08-29 [email protected] [flutter_tools] Pause web server requests until initial compilation finishes (flutter/flutter#191990) 2026-08-28 [email protected] fix(workflow): Mac Verify Binaries needs `Linux mac_android_aot_engine` (flutter/flutter#191999) 2026-08-28 [email protected] Roll Fuchsia Linux SDK from dDxH8G5cDBP602eyG... to J123CwfDPYyVDpkMl... (flutter/flutter#191984) 2026-08-28 [email protected] Update scheduled workflow for more tasks, add goldctl update (flutter/flutter#191991) 2026-08-28 [email protected] Update no-main-prs to leave a comment (flutter/flutter#191973) 2026-08-28 [email protected] [AGP 9.1.0 Migration flutter#4] Replace plugin build-type copy with initWith on public DSL (flutter/flutter#191606) 2026-08-28 [email protected] Roll Skia from fe0b9a5261f9 to 0b4249b26b38 (1 revision) (flutter/flutter#191974) 2026-08-28 [email protected] [UIScene] Migrate dev/benchmarks/macrobenchmarks to UIScene lifecycle (flutter/flutter#191648) 2026-08-28 [email protected] Uiscene migrate remaining apps (flutter/flutter#191652) 2026-08-28 [email protected] [tool] Migrate SymbolizeCommand to modular dependency injection (flutter/flutter#190744) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Packages: 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
Description
Fixes #191487
Android SDK cmdline-tools 23.0 deprecated
sdkmanager --licensesin favor of the newandroidCLI. Runningsdkmanager --licensesnow only prints a deprecation warning instead of the parseable license summary Flutter previously relied on:None of the existing regexes in
licensesAcceptedmatch this output, soflutter doctorincorrectly reportsAndroid license status unknowneven 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>/licensesdirectory and re-runningsdkmanager --licenses; the output was byte-for-byte identical either way.I also checked the new
androidCLI's--helpoutput (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:sdkmanager's output matches the specific new-CLI deprecation message (and only then — not for arbitrary unparseable/garbage output),licensesAcceptedchecks thelicenses/directory on disk directly instead of trusting stdout.sdkmanagerversions 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 previousLicensesAccepted.somestate 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.dartcontinue to pass (35/35).Also manually verified end-to-end:
flutter doctor -von the affected machine now correctly reportsAll Android licenses accepted.instead ofAndroid license status unknown.