Skip to content

[generator] Add support for emitting [UnsupportedOSPlatform]. #1307

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 20, 2025

Conversation

jpobst
Copy link
Contributor

@jpobst jpobst commented Feb 13, 2025

Fixes: #1309

Sometimes, Android removes APIs. For example, API-23 removed the android.Manifest.permission.CLEAR_APP_USER_DATA field.

We still list this field, though: Android.Manifest.Permission.ClearAppUserData field

We modified api-merge to add removed-since in dotnet/android#8897.

Here is the excerpt from https://github.com/dotnet/android/blob/main/src/Mono.Android/Profiles/api-Baklava.xml:

<field deprecated="not deprecated" final="true" name="CLEAR_APP_USER_DATA" jni-signature="Ljava/lang/String;" static="true" transient="false" type="java.lang.String" type-generic-aware="java.lang.String" value="&quot;android.permission.CLEAR_APP_USER_DATA&quot;" visibility="public" volatile="false" removed-since="23"></field>

Modify generator to consume this information and emit UnsupportedOSPlatformAttribute ("androidXX0")] as needed for API that has been removed from Mono.Android.

Tested in dotnet/android with dotnet/android#9791.

@jpobst jpobst marked this pull request as ready for review February 20, 2025 17:47
@jpobst jpobst requested review from jonpryor and Copilot February 20, 2025 17:47
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot reviewed 5 out of 9 changed files in this pull request and generated no comments.

Files not reviewed (4)
  • tools/generator/SourceWriters/Extensions/SourceWriterExtensions.cs: Evaluated as low risk
  • tools/generator/Java.Interop.Tools.Generator.Importers/XmlApiImporter.cs: Evaluated as low risk
  • tools/generator/ApiVersionsSupport.cs: Evaluated as low risk
  • tests/generator-Tests/Unit-Tests/XmlApiImporterTests.cs: Evaluated as low risk

@jonpryor
Copy link
Contributor

Fixes: https://github.com/dotnet/java-interop/issues/1309

Context: https://github.com/dotnet/android/commit/944d30615acd0924ac9adde46fca2430c30039fb

Sometimes, Android *removes* APIs.  For example, API-23 *removed* the
`android.Manifest.permission.CLEAR_APP_USER_DATA` field.

We still list this field, though:
[`Android.Manifest.Permission.ClearAppUserData` field][0].

>     [Android.Runtime.Register("CLEAR_APP_USER_DATA")]
>     public const string ClearAppUserData;

In dotnet/android@944d3061 we updated `api-merge` to emit
`//*/@#removed-since`.  Consider this snippet from
[`android/src/Mono.Android/Profiles/api-35.xml`][1]:

	<field
	    deprecated="not deprecated" final="true"
	    name="CLEAR_APP_USER_DATA" jni-signature="Ljava/lang/String;"
	    static="true" transient="false" type="java.lang.String" type-generic-aware="java.lang.String"
	    value="&quot;android.permission.CLEAR_APP_USER_DATA&quot;"
	    visibility="public" volatile="false"
	    removed-since="23"
	/>

Modify `generator` to consume this information and emit
`[UnsupportedOSPlatformAttribute ("androidXX.0")]` as needed for API
that has been removed from `Mono.Android`.  This would update
`Android.Manifest.Permission.ClearAppUserData` to be:

	[Android.Runtime.Register("CLEAR_APP_USER_DATA")]
	[System.Runtime.Versioning.UnsupportedOSPlatformAttribute ("android23.0")]
	public const string ClearAppUserData;

[0]: https://learn.microsoft.com/en-us/dotnet/api/android.manifest.permission.clearappuserdata?view=net-android-34.0
[1]: https://github.com/dotnet/android/blob/d012fb811b4bcebe260400f5fc7a0287108336d7/src/Mono.Android/Profiles/api-35.xml

@jonpryor jonpryor merged commit 1cfb4f4 into main Feb 20, 2025
4 checks passed
@jonpryor jonpryor deleted the dev/jpobst/unsupported-os branch February 20, 2025 18:12
jonpryor pushed a commit to dotnet/android that referenced this pull request Feb 21, 2025
Changes: dotnet/java-interop@f30e420...9dea87d

  * dotnet/java-interop@9dea87dc: [Java.Interop] .GetTypeSignature() supports unsigned types (dotnet/java-interop#1312)
  * dotnet/java-interop@1cfb4f4d: [generator] Add support for emitting `[UnsupportedOSPlatform]` (dotnet/java-interop#1307)

Context: #9811

The .NET MAUI template + NativeAOT currently crashes with:

	E AndroidRuntime: net.dot.jni.internal.JavaProxyThrowable: System.InvalidProgramException: InvalidProgram_Specific, IntPtr Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(System.Type, Byte*)
	E AndroidRuntime:    at Internal.Runtime.TypeLoaderExceptionHelper.CreateInvalidProgramException(ExceptionStringID, String) + 0x4c
	E AndroidRuntime:    at Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(Type, Byte*) + 0x18
	E AndroidRuntime:    at Android.Runtime.JNIEnv.TypemapManagedToJava(Type) + 0x104
	E AndroidRuntime:    at Android.Runtime.JNIEnv.GetJniName(Type) + 0x1c
	E AndroidRuntime:    at Android.Runtime.JNIEnv.FindClass(Type) + 0x38
	E AndroidRuntime:    at Android.Runtime.JNIEnv.NewArray(IJavaObject[]) + 0x28
	E AndroidRuntime:    at Android.Runtime.JNIEnv.NewArray[T](T[]) + 0x94
	E AndroidRuntime:    at Android.Graphics.Drawables.LayerDrawable..ctor(Drawable[] layers) + 0xd4
	E AndroidRuntime:    at Microsoft.Maui.Platform.MauiRippleDrawableExtensions.UpdateMauiRippleDrawableBackground(View, Paint, IButtonStroke, Func`1, Func`1, Action) + 0x2ac

This appears to be related to array usage, such as
`LayerDrawable.ctor(Drawable[])` in this example.

I can reproduce the same crash using a
`ColorStateList.ctor(int[][], int[])` in `samples/NativeAOT`:

	E AndroidRuntime: net.dot.jni.internal.JavaProxyThrowable: System.InvalidProgramException: InvalidProgram_Specific, IntPtr Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(System.Type, Byte*)
	E AndroidRuntime:    at Internal.Runtime.TypeLoaderExceptionHelper.CreateInvalidProgramException(ExceptionStringID, String) + 0x4c
	E AndroidRuntime:    at Android.Runtime.JNIEnv.monodroid_typemap_managed_to_java(Type, Byte*) + 0x18
	E AndroidRuntime:    at Android.Runtime.JNIEnv.TypemapManagedToJava(Type) + 0x104
	E AndroidRuntime:    at Android.Runtime.JNIEnv.GetJniName(Type) + 0x1c
	E AndroidRuntime:    at Android.Runtime.JNIEnv.FindClass(Type) + 0x38
	E AndroidRuntime:    at Android.Runtime.JNIEnv.NewArray[T](T[]) + 0xa8
	E AndroidRuntime:    at Android.Content.Res.ColorStateList..ctor(Int32[][], Int32[]) + 0xdc
	E AndroidRuntime:    at NativeAOT.MainActivity.OnCreate(Bundle savedInstanceState) + 0xb8

Update `JNIEnv.FindClass(Type)` to go through `TypeManager` instead
of using `TypemapManagedToJava`.  This avoids the P/Invoke which is
causing the crash (f800c1a).

Note that we can't directly use
`JniRuntime.JniTypeManager.GetTypeSignature()`, as the previous use
of `JavaNativeTypeManager.ToJniName(Type)` would default to using
`java/lang/Object` if there was no typemap entry for `type`.

After this change, the sample works and prints a log message
indicating `ColorStateList` is created successfully:

	D NativeAOT: MainActivity.OnCreate() ColorStateList: ColorStateList{mThemeAttrs=nullmChangingConfigurations=0mStateSpecs=[[0, 1]]mColors=[0, 1]mDefaultColor=0}
@github-actions github-actions bot locked and limited conversation to collaborators Mar 23, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Need to track API removals, mark bindings with [UnsupportedOSPlatform]
2 participants