Skip to content

[Ubuntu][Windows] Update Android command-line tools to 22.0 - #14676

Open
matanbaruch wants to merge 2 commits into
actions:mainfrom
matanbaruch:update-android-cmdline-tools-22
Open

matanbaruch wants to merge 2 commits into
actions:mainfrom
matanbaruch:update-android-cmdline-tools-22

Conversation

@matanbaruch

@matanbaruch matanbaruch commented Sep 2, 2026

Copy link
Copy Markdown

Addresses #14484 for the Ubuntu and Windows images: updates the preinstalled Android SDK Command-line Tools to 22.0 (build 15859902).

Why

cmdline-tools older than 20.0 cannot parse the Major.Minor package paths Android now publishes (android-37.0, system-images;android-37.0;google_apis_ps16k;x86_64). I confirmed the root cause directly against the sdklib shipped in each revision:

cmdline-tools AndroidTargetHash.getPlatformVersion("android-37.0") target= written into the AVD .ini
12.0 (current on ubuntu-24.04) null android-0
22.0 API 37.0 android-37.0

avdmanager create avd still exits 0, so the AVD looks fine but records target=android-0. The emulator then treats it as a very old system image, skips the Vulkan / GLDirectMem auto-enable and renders blank or corrupted frames while every step of the workflow reports success — nothing points back at the SDK tools.

22.0 is also the first revision that ships the Android CLI (cmdline-tools/latest/bin/android, android.exe on Windows) — the replacement that sdkmanager now advertises on every invocation. One version bump therefore covers both requests in the issue, with no new tool to package.

Images updated

Image Command-line tools before After
ubuntu-24.04 12.0 22.0
ubuntu-26.04 20.0 22.0
windows-2025 16.0 22.0
windows-2025 (VS2026) 19.0 22.0

The arm64 Ubuntu toolsets are kept in sync with their x64 counterparts, as they are today (no arm64 template runs install-android-sdk.sh).

Left on the current revision on purpose

ubuntu-22.04 (9.0) and windows-2022 (8.0). cmdline-tools 22.0 is compiled for Java 17 — class file version 61, against 55 in 12.0/20.0 and 52 in 8.0/9.0 — and those two images default to Java 11 and Java 8 respectively. Bumping them would break sdkmanager for every workflow that uses the image's default JDK, and the image build itself, which runs sdkmanager under that default. Glad to add them if you would prefer to pin the Android install step to JAVA_HOME_17_X64 instead.

macOS is untouched, per CONTRIBUTING. The same one-line change applies to toolset-14/15/26/xcode-27.json, with one caveat worth recording: starting with 22.0 Google renamed the macOS archive, so the value becomes commandlinetools-mac_x86_64-15859902_latest.zip (the contains("commandlinetools-mac") filter in install-android-sdk.sh still matches it).

Compatibility with the existing scripts

22.0 keeps the classic sdkmanager — a Java tool with the pipe-table --list output — so nothing in this repo needs to change. Verified against real 22.0 output:

  • sed -n '/Available Packages:/,/^$/p' | grep "platforms;android-[0-9]" | cut -d"|" -f 1 and the build-tools; / ndk;<major>. greps in install-android-sdk.sh still return the expected package paths
  • sdkmanager --version prints exactly 22.0 on stdout; the new deprecation notice goes to stderr, so Get-AndroidCommandLineToolsVersion in the software report keeps matching
  • the three deprecation lines that Get-AndroidPackages picks up through 2>&1 are dropped by its existing -NotMatch "^[^;]*$" filter, since none of them contains a ;

⚠️ One note for whoever bumps this next: 23.0 cannot be picked up as a drop-in. There sdkmanager becomes a shell shim over android sdk, --list switches to build-tools/17.0.0-style paths with no | columns, and --include_obsolete / --verbose are accepted-but-ignored. That silently breaks the platform/build-tools/NDK selection in install-android-sdk.sh, Get-AndroidPackages on Windows and the software report parsing. That is why this PR pins 22.0 explicitly rather than switching the pin to latest.

Second commit: latest resolution on Ubuntu

install-android-sdk.sh supports "cmdline-tools": "latest", but two defects meant it could never work:

  • the branch tests $cmdline_tools_version, which is never assigned — the toolset value is read into $cmdline_tools_package, so latest fell straight through and was used as a file name
  • the yq query addresses .sdk-repository, while repository2-1.xml declares the namespaced root sdk:sdk-repository, so the query returns nothing and the script exits with "Failed to parse latest command-line tools version"

With both fixed, the query resolves against the current repository index:

$ yq -p=xml '.["sdk:sdk-repository"].remotePackage[] | select(."+@path" == "cmdline-tools;latest" and .channelRef."+@ref" == "channel-0").archives.archive[].complete.url | select(contains("commandlinetools-linux"))' repository2-1.xml
commandlinetools-linux-16111833_latest.zip

The pins stay explicit; this only makes the documented latest option usable (and it now fails loudly rather than downloading a file called latest).

The macOS script carries a byte-identical copy of that block (images/macos/scripts/build/install-android-sdk.sh, differing only in commandlinetools-mac), with the same .sdk-repository root, so it needs the same one-line change. Left out of this PR per CONTRIBUTING, along with the toolset bump.

Validation

A Command-line tools context in images/ubuntu/scripts/tests/Android.Tests.ps1 and images/windows/scripts/tests/Android.Tests.ps1 asserts that the android CLI is present, and is skipped on the images that stay on the older revision. That single check also covers the revision, since android only ships from 22.0 on.

What I checked locally against the 22.0 package (macOS host with JDK 25 — sdkmanager is the same Java tool on every platform):

$ cmdline-tools/latest/bin/sdkmanager --version 2>/dev/null
22.0
$ cmdline-tools/latest/bin/android --version | tail -1
1.0.15985488
  • AndroidTargetHash.getPlatformVersion("android-37.0") against the sdklib of each revision gives the table above (null on 12.0, API 37.0 / android-37.0 on 22.0)
  • the SHA-1 of both archives I downloaded matches repository2-1.xml, and the Windows SHA-256 added to the toolsets is computed from that verified download
  • the --list parsing checks listed under Compatibility were run against real 22.0 output

I cannot build a full runner image here, so the end-to-end AVD check from the issue is unverified on my side. The issue reports target=android-37.0 from 20.0 onward, which is consistent with the parser results above.

I did not add the Android CLI to the software report: android self-updates from Google on first run, so its version is a property of when it is invoked rather than of the image. Happy to add a row if you would like it reported anyway.

cmdline-tools below 20.0 cannot parse Major.Minor package paths:
AndroidTargetHash.getPlatformVersion("android-37.0") returns null, so
avdmanager silently writes target=android-0 into the AVD .ini and the
emulator skips its Vulkan/GLDirectMem auto-enable. Revision 22.0 parses
those paths and also ships the Android CLI (bin/android), the announced
replacement for sdkmanager.

Images that default to Java 11 or older (ubuntu-22.04, windows-2022) keep
their current revision: 22.0 is compiled for Java 17.

Refs actions#14484
Two defects kept the "latest" toolset value from ever resolving:

- the branch tested $cmdline_tools_version, which is never assigned; the
  value is read into $cmdline_tools_package, so "latest" fell through and
  was used as a file name
- the yq query addressed .sdk-repository, but repository2-1.xml declares
  the namespaced root sdk:sdk-repository, so the query returned nothing
@matanbaruch
matanbaruch force-pushed the update-android-cmdline-tools-22 branch from fcbdde0 to cf7558a Compare September 2, 2026 20:34
@matanbaruch

Copy link
Copy Markdown
Author

@v-AndriiKhyliuk @v-SergeiRadich @v-sergei-pyshnoi mind taking a look? Ready for review and scoped to the Java 17 images only (ubuntu-24.04/26.04, windows-2025), ubuntu-22.04 and windows-2022 stay on 12.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant