Skip to content

[AndroidSdk] Replace uname and remove the unused manifest file writer - #13457

Open
simonrozsival wants to merge 7 commits into
mainfrom
simonrozsival-sdk-native-interop
Open

simonrozsival wants to merge 7 commits into
mainfrom
simonrozsival-sdk-native-interop

Conversation

@simonrozsival

@simonrozsival simonrozsival commented Nov 10, 2026 •

Copy link
Copy Markdown
Member

OS.IsMac currently calls uname to identify Darwin. Use managed runtime platform checks instead, while retaining the existing Windows and non-Darwin classification. Remove the unused duplicate build-tasks FileUtil and the AndroidSdk rename helper: its only production caller is AndroidAppManifest.WriteToFile, which has no in-repository callers.

Compatibility: This intentionally removes the shipped public AndroidAppManifest.WriteToFile(string) API. Write(XmlWriter) remains available, but callers must manage file creation and replacement themselves; it does not by itself preserve the removed method's replacement semantics. The chmod fallback and Windows path/registry interop are unchanged.

Platform limitation: The checks cover the Apple platforms recognized by the runtime. They include watchOS identifiers, but watchOS equivalence with uname remains unverified: the .NET 10/11 runtime sources omit WATCHOS from their platform-name list, and runtime main documents OperatingSystem.IsWatchOS() as always false. This affects both the modern and netstandard paths.

Validation (macOS arm64; baseline 6b8fb8c3742b8ea4aa5f9f92e70a601a28f83360):

  • make leeroy MSBUILD_ARGS=-p:IncludeAndroidJavadoc=true — passed using a session-owned toolchain. An initial make leeroy failed because the workload pack expected a Mono.Android.xml that the default build had not generated.
  • ./dotnet-local.sh test bin/TestDebug/net11.0/Xamarin.Android.Build.Tests.dll --filter 'FullyQualifiedName~RemoveDirTests|FullyQualifiedName~BuildTest2.NonAndroidNativeLibrariesDoNotProduceWarnings' -v minimal — 7 passed, 4 skipped.
  • dotnet build src/Xamarin.Android.Tools.AndroidSdk/Xamarin.Android.Tools.AndroidSdk.csproj -c Release -p:AndroidToolsDisableMultiTargeting=false -p:DotNetTargetFrameworkVersion=11.0 -v minimal — passed for net11.0 and netstandard2.0; repeating with -p:DotNetTargetFrameworkVersion=10.0 passed for net10.0 and netstandard2.0.
  • dotnet test tests/Xamarin.Android.Tools.AndroidSdk-Tests/Xamarin.Android.Tools.AndroidSdk-Tests.csproj -p:AndroidToolsDisableMultiTargeting=false -p:DotNetTargetFrameworkVersion=11.0 -v minimal — 536 passed, 8 skipped.
  • The same test command with -p:AndroidToolsDisableMultiTargeting=true — 533 passed, 8 skipped, 3 failed. The three ProcessUtilsTests argument-list failures also reproduce with the saved main-baseline assembly. With --filter 'FullyQualifiedName!~CreateProcessStartInfo_SingleArg&FullyQualifiedName!~CreateProcessStartInfo_MultipleArgs&FullyQualifiedName!~CreateProcessStartInfo_ArgWithSpaces', 529 passed and 8 skipped.
  • Reflection verified that WriteToFile and the rename helpers are absent and Write(XmlWriter) remains present in the final net11.0 and netstandard2.0 assemblies. Both baseline and candidate classified macOS as Darwin under arm64 and x64/Rosetta.
  • Forcing -p:DotNetTargetFrameworkVersion=12.0 together with multitargeting failed because main has no PublicAPI/net12.0 files; the full SDK build above succeeded with the project's default AndroidSdk targeting.

Performance: Final-candidate timing was deferred because the shared host was saturated. Earlier baseline comparisons used an intermediate candidate, so they are not used to claim a speedup for this final PR.

Overlap: #12988 changes AndroidSdk targeting and the chmod fallback and edits these files. #13375 adds safety annotations to the removed interop declarations. Neither is a prerequisite, but both will need coordination/rebasing.

simonrozsival and others added 6 commits November 10, 2026 04:35
* OS.IsRunningOnMac: use OperatingSystem (net) / RuntimeInformation
  (netstandard2.0) platform checks instead of P/Invoking uname(3).
  All Apple platforms are matched, as uname reports "Darwin" on each.
* FileUtil.SystemRename: use a LibraryImport'd rename(2) on .NET,
  keeping exact rename(2) and errno semantics; netstandard2.0 keeps
  the DllImport. File.Move(overwrite) was rejected: it falls back to
  non-atomic copy+delete on EXDEV, rejects directory sources, and
  throws UnauthorizedAccessException instead of errno IOExceptions.
* Remove unused Xamarin.Android.Build.Tasks Utilities/FileUtil.cs and
  its rename P/Invoke.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
uname() reports the "Darwin" sysname on watchOS too, so the managed
replacement for the uname P/Invoke must treat watchOS as Mac on both the
.NET (OperatingSystem.IsWatchOS) and netstandard2.0
(OSPlatform.Create ("WATCHOS")) paths.

Add a host test comparing OS.IsMac/IsLinux/IsWindows with the original
uname()-based classification.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The runtime platform checks do not establish uname equivalence on
unsupported platforms such as watchOS. Correct the comment without
changing the detection logic.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The platform detection implementation now relies on runtime platform checks instead of calling uname(3). Remove the host-only comparison, which required a separate uname P/Invoke in the test suite.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
AndroidAppManifest.WriteToFile remains public and uses the native rename helper. Cover non-ASCII paths and both new and existing destinations so the source-generated and netstandard marshalling paths preserve this behavior.

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

AndroidAppManifest.WriteToFile() is the only production caller of FileUtil.SystemRename(), and no in-tree callers use the file-writing method. The manifest type is still used by build tasks, so retain it while removing the file writer and its native rename implementation.

This removes a shipped public API. Consumers can use Write(XmlWriter) and manage file creation and replacement themselves. Record the removal in the public API baselines and remove tests for the deleted operations.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 10, 2026 15:01

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.

🔵 Needs a closer look

Removing the shipped public AndroidAppManifest.WriteToFile(string) API is binary-breaking and requires maintainer confirmation of downstream compatibility and release-policy acceptance.

No open issues 🎉

What changed in this PR

This PR simplifies Android SDK tooling by replacing native uname detection with managed platform checks and removing unused manifest-writing and rename code.

Changes:

  • Uses runtime platform checks for Darwin classification, with watchOS equivalence explicitly unverified.
  • Intentionally removes the shipped AndroidAppManifest.WriteToFile(string) API; Write(XmlWriter) remains, with file creation and replacement left to callers.
  • Removes unused rename helpers, the duplicate build-task utility, and their tests. The chmod fallback and Windows interop remain unchanged.
File Description
tests/​Xamarin.Android.Tools.AndroidSdk-Tests/​SystemRenameTests.cs Deletes tests for the removed rename helper.
tests/​Xamarin.Android.Tools.AndroidSdk-Tests/​FileUtilTests.cs Removes rename-specific cases and an unused import.
src/​Xamarin.Android.Tools.AndroidSdk/​PublicAPI/​netstandard2.0/​PublicAPI.Unshipped.txt Records the manifest writer API removal for netstandard2.0.
src/​Xamarin.Android.Tools.AndroidSdk/​PublicAPI/​net11.0/​PublicAPI.Unshipped.txt Records the manifest writer API removal for net11.0.
src/​Xamarin.Android.Tools.AndroidSdk/​PublicAPI/​net10.0/​PublicAPI.Unshipped.txt Records the manifest writer API removal for net10.0.
src/​Xamarin.Android.Tools.AndroidSdk/​OS.cs Replaces uname interop with managed Apple-platform checks.
src/​Xamarin.Android.Tools.AndroidSdk/​FileUtil.cs Removes temporary-name and rename helpers, including native interop.
src/​Xamarin.Android.Tools.AndroidSdk/​AndroidAppManifest.cs Removes WriteToFile, retaining Write(XmlWriter).
src/​Xamarin.Android.Build.Tasks/​Utilities/​FileUtil.cs Deletes the unused duplicate utility.

Review effort: Balanced

@simonrozsival

Copy link
Copy Markdown
Member Author

OS classification microbenchmark — final candidate

On macOS arm64 with the .NET 11 runtime, 40 counterbalanced cold-process pairs compared main 6b8fb8c3742b8ea4aa5f9f92e70a601a28f83360 with 9e977cbdf7e699a8ceb0d70a8f3cc00f94b2ccd7:

AndroidSdk assembly Baseline median Candidate median Ratio of medians
net11.0 841.9 µs 163.1 µs 5.16×
netstandard2.0 834.5 µs 179.4 µs 4.65×

These measure OS class-constructor time in fresh processes, not complete process startup, application startup, or build time. The run used heavy-slot.sh --toolchain; one-minute load ranged from 3.36 to 3.57 across six snapshots, four during measurement. No competing build/test processes or heavy-slot holders were detected in those samples, but the host was shared and short activity between samples cannot be ruled out. This result supersedes the earlier timing deferral in the description.

@simonrozsival

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ Android PR Reviewer completed successfully!

Generated by Android PR Reviewer for #13457

@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 — compatibility decision outstanding

Reviewed all nine changed files, their surrounding source, callers, and AndroidSdk target-framework configuration. 0 errors, 1 warning, 1 suggestion, posted inline. The warning asks for explicit downstream-compatibility/release acceptance of the intentional shipped WriteToFile(string) removal; absent that acceptance, preserve a compatibility entry point. The suggestion adds independent platform-classification coverage for both target-framework paths.

The managed Darwin checks remove the unmanaged allocation and uname call while retaining the existing Windows/non-Darwin classification on supported desktop hosts. No in-repository callers of the removed writer or rename helpers remain. The API-removal records are consistent across all three existing framework baselines, and the chmod fallback and Windows interop are unchanged. The description clearly distinguishes the API break and watchOS limitation; no additional correctness defect was identified in the remaining implementation.

CI: All 41 GitHub check runs report success, including the aggregate dotnet-android check for Azure build 1673052. Direct Azure build/timeline verification was blocked by CLI startup and authentication errors, so Azure status was not independently confirmed. No local builds or tests were run for this read-only review.

Generated by Android PR Reviewer for #13457 · copilot · gpt61 · 31.3 AIC · ⌖ 7.63 AIC · ⊞ 19.5K
Comment /review to run again

@@ -1,4 +1,5 @@
#nullable enable
*REMOVED*Xamarin.Android.Tools.AndroidAppManifest.WriteToFile(string! fileName) -> void

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.

🤖 ⚠️ API design — Could we confirm downstream-consumer compatibility and maintainer acceptance of this shipped API break before removing it? The absence of in-repository callers does not establish that consumers of the published AndroidSdk package no longer use it: an existing binary calling AndroidAppManifest.WriteToFile(string) will fail with MissingMethodException after upgrading. The description correctly acknowledges this, but Write(XmlWriter) is neither a binary-compatible replacement nor an equivalent file-replacement API. Unless the break is approved for this release, retain an obsolete compatibility entry point and preserve its replacement behavior. This applies to the net10.0 and net11.0 removals as well.

{Rule: Shared tooling API-shape changes require downstream binary-compatibility review.}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The API removal remains intentional and was explicitly requested by the PR author after confirming there are no in-repository callers. A compatibility entry point would retain the file-writing/rename behavior this change is removing. I cannot independently confirm downstream compatibility or release-policy acceptance, so I am leaving this thread open for maintainer review of that release decision.

Auto-replied by the GitHub Copilot app

Add independent runtime-platform assertions for the OS classification and native library format. Run the test with both the netstandard2.0 and modern .NET AndroidSdk assemblies.

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

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants