Skip to content

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

Open
simonrozsival wants to merge 2 commits into
simonrozsival-r8-remapping-tablesfrom
simonrozsival-fix-r8-obfuscation-policy
Open

simonrozsival wants to merge 2 commits into
simonrozsival-r8-remapping-tablesfrom
simonrozsival-fix-r8-obfuscation-policy

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Sep 5, 2026

Copy link
Copy Markdown
Member

Context: #12535

This is the product policy and build-orchestration layer for opt-in R8 runtime JNI remapping. It is stacked on:

A final dependent PR, #12844, moves the .NET-only R8 mapping task into Microsoft.Android.Build.Tasks.

This PR does not rewrite managed assemblies. Managed bindings retain their original JNI names; the lower layers generate native tables that translate lookups to the names and descriptors emitted by R8.

Opt-in

For a trimmed CoreCLR or NativeAOT application:

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

runtime-remapping is the sole opt-in; there is no separate enable property. It does not apply to library projects. The existing private-members and disabled behavior remains unchanged. Unknown mode values report XA1050, while incompatible runtime-remapping configurations report XA4329.

Build orchestration

  • Runs R8 once, after ILLink or all per-RID NativeAOT ILC compilations.
  • Converts that final mapping into runtime remapping tables before native linking.
  • Defers NativeAOT linking until the shared R8 pass completes, then relinks each RID without rerunning ILC.
  • Applies the runtime-remapping-specific bootstrap, native-callback, manifest, resource, and JNI safety keep rules.
  • Preserves existing MAM remapping precedence and asset handling.
  • Tracks mapping inputs, generated XML, native table sources, task assemblies, native-link inputs, configuration changes, missing-output recovery, and opt-out for incremental builds.
  • Preserves generated ProGuard rule timestamps when their contents are unchanged so managed-only rebuilds do not rerun R8 unnecessarily.

Coverage in this layer

Host tests cover mode defaults, configuration validation, keep-rule policy, NativeAOT ProGuard configuration, packaging metadata, and incremental behavior. Build/device integration tests cover renamed types and members, constructors, overloads, inherited lookups, peer activation, single-pass ordering, multi-RID builds, missing-output recovery, and opt-out for CoreCLR and NativeAOT.

The generic lookup semantics and mapping/table-generation tests live in #12847 and #12848 respectively.

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 and dependent layers.
  • Unit and integration coverage.

Fixes: #12535

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 added a commit that referenced this pull request Sep 6, 2026
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>
@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
@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 Outdated
@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
@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

simonrozsival added a commit that referenced this pull request Sep 18, 2026
## Motivation

The existing Intune/MAM JNI method-remapping path stores target type and method names as stable NUL-terminated UTF-8 strings in generated native data. The old path materialized those names as managed UTF-16 strings and then encoded them back to UTF-8 for `FindClass` and `GetMethodID`.

That round trip is unnecessary and becomes more important as remapping is reused by larger consumers such as R8.

## Approach

- Add pointer-backed target type, method-name, and method-signature values to `ReplacementMethodInfo`.
- Keep pointer and string representations independent so reading a compatibility string property does not implicitly decode native memory.
- Add `JniType` lookup paths for pointer/pointer and mixed pointer/span member names and signatures.
- Let `JniPeerMembers` retain a replacement type pointer and use it directly for `FindClass` and later member-remapping lookups.
- Keep native pointers in `JniMethodInfo` Debug metadata and decode them only if `Name`, `Signature`, or `ToString()` is explicitly requested.
- Retain the existing string/span paths for custom `JniTypeManager` implementations.
- Document UTF-8 encoding, NUL termination, ownership, and lifetime requirements for every pointer API.

The successful generated-remapping path therefore passes the pregenerated UTF-8 type, method name, and optional signature directly to JNI without copying them or converting them to a managed string.

This PR is method-only and does not add R8, field remapping, reverse-type mapping, inherited-member fallback, or NativeAOT remapping support.

## Relationship to other PRs

- This PR is based directly on `main` and provides the Java.Interop representation and JNI lookup primitives.
- #12796 supplies the generated pointers, performs managed table search, and removes the native remapping P/Invokes.
- #12692 can build on this stack to add the R8-specific field, reverse-type, inherited-member, and NativeAOT pieces.

## Validation

- Java.Interop Debug build.
- Java.Interop `JniPeerMembersTests`: 12 passed, 1 skipped.
- The JVM fixture exercises stable unmanaged UTF-8 type/name/signature storage, signature fallback, instance/static lookup, and instance-to-static remapping.
@simonrozsival simonrozsival changed the title [Xamarin.Android.Build.Tasks] Add opt-in R8 runtime remapping [Microsoft.Android.Build.Tasks] Add opt-in R8 runtime remapping Sep 21, 2026
@simonrozsival simonrozsival changed the title [Microsoft.Android.Build.Tasks] Add opt-in R8 runtime remapping [Xamarin.Android.Build.Tasks] Add opt-in R8 runtime remapping Sep 21, 2026
@simonrozsival
simonrozsival added this pull request to stack #12845 September 21, 2026 12:41
@simonrozsival
simonrozsival force-pushed the simonrozsival-fix-r8-obfuscation-policy branch 2 times, most recently from f8b006c to 1dee9ed Compare September 21, 2026 14:26
@simonrozsival
simonrozsival removed this pull request from stack #12845 September 21, 2026 14:31
@simonrozsival
simonrozsival changed the base branch from main to simonrozsival-r8-remapping-tables September 21, 2026 14:31
@simonrozsival
simonrozsival added this pull request to stack #12850 September 21, 2026 14:31
@simonrozsival simonrozsival changed the title [Xamarin.Android.Build.Tasks] Add opt-in R8 runtime remapping [Xamarin.Android.Build.Tasks] Wire opt-in R8 runtime remapping Sep 21, 2026
simonrozsival added a commit that referenced this pull request Sep 21, 2026
## Summary

Remove the experimental build-time managed-assembly rewriting approach for R8 so any future assembly-rewriting design can start from a clean foundation.

This cleanup is related to #12535 and the original prototype in #12575.

## What this PR undoes

This removes the managed rewriting implementation developed across the R8 obfuscation stack:

- #12629 added the PE metadata rebuild substrate.
- #12630 added managed JNI metadata rewriting from R8 mappings.
- #12631 added rewriting for generated trimmable type-map assemblies.
- #12632 and #12634 integrated and tested that rewriting approach for CoreCLR and NativeAOT.

Concretely, this PR removes the rewrite task, rewrite-only metadata/IL utilities, dedicated tests and fixtures, and the XA4325/XA4326 resources and documentation. The intent is to abandon this implementation rather than preserve an unused rewriting stack that a future design would need to work around.

## What remains in place

- The generic `R8Mapping` parser introduced in #12628 remains, along with its tests and the `MSBuildDeviceIntegration` consumer. It is independently useful for reading R8 mapping files.
- The ordinary R8 configuration and `private-members` obfuscation/optimization policy from #12668 remain unchanged. This PR does **not** disable R8 or remove private-member obfuscation.
- Existing D8/R8 packaging, ProGuard rule handling, and non-rewriting build behavior remain unchanged.
- Runtime remapping remains active as the stacked follow-up work in #12847, #12848, #12692, and #12844. Those PRs implement the alternative opt-in strategy without managed assembly rewriting and are not part of this cleanup diff.

We may revisit managed assembly rewriting in .NET 12 based on customer feedback and performance data, but with a fresh design rather than this implementation.

## Validation

- Built `Xamarin.Android.Build.Tasks`
- Ran `Microsoft.Android.Build.Tasks.Tests`
- Ran `Microsoft.Android.Sdk.TrimmableTypeMap.IntegrationTests`
- Built `MSBuildDeviceIntegration`
- Ran focused `R8MappingTests`
@simonrozsival
simonrozsival force-pushed the simonrozsival-fix-r8-obfuscation-policy branch from 1dee9ed to f549677 Compare September 21, 2026 20:49
simonrozsival and others added 2 commits September 22, 2026 14:46
Add the runtime-remapping mode, validation, CoreCLR and NativeAOT build ordering, incrementality, documentation, and end-to-end coverage on top of the runtime and table-generation layers.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Pass the generated remapping table aggregate to NativeAOT initialization, provide an empty weak fallback, and track legacy ProGuard configuration files as R8 incremental inputs.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@simonrozsival
simonrozsival force-pushed the simonrozsival-fix-r8-obfuscation-policy branch from f549677 to 5255c18 Compare September 22, 2026 13:12

This branch has not been deployed

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

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