From 983cf1fa87128b9db82c0493023821f5d1b02d2d Mon Sep 17 00:00:00 2001 From: John Carlson Date: Wed, 17 Jun 2026 18:52:55 -0500 Subject: [PATCH 1/5] aapt2: add protobuf utf8_range dir to libaapt2 include path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Android 17's bundled protobuf makes parse_context.h (a public header reached from every generated *.pb.h) include "utf8_validity.h", which lives in protobuf's vendored utf8_range copy rather than under src/. libaapt2 hand-compiles the generated .pb.cc files without linking protobuf, so it doesn't inherit protobuf's include dirs — same propagation gap already worked around for abseil just above. Add the utf8_range source dir directly. Co-Authored-By: Claude Opus 4.8 --- cmake/build-tools/aapt2.cmake | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmake/build-tools/aapt2.cmake b/cmake/build-tools/aapt2.cmake index 99c5f7f..c811f84 100644 --- a/cmake/build-tools/aapt2.cmake +++ b/cmake/build-tools/aapt2.cmake @@ -67,6 +67,11 @@ set(INCLUDES # we don't go through target_link_libraries for the protobuf-generated # headers — add abseil's source dir to the include path directly. ${SRC}/abseil-cpp + # Same propagation gap, newer trigger: protobuf (Android 17+) makes + # parse_context.h — a public header reached from every generated + # *.pb.h — include "utf8_validity.h", which lives in protobuf's + # bundled utf8_range copy rather than under src/. Add it directly. + ${SRC}/protobuf/third_party/utf8_range ${SRC}/logging/liblog/include ${SRC}/expat/lib ${SRC}/fmtlib/include From eb730eb30f6d0d9ba1b734ebfd328acf9a605159 Mon Sep 17 00:00:00 2001 From: John Carlson Date: Wed, 17 Jun 2026 21:26:29 -0500 Subject: [PATCH 2/5] androidfw: patch in include for Android 17 Asset.h Android 17 reworked android::Asset to back its buffer with using Data = std::variant; but Asset.h doesn't include . AOSP's bionic/libc++ build pulls it in transitively; under glibc + libstdc++ 12 it doesn't, so the header fails with "'variant' in namespace 'std' does not name a template type", cascading into every TU that includes Asset.h (libandroidfw, libaapt, aapt2's SymbolTable). Add the missing include. Verified: full linux-arm64 build of aapt2/aidl/zipalign/split-select goes green against android-17.0.0_r1 and the binaries run on arm64. Co-Authored-By: Claude Opus 4.8 --- patches/androidfw-asset-include-variant.patch | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 patches/androidfw-asset-include-variant.patch diff --git a/patches/androidfw-asset-include-variant.patch b/patches/androidfw-asset-include-variant.patch new file mode 100644 index 0000000..66b08d8 --- /dev/null +++ b/patches/androidfw-asset-include-variant.patch @@ -0,0 +1,20 @@ +# Project: src/base +# Android 17 reworked android::Asset to hold its backing buffer in a +# using Data = std::variant; +# but Asset.h never includes . AOSP's own bionic/libc++ build +# pulls in transitively, so upstream never noticed; under +# glibc + libstdc++ 12 it does not, and the header fails with +# error: 'variant' in namespace 'std' does not name a template type +# cascading into every TU that includes Asset.h (libandroidfw, libaapt, +# aapt2 SymbolTable). Add the include the source should have carried. +diff --git a/libs/androidfw/include/androidfw/Asset.h b/libs/androidfw/include/androidfw/Asset.h +--- a/libs/androidfw/include/androidfw/Asset.h ++++ b/libs/androidfw/include/androidfw/Asset.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include + #include From e44d59d4200011d5af7201ba9121f4e1fb15e452 Mon Sep 17 00:00:00 2001 From: John Carlson Date: Wed, 17 Jun 2026 21:26:29 -0500 Subject: [PATCH 3/5] shim: add android_content_res_xml_file_size_limit aconfig flag Android 17 adds a new content-res feature flag that AssetsProvider.cpp references (xml_file_size_limit()). Our aconfig stub didn't define it, so the build failed with "not declared in this scope". Force-disabled like every other flag in the stub, keeping the legacy code path. Co-Authored-By: Claude Opus 4.8 --- patches/misc/android_content_res.h | 1 + 1 file changed, 1 insertion(+) diff --git a/patches/misc/android_content_res.h b/patches/misc/android_content_res.h index 102c670..cbc9a3d 100644 --- a/patches/misc/android_content_res.h +++ b/patches/misc/android_content_res.h @@ -36,3 +36,4 @@ #define android_content_res_enhanced_debugging() false #define android_content_res_idmap_crc_is_mtime() false #define android_content_res_merge_idmap_binder_transactions() false +#define android_content_res_xml_file_size_limit() false From 0421d296d0ba9198e422f33b6040103abaf1e048 Mon Sep 17 00:00:00 2001 From: John Carlson Date: Wed, 17 Jun 2026 21:41:39 -0500 Subject: [PATCH 4/5] check_upstream: map build-tools 37.0.0 -> android-17.0.0_r1 AOSP has now tagged android-17.0.0_r1 and a full linux-arm64 build of all four tools succeeds against it (verified on arm64 hardware + CI), so promote the (37,0,0) resolution from the heuristic to an explicit, verified KNOWN_MAPPINGS entry. Drop the stale note claiming android-17 isn't tagged yet, and the docstring's now-wrong "37.0.0 is no-source" example. Co-Authored-By: Claude Opus 4.8 --- scripts/check_upstream.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scripts/check_upstream.py b/scripts/check_upstream.py index 65c64cf..2aae339 100755 --- a/scripts/check_upstream.py +++ b/scripts/check_upstream.py @@ -21,8 +21,8 @@ (which has been true since the renaming). If none of the three resolve, the version is `no-source` — Google has -published the binary but AOSP hasn't tagged the source yet (37.0.0 is -the current example). We track it but can't build it. +published the binary but AOSP hasn't tagged the source yet. We track +it but can't build it until the matching android-NN.0.0_rN appears. Output (stdout): JSON manifest of all sdkmanager versions and their resolutions. Output to $GITHUB_OUTPUT (when set): the legacy @@ -53,10 +53,8 @@ # build-tools 36.x lines up with Android 16 (NN = X + 20): (36, 0, 0): "android-16.0.0_r1", # Android 16 GA — verified local + CI (36, 1, 0): "android-16.0.0_r3", # Android 16 QPR1 — verified local + CI - # 37.0.0 is intentionally absent: as of writing, AOSP has no - # `android-17.*` branch or tag, and the sdkmanager binary uses - # proto fields not present in any 16.x snapshot. Will be filled - # in once Google publishes the matching source. + # build-tools 37.x -> Android 17 (same NN = X + 20 rule): + (37, 0, 0): "android-17.0.0_r1", # Android 17 GA — verified local (Pi) + CI } From 75654a7ac1b3ddc85fe18fec87aa0aa3662f7a36 Mon Sep 17 00:00:00 2001 From: John Carlson Date: Wed, 17 Jun 2026 21:41:39 -0500 Subject: [PATCH 5/5] fetch_sources: support Optional patches; quiet the protobuf one on 17 A patch can carry an `# Optional: true` header, meaning it's expected to apply only to some source revisions. When such a patch doesn't apply, fetch_sources now skips it quietly instead of printing the "STALE / refresh the patch" warning meant for genuinely-broken patches. Mark protobuf-include-config.patch Optional: it fixes a missing config.h include path that only exists through protobuf ~25.x (Android 16). Android 17 ships protobuf 33.5.0, which dropped the generated config.h / config dir entirely, so the patch correctly no longer applies and was noisily flagged STALE on every 17 build. Co-Authored-By: Claude Opus 4.8 --- patches/protobuf-include-config.patch | 12 +++++++++--- scripts/fetch_sources.py | 11 ++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/patches/protobuf-include-config.patch b/patches/protobuf-include-config.patch index 8fbcd4b..c73d7a4 100644 --- a/patches/protobuf-include-config.patch +++ b/patches/protobuf-include-config.patch @@ -1,9 +1,15 @@ # Project: src/protobuf -# AOSP's protobuf source has its config.h under config/, but upstream -# protobuf's CMakeLists.txt doesn't add that dir to the include path, -# so src/google/protobuf/stubs/common.cc fails with: +# Optional: true +# AOSP's protobuf through ~25.x (Android 16) keeps its config.h under +# config/, but upstream protobuf's CMakeLists.txt doesn't add that dir +# to the include path, so src/google/protobuf/stubs/common.cc fails with: # fatal error: config.h: No such file or directory # This adds the include path. Same as lzhiyong's protobuf_CMakeLists.txt.patch. +# +# Marked Optional: Android 17 ships protobuf 33.5.0, which dropped the +# generated config.h / config dir entirely (no config.h include left in +# the sources). The patch correctly no longer applies there and is +# skipped quietly rather than flagged STALE. diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt diff --git a/scripts/fetch_sources.py b/scripts/fetch_sources.py index 22c6962..e4f420e 100644 --- a/scripts/fetch_sources.py +++ b/scripts/fetch_sources.py @@ -212,10 +212,14 @@ def apply_patches(src_dir: Path, patch_dir: Path) -> None: log(f"applying patches from {patch_dir}") for p in patches: project = None + optional = False for line in p.read_text().splitlines(): if line.startswith("# Project:"): project = line[len("# Project:"):].strip() - break + elif line.startswith("# Optional:"): + optional = line[len("# Optional:"):].strip().lower() in ("1", "true", "yes") + elif line.startswith(("diff ", "--- ")): + break # reached the diff body; headers sit above it if not project: print(f" !! {p.name} missing '# Project:' header, skipping") continue @@ -248,6 +252,11 @@ def apply_patches(src_dir: Path, patch_dir: Path) -> None: ["git", "apply", "-p1", str(p)], cwd=proj_dir, check=True ) print(f" applied {p.name} -> {project}") + elif optional: + # Optional patches only apply to some source revisions — e.g. + # a fixup for a file or build-system layout that newer AOSP + # dropped. Not applying is expected here, not a breakage. + print(f" skipped {p.name} (optional; not applicable to {project})") else: err = (fwd.stderr or "").strip().split("\n")[-1] print(f" !! STALE {p.name} ({project}): {err}")