Skip to content

[Xamarin.Android.Build.Tasks] Add opt-in R8 runtime remapping - #12692

Open
simonrozsival wants to merge 17 commits into
mainfrom
simonrozsival-fix-r8-obfuscation-policy
Open

simonrozsival wants to merge 17 commits into
mainfrom
simonrozsival-fix-r8-obfuscation-policy

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Sep 5, 2026

Copy link
Copy Markdown
Member

Context: #12535

Adds experimental R8 obfuscation through the existing Intune/MAM runtime JNI remapping machinery instead of rewriting managed assemblies. Managed bindings keep their original JNI names; generated native tables translate lookups to the names and descriptors in R8's final mapping. This supports trimmed CoreCLR and NativeAOT applications and is an alternative to the assembly-rewriting workstreams in #12632 and #12634.

The shared R8 mode contract from #12668 is now integrated through main. This PR adds runtime-remapping without changing the .NET 11 private-members default or the existing disabled behavior. Remapping-specific keep rules apply only to the new mode.

Opt-in

For a CoreCLR or NativeAOT application:

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
  <AndroidLinkTool>r8</AndroidLinkTool>
  <AndroidTypeMapImplementation>trimmable</AndroidTypeMapImplementation>
  <PublishTrimmed>true</PublishTrimmed>
  <AndroidR8ObfuscationMode>runtime-remapping</AndroidR8ObfuscationMode>
</PropertyGroup>

AndroidR8ObfuscationMode=runtime-remapping is the sole opt-in; there is no separate enable property. The example leaves Debug unchanged, and runtime remapping does not apply to library projects. private-members preserves class/interface and public/protected member names while enabling optimization; disabled preserves all Java names and uses the non-optimizing Android defaults. Runtime remapping also uses the optimizing defaults, with additional JNI safety constraints.

Runtime remapping requires R8, trimming, trimmable type maps, and CoreCLR or NativeAOT. Incompatible configurations report XA4329. Unknown mode values report XA1050 when R8 is enabled. experimental-rewriting remains reserved and unavailable in this SDK; selecting it reports XA4329 rather than falling back.

Build and runtime changes

  • Run R8 exactly once, after ILLink/ILC. Convert that final mapping into runtime tables before native linking. There is no seed Java compilation, preliminary R8 pass, or SDK-generated -applymapping; no-op builds do not rerun R8.
  • Share the mapping across RIDs. NativeAOT performs per-RID ILC compilation before the shared R8 pass, then reconstructs linker inputs and links each RID afterward, without rerunning ILC or producing a preliminary native library.
  • Retain relevant mappings. CoreCLR scans linked assemblies without rewriting them. NativeAOT matches surviving JNI literals in allocated sections of ILC's ELF object, rather than treating the original publish assemblies as trimmed output.
  • Extend the existing lookup machinery. Support forward/reverse types, rewritten method and constructor descriptors, fields, inherited members, and managed-peer activation. Member keys use the post-R8 owner plus the original member name and descriptor, following the existing MAM owner convention. Field conflict keys also include the source descriptor.
  • Reuse native infrastructure. CoreCLR and NativeAOT share indexed lookup code; weak empty tables support NativeAOT builds without remapping data. Ordinary JNI member IDs remain cached after resolution. No libc++ dependency is introduced.
  • Preserve safety and incrementality. Keep bootstrap/native-callback names and manifest/resource rules. Existing MAM inputs retain precedence and stay in the normal asset pipeline; generated R8 remapping XML is a late native-link input. Track mappings, tables, native-link inputs, configuration changes, missing-output recovery, and opt-out. Unchanged generated ProGuard rules keep their timestamps so managed-only rebuilds do not unnecessarily rerun R8.

Coverage

Host tests cover mode policies, configuration validation, mapping conversion, field descriptors, MAM precedence, and retention filtering. Packaging tests exercise all three supported modes on CoreCLR and NativeAOT, including optimizing versus non-optimizing metadata, mapping-file embedding, and no-op rebuilds. Existing device/build integration coverage exercises renamed types, constructors, overloads, instance/static and inherited members, peer activation, single-pass ordering, multi-RID builds, missing-output recovery, and opt-out.

Earlier MAUI dotnet new maui --sample-content measurements predate this shared-mode integration; no new startup, build-time, or APK-size comparison is claimed for this head.

Experimental limitations

NativeAOT literal matching is conservative and can retain extra entries. Arbitrarily computed JNI names may require explicit remaps or keep rules. Conservative public/nested-class, interface, bootstrap, and native-callback keeps limit obfuscation. Existing Intune/R8 conflict handling is not full remapping-chain composition, and ambiguous reverse mappings for merged classes are omitted. This remains an experimental opt-in, not a production-readiness claim.


  • Useful description of why the change is necessary.
  • Links to related issues.
  • Unit tests.

Fixes: #12535

Context: #12535

R8 obfuscation changes JNI names that managed bindings still use.  Add an
experimental alternative to assembly rewriting by translating those names
through the existing runtime remapping machinery.

Run a naming-only R8 seed before ILLink or ILC and apply its mapping during
final R8.  Select CoreCLR remaps from linked assemblies and NativeAOT
remaps from retained ELF literals, then link the NativeAOT table after
ILC.  Extend lookups for reverse types, descriptors, fields, and peers.

Expose AndroidEnableR8Obfuscation, defaulting to false, and
AndroidR8ObfuscationMode, defaulting to runtime-remapping.  Reserve
experimental-rewriting with a clear error until its separate pipeline is
available.  Diagnose incompatible configurations with XA4329.

Preserve JNI bootstrap and resource keep rules, track incremental table
and native-link inputs, and support switching obfuscation back off.
Include task, configuration, device regression tests, and documentation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 5, 2026 19:02
@simonrozsival
simonrozsival marked this pull request as draft September 5, 2026 19:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It makes cross-cutting changes across MSBuild targets, build tasks, native runtime lookup code, and public API surface that require careful human validation beyond automated review.

Review tier: Lite
Findings: 3 Low severity

New issues introduced by this change (3)
Severity Finding
Low severity src/​Xamarin.Android.Build.Tasks/​Tests/​Xamarin.Android.Build.Tests/​Tasks/​GenerateJniRemappingNativeCodeTests.cs — ❌ error: Avoid the null-forgiving operator (!) in tests as well; it hides real nullability issues…
Low severity src/​Xamarin.Android.Build.Tasks/​Tests/​Xamarin.Android.Build.Tests/​Tasks/​R8Tests.cs⚠️ warning: Two [TestCase] attributes are on the same line, which makes the test metadata harder to…
Low severity src/​Xamarin.Android.Build.Tasks/​Utilities/​JniRemapping/​R8Mapping.cs⚠️ warning: Two method declarations are on the same line, which breaks the repo’s typical…
What changed in this PR

Adds an experimental opt-in for R8 obfuscation in .NET for Android by generating and consuming runtime JNI remapping tables (rather than rewriting managed assemblies), enabling obfuscated DEX outputs while preserving managed JNI name expectations.

Changes:

  • Introduces a two-pass R8 pipeline (seed mapping pre-trim + final R8 -applymapping) and generates JNI remapping XML/native tables for CoreCLR and NativeAOT.
  • Extends runtime remapping to cover reverse type lookups, rewritten method descriptors, and field remapping; shares native lookup code between CoreCLR and NativeAOT.
  • Adds/updates tests and documentation for new public properties and XA4327/8/9 diagnostics.
File Description
tests/​MSBuildDeviceIntegration/​Tests/​R8RuntimeRemappingTests.cs Device test validating obfuscated members/types and incremental/missing-output recovery.
src/​Xamarin.Android.Build.Tasks/​Xamarin.Android.D8.targets Wires new R8 inputs/outputs and enables mapping input/output + obfuscation flag.
src/​Xamarin.Android.Build.Tasks/​Xamarin.Android.Common.targets Adds opt-in properties, validation (XA4329), incremental inputs, and AAPT rules tracking changes.
src/​Xamarin.Android.Build.Tasks/​Utilities/​JniRemapping/​R8Mapping.cs Extends mapping parsing/projection for class/method/field data used by remapping generation.
src/​Xamarin.Android.Build.Tasks/​Utilities/​JniRemapping/​NativeAotJniRetention.cs NativeAOT ELF-based literal retention to conservatively select required remap entries.
src/​Xamarin.Android.Build.Tasks/​Utilities/​JniRemapping/​JniDescriptorText.cs Converts Java source-form types to JNI tokens + builds method descriptors.
src/​Xamarin.Android.Build.Tasks/​Utilities/​JniRemapping/​JniAssemblyRewriter.cs Adds scan-only entrypoint for linked-assembly analysis (no rewriting).
src/​Xamarin.Android.Build.Tasks/​Tests/​Xamarin.Android.Build.Tests/​Tasks/​R8Tests.cs Adds unit coverage for keep-option and config generation behavior.
src/​Xamarin.Android.Build.Tasks/​Tests/​Xamarin.Android.Build.Tests/​Tasks/​GenerateTrimmableTypeMapTests.cs Verifies NativeAOT proguard generation respects allowobfuscation.
src/​Xamarin.Android.Build.Tasks/​Tests/​Xamarin.Android.Build.Tests/​Tasks/​GenerateJniRemappingNativeCodeTests.cs New tests for native remap table emission, ordering, and legacy compatibility.
src/​Xamarin.Android.Build.Tasks/​Tests/​Xamarin.Android.Build.Tests/​InvalidConfigTests.cs Tests defaults + invalid configuration errors for new MSBuild properties.
src/​Xamarin.Android.Build.Tasks/​Tasks/​R8.cs Adds seed mapping mode, applymapping support, and conditional dontobfuscate removal.
src/​Xamarin.Android.Build.Tasks/​Tasks/​GenerateR8JniRemapping.cs Generates JNI remapping XML from R8 mapping + existing remaps; supports NativeAOT retention path.
src/​Xamarin.Android.Build.Tasks/​Tasks/​GenerateR8JniManifestProguardConfiguration.cs Generates manifest keep rules to stabilize seed mapping applicability.
src/​Xamarin.Android.Build.Tasks/​Tasks/​GenerateProguardConfiguration.cs Emits allowobfuscation on keep rules when runtime remapping is enabled.
src/​Xamarin.Android.Build.Tasks/​Tasks/​GenerateNativeAotProguardConfiguration.cs Emits allowobfuscation for NativeAOT-generated keep rules when enabled.
src/​Xamarin.Android.Build.Tasks/​Tasks/​GenerateJniRemappingNativeCode.cs Extends generated tables to include reverse types + fields; exposes info for tests.
src/​Xamarin.Android.Build.Tasks/​Resources/​proguard_xamarin.cfg Adds/adjusts keep rules needed for stable seed/final graphs and bootstrap types.
src/​Xamarin.Android.Build.Tasks/​Resources/​proguard_trimmable_nativeaot.cfg Aligns NativeAOT baseline keep rules with remapping needs and seed/final stability.
src/​Xamarin.Android.Build.Tasks/​Properties/​Resources.resx Adds XA4327/8/9 localized strings for errors/warnings/validation.
src/​Xamarin.Android.Build.Tasks/​Properties/​Resources.Designer.cs Updates generated resource accessors for XA4327/8/9.
src/​Xamarin.Android.Build.Tasks/​MSBuild/​Xamarin/​Android/​Xamarin.Android.Aapt2.targets Moves AAPT proguard rule tracking to incremental parent target.
src/​Xamarin.Android.Build.Tasks/​Microsoft.Android.Sdk/​targets/​Microsoft.Android.Sdk.TypeMap.Trimmable.targets Imports new R8 JNI remapping targets last to override pre-trim outputs as needed.
src/​Xamarin.Android.Build.Tasks/​Microsoft.Android.Sdk/​targets/​Microsoft.Android.Sdk.TypeMap.Trimmable.NativeAOT.targets Includes new properties in incremental stamps; passes obfuscation state into proguard generation.
src/​Xamarin.Android.Build.Tasks/​Microsoft.Android.Sdk/​targets/​Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets Reworks linked-assembly proguard inputs; adds remapping-assembly prep + incremental inputs.
src/​Xamarin.Android.Build.Tasks/​Microsoft.Android.Sdk/​targets/​Microsoft.Android.Sdk.TypeMap.LlvmIr.targets Adds remapping enable flag into proguard generation and incremental inputs.
src/​Xamarin.Android.Build.Tasks/​Microsoft.Android.Sdk/​targets/​Microsoft.Android.Sdk.R8JniRemapping.targets New MSBuild pipeline for seed mapping, remap XML, and NativeAOT late-linked table build.
src/​Xamarin.Android.Build.Tasks/​Microsoft.Android.Sdk/​targets/​Microsoft.Android.Sdk.NativeAOT.targets Links remapping object into NativeAOT shared library and updates incremental inputs.
src/​native/​nativeaot/​include/​runtime-base/​internal-pinvokes.hh Adds internal pinvokes for reverse-type and field lookup.
src/​native/​nativeaot/​host/​jni-remapping-tables-stub.cc Provides weak empty table symbols for apps without remapping objects.
src/​native/​nativeaot/​host/​internal-pinvoke-stubs.cc Removes now-shared remapping pinvoke stubs from NativeAOT host stubs.
src/​native/​nativeaot/​host/​host.cc Plumbs jniRemappingInUse via shared JniRemapping::is_in_use().
src/​native/​nativeaot/​host/​CMakeLists.txt Adds shared remapping sources and stub table compilation to NativeAOT host build.
src/​native/​native.targets Includes shared remapping sources/headers in NativeAOT flavor build inputs.
src/​native/​mono/​xamarin-app-stub/​xamarin-app.hh Updates stub ABI structs to include target_signature + field remapping structures.
src/​native/​mono/​xamarin-app-stub/​application_dso_stub.cc Updates stub table initializers for new method signature field.
src/​native/​mono/​runtime-base/​internal-pinvokes.hh Adds internal pinvoke declarations for reverse-type and field lookup.
src/​native/​mono/​pinvoke-override/​pinvoke-tables.include Extends pinvoke table entries/count for the new remapping exports.
src/​native/​mono/​pinvoke-override/​generate-pinvoke-tables.cc Adds new internal pinvoke names to generator input list.
src/​native/​mono/​monodroid/​internal-pinvokes.cc Adds MonoVM-safe placeholder exports for new remapping entrypoints.
src/​native/​clr/​xamarin-app-stub/​application_dso_stub.cc Extends CLR stub tables to include reverse types + fields + signature pinning.
src/​native/​clr/​runtime-base/​jni-remapping.cc Implements binary-search remapping lookups (types, reverse types, methods, fields) + is_in_use().
src/​native/​clr/​pinvoke-override/​precompiled.cc Maps new internal pinvoke entrypoints to implementations.
src/​native/​clr/​include/​xamarin-app.hh Declares remapping table symbols and adds field + reverse type structures.
src/​native/​clr/​include/​runtime-base/​jni-remapping.hh Declares shared lookup surface including reverse type and field lookup.
src/​native/​clr/​include/​runtime-base/​internal-pinvokes.hh Declares new remapping pinvokes for CoreCLR runtime.
src/​native/​clr/​host/​internal-pinvokes-shared.cc Centralizes shared remapping pinvoke implementations for CoreCLR/NativeAOT.
src/​native/​clr/​host/​internal-pinvokes-clr.cc Removes remapping implementations now provided by shared file.
src/​native/​clr/​host/​host.cc Uses JniRemapping::is_in_use() for init flag and includes remapping header.
src/​Mono.Android/​Microsoft.Android.Runtime/​TrimmableTypeMapValueManager.cs Ensures FindClass uses replacement type name when remapping is enabled.
src/​Mono.Android/​Microsoft.Android.Runtime/​TrimmableTypeMapTypeManager.cs Adds reverse-type handling for Java-to-managed lookups; uses replacement type for signatures.
src/​Mono.Android/​Microsoft.Android.Runtime/​TrimmableTypeMap.cs Uses reverse type for proxy lookup and replacement type for FindClass checks.
src/​Mono.Android/​Microsoft.Android.Runtime/​JniRemappingLookup.cs Adds reverse type + field lookup plumbing and supports target-method-signature.
src/​Mono.Android/​Android.Runtime/​RuntimeNativeMethods.cs Adds LibraryImport declarations for reverse type + field lookup pinvokes.
src/​Mono.Android/​Android.Runtime/​AndroidRuntime.cs Exposes GetOriginalTypeCore via reverse-type lookup.
external/​Java.Interop/​tests/​Java.Interop-Tests/​Java.Interop/​JniPeerMembersTests.cs Adds tests validating remapped field names and pinned target signatures.
external/​Java.Interop/​tests/​Java.Interop-Tests/​Java.Interop/​JavaVMFixture.cs Extends test runtime type manager with field replacement support.
external/​Java.Interop/​src/​Java.Interop/​PublicAPI.Unshipped.txt Records new public API surface additions for replacement fields + original type.
external/​Java.Interop/​src/​Java.Interop/​Java.Interop/​JniType.cs Adds TryGet{Static,Instance}Field helpers to support remapped field probing.
external/​Java.Interop/​src/​Java.Interop/​Java.Interop/​JniRuntime.ReflectionJniTypeManager.cs Adds null default implementation for field replacement in reflection manager.
external/​Java.Interop/​src/​Java.Interop/​Java.Interop/​JniRuntime.JniTypeManager.cs Adds ReplacementFieldInfo + original type + replacement field APIs.
external/​Java.Interop/​src/​Java.Interop/​Java.Interop/​JniPeerMembers.JniStaticMethods.cs Uses replacement lookup keyed by original type name (compat + remapping).
external/​Java.Interop/​src/​Java.Interop/​Java.Interop/​JniPeerMembers.JniStaticFields.cs Adds remapped static field probing and fallback to original lookup.
external/​Java.Interop/​src/​Java.Interop/​Java.Interop/​JniPeerMembers.JniInstanceMethods.cs Tracks original vs effective JNI type names; remaps ctor/method lookup accordingly.
external/​Java.Interop/​src/​Java.Interop/​Java.Interop/​JniPeerMembers.JniInstanceFields.cs Adds remapped instance field probing and fallback behavior.
external/​Java.Interop/​src/​Java.Interop/​Java.Interop/​JniPeerMembers.cs Tracks original type name and performs replacement lookups across base types/types.
Documentation/​docs-mobile/​TOC.yml Adds XA4327/8/9 docs to TOC.
Documentation/​docs-mobile/​messages/​xa4329.md Documents invalid/unsupported configuration errors and resolutions.
Documentation/​docs-mobile/​messages/​xa4328.md Documents remapping incompleteness warnings (conflicts/signature conversion).
Documentation/​docs-mobile/​messages/​xa4327.md Documents remapping generation failures and troubleshooting steps.
Documentation/​docs-mobile/​messages/​index.md Adds XA4327/8/9 to messages index.
Documentation/​docs-mobile/​building-apps/​build-properties.md Documents AndroidEnableR8Obfuscation + AndroidR8ObfuscationMode properties.
Files not reviewed (1)
  • src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs: Generated file
Suppressed comments (1)

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GenerateJniRemappingNativeCodeTests.cs:112

  • ❌ error: This uses the null-forgiving operator (info!) after Assert.IsNotNull, which the compiler can’t reason about. Prefer ?? throw so nullability is enforced without suppressions.

Comment thread src/Xamarin.Android.Build.Tasks/Utilities/JniRemapping/R8Mapping.cs Outdated
simonrozsival and others added 6 commits September 6, 2026 14:01
Context: #12692

Follow the existing Intune contract: member lookup keys contain the
replaced owner type and the original managed member name and descriptor.
Generate R8 member entries and collision keys in that same form rather
than teaching every consumer to try both original and replaced owners.

Remove JniPeerOriginalTypeName, the duplicate constructor identity, and
the now-unused Java.Interop reverse-type hook.  Keep reverse lookup for
peer activation and derive desugared companion names in the Android
remapping helper where the original name is actually needed.

Cover residual-owner keys, descriptors, MAM conflicts and duplicates, and
real renamed-class construction and member access on both runtimes.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Runtime remapping keeps original JNI names in managed code, so it does
not need an early naming pass.  Remove the seed compilation, seed R8
invocation, applymapping support, and early manifest-rule generation.

Generate remapping tables from the one final R8 mapping.  Defer CoreCLR
native linking until those tables exist.  For NativeAOT, compile IL early
and link each RID after the shared R8 pass without running ILC again.
Keep post-ILC table filtering, ordinary MAM assets, and opt-out behavior.

Add invocation-count and ordering coverage, including multi-RID builds,
no-op builds, missing mapping/table recovery, and changed R8 rules.

Context: #12535

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use content-based writes and generation stamps so managed-only rebuilds do not unnecessarily rerun R8. Preserve missing-output recovery, no-op incrementality, and cleanup across per-RID builds, with regression coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace null-forgiving operators in the native remapping tests with explicit assertion guards, and separate adjacent test attributes and mapping helper declarations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Resolve merged and per-manifest keep-rule paths against the captured project working directory during asynchronous AAPT execution. Preserve unchanged rule timestamps and use the existing packaged-resource output to recover missing rules without adding another stamp. Cover resource-only changes, no-op builds, and missing-rule recovery.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Delegate field remapping through AndroidTypeManager and supply the Android fixture with the field and target-descriptor mappings already used by desktop JVM tests.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival marked this pull request as ready for review September 8, 2026 13:34
@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

Generated by Android PR Reviewer for #12692

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs Changes — 1 error found.

The remapping pipeline is well covered and the runtime/native lookup design is coherent, but field-entry conflict detection currently omits the JNI descriptor from the key. Under R8 class merging this can discard a valid field remap and cause runtime lookup failure. CI has no observed failures, with the latest build checks still in progress.

Generated by Android PR Reviewer for #12692 · gpt56 · 770.9 AIC · ⌖ 5.5 AIC · ⊞ 26.3K
Comment /review to run again

Comment thread src/Xamarin.Android.Build.Tasks/Tasks/GenerateR8JniRemapping.cs Outdated
Include the original JNI descriptor in generated and existing-XML field claim keys. Keep fields from merged owners distinct even when their residual descriptors match, while preserving duplicate suppression and same-signature conflict warnings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

Generated by Android PR Reviewer for #12692

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Needs Changes

Found 2 errors in JNI field remapping: inherited remaps can override hidden derived fields, and the newly enabled field fixtures run on MonoVM even though its field-remapping entry point is a stub. The overall cross-runtime design and focused coverage are substantial, but these correctness gaps should be addressed before merge.

CI has not run for the latest commit: the dotnet-android check is currently action_required (awaiting pipeline authorization); CLA passes.

Generated by Android PR Reviewer for #12692 · gpt56 · 1.1K AIC · ⌖ 18.7 AIC · ⊞ 25.7K
Comment /review to run again

Comment thread external/Java.Interop/src/Java.Interop/Java.Interop/JniPeerMembers.cs Outdated
Comment thread tests/Mono.Android-Tests/Mono.Android-Tests/Remaps.xml
simonrozsival and others added 8 commits September 9, 2026 11:58
Consolidate duplicate class and member mapping checks into retained regression cases. Drop standalone count/symbol and property checks, and reduce malformed-input permutations while keeping representative failures, Intune compatibility, retention, ordering, and end-to-end coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve main's net11 test relocation and carry the obfuscation cases into GenerateNativeAotProguardConfigurationTests. Adapt the scan-only JNI remapping entry point to the shared planner's FieldRvaTable input. Retain main's lazy JNI caches and libc++ removal alongside single-pass R8.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve Java field-hiding semantics and enable reverse and field remapping on MonoVM, including field-only configurations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Mirror the dedicated field-remapping fixtures in the on-device remap table so the hiding and inherited-fallback tests exercise the intended mappings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use AndroidR8ObfuscationMode as the sole opt-in, place its behavior-preserving default with the shared R8 defaults, and keep runtime-specific derivation and validation late. This prepares the branch to add runtime-remapping to the mode contract from PR #12668 after it merges.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Preserve the shared private-members default, isolate runtime-remapping rules, and reconcile mode validation and packaging coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

Generated by Android PR Reviewer for #12692

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❌ Needs changes

Found 4 errors in the new runtime-remapping paths:

  • Member lookup can select a renamed base member before an unchanged hiding member on the current type.
  • Java-to-managed lookup can resolve a residual-name/original-name collision to the wrong managed type.
  • MonoVM wildcard and parameter-only remaps can shadow more-specific descriptors because of generated sort order.
  • Generated LLVM member-array symbols can collide or become invalid for Unicode JNI names.

The overall single-pass R8 pipeline is thoughtfully integrated across CoreCLR and NativeAOT, with substantial build, unit, and device coverage. All 44 current CI checks completed successfully, but the cases above require adversarial regression coverage before merge.

Generated by Android PR Reviewer for #12692 · copilot · gpt56 · 1.8K AIC · ⌖ 11.5 AIC · ⊞ 21K
Comment /review to run again

Comment thread src/Xamarin.Android.Build.Tasks/Utilities/JniRemappingAssemblyGenerator.cs Outdated
Comment thread src/Mono.Android/Microsoft.Android.Runtime/TrimmableTypeMapTypeManager.cs Outdated
Resolve method remaps in exact, parameter-only, then wildcard order; preserve hidden methods before inherited remaps; emit collision-proof native symbols; and make reverse type mappings authoritative.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Android PR Reviewer completed successfully!

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • azcliprod.blob.core.windows.net

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "azcliprod.blob.core.windows.net"

See Network Configuration for more information.

Generated by Android PR Reviewer for #12692

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Needs Changes — 0 errors, 1 warning, 0 suggestions.

The runtime-remapping implementation has broad coverage across Java.Interop, CoreCLR, NativeAOT, MSBuild incrementality, and device/build tests. One MSBuild ordering issue remains: the post-R8 NativeAOT link can run after _CompileToDalvik fails and may consume stale output or obscure the primary failure.

CI is still in progress: the completed checks are passing, with no failures currently reported.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • azcliprod.blob.core.windows.net

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "azcliprod.blob.core.windows.net"

See Network Configuration for more information.

Generated by Android PR Reviewer for #12692 · copilot · gpt56 · 738.1 AIC · ⌖ 18.2 AIC · ⊞ 21K
Comment /review to run again

ILC object/output paths. The final mapping path is absolute and shared by every RID. -->
<Target Name="_AndroidLinkNativeAotAfterR8"
AfterTargets="_CompileToDalvik"
Condition=" '$(_AndroidR8RuntimeRemappingEnabled)' == 'true' and '$(_OuterIntermediateOutputPath)' == '' and '$(DesignTimeBuild)' != 'true' "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 ⚠️ MSBuild targetsAfterTargets is scheduled even when _CompileToDalvik fails. In that case this still launches the per-RID NativeAOT links, potentially consuming a stale mapping from an earlier build or adding XA4327 errors on top of the original R8 failure. Please gate this target on $(MSBuildLastTaskResult) == true (or order it through a success-only dependency).

Rule: Avoid unguarded AfterTargets

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.

R8: unconditional -dontobfuscate makes Google Play's Feb 2027 25% obfuscation requirement unachievable

2 participants