-
Notifications
You must be signed in to change notification settings - Fork 528
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
[Mono.Android] Bind Android 14 DP 1. #7796
Conversation
d34f285
to
a126260
Compare
Context: dotnet/android#7796 Context: 22d5687 Context: 5a0e37e Imagine the following covariant-return-type -using construct, which is new in API-34 `android.jar`: // Java public abstract class Buffer { public abstract Buffer duplicate (); } public abstract class CharBuffer extends Buffer { public abstract CharBuffer duplicate (); } By default this is bound as: // C# [Register(…)] public abstract partial class Buffer { [Register(…)] public abstract Buffer Duplicate (); } [Register(…)] public abstract partial class CharBuffer : Buffer { [Register(…)] public abstract CharBuffer Duplicate (); } Alas, this results in [error CS0533][0]: error CS0533: 'CharBuffer.Duplicate()' hides inherited abstract member 'Buffer.Duplicate()' C# supports this semantic if we use [`abstract override`][1], similar to [reabstraction of Default Interface Methods][2] in 22d5687: public abstract class CharBuffer : Buffer { public override abstract CharBuffer Duplicate (); } Theoretically, we can tell `generator` how to fix this via the `//attr[@name='managedOverride']` metadata property (5a0e37e): <attr path="/api/package[@name='java.nio']/class[@name='CharBuffer']/method[@name='duplicate']" name="managedOverride">override</attr> However, `//attr[@name='managedOverride']` was not written to support updating`abstract` methods. Fix that oversight so that using `//attr[@name='managedOverride']` can be used to emit `override abstract`: [Register(…)] public abstract partial class CharBuffer : Buffer { [Register(…)] public override abstract CharBuffer Duplicate (); } ~~ Method Invokers ~~ This gets us halfway there, but there is another issue: method invokers for both the class and base class methods are *also* emitted into the `*Invoker` subclass: partial class BufferInvoker : CharBuffer { public override sealed unsafe Buffer Duplicate() {…} // so far so good… } partial class CharBufferInvoker : CharBuffer { [Register ("duplicate", "()Ljava/nio/Buffer;", "")] public override sealed unsafe Buffer Duplicate() {…} [Register ("duplicate", "()Ljava/nio/CharBuffer;", "")] public override sealed unsafe CharBuffer Duplicate() {…} // uh oh } This results in the following error: error CS0111: Type 'CharBufferInvoker' already defines a member called 'Duplicate' with the same parameter types error CS0508: 'CharBufferInvoker.Duplicate()': return type must be 'CharBuffer' to match overridden member 'CharBuffer.Duplicate()' This perhaps(?) could be something `generator` could detect and prevent, but the feasibility and cost is unknown and expected to be high. Since this is a very rare case, we will fix it with metadata, however we have never had metadata to apply to invokers before. We have decided to support `//attr[@name='skipInvokerMethods']` metadata on the `class` that the invoker class would be created for: <attr path="/api/package[@name='java.nio']/class[@name='CharBuffer']" name="skipInvokerMethods">java/nio/Buffer.duplicate()Ljava/nio/Buffer;</attr> The value is a comma, space, and newline-separated list of "JNI signature-like" values consisting of: 1. The simplified JNI name of the declaring class that contains the the invoker method to skip, e.g. `java/nio/Buffer` 2. `.` 3. The Java name of the invoker method to skip, e.g. `duplicate`. 4. The JNI method signature of the method to skip, e.g. `()Ljava/nio/Buffer;` The above `java/nio/Buffer.duplicate()Ljava/nio/Buffer;` value tells `generator` to skip generating the `Buffer Buffer.duplicate ()` invoker method when generating the `CharBufferInvoker` type. Multiple invokers to skip can be specified as a comma or space separated list. [0]: https://learn.microsoft.com/en-us/dotnet/csharp/misc/cs0533 [1]: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#1467-abstract-methods [2]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods#reabstraction
e3efbc9
to
8f94b0c
Compare
@pjcollins We are going to use covariant return types in this binding level, which are not supported by Classic. With your recent work on building fewer API levels for Classic in |
I think adding something like this to Mono.Android.csproj and Mono.Android.Runtime.csproj will work for now: <!-- Do not build classic for API versions above 33 -->
<PropertyGroup Condition=" '$(TargetFramework)' == 'monoandroid10' And '$(AndroidApiLevel)' > '33'">
<BuildDependsOn></BuildDependsOn>
</PropertyGroup> We'll need more changes when we go to make this API level stable, but by then we will likely have pulled out more of the classic build. |
ed1b3d3
to
8b7dac8
Compare
@@ -31,6 +31,7 @@ public sealed class CheckApiCompatibility : Task | |||
{ "v12.0", "v11.0" }, | |||
{ "v12.1", "v12.0" }, | |||
{ "v13.0", "v12.1" }, | |||
{ "v13.0.99", "v13.0" }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this task work in a .NET Android world order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently not! 😁
It appears we only run ApiCompat against the stable API platform on .NET. This is something that will need to be fixed, but will be much easier once Classic has been removed from main
. I propose we prioritize this work for later. I ran it manually locally, so the breakages included in this PR are correct, but CI will not be able to verify them until then.
At the very worst, the PR in ~June that marks API-34 stable will check it with today's ApiCompat.
@@ -58,7 +58,7 @@ variables: | |||
- name: ExcludedNUnitCategories | |||
value: '& cat != DotNetIgnore & cat != HybridAOT & cat != MkBundle & cat != MonoSymbolicate & cat != PackagesConfig & cat != StaticProject & cat != SystemApplication' | |||
- name: DefaultTestSdkPlatforms # Comma-separated SDK Platform(s) to install on test agents (no spaces) | |||
value: 33 | |||
value: 33,UpsideDownCake |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UpsideDownCake is required for tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there are some tests to ensure users can build with our unstable packages.
{ | ||
|
||
#if ANDROID_34 | ||
// This implements an interface method that should be marked as 'default' but isn't. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be useful to link to: https://developer.android.com/reference/java/util/Iterator#remove()
MembersMustExist : Member 'public void Android.Views.PixelCopy.Request(Android.Views.Window, Android.Graphics.Bitmap, Android.Views.PixelCopy.IOnPixelCopyFinishedListener, Android.OS.Handler)' does not exist in the implementation but it does exist in the contract. | ||
MembersMustExist : Member 'public void Android.Views.PixelCopy.Request(Android.Views.Window, Android.Graphics.Rect, Android.Graphics.Bitmap, Android.Views.PixelCopy.IOnPixelCopyFinishedListener, Android.OS.Handler)' does not exist in the implementation but it does exist in the contract. | ||
CannotRemoveAttribute : Attribute 'System.ObsoleteAttribute' exists on 'Dalvik.SystemInterop.DexFile' in the contract but not the implementation. | ||
CannotAddAbstractMembers : Member 'public Java.Nio.ByteBuffer Java.Nio.ByteBuffer.Slice(System.Int32, System.Int32)' is abstract in the implementation but is missing in the contract. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This confuses me; we're using compatVirtualMethod
, which should emit a virtual
method, not an abstract
method, so why is this warning emitted at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a rebase conflict error that I fixed incorrectly. Updated the acceptable-breakages
to the only actual entry.
* main: [Mono.Android] Bind API-UpsideDownCake Developer Preview 1 (dotnet#7796) Bump to dotnet/installer@d109cba3ff 8.0.100-preview.4.23176.5 (dotnet#7921)
* main: (94 commits) [ci] Remove remaining Classic test jobs. (dotnet#7924) Add Nightly Tests for Humanizer [readme] Add aka.ms links for d17.5. (dotnet#7935) [tests] Remove `net472` multitargeting (dotnet#7932) [monodroid] Fix `ld` build error on Nightly Builds. (dotnet#7925) Bump to xamarin/Java.Interop/main@0355acf (dotnet#7931) [tests] Use msftconnecttest.com in QuoteInvalidQuoteUrlsShouldWork (dotnet#7919) [ci] Don't set demands for megapipeline (dotnet#7929) [Mono.Android] Bind API-UpsideDownCake Developer Preview 1 (dotnet#7796) Bump to dotnet/installer@d109cba3ff 8.0.100-preview.4.23176.5 (dotnet#7921) [Xamarin.Android.Build.Tasks] Fix Android Version Code for Release builds (dotnet#7795) Bump to dotnet/installer@27d6769dfb 8.0.100-preview.4.23172.16 (dotnet#7910) [Xamarin.Android.Build.Tasks] Fix native code generation when marshal methods are disabled (dotnet#7899) [ci] Optimize 'APK's .NET' test job overhead. (dotnet#7904) [Mono.Android] delay JNINativeWrapper.get_runtime_types() (dotnet#7913) Bump external/Java.Interop from `73ebad2` to `53bfb4a` (dotnet#7914) [build] remove .NET 6 support (dotnet#7900) [profiled-aot] update `dotnet.aotprofile` for .NET 8 (dotnet#7908) [tests] Add backup ssl sites in case of 429 response. (dotnet#7909) $(AndroidPackVersionSuffix)=preview.4; net8 is 34.0.0-preview.4 (dotnet#7912) ...
Context: dotnet/android#7796 Context: 22d5687 Context: 5a0e37e Imagine the following covariant-return-type -using construct, which is new in API-34 `android.jar`: // Java public abstract class Buffer { public abstract Buffer duplicate (); } public abstract class CharBuffer extends Buffer { public abstract CharBuffer duplicate (); } By default this is bound as: // C# [Register(…)] public abstract partial class Buffer { [Register(…)] public abstract Buffer Duplicate (); } [Register(…)] public abstract partial class CharBuffer : Buffer { [Register(…)] public abstract CharBuffer Duplicate (); } Alas, this results in [error CS0533][0]: error CS0533: 'CharBuffer.Duplicate()' hides inherited abstract member 'Buffer.Duplicate()' C# supports this semantic if we use [`abstract override`][1], similar to [reabstraction of Default Interface Methods][2] in 22d5687: public abstract class CharBuffer : Buffer { public override abstract CharBuffer Duplicate (); } Theoretically, we can tell `generator` how to fix this via the `//attr[@name='managedOverride']` metadata property (5a0e37e): <attr path="/api/package[@name='java.nio']/class[@name='CharBuffer']/method[@name='duplicate']" name="managedOverride">override</attr> However, `//attr[@name='managedOverride']` was not written to support updating`abstract` methods. Fix that oversight so that using `//attr[@name='managedOverride']` can be used to emit `override abstract`: [Register(…)] public abstract partial class CharBuffer : Buffer { [Register(…)] public override abstract CharBuffer Duplicate (); } ~~ Method Invokers ~~ This gets us halfway there, but there is another issue: method invokers for both the class and base class methods are *also* emitted into the `*Invoker` subclass: partial class BufferInvoker : CharBuffer { public override sealed unsafe Buffer Duplicate() {…} // so far so good… } partial class CharBufferInvoker : CharBuffer { [Register ("duplicate", "()Ljava/nio/Buffer;", "")] public override sealed unsafe Buffer Duplicate() {…} [Register ("duplicate", "()Ljava/nio/CharBuffer;", "")] public override sealed unsafe CharBuffer Duplicate() {…} // uh oh } This results in the following error: error CS0111: Type 'CharBufferInvoker' already defines a member called 'Duplicate' with the same parameter types error CS0508: 'CharBufferInvoker.Duplicate()': return type must be 'CharBuffer' to match overridden member 'CharBuffer.Duplicate()' This perhaps(?) could be something `generator` could detect and prevent, but the feasibility and cost is unknown and expected to be high. Since this is a very rare case, we will fix it with metadata, however we have never had metadata to apply to invokers before. We have decided to support `//attr[@name='skipInvokerMethods']` metadata on the `class` that the invoker class would be created for: <attr path="/api/package[@name='java.nio']/class[@name='CharBuffer']" name="skipInvokerMethods">java/nio/Buffer.duplicate()Ljava/nio/Buffer;</attr> The value is a comma, space, and newline-separated list of "JNI signature-like" values consisting of: 1. The simplified JNI name of the declaring class that contains the the invoker method to skip, e.g. `java/nio/Buffer` 2. `.` 3. The Java name of the invoker method to skip, e.g. `duplicate`. 4. The JNI method signature of the method to skip, e.g. `()Ljava/nio/Buffer;` The above `java/nio/Buffer.duplicate()Ljava/nio/Buffer;` value tells `generator` to skip generating the `Buffer Buffer.duplicate ()` invoker method when generating the `CharBufferInvoker` type. Multiple invokers to skip can be specified as a comma or space separated list. [0]: https://learn.microsoft.com/en-us/dotnet/csharp/misc/cs0533 [1]: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#1467-abstract-methods [2]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods#reabstraction (cherry picked from commit 73ebad2)
Context: dotnet/android#7796 Context: 22d5687 Context: 5a0e37e Imagine the following covariant-return-type -using construct, which is new in API-34 `android.jar`: // Java public abstract class Buffer { public abstract Buffer duplicate (); } public abstract class CharBuffer extends Buffer { public abstract CharBuffer duplicate (); } By default this is bound as: // C# [Register(…)] public abstract partial class Buffer { [Register(…)] public abstract Buffer Duplicate (); } [Register(…)] public abstract partial class CharBuffer : Buffer { [Register(…)] public abstract CharBuffer Duplicate (); } Alas, this results in [error CS0533][0]: error CS0533: 'CharBuffer.Duplicate()' hides inherited abstract member 'Buffer.Duplicate()' C# supports this semantic if we use [`abstract override`][1], similar to [reabstraction of Default Interface Methods][2] in 22d5687: public abstract class CharBuffer : Buffer { public override abstract CharBuffer Duplicate (); } Theoretically, we can tell `generator` how to fix this via the `//attr[@name='managedOverride']` metadata property (5a0e37e): <attr path="/api/package[@name='java.nio']/class[@name='CharBuffer']/method[@name='duplicate']" name="managedOverride">override</attr> However, `//attr[@name='managedOverride']` was not written to support updating`abstract` methods. Fix that oversight so that using `//attr[@name='managedOverride']` can be used to emit `override abstract`: [Register(…)] public abstract partial class CharBuffer : Buffer { [Register(…)] public override abstract CharBuffer Duplicate (); } ~~ Method Invokers ~~ This gets us halfway there, but there is another issue: method invokers for both the class and base class methods are *also* emitted into the `*Invoker` subclass: partial class BufferInvoker : CharBuffer { public override sealed unsafe Buffer Duplicate() {…} // so far so good… } partial class CharBufferInvoker : CharBuffer { [Register ("duplicate", "()Ljava/nio/Buffer;", "")] public override sealed unsafe Buffer Duplicate() {…} [Register ("duplicate", "()Ljava/nio/CharBuffer;", "")] public override sealed unsafe CharBuffer Duplicate() {…} // uh oh } This results in the following error: error CS0111: Type 'CharBufferInvoker' already defines a member called 'Duplicate' with the same parameter types error CS0508: 'CharBufferInvoker.Duplicate()': return type must be 'CharBuffer' to match overridden member 'CharBuffer.Duplicate()' This perhaps(?) could be something `generator` could detect and prevent, but the feasibility and cost is unknown and expected to be high. Since this is a very rare case, we will fix it with metadata, however we have never had metadata to apply to invokers before. We have decided to support `//attr[@name='skipInvokerMethods']` metadata on the `class` that the invoker class would be created for: <attr path="/api/package[@name='java.nio']/class[@name='CharBuffer']" name="skipInvokerMethods">java/nio/Buffer.duplicate()Ljava/nio/Buffer;</attr> The value is a comma, space, and newline-separated list of "JNI signature-like" values consisting of: 1. The simplified JNI name of the declaring class that contains the the invoker method to skip, e.g. `java/nio/Buffer` 2. `.` 3. The Java name of the invoker method to skip, e.g. `duplicate`. 4. The JNI method signature of the method to skip, e.g. `()Ljava/nio/Buffer;` The above `java/nio/Buffer.duplicate()Ljava/nio/Buffer;` value tells `generator` to skip generating the `Buffer Buffer.duplicate ()` invoker method when generating the `CharBufferInvoker` type. Multiple invokers to skip can be specified as a comma or space separated list. [0]: https://learn.microsoft.com/en-us/dotnet/csharp/misc/cs0533 [1]: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#1467-abstract-methods [2]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods#reabstraction (cherry picked from commit 73ebad2)
Context: https://developer.android.com/about/versions/14
Context: https://android-developers.googleblog.com/2023/02/first-developer-preview-android14.html
Android 14 Developer Preview 1 has been released. The Android 14
Developer Preview Program Overview Timeline and updates section
suggests the following timeline:
Acceptable Breakages
Dalvik.SystemInterop.DexFile
was un-deprecated. A new nested class was added to it. (Documentation)