Skip to content

Tags: dotnet/android

Tags

35.0.24

Toggle 35.0.24's commit message
[native/monodroid] Fix unmangling of satellite assembly names (#9533)

Fixes: #9532

Context: #9410
Context: 86260ed
Context: c927026

In Debug configuration builds, `$(EmbedAssembliesIntoApk)`=false by
default.  This enables Fast Deployment in commercial/non-OSS builds.

When `$(EmbedAssembliesIntoApk)`=true, there are two separate ways to
embed assemblies into the `.apk`:

  * Assembly Stores (c927026), which is a "single" (-ish) file that
    contains multiple assemblies, enabled by setting
    `$(AndroidUseAssemblyStore)`=true.

    This is the default behavior for Release configuration builds.

  * One file per assembly (86260ed).

    This is the default behavior for Debug configuration builds when
    `$(EmbedAssembliesIntoApk)`=true.

Aside: #9410 is an attempt to *remove* support for the
"one file per assembly" packaging strategy, which will *not* be
applied to release/9.0.1xx.

When using the "one file per assembly" strategy, all the assemblies
are wrapped in a valid ELF shared library image and placed in the
`lib/{ABI}` directories inside the APK/AAB archive.  Since those
directories don't support subdirectories, we need to encode satellite
assembly culture in a way that doesn't use the `/` directory
separator char.

This encoding, as originally implemented, unfortunately used the `-`
character which made it ambiguous with culture names that consist of
two parts, e.g. `de-DE`, since the unmangling process would look for
the first occurrence of `-` to replace it with `/`, which would form
invalid assembly names such as `de/DE-MyAssembly.resources.dll`
instead of the correct `de-DE/MyAssembly.resources.dll`.  This would,
eventually, lead to a mismatch when looking for satellite assembly for
that specific culture.

Fix it by changing the encoding for `/` from `-` to `_`, so that the
mangled assembly name looks like
`lib_de-DE_MyAssembly.resources.dll.so` and we can unambiguously
decode it to the correct `de-DE/MyAssembly.resources.dll` name.

35.0.7

Toggle 35.0.7's commit message
[Xamarin.Android.Build.Tasks] Add retry ability to RemoveDirFixed (#9409

)

Fixes: #9133

Context: dotnet/android-tools@60fae19

Much to our chagrin, in .NET 6+ it is possible for Design-Time Builds
(DTBs) to run concurrently with "normal" builds, as there is nothing
within the [.NET Project System][0] or [Common Project System (CPS)][1]
which would actively *prevent* such concurrency.

Consequently, it is possible to encounter locked files and
directories during the build process, and user may see errors such as:

	Error (active)	XARDF7019	System.UnauthorizedAccessException: Access to the path 'GoogleGson.dll' is denied.
	   at System.IO.Directory.DeleteHelper(String fullPath, String userPath, Boolean recursive, Boolean throwOnTopLevelDirectoryNotFound, WIN32_FIND_DATA& data)
	   at System.IO.Directory.Delete(String fullPath, String userPath, Boolean recursive, Boolean checkHost)
	   at Xamarin.Android.Tasks.RemoveDirFixed.RunTask() in /Users/runner/work/1/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Tasks/RemoveDirFixed.cs:line 54	MauiApp2 (net9.0-android)	C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.99.0-preview.6.340\tools\Xamarin.Android.Common.targets	2503

dotnet/android-tools@60fae192 introduced the concept of a "Retry" in
the cases of `UnauthorizedAccessException`s or `IOException`s when
the code is `ACCESS_DENIED` or `ERROR_SHARING_VIOLATION`.

Builds upon that work to use the API's added to add retry semantics
to the `<RemoveDirFixed/>` task. 

This also simplifies the Task somewhat as it had quite complex
exception handling. 

[0]: https://github.com/dotnet/project-system
[1]: https://github.com/microsoft/VSProjectSystem

34.0.145

Toggle 34.0.145's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Bump to xamarin/monodroid@b753d75f (#9415)

Changes: xamarin/monodroid@352bcbe...b753d75

Updates the recommended Android SDK component feed to the latest d17-12
version.

35.0.0-rc.2.152

Toggle 35.0.0-rc.2.152's commit message
LEGO: Pull request (#9358)

LEGO: Pull request from juno/hb_6dddf33b-c6da-43d8-ac04-14d2c339cb00_20241002103533710 to main with localized lcls

34.0.143

Toggle 34.0.143's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
[tests] add test for `$(AdbTargetArchitecture)` (#9227) (#9317)

Backport of: #9227
Context: #8662
Context: xamarin/monodroid#1537

* Bump to xamarin/monodroid@352bcbe8

Changes: xamarin/monodroid@1a9ee37...352bcbe

* [tools/msbuild] implement $(AdbTargetArchitecture) for IDEs

* Bump to c158adfd6f

35.0.0-rc.1.80

Toggle 35.0.0-rc.1.80's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Bump to dotnet/runtime@c4d7f7c6f2 9.0.0-rc.1.24431.7 (#9274)

Changes: dotnet/runtime@a7d6f0c...c4d7f7c
Changes: dotnet/emsdk@459c929...08499c1

Updates:

* Microsoft.NET.ILLink.Tasks: from 9.0.0-rc.1.24430.5 to 9.0.0-rc.1.24431.7
* Microsoft.NETCore.App.Ref: from 9.0.0-rc.1.24430.5 to 9.0.0-rc.1.24431.7
* Microsoft.NET.Workload.Emscripten.Current.Manifest-9.0.100.Transport: from 9.0.0-rc.1.24420.5 to 9.0.0-rc.1.24430.3

34.0.138

Toggle 34.0.138's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Bump to dotnet/runtime@2d5c0b72 8.0.8 (#9266)

Reverts 732db0c
Reverts e039014

35.0.0-preview.7.41

Toggle 35.0.0-preview.7.41's commit message
[installers] Ship `NuGet*` files needed by `<AndroidMavenLibrary>` (#…

…9098)

Fixes: #9037

Attempting to use `@(AndroidMavenLibrary)` in Visual Studio 17.11 P3,
which ships .NET 9 P5, like this:

	<ItemGroup>
	  <AndroidMavenLibrary Include="com.squareup.okhttp3:okhttp" Version="4.9.3" />
	</ItemGroup>

gives you the error:

	…\Microsoft.Android.Sdk.Windows\34.99.0-preview.5.308\tools\Xamarin.Android.Bindings.JavaDependencyVerification.targets(27,5): error XAJDV7028: System.IO.FileNotFoundException: Could not load file or assembly 'NuGet.ProjectModel, Version=6.9.1.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The specified file cannot be found.
	…\Microsoft.Android.Sdk.Windows\34.99.0-preview.5.308\tools\Xamarin.Android.Bindings.JavaDependencyVerification.targets(27,5): error XAJDV7028: File name: 'NuGet.ProjectModel, Version=6.9.1.3, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
	…\Microsoft.Android.Sdk.Windows\34.99.0-preview.5.308\tools\Xamarin.Android.Bindings.JavaDependencyVerification.targets(27,5): error XAJDV7028:    at Xamarin.Android.Tasks.NuGetPackageVersionFinder.Create(String filename, TaskLoggingHelper log)
	…\Microsoft.Android.Sdk.Windows\34.99.0-preview.5.308\tools\Xamarin.Android.Bindings.JavaDependencyVerification.targets(27,5): error XAJDV7028:    at Xamarin.Android.Tasks.DependencyResolver..ctor(String lockFile, TaskLoggingHelper log) in /Users/runner/work/1/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs:line 124
	…\Microsoft.Android.Sdk.Windows\34.99.0-preview.5.308\tools\Xamarin.Android.Bindings.JavaDependencyVerification.targets(27,5): error XAJDV7028:    at Xamarin.Android.Tasks.JavaDependencyVerification.RunTask() in /Users/runner/work/1/s/xamarin-android/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs:line 77
	…\Microsoft.Android.Sdk.Windows\34.99.0-preview.5.308\tools\Xamarin.Android.Bindings.JavaDependencyVerification.targets(27,5): error XAJDV7028:    at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:line 25

We need to ship `NuGet.ProjectModel.dll` as well as its dependencies
to ensure they are always available to our MSBuild tasks.

Note that NuGet does not ship `.pdb` files for these assemblies in
their NuGet packages.  We will need to exclude these assemblies from
`.pdb` checking.

This wasn't caught by CI because CI tests use `dotnet build`, *not*
Visual Studio, and the `dotnet` install contains `NuGet.ProjectModel`
and related dependencies:

	% find bin/Debug/dotnet -iname NuGet.Project\*
	bin/Debug/dotnet/sdk/…/Sdks/Microsoft.NET.Sdk/tools/net472/NuGet.ProjectModel.dll
	bin/Debug/dotnet/sdk/…/NuGet.ProjectModel.dll
	…

34.99.0-preview.6.340

Toggle 34.99.0-preview.6.340's commit message

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Bump to dotnet/sdk@89054b0c37 9.0.100-preview.6.24325.8 (#9059)

Changes: dotnet/sdk@3c7b1bd...89054b0

Updates: VS.Tools.Net.Core.SDK.Resolver: from 9.0.100-preview.6.24324.9 to 9.0.100-preview.6.24325.8

34.99.0-preview.5.308

Toggle 34.99.0-preview.5.308's commit message
[Xamarin.Android.Build.Tasks] LLVM Marshal Methods by Default, Take 2 (

…#8925)

Context: 6836818
Context: 8bc7a3e

Commit 8bc7a3e enabled LLVM Marshal Methods by default, and commit
6836818 *disabled* LLVM Marshal Methods by default, because it
appeared to contribute to hangs in MAUI+Blazor apps.

After lots of additional cleanup, refactoring, and investigation… we
*still* don't understand why MAUI+Blazor apps hang, and we want the
app time startup improvements that LLVM Marshal Methods allow.

Square this circle by enabling LLVM Marshal Methods by default,
*unless* Blazor is detected, in which case LLVM Marshal Methods will
be *disabled* automatically.

~~ App startup time improvements ~~

Measurements are across 50 runs if a test app, with the fastest and
slowest runs removed from the set.

  * Displayed time
      * Best result: **15.73%** faster (default settings
        *without* ProfiledAOT and compression)
      * Default settings result: **12.66%** faster.
  * Native to managed transition
      * Best result: **1.31%** faster
      * Default settings result: **0.35%** slower
  * Total managed runtime init
      * Best result: **2.55%** faster (default settings without ProfiledAOT)
      * Default settings result: **0.71%** faster


~~ Build Target Interdependencies ~~

While developing this change, we ran into an odd bug, via the
`InstallAndRunTests.EnableAndroidStripILAfterAOT(false)` test:

	% dotnet new android
	% dotnet build -c Release -v:diag -p:AndroidEnableMarshalMethods=true \
	  -p:AndroidStripILAfterAOT=true -p:AndroidEnableProfiledAot=false > b.txt
	% dotnet build -c Release -v:diag -p:AndroidEnableMarshalMethods=true \
	  -p:AndroidStripILAfterAOT=true -p:AndroidEnableProfiledAot=false -t:Install > i.txt
	% dotnet build -c Release -t:StartAndroidActivity

The app immediately crashes on startup; from `adb logcat`:

	F mono-rt : [ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidProgramException: Invalid IL code in Android.Runtime.JNIEnvInit:Initialize (Android.Runtime.JNIEnvInit/JnienvInitializeArgs*): method body is empty.

The reason fo the crash is that during the first `dotnet build`
invocation, the marshal methods classifier works as it should and,
consequently, the marshal methods rewriter *modifies the assemblies*:
removes connector methods, generates wrapper methods, etc etc.
As part of this, the `_GenerateJavaStubs` target eventually creates a
stamp file which it then uses to decide whether all the inputs are up
to date with regards to their corresponding outputs.

However, at the end of the first `dotnet build`, `ILStrip` runs which
modifies assemblies *after* marshal methods processing is done.

When we run the `dotnet build -t:Install` command, the
the `_GenerateJavaStubs` target runs *again* as MSBuild notices that
the stamp file is older than some of the inputs: assemblies modified
by `ILStrip` after `_GenerateJavaStubs` created its stamp file.
This causes the target to run completely:

	Target "_GenerateJavaStubs: (TargetId:337)" in file "/usr/local/share/dotnet/packs/Microsoft.Android.Sdk.Darwin/34.0.95/tools/Xamarin.Android.Common.targets" from project "…/gxa-8925.csproj" (target "_GeneratePackageManagerJava" depends on it):
	Building target "_GenerateJavaStubs" completely.
	Input file "obj/Release/net8.0-android/android-arm/linked/gxa-8925.dll" is newer than output file "obj/Release/net8.0-android/stamp/_GenerateJavaStubs.stamp".

which causes the whole marshal methods processing to be initiated
again, but this time the connector methods and anything else the
classifier looks for aren't there, because they were previously
removed by the rewriter during the first `dotnet build` command.
This, in turn, causes the classifier to decide that types need to be
registered dynamically, but they can't because the connector methods
which are required to create delegates are no longer there and we get
a runtime crash instead.

The solution is to update the `_GenerateJavaStubs` stamp file after
`ILStrip` is done, within the `_AndroidAotCompilation` target,
if it modified any assemblies.

One problem with that is that the path to the stamp file's directory
is different when `_GenerateJavaStubs` runs during the build phase,
and when AOT and `ILStrip` run.  In the former case, the stamp file
is created in `obj/${Configuration}/stamp` directory, in the latter
case in `obj/${Configuration}/android-ARCH/stamp` directory, but
*both* locations are initialized in the same spot: at the top of
`Xamarin.Android.Common.targets`.  In effect, after `ILStrip` runs,
we don't really know where `_GenerateJavaStubs` created its stamp file.

Workaround this by taking advantage of the fact that we know where
the stamp directories are in relation to each other.  It's a hack,
but if the relation is somehow broken, the
`InstallAndRunTests.EnableAndroidStripILAfterAOT(false)` test will
break again.