Skip to content

R8: emit compiler r8.json into the AAB, and bump 10.0.x pack R8 off 8.11.18 (Play scores 9.0.32, not 8.11.18) #12639

Description

@yuseok-kim-edushare

Android framework version

net10.0-android

Affected platform version

Microsoft.Android.Sdk 36.1.69

Description

This is scoped to the shrinking and optimization percentages on Play Console. The obfuscation / -dontobfuscate work (#12535, #12575 and the [r8-obfuscation] stack) is separate and untouched here.

With $(AndroidLinkTool)=r8, R8 already runs with shrinking enabled, yet Play's App Bundle Explorer shows optimization and shrinking as - and only obfuscation gets a value (from mapping.txt). Per the DEX code optimization docs, for AGP 8.10+ the percentages come from BUNDLE-METADATA/com.android.tools/r8.json. The docs also say Play falls back to mapping.txt when r8.json is absent; in our measurements that fallback produced obfuscation only, never the other two.

The SDK never produces or embeds that file:

  • R8.cs has no build-metadata output. $(AndroidR8ExtraArguments) cannot be used for it from outside the SDK: D8.WriteArg writes the whole property as one response-file line, and R8's FlagFile treats one line as one token, so --build-metadata-output <path> arrives as a single unknown option. (The flag itself is supported by 8.11.18 — this is an SDK limitation, not an R8 one.)
  • _PrepareBuildApk adds exactly one AndroidAppBundleMetaDataFile entry, com.android.tools.build.obfuscation/proguard.map. Nothing for com.android.tools/r8.json.

Measurements (production .NET MAUI app, same project, same R8 flags, AndroidPackageFormat=aab, no AGP metadata injected anywhere)

DEX compiled by r8.json in AAB version in that json Play shrinking / optimization
stock pack 8.11.18 none -
A pack 8.11.18 generated via setBuildMetadataConsumer 8.11.18 - (obfuscation 37% from mapping)
B R8 9.0.32 via AndroidR8JarPath generated by 9.0.32 9.0.32 percentages shown
111 pack 8.11.18 A's json, only version changed 9.0.32 percentages shown
112 R8 9.0.32 B's json, only version changed 8.11.18 -

111/112 keep DEX bytes and dexFiles[].checksum unchanged; only the version string differs. Diffing honest 8.11.18 vs 9.0.32 json (same input): identical stats, options, dexFiles[].checksum; 8.11 additionally has compilation.*; 9.0 has no key 8.11 lacks.

Together that isolates the gate to the version string in r8.json. Two points only: 8.11.18 is rejected, 9.0.32 is accepted. The cutoff between them was not probed (it could be 8.12, 9.0.0, or something else). There is no honest way for pack 8.11.18 to produce a version Play will score.

Ask — two separable changes

  1. Generate and embed r8.json (backportable without changing the jar): an R8 task parameter that writes --build-metadata-output and the path as two response-file lines, plus one AndroidAppBundleMetaDataFile entry for com.android.tools/r8.json next to the existing proguard.map one. main already pins 9.4.17 and the net11 line (release/11.0.1xx-preview6) already pins 9.1.31; (1) is likely sufficient there. We uploaded and scored 9.0.32, and later the same production app compiled with main's R8 9.4.17 (src/r8 fat jar) — Play still filled optimization, obfuscation, and shrinking.
  2. Bump src/r8/build.gradle on release/10.0.1xx (the live net10.0-android pack line; tools jar is 8.11.18 today) to a compiler that emits a version Play accepts. 9.0.32 is the version we first uploaded and Play scored; 9.4.17 is the main pin and also scored. Change (1) alone still emits "version": "8.11.18", which Play does not score. Rewriting version in json is not an SDK solution.

Follow-up, not required to get Play to read the file: the [r8-obfuscation] PRs (#12575, #12628#12634) address -dontobfuscate / JNI renaming, not this. _CalculateProguardConfigurationFiles still passes tools/proguard-android.txt (line 16: -dontoptimize). The SDK does not currently ship proguard-android-optimize.txt. Switching that default would let compiler r8.json report optimizations enabled; it is independent of emit+embed and of the obfuscation stack.

Out of scope: -dontobfuscate / JNI remapping, shrinkResources, fabricating androidGradlePluginVersion, running Gradle in the SDK.

Steps to Reproduce

  1. Release net10.0-android, AndroidLinkTool=r8, AndroidCreateProguardMappingFile=true, AndroidPackageFormat=aab, dotnet publish.
  2. unzip -l app.aab | grep BUNDLE-METADATA → only proguard.map.
  3. Upload → App Bundle Explorer → shrinking/optimization -.
  4. Set AndroidR8JarPath to an R8 9.0.32 jar, produce r8.json via setBuildMetadataConsumer (or CLI --build-metadata-output on its own line), add it via AndroidAppBundleMetaDataFile Include="com.android.tools/r8.json:<path>", publish, upload.
  5. Percentages appear. The same DEX with json version 8.11.18 (honest pack output, or 112 in the table) shows - again.

Did you find any workaround?

the csproj targets in step 4 — an external 9.0.32 jar plus an out-of-band json producer. Apps should not have to carry that.

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: App+Library BuildIssues when building Library projects or Application projects.needs-triageIssues that need to be assigned.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions