Make trimmable typemap ACWs conditional - #12498
Open
simonrozsival wants to merge 3 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the trimmable typemap pipeline so ordinary Java peers (including ACW types) become conditional on managed reachability by default, while still preserving externally-instantiated roots (manifest references, explicit component/JNI-provider roots, and XML-only custom views). It also expands test coverage to validate trimming behavior for unused binding listener implementors and custom views referenced only from Android XML resources.
Changes:
- Adjust Java peer scanning/model-building so ACW peers are conditional unless explicitly rooted (manifest/component/JniTypeSignature/custom-view roots).
- Feed custom view map roots into typemap generation prior to trimming.
- Add/adjust unit and integration tests to cover conditionality, unused implementor trimming, and XML-only custom view survival.
Show a summary per file
| File | Description |
|---|---|
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Scanner/JavaPeerScannerTests.cs | Updates scanner assertions for framework vs non-framework unconditional rooting behavior. |
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/TypeMapModelBuilderTests.cs | Revises model-building expectations so ACW-related entries are conditional unless explicitly rooted. |
| tests/Microsoft.Android.Sdk.TrimmableTypeMap.Tests/Generator/TrimmableTypeMapGeneratorTests.cs | Adds unit coverage for rooting only the custom views referenced in XML. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs | Adds CoreCLR release integration coverage for trimming unused binding listener implementors and preserving XML-only custom views; introduces Cecil-based inspection helpers. |
| src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs | Plumbs custom view map type names into typemap generation. |
| src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets | Ensures typemap generation depends on resource case conversion and is incremental with the custom view map as an input. |
| src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapGenerator.cs | Roots custom view types (from the custom view map) as unconditional peers before downstream generation. |
| src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs | Refines unconditional detection (framework vs non-framework, plus legacy IJniNameProviderAttribute rooting for JniTypeSignature peers) and narrows forced cross-references. |
| src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs | Removes the blanket “user ACWs are unconditional” rule so conditionality is driven by explicit roots. |
Review details
- Files reviewed: 9/9 changed files
- Comments generated: 2
- Review effort level: Lite
Member
Author
|
/azp run |
|
Azure Pipelines: 1 pipeline(s) were filtered out due to trigger conditions. |
Base automatically changed from
simonrozsival/fix-trimmable-typemap-retention
to
main
August 25, 2026 17:09
Let ILLink trim ordinary Java peers while preserving explicit external Java roots from attributes, manifests, and custom-view resources. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a6de09d8-fc09-4560-a976-ffcccd21ba70
Load custom view roots through the build-engine cache shared with the resource conversion tasks. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a6de09d8-fc09-4560-a976-ffcccd21ba70
Use unambiguous Cecil full names when asserting whether trimming retained generated implementors and custom views. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a6de09d8-fc09-4560-a976-ffcccd21ba70
jonathanpeppers
force-pushed
the
simonrozsival/trimmable-typemap-conditional-acws
branch
from
August 25, 2026 17:09
20a8b1c to
c0d288e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Why custom views are part of this change
Removing the blanket unconditional ACW rule allows ILLink to trim ordinary Java peers. Types instantiated externally by Android still need explicit roots even when managed code does not reference them. Custom views used only in layout XML are one such root, so the custom-view map is consumed by the typemap generator before trimming.
Dependency
Stacked on #12497 so the trimmed integration coverage runs with correct UTF-8 metadata field ownership. The diff in this PR contains only conditionality and external-root behavior.
Testing
Microsoft.Android.Sdk.TrimmableTypeMap.Tests: 800 passedReleaseCoreClrTrimmableTypeMap_TrimsUnusedBindingListenerImplementorsReleaseCoreClrTrimmableTypeMap_UsesExternalJavaRootsFollow-up before marking ready
Component attributes are currently treated as roots for every non-framework assembly. This still retains
AndroidX.Browser.CustomTabs.KeepAliveService, unlike the legacy linker. The remaining work is to distinguish app-authored component roots from unused package components without weakening manifest correctness.