diff --git a/.github/instructions/java-interop.instructions.md b/.github/instructions/java-interop.instructions.md index d3203d115b5..0dca712ffd9 100644 --- a/.github/instructions/java-interop.instructions.md +++ b/.github/instructions/java-interop.instructions.md @@ -42,7 +42,7 @@ Additional context for code under `external/Java.Interop/`. This complements the - **`generator/`** — primary tool for generating C# bindings from Java API descriptions. - **`class-parse/`** — parses Java `.class` files and generates API descriptions. - **`java-source-utils/`** — utilities for processing Java source code. -- **`jcw-gen/`** — generates Java Callable Wrapper classes. +- Application Java Callable Wrappers are generated by `src/Microsoft.Android.Sdk.TrimmableTypeMap/`. - **`param-name-importer/`** — imports parameter names from Java source. ### Supporting libraries diff --git a/.github/skills/tests/references/test-catalog.md b/.github/skills/tests/references/test-catalog.md index dbcd13b2bd4..c5ce1795c12 100644 --- a/.github/skills/tests/references/test-catalog.md +++ b/.github/skills/tests/references/test-catalog.md @@ -27,7 +27,7 @@ These tests can be run immediately with `dotnet test` on the `.csproj`, even if | **java source** | `external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/Java.Interop.Tools.JavaSource-Tests.csproj -v minimal` | | **maven** | `external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/Java.Interop.Tools.Maven-Tests.csproj -v minimal` | | **api xml adjuster** | `external/Java.Interop/tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests/` | `dotnet test external/Java.Interop/tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests.csproj -v minimal` | -| **java callable wrappers** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -v minimal` | +| **Java peer naming/scanning** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -v minimal` | | **java type system** | `external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/Java.Interop.Tools.JavaTypeSystem-Tests.csproj -v minimal` | | **expressions** | `external/Java.Interop/tests/Java.Interop.Tools.Expressions-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Expressions-Tests/Java.Interop.Tools.Expressions-Tests.csproj -v minimal` ⚠️ Requires `javac` | | **generator tools** | `external/Java.Interop/tests/Java.Interop.Tools.Generator-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Generator-Tests/Java.Interop.Tools.Generator-Tests.csproj -v minimal` | @@ -198,7 +198,7 @@ cause, or stack-trace extraction fails, while borrowed references remain valid. | Test Area | Assembly / Project | Notes | |-----------|--------------------|-------| | **generator** | `external/Java.Interop/tests/generator-Tests/` | Binding generator tests | -| **java callable wrappers** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | JCW generation | +| **Java peer naming/scanning** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | Naming, scanning, and type-name mapping; current JCW generation is covered by the trimmable type map suites | | **java type system** | `external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/` | Java type system tooling | | **java source** | `external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/` | Java source generation | | **maven** | `external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/` | Maven integration | diff --git a/Documentation/docs-mobile/messages/index.md b/Documentation/docs-mobile/messages/index.md index 58ab09fbbbd..8ca55108d68 100644 --- a/Documentation/docs-mobile/messages/index.md +++ b/Documentation/docs-mobile/messages/index.md @@ -188,7 +188,6 @@ Either change the value in the AndroidManifest.xml to match the $(SupportedOSPla + [XA4214](xa4214.md): The managed type \`Library1.Class1\` exists in multiple assemblies: Library1, Library2. Please refactor the managed type names in these assemblies so that they are not identical. + [XA4215](xa4215.md): The Java type \`com.contoso.library1.Class1\` is generated by more than one managed type. Please change the \[Register\] attribute so that the same Java type is not emitted. + [XA4216](xa4216.md): The deployment target '19' is not supported (the minimum is '24'). Please increase the $(SupportedOSPlatformVersion) property value in your project file. -+ XA4217: Cannot override Kotlin-generated method '{method}' because it is not a valid Java method name. This method can only be overridden from Kotlin. + [XA4217](xa4217.md): Architecture '{arch}' has Java types which have no counterparts in template architecture '{templateArch}': {types} + [XA4218](xa4218.md): Unable to find //manifest/application/uses-library at path: {path} + XA4219: Cannot find binding generator for language {language} or {defaultLanguage}. diff --git a/Documentation/guides/internals/JavaJNI_Interop.md b/Documentation/guides/internals/JavaJNI_Interop.md index 6863195103e..7abbc92ec34 100644 --- a/Documentation/guides/internals/JavaJNI_Interop.md +++ b/Documentation/guides/internals/JavaJNI_Interop.md @@ -82,6 +82,27 @@ The main outputs are: The app build also generates needed **platform JCWs** from framework inputs alongside user JCWs: for example, the [build tests](../../../src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs) check for `typemap/java/android/app/ActivityTracker.java` and its `Runtime.registerNatives` call. The [reference pack](../../../build-tools/create-packs/Microsoft.Android.Ref.proj) no longer ships prebuilt `mono.android.jar` or `mono.android.dex`. The handwritten Java runtime support instead comes from `java_runtime_trimmable.jar`, selected by [`_CollectRuntimeJarFilenames`](../../../src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets); this is not a jar of pre-generated platform JCWs. `ApplicationRegistration.java` is generated separately during the app build. +The .NET 12 cleanup retires the standalone `jcw-gen` tool and the legacy public +JCW emitter in `Java.Interop.Tools.JavaCallableWrappers`: its `CallableWrapper*` +model/writers, reader/writer options, `JavaPeerStyle`, method classifier, and +Cecil/XML import/export adapters. That emitter produced `__md_methods`, +`Runtime.register`, and `TypeManager.Activate` references whose runtime +implementations had already been removed. The assembly's shared naming, +scanning, hashing, and type-name mapping utilities remain available, as does +the supported XAJavaInterop1 **C# binding** generator. Application JCWs are +generated exclusively by the trimmable pipeline. + +The SDK likewise ships only `java_runtime_trimmable.jar` and its DEX companion. +The unused `java_runtime`, `java_runtime_fastdev`, `java_runtime_clr`, and +`java_runtime_fastdev_clr` artifact pairs, Java `DebugRuntime`/`BuildConfig` +classes, and old environment placeholder are retired. `Runtime.init`, +`createNewContext`, `createNewContextWithData`, `switchToContext`, +`destroyContexts`, `MonoPackageManager.setContext`, and `getDependencies` +are no longer supplied. These are intentional tooling/bootstrap compatibility +removals; custom build tools and Java sources must use the retained runtime +artifact and current startup path. `Runtime.initInternal`, `registerNatives`, +GC peers, and `ApplicationRegistration.Context` remain live. + Each per-assembly TypeMap contains assembly-level mapping attributes: a key such as `my/app/MainActivity`, a proxy type, and, for a trimmable mapping, the managed target type. The root references the per-assembly maps via `TypeMapAssemblyTargetAttribute`. The emitter writes **IL and metadata**, not `.cs` files; the C# in the sections below is an explanatory translation of emitted code, not a file that a developer should edit. See [`TypeMapAssemblyGenerator`](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyGenerator.cs), [`TypeMapAssemblyEmitter.EmitTypeMapAttribute`](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyEmitter.cs), and the [build-pipeline guide](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/README.md). For the example Activity, think of a mapping like this **conceptual C#**: @@ -122,6 +143,15 @@ When JNI returns an object or Java passes one into managed code, [`TrimmableType The generated Java `onCreate` calls its native `n_OnCreate_Landroid_os_Bundle_`; constructors similarly declare generated `nctor_*` native callbacks, and instantiate/activate the managed peer when appropriate. The class's static block calls `mono.android.Runtime.registerNatives (MainActivity.class)` when the class is first initialized. This is **per Java class**. Application and instrumentation JCWs instead use a guarded `__md_registerNatives()` helper called from their generated wrappers: registration in their static initializer can be too early in startup. The declaration of `registerNatives(Class)` in [`mono.android.Runtime`](../../../src/java-runtime/java/mono/android/Runtime.java) is handwritten Java; individual JCWs and their registration calls are generated. +Abstract JCWs retain their Java constructors and `super(...)` calls for +subclasses, but do not declare or call native constructor bridges. Deferred +Application/Instrumentation hierarchies also omit those bridges and their +unused managed UCO constructor registrations; managed `CreateInstance` +activation remains available. A deferred class with no non-constructor +callbacks needs no lazy registration helper or flag. Callback-bearing +deferred classes still use the helper, and nonempty native registration, +concrete constructor guards, GC hooks, and startup registration remain intact. + There is no concatenated `__md_methods` string and no `Runtime.register("managed.Type, Assembly", ...)` registration in this path. The old JNI native-symbol mangling rules (`Java_package_Class_method...`) matter for symbol-lookup-based JNI code, but generated app JCW callbacks here are associated with their Java declarations through [`RegisterNatives`](https://docs.oracle.com/en/java/javase/17/docs/specs/jni/functions.html#registernatives): the Java method **name** and **signature** must match; no `Java_...` export is required for each method. ### Runtime startup and registration handshake diff --git a/Microsoft.Android.slnx b/Microsoft.Android.slnx index e84e48445a9..d29f46a7f87 100644 --- a/Microsoft.Android.slnx +++ b/Microsoft.Android.slnx @@ -71,7 +71,6 @@ - diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets index cc91f283684..ea3fdb56c25 100644 --- a/build-tools/installers/create-installers.targets +++ b/build-tools/installers/create-installers.targets @@ -58,16 +58,8 @@ <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)NuGet.Versioning.dll" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)r8.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)bundletool.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_trimmable.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime.dex" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev.dex" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_trimmable.dex" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_clr.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_clr.jar" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_clr.dex" /> - <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_clr.dex" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)manifestmerger.jar" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)proguard-android-optimize.txt" /> <_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)proguard-android.txt" /> diff --git a/build-tools/scripts/Jar.targets b/build-tools/scripts/Jar.targets index 26953d7344e..eff4dbac267 100644 --- a/build-tools/scripts/Jar.targets +++ b/build-tools/scripts/Jar.targets @@ -9,14 +9,14 @@ - <_RuntimeJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java_runtime.jar - <_RuntimeJar_System Condition=" '$(_XamarinAndroidMSBuildDirectory)' != '' ">$(_XamarinAndroidMSBuildDirectory)\java_runtime.jar + <_RuntimeJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java_runtime_trimmable.jar + <_RuntimeJar_System Condition=" '$(_XamarinAndroidMSBuildDirectory)' != '' ">$(_XamarinAndroidMSBuildDirectory)\java_runtime_trimmable.jar <_JavaRuntimeJarPath Condition=" Exists($(_RuntimeJar_InTree)) ">$(_RuntimeJar_InTree) <_JavaRuntimeJarPath Condition=" '$(_JavaRuntimeJarPath)' == '' and Exists($(_RuntimeJar_System)) ">$(_RuntimeJar_System) - diff --git a/external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs b/external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs index 1dbc8440e70..1285bfe8133 100644 --- a/external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs +++ b/external/Java.Interop/src/Java.Interop.Localization/Resources.Designer.cs @@ -447,42 +447,6 @@ public static string Generator_BG8C03 { } } - /// - /// Looks up a localized string similar to Cannot generate Java wrapper for type '{0}'. Only 'class' types are supported.. - /// - public static string JavaCallableWrappers_XA4200 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4200", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot determine JNI name for type '{0}'.. - /// - public static string JavaCallableWrappers_XA4201 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4201", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The 'Name' property must be a fully qualified type like 'com.example.MyClass' and no package was found for '{0}'.. - /// - public static string JavaCallableWrappers_XA4203 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4203", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to resolve interface type '{0}'. Are you missing an assembly reference?. - /// - public static string JavaCallableWrappers_XA4204 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4204", resourceCulture); - } - } - /// /// Looks up a localized string similar to [ExportField] can only be used on methods with 0 parameters.. /// @@ -519,15 +483,6 @@ public static string JavaCallableWrappers_XA4208 { } } - /// - /// Looks up a localized string similar to Cannot override Kotlin-generated method '{0}' because it is not a valid Java method name. This method can only be overridden from Kotlin.. - /// - public static string JavaCallableWrappers_XA4217 { - get { - return ResourceManager.GetString("JavaCallableWrappers_XA4217", resourceCulture); - } - } - /// /// Looks up a localized string similar to Unable to preload reference '{0}'.. /// diff --git a/external/Java.Interop/src/Java.Interop.Localization/Resources.resx b/external/Java.Interop/src/Java.Interop.Localization/Resources.resx index 18a5041ecad..29fa2c0e46a 100644 --- a/external/Java.Interop/src/Java.Interop.Localization/Resources.resx +++ b/external/Java.Interop/src/Java.Interop.Localization/Resources.resx @@ -316,27 +316,6 @@ The following terms should not be translated: Metadata.xml, path. JNI signature override '{0}' is invalid or does not match the parameter count for member '{1}'. {0} - JNI method signature. {1} - .NET member. - - Cannot generate Java wrapper for type '{0}'. Only 'class' types are supported. - {0} - Java type. -The following terms should not be translated: -class. - - - Cannot determine JNI name for type '{0}'. - {0} - Java type. -The following terms should not be translated: JNI. - - - The 'Name' property must be a fully qualified type like 'com.example.MyClass' and no package was found for '{0}'. - {0} - Java type. -The following terms should not be translated: -Name, com.example.MyClass. - - - Unable to resolve interface type '{0}'. Are you missing an assembly reference? - {0} - Java interface. - [ExportField] can only be used on methods with 0 parameters. The following terms should not be translated: [ExportField]. @@ -353,10 +332,6 @@ Name, com.example.MyClass. [ExportField] cannot be used on a method returning 'void'. The following terms should not be translated: [ExportField], void. - - Cannot override Kotlin-generated method '{0}' because it is not a valid Java method name. This method can only be overridden from Kotlin. - {0} - Kotlin method name. - Unable to preload reference '{0}'. {0} - assembly path diff --git a/external/Java.Interop/src/Java.Interop.Tools.Diagnostics/Java.Interop.Tools.Diagnostics/Diagnostic.cs b/external/Java.Interop/src/Java.Interop.Tools.Diagnostics/Java.Interop.Tools.Diagnostics/Diagnostic.cs index a260ba98f42..0f5efbb563c 100644 --- a/external/Java.Interop/src/Java.Interop.Tools.Diagnostics/Java.Interop.Tools.Diagnostics/Diagnostic.cs +++ b/external/Java.Interop/src/Java.Interop.Tools.Diagnostics/Java.Interop.Tools.Diagnostics/Diagnostic.cs @@ -91,10 +91,6 @@ namespace Java.Interop.Tools.Diagnostics { // XA4110 The registrar cannot marshal the out parameter of type `{0}` in signature for method `{1}`. // XA4111 The registrar cannot build a signature for type `{0}' in method `{1}`. // XA42xx ACW generation - // XA4200 Can only generate ACW's for `claas` types. - // XA4201 Unable to determine JNI name for type {0}. - // XA4203 The specified type name must be fully qualified. - // XA4204 Unable to resolve interface type '{0}'. Are you missing an assembly reference? // XA4205 [ExportField] can only be used on methods with 0 parameters. // XA4206 [Export] cannot be used on a generic type. // XA4207 [ExportField] cannot be used on a generic type. @@ -103,7 +99,6 @@ namespace Java.Interop.Tools.Diagnostics { // XA4210 "You need to add a reference to Mono.Android.Export.dll when you use ExportAttribute or ExportFieldAttribute." // XA4211 AndroidManifest.xml //uses-sdk/@android:targetSdkVersion '{0}' is less than $(TargetFrameworkVersion) '{1}'. Using API-{1} for ACW compilation. // XA4212 Type `{0}` implements `Android.Runtime.IJavaObject` but does not inherit `Java.Lang.Object` or `Java.Lang.Throwable`. This is not supported. - // XA4217 Cannot override Kotlin-generated method '{0}' because it is not a valid Java method name. This method can only be overridden from Kotlin." // XA5xxx GCC and toolchain // XA32xx .apk generation // XA4300 Unsupported $(AndroidSupportedAbis) value '{0}'; ignoring. @@ -195,4 +190,3 @@ public static Action CreateConsoleLogger () } } } - diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Extensions/XmlExtensions.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Extensions/XmlExtensions.cs deleted file mode 100644 index b70f24aae8e..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Extensions/XmlExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Xml; -using System.Xml.Linq; - -namespace Java.Interop.Tools.JavaCallableWrappers.Extensions; - -static class XmlExtensions -{ - public static T GetAttributeOrDefault (this XElement xml, string name, T defaultValue) - { - var value = xml.Attribute (name)?.Value; - - if (string.IsNullOrWhiteSpace (value)) - return defaultValue; - - return (T) Convert.ChangeType (value, typeof (T)); - } - - public static string GetRequiredAttribute (this XElement xml, string name) - { - var value = xml.Attribute (name)?.Value; - - if (string.IsNullOrWhiteSpace (value)) - throw new InvalidOperationException ($"Missing required attribute '{name}' within element `{xml.ToString()}`."); - - return value!; // NRT - Guarded by IsNullOrWhiteSpace check above - } - - public static void WriteAttributeStringIfNotNull (this XmlWriter xml, string name, string? value) - { - if (value is not null) - xml.WriteAttributeString (name, value); - } - - public static void WriteAttributeStringIfNotFalse (this XmlWriter xml, string name, bool value) - { - // If value is false, don't write the attribute, we'll default to false on import - if (value) - xml.WriteAttributeString (name, value.ToString ()); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/CecilImporter.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/CecilImporter.cs deleted file mode 100644 index 75b14dd618e..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/CecilImporter.cs +++ /dev/null @@ -1,573 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Android.Runtime; -using Java.Interop.Tools.Cecil; -using Java.Interop.Tools.Diagnostics; -using Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; -using Java.Interop.Tools.JavaCallableWrappers.Utilities; -using Java.Interop.Tools.TypeNameMappings; -using Mono.Cecil; - -namespace Java.Interop.Tools.JavaCallableWrappers.Adapters; - -public class CecilImporter -{ - // Don't expose internal "outerType" parameter to the public API - public static CallableWrapperType CreateType (TypeDefinition type, IMetadataResolver resolver, CallableWrapperReaderOptions? options = null) - => CreateType (type, resolver, options, null); - - static CallableWrapperType CreateType (TypeDefinition type, IMetadataResolver resolver, CallableWrapperReaderOptions? options = null, string? outerType = null) - { - if (type.IsEnum || type.IsInterface || type.IsValueType) - Diagnostic.Error (4200, CecilExtensions.LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4200, type.FullName); - - var jniName = JavaNativeTypeManager.ToJniName (type, resolver); - - if (jniName is null) - Diagnostic.Error (4201, CecilExtensions.LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4201, type.FullName); - - if (outerType != null && !string.IsNullOrEmpty (outerType)) { - jniName = jniName.Substring (outerType.Length + 1); - ExtractJavaNames (outerType, out var p, out outerType); - } - - ExtractJavaNames (jniName, out var package, out var name); - - options ??= new CallableWrapperReaderOptions (); - - if (string.IsNullOrEmpty (package) && - (type.IsSubclassOf ("Android.App.Activity", resolver) || - type.IsSubclassOf ("Android.App.Application", resolver) || - type.IsSubclassOf ("Android.App.Service", resolver) || - type.IsSubclassOf ("Android.Content.BroadcastReceiver", resolver) || - type.IsSubclassOf ("Android.Content.ContentProvider", resolver))) - Diagnostic.Error (4203, CecilExtensions.LookupSource (type), Localization.Resources.JavaCallableWrappers_XA4203, jniName); - - var cwt = new CallableWrapperType (name, package, type.GetPartialAssemblyQualifiedName (resolver)) { - IsApplication = JavaNativeTypeManager.IsApplication (type, resolver), - IsInstrumentation = JavaNativeTypeManager.IsInstrumentation (type, resolver), - IsAbstract = type.IsAbstract, - ApplicationJavaClass = options.DefaultApplicationJavaClass, - GenerateOnCreateOverrides = options.DefaultGenerateOnCreateOverrides, - MonoRuntimeInitialization = options.DefaultMonoRuntimeInitialization, - }; - - // Type annotations - cwt.Annotations.AddRange (CreateAnnotations (type, resolver)); - - // Extends - cwt.ExtendsType = GetJavaTypeName (type.BaseType, resolver); - - // Implemented interfaces - var interfaces = type.Interfaces - .Select (iface => resolver.Resolve (iface.InterfaceType)) - .Where (iface => iface is not null && CecilExtensions.GetTypeRegistrationAttributes (iface).Any ()) - .ToList (); - var addedInterfaces = new HashSet (); - foreach (var iface in interfaces) { - if (interfaces.Any (other => iface.FullName != other.FullName && iface.IsAssignableFrom (other, resolver))) - continue; - - var javaTypeName = GetJavaTypeName (iface, resolver); - if (addedInterfaces.Add (javaTypeName)) - cwt.ImplementedInterfaces.Add (javaTypeName); - } - - // Application constructor - if (CreateApplicationConstructor (cwt.Name, type, resolver) is CallableWrapperApplicationConstructor app_ctor) - cwt.ApplicationConstructor = app_ctor; - - // Methods - foreach (var minfo in type.Methods.Where (m => !m.IsConstructor)) { - var baseRegisteredMethod = CecilExtensions.GetBaseRegisteredMethod (minfo, resolver); - - if (baseRegisteredMethod is not null) - AddMethod (cwt, type, baseRegisteredMethod, minfo, options.MethodClassifier, resolver); - else if (minfo.AnyCustomAttributes ("Java.Interop.JavaCallableAttribute")) { - AddMethod (cwt, type, null, minfo, options.MethodClassifier, resolver); - cwt.HasExport = true; - } else if (minfo.AnyCustomAttributes ("Java.Interop.JavaCallableConstructorAttribute")) { - AddMethod (cwt, type, null, minfo, options.MethodClassifier, resolver); - cwt.HasExport = true; - } else if (minfo.AnyCustomAttributes (typeof (ExportFieldAttribute))) { - AddMethod (cwt, type, null, minfo, options.MethodClassifier, resolver); - cwt.HasExport = true; - } else if (minfo.AnyCustomAttributes (typeof (ExportAttribute))) { - AddMethod (cwt, type, null, minfo, options.MethodClassifier, resolver); - cwt.HasExport = true; - } - } - - // Methods from interfaces - foreach (InterfaceImplementation ifaceInfo in type.Interfaces) { - var typeReference = ifaceInfo.InterfaceType; - var typeDefinition = resolver.Resolve (typeReference); - - if (typeDefinition is null) { - Diagnostic.Error (4204, - CecilExtensions.LookupSource (type), - Localization.Resources.JavaCallableWrappers_XA4204, - typeReference.FullName); - continue; - } - - if (!CecilExtensions.GetTypeRegistrationAttributes (typeDefinition).Any ()) - continue; - - foreach (MethodDefinition imethod in typeDefinition.Methods) { - if (imethod.IsStatic) - continue; - - AddMethod (cwt, type, imethod, imethod, options.MethodClassifier, resolver); - } - } - - // Constructors - var ctorTypes = new List () { - type, - }; - - foreach (var bt in type.GetBaseTypes (resolver)) { - ctorTypes.Add (bt); - var rattr = CecilExtensions.GetTypeRegistrationAttributes (bt).FirstOrDefault (); - - if (rattr != null && rattr.DoNotGenerateAcw) - break; - } - - ctorTypes.Reverse (); - - var curCtors = new List (); - - foreach (var minfo in type.Methods) { - if (minfo.IsConstructor && minfo.AnyCustomAttributes (typeof (ExportAttribute))) { - if (minfo.IsStatic) { - // Diagnostic.Warning (log, "ExportAttribute does not work on static constructor"); - } else { - if (CreateConstructor (cwt, minfo, ctorTypes [0], type, outerType, null, curCtors, false, true, resolver) is CallableWrapperConstructor c) - cwt.Constructors.Add (c); - - cwt.HasExport = true; - } - } - } - - AddConstructors (cwt, ctorTypes [0], type, outerType, null, curCtors, true, resolver); - - for (var i = 1; i < ctorTypes.Count; ++i) { - var baseCtors = curCtors; - curCtors = new List (); - AddConstructors (cwt, ctorTypes [i], type, outerType, baseCtors, curCtors, false, resolver); - } - - AddNestedTypes (cwt, type, resolver, options); - - return cwt; - } - - static CallableWrapperField CreateField (MethodDefinition method, string fieldName, IMetadataResolver resolver) - { - var visibility = GetJavaAccess (method.Attributes & MethodAttributes.MemberAccessMask); - var type_name = JavaNativeTypeManager.ReturnTypeFromSignature (JavaNativeTypeManager.GetJniSignature (method, resolver))?.Type - ?? throw new ArgumentException ($"Could not get JNI signature for method `{method.Name}`", nameof (method)); - - var field = new CallableWrapperField (fieldName, type_name, visibility, method.Name) { - IsStatic = method.IsStatic, - }; - - field.Annotations.AddRange (CreateAnnotations (method, resolver)); - - return field; - } - - // Constructor with [Register] attribute - static CallableWrapperConstructor CreateConstructor (MethodDefinition methodDefinition, CallableWrapperType type, RegisterAttribute register, string? managedParameters, string? outerType, IMetadataResolver cache, bool shouldBeDynamicallyRegistered = true) - { - var method = CreateConstructor (methodDefinition.Name, type, register.Signature, register.Connector, managedParameters, outerType, null); - - method.Annotations.AddRange (CreateAnnotations (methodDefinition, cache)); - method.IsDynamicallyRegistered = shouldBeDynamicallyRegistered; - - return method; - } - - // Constructor with [Export] attribute - static CallableWrapperConstructor CreateConstructor (MethodDefinition methodDefinition, CallableWrapperType type, ExportAttribute export, string? managedParameters, IMetadataResolver resolver) - { - var method = CreateConstructor (methodDefinition.Name, type, JavaNativeTypeManager.GetJniSignature (methodDefinition, resolver), "__export__", null, null, export.SuperArgumentsString); - - method.IsExport = true; - method.IsStatic = methodDefinition.IsStatic; - method.JavaAccess = GetJavaAccess (methodDefinition.Attributes & MethodAttributes.MemberAccessMask); - method.ThrownTypeNames = export.ThrownNames; - method.JavaNameOverride = export.Name; - method.ManagedParameters = managedParameters; - method.Annotations.AddRange (CreateAnnotations (methodDefinition, resolver)); - - return method; - } - - // Common constructor creation code - static CallableWrapperConstructor CreateConstructor (string name, CallableWrapperType type, string? signature, string? connector, string? managedParameters, string? outerType, string? superCall) - { - signature = signature ?? throw new ArgumentNullException ("`connector` cannot be null.", nameof (connector)); - var method_name = "n_" + name + ":" + signature + ":" + connector; - - var method = new CallableWrapperConstructor (type, name, method_name, signature); - - PopulateMethod (method, signature, managedParameters, outerType, superCall); - - method.Name = type.Name; - - return method; - } - - // Method with a [Register] attribute - static CallableWrapperMethod CreateMethod (MethodDefinition methodDefinition, CallableWrapperType declaringType, RegisterAttribute register, string? managedParameters, string? outerType, IMetadataResolver resolver, bool shouldBeDynamicallyRegistered = true) - { - var method = CreateMethod (register.Name, declaringType, register.Signature, register.Connector, managedParameters, outerType, null); - - method.Annotations.AddRange (CreateAnnotations (methodDefinition, resolver)); - method.IsDynamicallyRegistered = shouldBeDynamicallyRegistered; - - return method; - } - - // Method with an [Export] attribute - static CallableWrapperMethod CreateMethod (MethodDefinition methodDefinition, CallableWrapperType declaringType, ExportAttribute export, string? managedParameters, IMetadataResolver resolver) - { - var method = CreateMethod (methodDefinition.Name, declaringType, JavaNativeTypeManager.GetJniSignature (methodDefinition, resolver), "__export__", null, null, export.SuperArgumentsString); - - method.IsExport = true; - method.IsStatic = methodDefinition.IsStatic; - method.JavaAccess = GetJavaAccess (methodDefinition.Attributes & MethodAttributes.MemberAccessMask); - method.ThrownTypeNames = export.ThrownNames; - method.JavaNameOverride = export.Name; - method.ManagedParameters = managedParameters; - method.Annotations.AddRange (CreateAnnotations (methodDefinition, resolver)); - - return method; - } - - // Method with an [ExportField] attribute - static CallableWrapperMethod CreateMethod (MethodDefinition methodDefinition, CallableWrapperType declaringType, IMetadataResolver resolver) - { - var method = CreateMethod (methodDefinition.Name, declaringType, JavaNativeTypeManager.GetJniSignature (methodDefinition, resolver), "__export__", null, null, null); - - if (methodDefinition.HasParameters) - Diagnostic.Error (4205, CecilExtensions.LookupSource (methodDefinition), Localization.Resources.JavaCallableWrappers_XA4205); - if (methodDefinition.ReturnType.MetadataType == MetadataType.Void) - Diagnostic.Error (4208, CecilExtensions.LookupSource (methodDefinition), Localization.Resources.JavaCallableWrappers_XA4208); - - method.IsExport = true; - method.IsStatic = methodDefinition.IsStatic; - method.JavaAccess = GetJavaAccess (methodDefinition.Attributes & MethodAttributes.MemberAccessMask); - - // Annotations are processed within CallableWrapperField, not the initializer method. So we don't generate them here. - - return method; - } - - // Common method creation code - static CallableWrapperMethod CreateMethod (string name, CallableWrapperType declaringType, string? signature, string? connector, string? managedParameters, string? outerType, string? superCall) - { - signature = signature ?? throw new ArgumentNullException ("`connector` cannot be null.", nameof (connector)); - var method_name = "n_" + name + ":" + signature + ":" + connector?.Replace ('/', '+'); - - var method = new CallableWrapperMethod (declaringType, name, method_name, signature); - - PopulateMethod (method, signature, managedParameters, outerType, superCall); - - return method; - } - - // This is done this way to allow sharing between CallableWrapperMethod and CallableWrapperConstructor - static void PopulateMethod (CallableWrapperMethod method, string signature, string? managedParameters, string? outerType, string? superCall) - { - method.ManagedParameters = managedParameters; - - var jnisig = signature; - var closer = jnisig.IndexOf (')'); - var ret = jnisig.Substring (closer + 1); - - method.Retval = JavaNativeTypeManager.Parse (ret)?.Type; - - var jniparms = jnisig.Substring (1, closer - 1); - - if (string.IsNullOrEmpty (jniparms) && string.IsNullOrEmpty (superCall)) - return; - - var parms = new StringBuilder (); - var scall = new StringBuilder (); - var acall = new StringBuilder (); - var first = true; - var i = 0; - - foreach (var jti in JavaNativeTypeManager.FromSignature (jniparms)) { - if (outerType != null) { - acall.Append (outerType).Append (".this"); - outerType = null; - continue; - } - - var parmType = jti.Type; - - if (!first) { - parms.Append (", "); - scall.Append (", "); - acall.Append (", "); - } - - first = false; - parms.Append (parmType).Append (" p").Append (i); - scall.Append ("p").Append (i); - acall.Append ("p").Append (i); - ++i; - } - - method.Params = parms.ToString (); - method.SuperCall = superCall ?? scall.ToString (); - method.ActivateCall = acall.ToString (); - } - - static void AddConstructors (CallableWrapperType declaringType, TypeDefinition type, TypeDefinition rootType, string? outerType, List? baseCtors, List curCtors, bool onlyRegisteredOrExportedCtors, IMetadataResolver cache) - { - foreach (var ctor in type.Methods) - if (ctor.IsConstructor && !ctor.IsStatic && !ctor.AnyCustomAttributes (typeof (ExportAttribute))) - if (CreateConstructor (declaringType, ctor, type, rootType, outerType, baseCtors, curCtors, onlyRegisteredOrExportedCtors, false, cache) is CallableWrapperConstructor c) - declaringType.Constructors.Add (c); - } - - static CallableWrapperConstructor? CreateConstructor (CallableWrapperType declaringType, MethodDefinition ctor, TypeDefinition type, TypeDefinition rootType, string? outerType, List? baseCtors, List curCtors, bool onlyRegisteredOrExportedCtors, bool skipParameterCheck, IMetadataResolver cache) - { - // We create a parameter-less constructor for the application class, so don't use the imported one - if (!ctor.HasParameters && JavaNativeTypeManager.IsApplication (rootType, cache)) - return null; - - var managedParameters = GetManagedParameters (ctor, outerType, type, cache); - - if (!skipParameterCheck && (managedParameters == null || declaringType.Constructors.Any (c => c.ManagedParameters == managedParameters))) - return null; - - // Constructor with [Export] attribute - var eattr = CecilExtensions.GetExportAttributes (ctor, cache).FirstOrDefault (); - - if (eattr != null) { - if (!string.IsNullOrEmpty (eattr.Name)) { - // Diagnostic.Warning (log, "Use of ExportAttribute.Name property is invalid on constructors"); - } - - curCtors.Add (ctor); - return CreateConstructor (ctor, declaringType, eattr, managedParameters, cache); - } - - // Constructor with [Register] attribute - var rattr = CecilExtensions.GetMethodRegistrationAttributes (ctor).FirstOrDefault (); - - if (rattr != null) { - if (declaringType.Constructors.Any (c => c.JniSignature == rattr.Signature)) - return null; - - curCtors.Add (ctor); - return CreateConstructor (ctor, declaringType, rattr, managedParameters, outerType, cache); - } - - if (onlyRegisteredOrExportedCtors) - return null; - - // Constructors without [Export] or [Register] attributes - var jniSignature = JavaNativeTypeManager.GetJniSignature (ctor, cache); - - if (jniSignature is null) - return null; - - if (declaringType.Constructors.Any (c => c.JniSignature == jniSignature)) - return null; - - if (baseCtors is null) - throw new InvalidOperationException ("`baseCtors` should not be null!"); - - if (baseCtors.Any (m => m.Parameters.AreParametersCompatibleWith (ctor.Parameters, cache))) { - curCtors.Add (ctor); - return CreateConstructor (".ctor", declaringType, jniSignature, "", managedParameters, outerType, null); - } - - if (baseCtors.Any (m => !m.HasParameters)) { - curCtors.Add (ctor); - return CreateConstructor (".ctor", declaringType, jniSignature, "", managedParameters, outerType, ""); - } - - return null; - } - - static string GetManagedParameters (MethodDefinition ctor, string? outerType, TypeDefinition type, IMetadataResolver cache) - { - var sb = new StringBuilder (); - - foreach (var pdef in ctor.Parameters) { - if (sb.Length > 0) - sb.Append (':'); - if (outerType != null && sb.Length == 0) - sb.Append (type.DeclaringType.GetPartialAssemblyQualifiedName (cache)); - else - sb.Append (pdef.ParameterType.GetPartialAssemblyQualifiedName (cache)); - } - - return sb.ToString (); - } - - static CallableWrapperApplicationConstructor? CreateApplicationConstructor (string name, TypeDefinition type, IMetadataResolver resolver) - { - if (!JavaNativeTypeManager.IsApplication (type, resolver)) - return null; - - return new CallableWrapperApplicationConstructor (name); - } - - static void AddNestedTypes (CallableWrapperType declaringType, TypeDefinition type, IMetadataResolver cache, CallableWrapperReaderOptions? options) - { - if (!type.HasNestedTypes) - return; - - foreach (var nt in type.NestedTypes) { - if (!nt.HasJavaPeer (cache)) - continue; - if (!JavaNativeTypeManager.IsNonStaticInnerClass (nt, cache)) - continue; - - declaringType.NestedTypes.Add (CreateType (nt, cache, options, JavaNativeTypeManager.ToJniName (type, cache))); - AddNestedTypes (declaringType, nt, cache, options); - } - - declaringType.HasExport |= declaringType.NestedTypes.Any (t => t.HasExport); - } - - static void AddMethod (CallableWrapperType declaringType, TypeDefinition type, MethodDefinition? registeredMethod, MethodDefinition implementedMethod, JavaCallableMethodClassifier? methodClassifier, IMetadataResolver cache) - { - if (registeredMethod != null) - foreach (RegisterAttribute attr in CecilExtensions.GetMethodRegistrationAttributes (registeredMethod)) { - // Check for Kotlin-mangled methods that cannot be overridden - if (attr.Name.Contains ("-impl") || (attr.Name.Length > 7 && attr.Name [attr.Name.Length - 8] == '-')) - Diagnostic.Error (4217, CecilExtensions.LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4217, attr.Name); - - var shouldBeDynamicallyRegistered = methodClassifier?.ShouldBeDynamicallyRegistered (type, registeredMethod, implementedMethod, attr.OriginAttribute) ?? true; - var method = CreateMethod (implementedMethod, declaringType, attr, null, null, cache, shouldBeDynamicallyRegistered); - - if (!registeredMethod.IsConstructor && !declaringType.Methods.Any (m => m.Name == method.Name && m.Params == method.Params)) - declaringType.Methods.Add (method); - } - foreach (ExportAttribute attr in CecilExtensions.GetExportAttributes (implementedMethod, cache)) { - if (type.HasGenericParameters) - Diagnostic.Error (4206, CecilExtensions.LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4206); - - var method = CreateMethod (implementedMethod, declaringType, attr, null, cache); - - if (!string.IsNullOrEmpty (attr.SuperArgumentsString)) { - // Diagnostic.Warning (log, "Use of ExportAttribute.SuperArgumentsString property is invalid on methods"); - } - - if (!implementedMethod.IsConstructor && !declaringType.Methods.Any (m => m.Name == method.Name && m.Params == method.Params)) - declaringType.Methods.Add (method); - } - foreach (ExportFieldAttribute attr in CecilExtensions.GetExportFieldAttributes (implementedMethod)) { - if (type.HasGenericParameters) - Diagnostic.Error (4207, CecilExtensions.LookupSource (implementedMethod), Localization.Resources.JavaCallableWrappers_XA4207); - - var method = CreateMethod (implementedMethod, declaringType, cache); - - if (!implementedMethod.IsConstructor && !declaringType.Methods.Any (m => m.Name == method.Name && m.Params == method.Params)) { - declaringType.Methods.Add (method); - declaringType.Fields.Add (CreateField (implementedMethod, attr.Name, cache)); - } - } - } - - static void ExtractJavaNames (string jniName, out string package, out string type) - { - var i = jniName.LastIndexOf ('/'); - - if (i < 0) { - type = jniName; - package = string.Empty; - } else { - type = jniName.Substring (i + 1); - package = jniName.Substring (0, i).Replace ('/', '.'); - } - } - - static string GetJavaTypeName (TypeReference r, IMetadataResolver cache) - { - var d = cache.Resolve (r); - var jniName = JavaNativeTypeManager.ToJniName (d, cache); - - if (jniName is null) { - Diagnostic.Error (4201, Localization.Resources.JavaCallableWrappers_XA4201, r.FullName); - throw new InvalidOperationException ("--nrt:jniName-- Should not be reached"); - } - - return jniName.Replace ('/', '.').Replace ('$', '.'); - } - - static IEnumerable CreateAnnotations (ICustomAttributeProvider type, IMetadataResolver resolver) - { - foreach (var ca in type.CustomAttributes) { - var annotation = CreateAnnotation (ca, resolver); - - if (annotation is not null) - yield return annotation; - } - } - - static CallableWrapperTypeAnnotation? CreateAnnotation (CustomAttribute ca, IMetadataResolver resolver) - { - var catype = resolver.Resolve (ca.AttributeType); - var tca = catype.CustomAttributes.FirstOrDefault (a => a.AttributeType.FullName == "Android.Runtime.AnnotationAttribute"); - - if (tca is null) - return null; - - var name_object = tca.ConstructorArguments [0].Value; - - // Should never be hit - if (name_object is not string name) - throw new ArgumentException ($"Expected a string for the first argument of the {nameof (RegisterAttribute)} constructor.", nameof (ca)); - - var annotation = new CallableWrapperTypeAnnotation (name); - - foreach (var p in ca.Properties) { - var pd = catype.Properties.FirstOrDefault (pp => pp.Name == p.Name); - var reg = pd?.CustomAttributes.FirstOrDefault (pdca => pdca.AttributeType.FullName == "Android.Runtime.RegisterAttribute"); - var key = reg != null ? (string) reg.ConstructorArguments [0].Value : p.Name; - var value = ManagedValueToJavaSource (p.Argument.Value); - - annotation.Properties.Add (new KeyValuePair (key, value)); - } - - return annotation; - } - - // FIXME: this is hacky. Is there any existing code for value to source conversion? - static string ManagedValueToJavaSource (object value) - { - if (value is string) - return "\"" + value.ToString ()?.Replace ("\"", "\"\"") + '"'; - else if (value.GetType ().FullName == "Java.Lang.Class") - return value.ToString () + ".class"; - else if (value is bool v) - return v ? "true" : "false"; - else - return value.ToString () ?? ""; - } - - static string GetJavaAccess (MethodAttributes access) - { - return access switch { - MethodAttributes.Public => "public", - MethodAttributes.FamORAssem => "protected", - MethodAttributes.Family => "protected", - _ => "private", - }; - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlExporter.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlExporter.cs deleted file mode 100644 index 748270142f0..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlExporter.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Xml; -using Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; -using Java.Interop.Tools.JavaCallableWrappers.Extensions; - -namespace Java.Interop.Tools.JavaCallableWrappers.Adapters; - -public static class XmlExporter -{ - static XmlWriterSettings settings = new XmlWriterSettings { - Indent = true, - NewLineOnAttributes = false, - OmitXmlDeclaration = true, - }; - - public static void Export (string filename, IEnumerable types) - { - using (var sw = new StreamWriter (filename, false, Encoding.UTF8)) - Export (sw, types); - } - - public static void Export (TextWriter sw, IEnumerable types) - { - using (var xml = XmlWriter.Create (sw, settings)) - Export (xml, types); - } - - public static void Export (XmlWriter xml, IEnumerable types) - { - ExportTypes (xml, types); - } - - static void ExportTypes (XmlWriter xml, IEnumerable types) - { - foreach (var type in types) - ExportType (xml, type); - } - - public static void ExportType (XmlWriter xml, CallableWrapperType type) - { - xml.WriteStartElement ("type"); - xml.WriteAttributeString ("name", type.Name); - xml.WriteAttributeString ("package", type.Package); - xml.WriteAttributeStringIfNotFalse ("is_abstract", type.IsAbstract); - xml.WriteAttributeStringIfNotNull ("application_java_class", type.ApplicationJavaClass); - xml.WriteAttributeStringIfNotFalse ("generate_on_create_overrides", type.GenerateOnCreateOverrides); - xml.WriteAttributeStringIfNotNull ("mono_runtime_initialization", type.MonoRuntimeInitialization); - xml.WriteAttributeStringIfNotNull ("extends_type", type.ExtendsType); - xml.WriteAttributeStringIfNotFalse ("is_application", type.IsApplication); - xml.WriteAttributeStringIfNotFalse ("is_instrumentation", type.IsInstrumentation); - xml.WriteAttributeString ("partial_assembly_qualified_name", type.PartialAssemblyQualifiedName); - xml.WriteAttributeStringIfNotFalse ("has_export", type.HasExport); - - if (type.ApplicationConstructor is not null) - xml.WriteAttributeString ("application_constructor", type.ApplicationConstructor.Name); - - ExportAnnotations (xml, type.Annotations); - ExportImplementedInterfaces (xml, type.ImplementedInterfaces); - ExportConstructors (xml, type.Constructors); - ExportFields (xml, type.Fields); - ExportMethods (xml, type.Methods); - ExportNestedTypes (xml, type.NestedTypes); - - xml.WriteEndElement (); - } - - static void ExportAnnotations (XmlWriter writer, IEnumerable annotations) - { - if (annotations.Count () == 0) - return; - - writer.WriteStartElement ("annotations"); - - foreach (var annotation in annotations) { - writer.WriteStartElement ("annotation"); - writer.WriteAttributeString ("name", annotation.Name); - - foreach (var property in annotation.Properties) { - writer.WriteStartElement ("property"); - writer.WriteAttributeString ("name", property.Key); - writer.WriteAttributeString ("value", property.Value); - writer.WriteEndElement (); - } - - writer.WriteEndElement (); - } - - writer.WriteEndElement (); - } - - static void ExportImplementedInterfaces (XmlWriter writer, List interfaces) - { - if (interfaces.Count == 0) - return; - - writer.WriteStartElement ("implemented_interfaces"); - - foreach (var @interface in interfaces) { - writer.WriteStartElement ("interface"); - writer.WriteAttributeString ("name", @interface); - writer.WriteEndElement (); - } - - writer.WriteEndElement (); - } - - static void ExportConstructors (XmlWriter xml, IEnumerable constructors) - { - if (constructors.Count () == 0) - return; - - xml.WriteStartElement ("constructors"); - - foreach (var constructor in constructors) - ExportMethod (xml, constructor); - - xml.WriteEndElement (); - } - - static void ExportFields (XmlWriter xml, IEnumerable fields) - { - if (fields.Count () == 0) - return; - - xml.WriteStartElement ("fields"); - - foreach (var field in fields) { - xml.WriteStartElement ("field"); - xml.WriteAttributeString ("name", field.FieldName); - xml.WriteAttributeString ("type", field.TypeName); - xml.WriteAttributeString ("visibility", field.Visibility); - xml.WriteAttributeStringIfNotFalse ("is_static", field.IsStatic); - xml.WriteAttributeString ("initializer_name", field.InitializerName); - ExportAnnotations (xml, field.Annotations); - xml.WriteEndElement (); - } - - xml.WriteEndElement (); - } - - static void ExportMethods (XmlWriter xml, IEnumerable methods) - { - if (methods.Count () == 0) - return; - - xml.WriteStartElement ("methods"); - - foreach (var method in methods) - ExportMethod (xml, method); - - xml.WriteEndElement (); - } - - static void ExportMethod (XmlWriter xml, CallableWrapperMethod method) - { - xml.WriteStartElement (method is CallableWrapperConstructor ? "constructor" : "method"); - xml.WriteAttributeString ("name", method.Name); - xml.WriteAttributeString ("method", method.Method); - xml.WriteAttributeString ("jni_signature", method.JniSignature); - xml.WriteAttributeStringIfNotNull ("managed_parameters", method.ManagedParameters); - xml.WriteAttributeStringIfNotNull ("java_name_override", method.JavaNameOverride); - xml.WriteAttributeStringIfNotNull ("params", method.Params); - xml.WriteAttributeStringIfNotNull ("retval", method.Retval); - xml.WriteAttributeStringIfNotNull ("java_access", method.JavaAccess); - xml.WriteAttributeStringIfNotFalse ("is_export", method.IsExport); - xml.WriteAttributeStringIfNotFalse ("is_static", method.IsStatic); - xml.WriteAttributeStringIfNotFalse ("is_dynamically_registered", method.IsDynamicallyRegistered); - xml.WriteAttributeStringIfNotNull ("thrown_type_names", method.ThrownTypeNames != null ? string.Join (", ", method.ThrownTypeNames) : null); - xml.WriteAttributeStringIfNotNull ("super_call", method.SuperCall); - xml.WriteAttributeStringIfNotNull ("activate_call", method.ActivateCall); - - ExportAnnotations (xml, method.Annotations); - - xml.WriteEndElement (); - } - - static void ExportNestedTypes (XmlWriter xml, IEnumerable nestedTypes) - { - if (nestedTypes.Count () == 0) - return; - - xml.WriteStartElement ("nested_types"); - - foreach (var nestedType in nestedTypes) - ExportType (xml, nestedType); - - xml.WriteEndElement (); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlImporter.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlImporter.cs deleted file mode 100644 index 32702c75013..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.Adapters/XmlImporter.cs +++ /dev/null @@ -1,237 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Xml; -using System.Xml.Linq; -using Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; -using Java.Interop.Tools.JavaCallableWrappers.Extensions; -using Java.Interop.Tools.TypeNameMappings; - -namespace Java.Interop.Tools.JavaCallableWrappers.Adapters; - -public static class XmlImporter -{ - public static List Import (string filename) - { - using (var sr = new StreamReader (filename, Encoding.UTF8)) - return Import (sr); - } - - public static List Import (TextReader sr) - { - using (var xml = XmlReader.Create (sr)) - return Import (xml); - } - - public static List Import (XmlReader xml) - { - var doc = XDocument.Load (xml); - - var types = new List (); - - foreach (var type in doc.Root.Elements ("type")) - types.Add (ImportType (type)); - - return types; - } - - - public static List Import (XElement xml) - { - var types = new List (); - - foreach (var type in xml.Elements ("type")) - types.Add (ImportType (type)); - - return types; - } - - public static CallableWrapperType ImportType (XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var package = xml.GetAttributeOrDefault ("package", (string?) ""); - var partial_assembly_qualified_name = xml.GetRequiredAttribute ("partial_assembly_qualified_name"); - - // If package is empty, generate a crc64 package name from the assembly qualified name - if (string.IsNullOrEmpty (package)) - package = GeneratePackageFromAssemblyQualifiedName (partial_assembly_qualified_name); - - var type = new CallableWrapperType (name, package ?? "", partial_assembly_qualified_name) { - ApplicationJavaClass = xml.GetAttributeOrDefault ("application_java_class", (string?) null), - ExtendsType = xml.GetAttributeOrDefault ("extends_type", (string?) null), - GenerateOnCreateOverrides = xml.GetAttributeOrDefault ("generate_on_create_overrides", false), - HasExport = xml.GetAttributeOrDefault ("has_export", false), - IsAbstract = xml.GetAttributeOrDefault ("is_abstract", false), - IsApplication = xml.GetAttributeOrDefault ("is_application", false), - IsInstrumentation = xml.GetAttributeOrDefault ("is_instrumentation", false), - MonoRuntimeInitialization = xml.GetAttributeOrDefault ("mono_runtime_initialization", (string?) null), - }; - - if (xml.GetAttributeOrDefault ("application_constructor", (string?) null) is string applicationConstructor) - type.ApplicationConstructor = new CallableWrapperApplicationConstructor (applicationConstructor); - - ImportAnnotations (type.Annotations, xml.Element ("annotations")); - ImportImplementedInterfaces (type, xml.Element ("implemented_interfaces")); - ImportConstructors (type, xml.Element ("constructors")); - ImportMethods (type, xml.Element ("methods")); - ImportFields (type, xml.Element ("fields")); - - foreach (var nestedType in xml.Elements ("nested_type")) - type.NestedTypes.Add (ImportType (nestedType)); - - return type; - } - - static void ImportAnnotations (List annotations, XElement? xml) - { - foreach (var annotation in xml?.Elements ("annotation") ?? []) { - var a = ImportAnnotation (annotation); - annotations.Add (a); - } - } - - static CallableWrapperTypeAnnotation ImportAnnotation (XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var annotation = new CallableWrapperTypeAnnotation (name); - - foreach (var property in xml.Elements ("property")) { - var p = ImportAnnotationProperty (property); - annotation.Properties.Add (p); - } - - return annotation; - } - - static KeyValuePair ImportAnnotationProperty (XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var value = xml.GetRequiredAttribute ("value"); - - return new KeyValuePair (name, value); - } - - static void ImportImplementedInterfaces (CallableWrapperType type, XElement? xml) - { - foreach (var iface in xml?.Elements ("interface") ?? []) { - var name = iface.GetRequiredAttribute ("name"); - type.ImplementedInterfaces.Add (name); - } - } - - static void ImportConstructors (CallableWrapperType type, XElement? xml) - { - foreach (var ctor in xml?.Elements ("constructor") ?? []) { - var c = ImportConstructor (type, ctor); - type.Constructors.Add (c); - } - } - - static void ImportMethods (CallableWrapperType type, XElement? xml) - { - foreach (var method in xml?.Elements ("method") ?? []) { - var m = ImportMethod (type, method); - type.Methods.Add (m); - } - } - - static CallableWrapperConstructor ImportConstructor (CallableWrapperType type, XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var method = xml.GetRequiredAttribute ("method"); - var jniSig = xml.GetRequiredAttribute ("jni_signature"); - - var ctor = new CallableWrapperConstructor (type, name, method, jniSig); - FillInMethodDetails (ctor, xml); - - return ctor; - } - - static CallableWrapperMethod ImportMethod (CallableWrapperType type, XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var method = xml.GetRequiredAttribute ("method"); - var jniSig = xml.GetRequiredAttribute ("jni_signature"); - - var m = new CallableWrapperMethod (type, name, method, jniSig); - FillInMethodDetails (m, xml); - - return m; - } - - static void FillInMethodDetails (CallableWrapperMethod method, XElement xml) - { - // Common between constructors and methods - method.ManagedParameters = xml.GetAttributeOrDefault ("managed_parameters", (string?) null); - method.JavaNameOverride = xml.GetAttributeOrDefault ("java_name_override", (string?) null); - method.Params = xml.GetAttributeOrDefault ("params", (string?) null); - method.Retval = xml.GetAttributeOrDefault ("retval", (string?) null); - method.JavaAccess = xml.GetAttributeOrDefault ("java_access", (string?) null); - method.IsExport = xml.GetAttributeOrDefault ("is_export", false); - method.IsStatic = xml.GetAttributeOrDefault ("is_static", false); - method.IsDynamicallyRegistered = xml.GetAttributeOrDefault ("is_dynamically_registered", false); - method.SuperCall = xml.GetAttributeOrDefault ("super_call", (string?) null); - method.ActivateCall = xml.GetAttributeOrDefault ("activate_call", (string?) null); - - if (xml.GetAttributeOrDefault ("thrown_type_names", (string?) null) is string thrownTypeNames) - method.ThrownTypeNames = thrownTypeNames.Split (new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - ImportAnnotations (method.Annotations, xml.Element ("annotations")); - } - - static void ImportFields (CallableWrapperType type, XElement? xml) - { - foreach (var field in xml?.Elements ("field") ?? []) { - var f = ImportField (field); - type.Fields.Add (f); - } - } - - static CallableWrapperField ImportField (XElement xml) - { - var name = xml.GetRequiredAttribute ("name"); - var type = xml.GetRequiredAttribute ("type"); - var visibility = xml.GetRequiredAttribute ("visibility"); - var initializer_name = xml.GetRequiredAttribute ("initializer_name"); - - var field = new CallableWrapperField (name, type, visibility, initializer_name) { - IsStatic = xml.GetAttributeOrDefault ("is_static", false), - }; - - ImportAnnotations (field.Annotations, xml.Element ("annotations")); - - return field; - } - - /// - /// Generates a package name from a partial assembly qualified name. - /// This is used when the package attribute is missing or empty in the XML. - /// - /// The partial assembly qualified name in format "Namespace.TypeName, AssemblyName" - /// A package name based on the current - static string GeneratePackageFromAssemblyQualifiedName (string partialAssemblyQualifiedName) - { - // Format: "Namespace.TypeName, AssemblyName" or "Namespace.TypeName+NestedType, AssemblyName" - var commaIndex = partialAssemblyQualifiedName.IndexOf (','); - if (commaIndex < 0) - return ""; - - var fullTypeName = partialAssemblyQualifiedName.Substring (0, commaIndex).Trim (); - var assemblyName = partialAssemblyQualifiedName.Substring (commaIndex + 1).Trim (); - - // Extract namespace from full type name - // Handle nested types by using '+' as separator - var plusIndex = fullTypeName.IndexOf ('+'); - var typeNameWithoutNested = plusIndex >= 0 ? fullTypeName.Substring (0, plusIndex) : fullTypeName; - - var lastDotIndex = typeNameWithoutNested.LastIndexOf ('.'); - var ns = lastDotIndex >= 0 ? typeNameWithoutNested.Substring (0, lastDotIndex) : ""; - - // If no namespace, return empty (will use default package) - if (string.IsNullOrEmpty (ns)) - return ""; - - return JavaNativeTypeManager.GetPackageName (ns, assemblyName); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperApplicationConstructor.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperApplicationConstructor.cs deleted file mode 100644 index 2d8c40938d2..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperApplicationConstructor.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.IO; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperApplicationConstructor -{ - public string Name { get; set; } - - public CallableWrapperApplicationConstructor (string name) - { - Name = name; - } - - public void Generate (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - - sw.Write ("\tpublic "); - sw.Write (Name); - sw.WriteLine (" ()"); - - sw.WriteLine ("\t{"); - sw.WriteLine ("\t\tmono.MonoPackageManager.setContext (this);"); - sw.WriteLine ("\t}"); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperConstructor.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperConstructor.cs deleted file mode 100644 index 782f0f9885f..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperConstructor.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.IO; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperConstructor : CallableWrapperMethod -{ - public CallableWrapperConstructor (CallableWrapperType declaringType, string name, string method, string jniSignature) : base (declaringType, name, method, jniSignature) - { - } - - public override void Generate (TextWriter sw, CallableWrapperWriterOptions options) - { - // TODO: we only generate constructors so that Android types w/ no - // default constructor can be subclasses by our generated code. - // - // This does NOT currently allow creating managed types from Java. - sw.WriteLine (); - - foreach (var annotation in Annotations) - annotation.Generate (sw, "", options); - - sw.Write ("\tpublic "); - sw.Write (Name); - - sw.Write (" ("); - sw.Write (Params); - sw.Write (')'); - - sw.WriteLine (ThrowsDeclaration); - - sw.WriteLine ("\t{"); - sw.Write ("\t\tsuper ("); - sw.Write (SuperCall); - sw.WriteLine (");"); - -#if MONODROID_TIMING - sw.WriteLine ("\t\tandroid.util.Log.i(\"MonoDroid-Timing\", \"{0}..ctor({1}): time: \"+java.lang.System.currentTimeMillis());", Name, Params); -#endif - - if (!DeclaringType.CannotRegisterInStaticConstructor) { - - sw.Write ("\t\tif (getClass () == "); - sw.Write (Name); - sw.WriteLine (".class) {"); - - sw.Write ("\t\t\t"); - - sw.Write ("mono.android.TypeManager.Activate (\""); - sw.Write (DeclaringType.PartialAssemblyQualifiedName); - sw.Write ("\", \""); - sw.Write (ManagedParameters); - sw.Write ("\", this, new java.lang.Object[] { "); - sw.Write (ActivateCall); - sw.WriteLine (" });"); - - sw.WriteLine ("\t\t}"); - } - - sw.WriteLine ("\t}"); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperField.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperField.cs deleted file mode 100644 index 043dedc9ee1..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperField.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using System.IO; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperField -{ - public string FieldName { get; set; } - public string TypeName { get; set; } - public string Visibility { get; set; } - public bool IsStatic { get; set; } - public string InitializerName { get; set; } - public List Annotations { get; } = new List (); - - public CallableWrapperField (string fieldName, string typeName, string visibility, string initializerName) - { - FieldName = fieldName; - TypeName = typeName; - Visibility = visibility; - InitializerName = initializerName; - } - - public void Generate (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - - foreach (var annotation in Annotations) - annotation.Generate (sw, "", options); - - sw.Write ("\t"); - sw.Write (Visibility); - sw.Write (' '); - - if (IsStatic) - sw.Write ("static "); - - sw.Write (TypeName); - sw.Write (' '); - - sw.Write (FieldName); - sw.Write (" = "); - - sw.Write (InitializerName); - sw.WriteLine (" ();"); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperMethod.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperMethod.cs deleted file mode 100644 index 9b9e692d5f1..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperMethod.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperMethod -{ - public string Name { get; set; } - public string Method { get; set; } - public string JniSignature { get; set; } - public string? ManagedParameters { get; set; } - public string? JavaNameOverride { get; set; } - public string? Params { get; set; } - public string? Retval { get; set; } - public string? JavaAccess { get; set; } - public bool IsExport { get; set; } - public bool IsStatic { get; set; } - public bool IsDynamicallyRegistered { get; set; } = true; - public string []? ThrownTypeNames { get; set; } - public string? SuperCall { get; set; } - public string? ActivateCall { get; set; } - public string JavaName => JavaNameOverride ?? Name; - public List Annotations { get; } = new List (); - public CallableWrapperType DeclaringType { get; } - - public string? ThrowsDeclaration => ThrownTypeNames?.Length > 0 ? $" throws {string.Join (", ", ThrownTypeNames)}" : null; - - public CallableWrapperMethod (CallableWrapperType declaringType, string name, string method, string jniSignature) - { - DeclaringType = declaringType; - Name = name; - Method = method; - JniSignature = jniSignature; - } - - public virtual void Generate (TextWriter sw, CallableWrapperWriterOptions options) - { - sw.WriteLine (); - - foreach (var annotation in Annotations) - annotation.Generate (sw, "", options); - - sw.Write ("\t"); - - sw.Write (IsExport ? JavaAccess : "public"); - sw.Write (' '); - - if (IsStatic) - sw.Write ("static "); - - sw.Write (Retval); - sw.Write (' '); - - sw.Write (JavaName); - - sw.Write (" ("); - sw.Write (Params); - sw.Write (')'); - - sw.WriteLine (ThrowsDeclaration); - sw.WriteLine ("\t{"); - -#if MONODROID_TIMING - sw.WriteLine ("\t\tandroid.util.Log.i(\"MonoDroid-Timing\", \"{0}.{1}: time: \"+java.lang.System.currentTimeMillis());", Name, Method); -#endif - - sw.Write ("\t\t"); - sw.Write (Retval == "void" ? string.Empty : "return "); - - sw.Write ("n_"); - sw.Write (Name); - - sw.Write (" ("); - sw.Write (ActivateCall); - sw.WriteLine (");"); - - sw.WriteLine ("\t}"); - sw.WriteLine (); - - sw.Write ("\tprivate "); - - if (IsStatic) - sw.Write ("static "); - - sw.Write ("native "); - - sw.Write (Retval); - - sw.Write (" n_"); - sw.Write (Name); - - sw.Write (" ("); - sw.Write (Params); - sw.WriteLine (");"); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperType.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperType.cs deleted file mode 100644 index 85beee2f2cc..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperType.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperType -{ - public string Name { get; set; } - public string Package { get; set; } - public bool IsAbstract { get; set; } - public string? ApplicationJavaClass { get; set; } - public bool GenerateOnCreateOverrides { get; set; } - /// - /// The Java source code to be included in Instrumentation.onCreate - /// - /// Originally came from MonoRuntimeProvider.java delimited by: - /// // Mono Runtime Initialization {{{ - /// // }}} - /// - public string? MonoRuntimeInitialization { get; set; } - public string? ExtendsType { get; set; } - public CallableWrapperApplicationConstructor? ApplicationConstructor { get; set; } - public bool IsApplication { get; set; } - public bool IsInstrumentation { get; set; } - public string PartialAssemblyQualifiedName { get; set; } - public bool HasExport { get; set; } - - public List Annotations { get; } = new List (); - public List ImplementedInterfaces { get; } = new List (); - public List Constructors { get; } = new List (); - public List Fields { get; } = new List (); - public List Methods { get; } = new List (); - public List NestedTypes { get; } = new List (); - - public bool CannotRegisterInStaticConstructor => IsApplication || IsInstrumentation; - - public CallableWrapperType (string name, string package, string partialAssemblyQualifiedName) - { - Name = name; - Package = package; - PartialAssemblyQualifiedName = partialAssemblyQualifiedName; - } - - // example of java target to generate for a type - // - // package mono.droid; - // - // import android.app.Activity; - // import android.os.Bundle; - // - // public class MonoActivity extends android.app.Activity - // { - // static final String __md_methods; - // static { - // __md_methods = - // "n_OnCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler\n" + - // ""; - // mono.android.Runtime.register ("Mono.Droid.MonoActivity, AssemblyName", MonoActivity.class, __md_methods); - // } - // - // public void onCreate(android.os.Bundle savedInstanceState) - // { - // n_onCreate (savedInstanceState); - // } - // - // private native void n_onCreate (android.os.Bundle bundle); - // } - public void Generate (TextWriter writer, CallableWrapperWriterOptions options, bool isNested = false) - { - if (!isNested && !string.IsNullOrEmpty (Package)) { - writer.WriteLine ("package " + Package + ";"); - writer.WriteLine (); - } - - writer.WriteLine (); - - // Type annotations - foreach (var annotation in Annotations) - annotation.Generate (writer, "", options); - - GenerateHeader (writer); - - if (!isNested) - GenerateInfrastructure (writer); - - GenerateBody (writer, options); - - foreach (var nested in NestedTypes) - nested.Generate (writer, options, true); - - GenerateFooter (writer); - } - - void GenerateHeader (TextWriter sw) - { - sw.WriteLine ("public " + (IsAbstract ? "abstract " : "") + "class " + Name); - - var extends = ExtendsType; - - // Do this check here rather than the constructor because it can be set after the constructor is called - if (extends == "android.app.Application" && ApplicationJavaClass != null && !string.IsNullOrEmpty (ApplicationJavaClass)) - extends = ApplicationJavaClass; - - sw.WriteLine ("\textends " + extends); - - sw.WriteLine ("\timplements"); - sw.Write ("\t\t"); - - sw.Write ("mono.android.IGCUserPeer"); - - foreach (var iface in ImplementedInterfaces) { - sw.WriteLine (","); - sw.Write ("\t\t"); - sw.Write (iface); - } - - sw.WriteLine (); - sw.WriteLine ("{"); - } - - void GenerateInfrastructure (TextWriter writer) - { - var needCtor = false; - - if (HasDynamicallyRegisteredMethods) { - needCtor = true; - writer.WriteLine ("/** @hide */"); - writer.WriteLine ("\tpublic static final String __md_methods;"); - } - - for (var i = 0; i < NestedTypes.Count; i++) { - if (!NestedTypes [i].HasDynamicallyRegisteredMethods) - continue; - - needCtor = true; - writer.Write ("\tstatic final String __md_"); - writer.Write (i + 1); - writer.WriteLine ("_methods;"); - } - - if (needCtor) { - writer.WriteLine ("\tstatic {"); - - if (HasDynamicallyRegisteredMethods) - GenerateRegisterType (writer, this, "__md_methods"); - - for (var i = 0; i < NestedTypes.Count; ++i) - GenerateRegisterType (writer, NestedTypes [i], $"__md_{i + 1}_methods"); - - writer.WriteLine ("\t}"); - } - } - - void GenerateBody (TextWriter sw, CallableWrapperWriterOptions options) - { - foreach (var ctor in Constructors) - ctor.Generate (sw, options); - - ApplicationConstructor?.Generate (sw, options); - - foreach (var field in Fields) - field.Generate (sw, options); - - foreach (var method in Methods) - method.Generate (sw, options); - - if (GenerateOnCreateOverrides && IsApplication && !Methods.Any (m => m.Name == "onCreate")) - WriteApplicationOnCreate (sw); - - if (GenerateOnCreateOverrides && IsInstrumentation && !Methods.Any (m => m.Name == "onCreate")) - WriteInstrumentationOnCreate (sw); - - sw.WriteLine (); - sw.WriteLine ("\tprivate java.util.ArrayList refList;"); - - sw.WriteLine ("\tpublic void monodroidAddReference (java.lang.Object obj)"); - sw.WriteLine ("\t{"); - sw.WriteLine ("\t\tif (refList == null)"); - sw.WriteLine ("\t\t\trefList = new java.util.ArrayList ();"); - sw.WriteLine ("\t\trefList.add (obj);"); - sw.WriteLine ("\t}"); - sw.WriteLine (); - - sw.WriteLine ("\tpublic void monodroidClearReferences ()"); - sw.WriteLine ("\t{"); - sw.WriteLine ("\t\tif (refList != null)"); - sw.WriteLine ("\t\t\trefList.clear ();"); - sw.WriteLine ("\t}"); - } - - void GenerateFooter (TextWriter sw) - { - sw.WriteLine ("}"); - } - - void WriteApplicationOnCreate (TextWriter sw) - { - sw.WriteLine (); - - sw.WriteLine ("\tpublic void onCreate ()"); - sw.WriteLine ("\t{"); - - sw.Write ("\t\tmono.android.Runtime.register (\""); - sw.Write (PartialAssemblyQualifiedName); - sw.Write ("\", "); - sw.Write (Name); - sw.WriteLine (".class, __md_methods);"); - - sw.WriteLine ("\t\tsuper.onCreate ();"); - sw.WriteLine ("\t}"); - } - - void WriteInstrumentationOnCreate (TextWriter sw) - { - sw.WriteLine (); - sw.WriteLine ("\tpublic void onCreate (android.os.Bundle arguments)"); - sw.WriteLine ("\t{"); - -#if MONODROID_TIMING - sw.WriteLine ("\t\tandroid.util.Log.i(\"MonoDroid-Timing\", \"{0}.onCreate(Bundle): time: \"+java.lang.System.currentTimeMillis());", Name); - sw.WriteLine (); -#endif - - sw.WriteLine ("\t\tandroid.content.Context context = getContext ();"); - sw.WriteLine (); - - if (!string.IsNullOrEmpty (MonoRuntimeInitialization)) { - sw.WriteLine (MonoRuntimeInitialization); - sw.WriteLine (); - } - - sw.Write ("\t\tmono.android.Runtime.register (\""); - sw.Write (PartialAssemblyQualifiedName); - sw.Write ("\", "); - sw.Write (Name); - sw.WriteLine (".class, __md_methods);"); - - sw.WriteLine ("\t\tsuper.onCreate (arguments);"); - sw.WriteLine ("\t}"); - } - - void GenerateRegisterType (TextWriter sw, CallableWrapperType self, string field) - { - if (!self.HasDynamicallyRegisteredMethods) - return; - - sw.Write ("\t\t"); - sw.Write (field); - sw.WriteLine (" = "); - - foreach (var method in self.Methods) { - if (method.IsDynamicallyRegistered) { - sw.Write ("\t\t\t\"", method.Method); - sw.Write (method.Method); - sw.WriteLine ("\\n\" +"); - } - } - - sw.WriteLine ("\t\t\t\"\";"); - - if (CannotRegisterInStaticConstructor) - return; - - sw.Write ("\t\t"); - - sw.Write ("mono.android.Runtime.register (\""); - sw.Write (self.PartialAssemblyQualifiedName); - sw.Write ("\", "); - sw.Write (self.Name); - sw.Write (".class, "); - sw.Write (field); - sw.WriteLine (");"); - } - - // If there are no methods, we need to generate "empty" registration because of backward compatibility - public bool HasDynamicallyRegisteredMethods => Methods.Count == 0 || Methods.Any (sig => sig.IsDynamicallyRegistered); - - /// - /// Returns a destination file path based on the package name of this Java type - /// - public string GetDestinationPath (string outputPath) - { - var dir = Package.Replace ('.', Path.DirectorySeparatorChar); - return Path.Combine (outputPath, dir, Name + ".java"); - } - - public void Generate (string outputPath, CallableWrapperWriterOptions options) - { - using (StreamWriter sw = OpenStream (outputPath)) - Generate (sw, options, false); - } - - StreamWriter OpenStream (string outputPath) - { - var destination = GetDestinationPath (outputPath); - Directory.CreateDirectory (Path.GetDirectoryName (destination)!); - - return new StreamWriter (new FileStream (destination, FileMode.Create, FileAccess.Write)); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperTypeAnnotation.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperTypeAnnotation.cs deleted file mode 100644 index e605eee62e7..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers/CallableWrapperTypeAnnotation.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Java.Interop.Tools.JavaCallableWrappers.CallableWrapperMembers; - -public class CallableWrapperTypeAnnotation -{ - public string Name { get; set; } - public List> Properties { get; } = new (); - - public CallableWrapperTypeAnnotation (string name) - { - Name = name; - } - - public void Generate (TextWriter sw, string indent, CallableWrapperWriterOptions options) - { - sw.Write (indent); - sw.Write ('@'); - sw.Write (Name); - - var properties = string.Join (", ", Properties.Select (p => $"{p.Key} = {p.Value}")); - - if (!string.IsNullOrEmpty (properties)) { - sw.Write (" ("); - sw.Write (properties); - sw.Write (")"); - } - - sw.WriteLine (); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperReaderOptions.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperReaderOptions.cs deleted file mode 100644 index acd5a9633ab..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperReaderOptions.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Java.Interop.Tools.JavaCallableWrappers; - -public class CallableWrapperReaderOptions -{ - public string? DefaultApplicationJavaClass { get; set; } - public bool DefaultGenerateOnCreateOverrides { get; set; } - public string? DefaultMonoRuntimeInitialization { get; set; } - public JavaCallableMethodClassifier? MethodClassifier { get; set; } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperWriterOptions.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperWriterOptions.cs deleted file mode 100644 index 9cbfe5ddc53..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/CallableWrapperWriterOptions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Java.Interop.Tools.JavaCallableWrappers; - -public class CallableWrapperWriterOptions -{ - JavaPeerStyle codeGenerationTarget; - - public JavaPeerStyle CodeGenerationTarget { - get => codeGenerationTarget; - set { - if (value != JavaPeerStyle.XAJavaInterop1) - throw new NotSupportedException ($"The Java callable wrapper code generation target '{value}' is not supported. Use XAJavaInterop1 instead."); - codeGenerationTarget = value; - } - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableMethodClassifier.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableMethodClassifier.cs deleted file mode 100644 index 75e8061d6d4..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaCallableMethodClassifier.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Mono.Cecil; - -namespace Java.Interop.Tools.JavaCallableWrappers -{ - public abstract class JavaCallableMethodClassifier - { - public abstract bool ShouldBeDynamicallyRegistered (TypeDefinition topType, MethodDefinition registeredMethod, MethodDefinition implementedMethod, CustomAttribute? registerAttribute); - } -} diff --git a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaPeerStyle.cs b/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaPeerStyle.cs deleted file mode 100644 index 22ea687104e..00000000000 --- a/external/Java.Interop/src/Java.Interop.Tools.JavaCallableWrappers/Java.Interop.Tools.JavaCallableWrappers/JavaPeerStyle.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Java.Interop.Tools.JavaCallableWrappers -{ - public enum JavaPeerStyle { - XAJavaInterop1, - } -} diff --git a/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGeneratorTests.cs b/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGeneratorTests.cs deleted file mode 100644 index cf83f0d0171..00000000000 --- a/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/JavaCallableWrapperGeneratorTests.cs +++ /dev/null @@ -1,740 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -using Mono.Cecil; - -using NUnit.Framework; - -using Java.Interop.Tools.Diagnostics; -using Java.Interop.Tools.JavaCallableWrappers; -using Java.Interop.Tools.JavaCallableWrappersTests; -using Java.Interop.Tools.TypeNameMappings; - -using Xamarin.Android.ToolsTests; -using Java.Interop.Tools.JavaCallableWrappers.Adapters; -using Java.Interop.Tools.Cecil; - -namespace Java.Interop.Tools.JavaCallableWrappersTests -{ - [TestFixture] - public class JavaCallableWrapperGeneratorTests - { - [Test] - public void ConstructorExceptions () - { - Action logger = (f, o) => { }; - - // structs aren't supported - var td = SupportDeclarations.GetTypeDefinition (typeof (int)); - var e = Assert.Throws (() => CecilImporter.CreateType (td, new TypeDefinitionCache ())); - Assert.AreEqual (4200, e.Code); - } - - [Test] - public void KotlinInvalidImplRegisterName () - { - Action logger = (f, o) => { }; - - // Contains invalid [Register] name of "foo-impl" - var td = SupportDeclarations.GetTypeDefinition (typeof (KotlinInvalidImplRegisterName)); - var e = Assert.Throws (() => CecilImporter.CreateType (td, new TypeDefinitionCache ())); - Assert.AreEqual (4217, e.Code); - } - - [Test] - public void KotlinInvalidHashRegisterName () - { - Action logger = (f, o) => { }; - - // Contains invalid [Register] name of "foo-f8k2a13" - var td = SupportDeclarations.GetTypeDefinition (typeof (KotlinInvalidHashRegisterName)); - var e = Assert.Throws (() => CecilImporter.CreateType (td, new TypeDefinitionCache ())); - Assert.AreEqual (4217, e.Code); - } - - [Test] - public void GenerateApplication ( - [Values (null, "android.app.Application", "android.support.multidex.MultiDexApplication")] string applicationJavaClass - ) - { - var actual = Generate (typeof (ApplicationName), applicationJavaClass); - var expected = $@"package application; - - -public class Name - extends {applicationJavaClass ?? "android.app.Application"} - implements - mono.android.IGCUserPeer -{{ -/** @hide */ - public static final String __md_methods; - static {{ - __md_methods = - """"; - }} - - public Name () - {{ - mono.MonoPackageManager.setContext (this); - }} - - public void onCreate () - {{ - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ApplicationName, Java.Interop.Tools.JavaCallableWrappers-Tests"", Name.class, __md_methods); - super.onCreate (); - }} - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - {{ - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - }} - - public void monodroidClearReferences () - {{ - if (refList != null) - refList.clear (); - }} -}} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateTypeMentioningNestedInvoker () - { - var actual = Generate (typeof (ApplicationName.ActivityLifecycleCallbacks)); - var expected = """ -package application; - - -public class Name_ActivityLifecycleCallbacks - extends java.lang.Object - implements - mono.android.IGCUserPeer, - java.lang.Object -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - "n_onActivityCreated:(Landroid/app/Activity;Landroid/os/Bundle;)V:GetOnActivityCreated_Landroid_app_Activity_Landroid_os_Bundle_Handler:Android.App.Application+IActivityLifecycleCallbacksInvoker, Mono.Android\n" + - ""; - mono.android.Runtime.register ("Xamarin.Android.ToolsTests.ApplicationName+ActivityLifecycleCallbacks, Java.Interop.Tools.JavaCallableWrappers-Tests", Name_ActivityLifecycleCallbacks.class, __md_methods); - } - - public void onActivityCreated (android.app.Activity p0, android.os.Bundle p1) - { - n_onActivityCreated (p0, p1); - } - - private native void n_onActivityCreated (android.app.Activity p0, android.os.Bundle p1); - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} - -"""; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateOnlyMostDerivedInterfaces () - { - var actual = Generate (typeof (OnTabSelectedListener)); - - Assert.That (actual, Does.Contain ("\t\tcom.xamarin.android.OnTabSelectedListener")); - Assert.That (actual, Does.Not.Contain ("\t\tcom.xamarin.android.BaseOnTabSelectedListener")); - } - - static string Generate (Type type, string applicationJavaClass = null, string monoRuntimeInit = null) - { - var reader_options = new CallableWrapperReaderOptions { - DefaultApplicationJavaClass = applicationJavaClass, - DefaultGenerateOnCreateOverrides = true, - DefaultMonoRuntimeInitialization = monoRuntimeInit, - }; - - var td = SupportDeclarations.GetTypeDefinition (type); - var g = CecilImporter.CreateType (td, new TypeDefinitionCache (), reader_options); - - var o = new StringWriter (); - var dir = Path.GetDirectoryName (typeof (JavaCallableWrapperGeneratorTests).Assembly.Location); - var options = new CallableWrapperWriterOptions (); - - g.Generate (Path.Combine (dir, "__o"), options); - g.Generate (o, options); - - return o.ToString (); - } - - - [Test] - public void GenerateIndirectApplication ( - [Values (null, "android.app.Application", "android.support.multidex.MultiDexApplication")] string applicationJavaClass - ) - { - var actual = Generate (typeof (IndirectApplication), applicationJavaClass); - var expected = @"package crc64197ae30a36756915; - - -public class IndirectApplication - extends application.Name - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - ""n_onCreate:()V:Application.OnCreate\n"" + - """"; - } - - public IndirectApplication () - { - mono.MonoPackageManager.setContext (this); - } - - public void onCreate () - { - n_onCreate (); - } - - private native void n_onCreate (); - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateExportedMembers () - { - var actual = Generate (typeof (ExportsMembers)); - var expected = @"package crc64197ae30a36756915; - - -public class ExportsMembers - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - ""n_GetInstance:()Lcrc64197ae30a36756915/ExportsMembers;:__export__\n"" + - ""n_GetValue:()Ljava/lang/String;:__export__\n"" + - ""n_staticMethodNotMangled:()V:__export__\n"" + - ""n_methodNamesNotMangled:()V:__export__\n"" + - ""n_CompletelyDifferentName:(Ljava/lang/String;I)Ljava/lang/String;:__export__\n"" + - ""n_methodThatThrows:()V:__export__\n"" + - ""n_methodThatThrowsEmptyArray:()V:__export__\n"" + - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExportsMembers, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExportsMembers.class, __md_methods); - } - - public static crc64197ae30a36756915.ExportsMembers STATIC_INSTANCE = GetInstance (); - - public java.lang.String VALUE = GetValue (); - - public static crc64197ae30a36756915.ExportsMembers GetInstance () - { - return n_GetInstance (); - } - - private static native crc64197ae30a36756915.ExportsMembers n_GetInstance (); - - public java.lang.String GetValue () - { - return n_GetValue (); - } - - private native java.lang.String n_GetValue (); - - public static void staticMethodNotMangled () - { - n_staticMethodNotMangled (); - } - - private static native void n_staticMethodNotMangled (); - - public void methodNamesNotMangled () - { - n_methodNamesNotMangled (); - } - - private native void n_methodNamesNotMangled (); - - public java.lang.String attributeOverridesNames (java.lang.String p0, int p1) - { - return n_CompletelyDifferentName (p0, p1); - } - - private native java.lang.String n_CompletelyDifferentName (java.lang.String p0, int p1); - - public void methodThatThrows () throws java.lang.Throwable - { - n_methodThatThrows (); - } - - private native void n_methodThatThrows (); - - public void methodThatThrowsEmptyArray () - { - n_methodThatThrowsEmptyArray (); - } - - private native void n_methodThatThrowsEmptyArray (); - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateInnerClass () - { - var actual = Generate (typeof (ExampleOuterClass)); - var expected = @"package crc64197ae30a36756915; - - -public class ExampleOuterClass - extends register.NonStaticOuterClass - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static final String __md_1_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExampleOuterClass, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExampleOuterClass.class, __md_methods); - __md_1_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExampleOuterClass+ExampleInnerClass, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExampleOuterClass_ExampleInnerClass.class, __md_1_methods); - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } - -public class ExampleOuterClass_ExampleInnerClass - extends register.NonStaticOuterClass.NonStaticInnerClass - implements - mono.android.IGCUserPeer -{ - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateNestedClass_DefaultName () - { - var actual = Generate (typeof (RegisterName.DefaultNestedName)); - var expected = @"package register; - - -public class Name_DefaultNestedName - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.RegisterName+DefaultNestedName, Java.Interop.Tools.JavaCallableWrappers-Tests"", Name_DefaultNestedName.class, __md_methods); - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateNestedClass_OverrideName () - { - var actual = Generate (typeof (RegisterName.OverrideNestedName)); - var expected = @"package register; - - -public class Name$Override - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.RegisterName+OverrideNestedName, Java.Interop.Tools.JavaCallableWrappers-Tests"", Name$Override.class, __md_methods); - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateConstructors () - { - var actual = Generate (typeof (ExportsConstructors)); - var expected = @"package register; - - -public class ExportsConstructors - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExportsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExportsConstructors.class, __md_methods); - } - - public ExportsConstructors () - { - super (); - if (getClass () == ExportsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", """", this, new java.lang.Object[] { }); - } - } - - public ExportsConstructors (int p0) - { - super (p0); - if (getClass () == ExportsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ""System.Int32, System.Private.CoreLib"", this, new java.lang.Object[] { p0 }); - } - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateConstructors_WithThrows () - { - var actual = Generate (typeof (ExportsThrowsConstructors)); - var expected = @"package register; - - -public class ExportsThrowsConstructors - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExportsThrowsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExportsThrowsConstructors.class, __md_methods); - } - - public ExportsThrowsConstructors () throws java.lang.Throwable - { - super (); - if (getClass () == ExportsThrowsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsThrowsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", """", this, new java.lang.Object[] { }); - } - } - - public ExportsThrowsConstructors (int p0) throws java.lang.Throwable - { - super (p0); - if (getClass () == ExportsThrowsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsThrowsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ""System.Int32, System.Private.CoreLib"", this, new java.lang.Object[] { p0 }); - } - } - - public ExportsThrowsConstructors (java.lang.String p0) - { - super (p0); - if (getClass () == ExportsThrowsConstructors.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.ExportsThrowsConstructors, Java.Interop.Tools.JavaCallableWrappers-Tests"", ""System.String, System.Private.CoreLib"", this, new java.lang.Object[] { p0 }); - } - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateActivity () - { - var actual = Generate (typeof (ExampleActivity)); - var expected = @"package my; - - -public class ExampleActivity - extends android.app.Activity - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExampleActivity, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExampleActivity.class, __md_methods); - } - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateInstrumentation () - { - var init = "mono.MonoPackageManager.LoadApplication (context, context.getApplicationInfo (), new String[]{context.getApplicationInfo ().sourceDir});"; - var actual = Generate (typeof (ExampleInstrumentation), monoRuntimeInit: init); - var expected = $@"package my; - - -public class ExampleInstrumentation - extends android.app.Instrumentation - implements - mono.android.IGCUserPeer -{{ -/** @hide */ - public static final String __md_methods; - static {{ - __md_methods = - """"; - }} - - public void onCreate (android.os.Bundle arguments) - {{ - android.content.Context context = getContext (); - -{init} - - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.ExampleInstrumentation, Java.Interop.Tools.JavaCallableWrappers-Tests"", ExampleInstrumentation.class, __md_methods); - super.onCreate (arguments); - }} - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - {{ - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - }} - - public void monodroidClearReferences () - {{ - if (refList != null) - refList.clear (); - }} -}} -"; - Assert.AreEqual (expected, actual); - } - - [Test] - public void GenerateJavaInteropExample () - { - var actual = Generate (typeof (JavaInteropExample)); - var expected = @"package register; - - -public class JavaInteropExample - extends java.lang.Object - implements - mono.android.IGCUserPeer -{ -/** @hide */ - public static final String __md_methods; - static { - __md_methods = - ""n_Example:()V:__export__\n"" + - """"; - mono.android.Runtime.register (""Xamarin.Android.ToolsTests.JavaInteropExample, Java.Interop.Tools.JavaCallableWrappers-Tests"", JavaInteropExample.class, __md_methods); - } - - public JavaInteropExample (int p0, int p1) - { - super (); - if (getClass () == JavaInteropExample.class) { - mono.android.TypeManager.Activate (""Xamarin.Android.ToolsTests.JavaInteropExample, Java.Interop.Tools.JavaCallableWrappers-Tests"", ""System.Int32, System.Private.CoreLib:System.Int32, System.Private.CoreLib"", this, new java.lang.Object[] { p0, p1 }); - } - } - - public void example () - { - n_Example (); - } - - private native void n_Example (); - - private java.util.ArrayList refList; - public void monodroidAddReference (java.lang.Object obj) - { - if (refList == null) - refList = new java.util.ArrayList (); - refList.add (obj); - } - - public void monodroidClearReferences () - { - if (refList != null) - refList.clear (); - } -} -"; - Assert.AreEqual (expected, actual); - } - - [TestCase (-1)] - [TestCase (1)] - public void UndefinedCodeGenerationTargetIsRejected (int target) - { - Assert.Throws (() => - new CallableWrapperWriterOptions { CodeGenerationTarget = (JavaPeerStyle) target }); - } - } -} diff --git a/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/XmlImporterTests.cs b/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/XmlImporterTests.cs deleted file mode 100644 index 6486045ae7b..00000000000 --- a/external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers/XmlImporterTests.cs +++ /dev/null @@ -1,144 +0,0 @@ -using System.IO; -using System.Xml.Linq; -using Java.Interop.Tools.JavaCallableWrappers.Adapters; -using Java.Interop.Tools.TypeNameMappings; -using NUnit.Framework; - -namespace Java.Interop.Tools.JavaCallableWrappersTests -{ - [TestFixture] - public class XmlImporterTests - { - PackageNamingPolicy existingValue; - - [SetUp] - public void SetUp () - { - existingValue = JavaNativeTypeManager.PackageNamingPolicy; - JavaNativeTypeManager.PackageNamingPolicy = PackageNamingPolicy.LowercaseCrc64; - } - - [TearDown] - public void TearDown () - { - JavaNativeTypeManager.PackageNamingPolicy = existingValue; - } - - [Test] - public void ImportType_EmptyPackage_GeneratesCrc64Package () - { - // Simulate the case where [Register("CustomView")] is used without a package prefix - // The XML has an empty package attribute, and we expect XmlImporter to generate a crc64 package - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // The generated package should be "crc64" + crc64hash of "MyApp.Views:MyApp.Android" - Assert.AreEqual ("crc64b8e52a012da2d805", type.Package); - Assert.AreEqual ("CustomView", type.Name); - } - - [Test] - public void ImportType_EmptyPackage_NestedType_GeneratesCrc64Package () - { - // Simulate the case with a nested type - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // The generated package should be based on "MyApp.Views:MyApp.Android" (ignoring nested type part) - Assert.AreEqual ("crc64b8e52a012da2d805", type.Package); - Assert.AreEqual ("InnerView", type.Name); - } - - [Test] - public void ImportType_MissingPackageAttribute_GeneratesCrc64Package () - { - // Simulate the case where the package attribute is completely missing - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // The generated package should be "crc64" + crc64hash of "MyApp.Views:MyApp.Android" - Assert.AreEqual ("crc64b8e52a012da2d805", type.Package); - } - - [Test] - public void ImportType_WithPackage_UsesProvidedPackage () - { - // Ensure that when a package is provided, it is used directly - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - Assert.AreEqual ("my.custom.package", type.Package); - } - - [Test] - public void ImportType_NoNamespace_ReturnsEmptyPackage () - { - // When there's no namespace in the type name, we can't generate a package - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // Without a namespace, we can't generate a crc64 package, so it should remain empty - Assert.AreEqual ("", type.Package); - } - - [Test] - public void ImportType_XamarinAndroidToolsTests_MatchesExpectedCrc64 () - { - // This test verifies the crc64 generation matches what JavaNativeTypeManager would generate - // Based on the test data in JavaCallableWrapperGeneratorTests, namespace "Xamarin.Android.ToolsTests" - // with assembly "Java.Interop.Tools.JavaCallableWrappers-Tests" should produce crc64197ae30a36756915 - var xml = XElement.Parse (@" - - - - "); - - var type = XmlImporter.ImportType (xml); - - // This should match the expected crc64 from JavaCallableWrapperGeneratorTests - Assert.AreEqual ("crc64197ae30a36756915", type.Package); - } - } -} diff --git a/external/Java.Interop/tools/jcw-gen/App.cs b/external/Java.Interop/tools/jcw-gen/App.cs deleted file mode 100644 index a962b749966..00000000000 --- a/external/Java.Interop/tools/jcw-gen/App.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Diagnostics; -using System.Linq; -using System.IO; -using System.Threading.Tasks; - -using Java.Interop.Tools.Cecil; -using Java.Interop.Tools.Diagnostics; -using Java.Interop.Tools.JavaCallableWrappers; -using Mono.Cecil; -using Mono.Options; -using Java.Interop.Tools.JavaCallableWrappers.Adapters; - -namespace Java.Interop.Tools -{ - class App - { - public static int Main (string [] args) - { - var resolver = new DirectoryAssemblyResolver (logger: Diagnostic.CreateConsoleLogger (), loadDebugSymbols: false); - - bool help = false; - string outputPath = null; - int verbosity = 0; - var target = new CallableWrapperWriterOptions (); - - var options = new OptionSet { - "Usage: jcw-gen.exe OPTIONS* ASSEMBLY+ [@RESPONSE-FILES]", - "", - "Generates Java Callable Wrappers from specified assemblies.", - "", - "Copyright 2016 Xamarin Inc.", - "", - "Options:", - { "L=", - "{DIRECTORY} to resolve assemblies from.", - v => resolver.SearchDirectories.Add (v) }, - { "o=", - "{DIRECTORY} to write Java source code to.", - v => outputPath = v }, - { "codegen-target=", - "STYLE of Java Callable Wrappers to generate", - (JavaPeerStyle? v) => { - if (v.HasValue) - target.CodeGenerationTarget = v.Value; - } }, - { "v:", - "Logging verbosity.", - (int? v) => verbosity = v.HasValue ? v.Value : verbosity + 1 }, - { "h|help|?", - "Show this message and exit", - v => help = v != null }, - new ResponseFileSource (), - }; - var cache = new TypeDefinitionCache (); - var scanner = new JavaTypeScanner (Diagnostic.CreateConsoleLogger (), cache); - try { - var assemblies = options.Parse (args); - if (assemblies.Count == 0 || outputPath == null || help) { - int r = 0; - if (assemblies.Count == 0) { - Console.Error.WriteLine ("jcw-gen: No assemblies specified."); - r = 1; - } - else if (outputPath == null) { - Console.Error.WriteLine ("jcw-gen: No output directory specified. Use `jcw-gen -o PATH`."); - r = 1; - } - options.WriteOptionDescriptions (Console.Out); - return r; - } - foreach (var assembly in assemblies) { - resolver.SearchDirectories.Add (Path.GetDirectoryName (assembly)); - resolver.Load (assembly); - } - var types = scanner.GetJavaTypes (assemblies, resolver) - .Where (td => !JavaTypeScanner.ShouldSkipJavaCallableWrapperGeneration (td, cache)); - foreach (var type in types) { - if (type.IsInterface) - continue; - - var wrapper = CecilImporter.CreateType (type, cache); - wrapper.Generate (outputPath, new CallableWrapperWriterOptions ()); - } - return 0; - } - catch (Exception e) { - Console.Error.Write ("jcw-gen: {0}", verbosity > 0 ? e.ToString () : e.Message); - return 1; - } - finally { - resolver.Dispose (); - } - } - } -} diff --git a/external/Java.Interop/tools/jcw-gen/jcw-gen.csproj b/external/Java.Interop/tools/jcw-gen/jcw-gen.csproj deleted file mode 100644 index f99367616b8..00000000000 --- a/external/Java.Interop/tools/jcw-gen/jcw-gen.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - $(DotNetTargetFramework) - Exe - - - - - - $(UtilityOutputFullPath) - - - - - - - - - - - - - - - - - - - - diff --git a/external/Java.Interop/tools/jcw-gen/jcw-gen.slnf b/external/Java.Interop/tools/jcw-gen/jcw-gen.slnf deleted file mode 100644 index 26d4de23d53..00000000000 --- a/external/Java.Interop/tools/jcw-gen/jcw-gen.slnf +++ /dev/null @@ -1,13 +0,0 @@ -{ - "solution": { - "path": "..\\..\\Java.Interop.slnx", - "projects": [ - "src\\Java.Interop.Localization\\Java.Interop.Localization.csproj", - "src\\Java.Interop.Tools.Cecil\\Java.Interop.Tools.Cecil.csproj", - "src\\Java.Interop.Tools.Diagnostics\\Java.Interop.Tools.Diagnostics.csproj", - "src\\Java.Interop.Tools.JavaCallableWrappers\\Java.Interop.Tools.JavaCallableWrappers.csproj", - "tests\\Java.Interop.Tools.JavaCallableWrappers-Tests\\Java.Interop.Tools.JavaCallableWrappers-Tests.csproj", - "tools\\jcw-gen\\jcw-gen.csproj" - ] - } -} \ No newline at end of file diff --git a/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateTrimmableTypeMapTests.cs b/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateTrimmableTypeMapTests.cs index 283dc2cf301..16f3043ebf0 100644 --- a/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateTrimmableTypeMapTests.cs +++ b/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/GenerateTrimmableTypeMapTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Android.Sdk.TrimmableTypeMap; using Microsoft.Android.Tasks; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -12,6 +13,87 @@ namespace Xamarin.Android.Build.Tests { [Parallelizable (ParallelScope.Children)] public class GenerateTrimmableTypeMapTests : BaseTest { + [TestCase (false, false, false)] + [TestCase (false, false, true)] + [TestCase (false, true, false)] + [TestCase (false, true, true)] + [TestCase (true, false, false)] + [TestCase (true, false, true)] + [TestCase (true, true, false)] + [TestCase (true, true, true)] + public void ConstructorCallbacksMatchJavaCallSites (bool isAbstract, bool deferred, bool hasCallback) + { + var constructor = new MarshalMethodInfo { + JniName = ".ctor", + JniSignature = "()V", + NativeCallbackName = "n_ctor", + ManagedMethodName = ".ctor", + IsConstructor = true, + }; + var callback = new MarshalMethodInfo { + JniName = "onCallback", + JniSignature = "()V", + NativeCallbackName = "n_onCallback", + ManagedMethodName = "OnCallback", + Connector = "GetOnCallbackHandler", + }; + var peer = new JavaPeerInfo { + JavaName = "example/Peer", + CompatJniName = "example/Peer", + ManagedTypeName = "Example.Peer", + ManagedTypeNamespace = "Example", + ManagedTypeShortName = "Peer", + AssemblyName = "Example", + BaseJavaName = "java/lang/Object", + IsAbstract = isAbstract, + CannotRegisterInStaticConstructor = deferred, + ActivationCtor = new ActivationCtorInfo { + DeclaringTypeName = "Example.Peer", + DeclaringAssemblyName = "Example", + DeclaringType = new TypeRefData { ManagedTypeName = "Example.Peer", AssemblyName = "Example" }, + Style = ActivationCtorStyle.XamarinAndroid, + }, + JavaConstructors = [new JavaConstructorInfo { JniSignature = "()V", ConstructorIndex = 0 }], + MarshalMethods = hasCallback ? [constructor, callback] : [constructor], + }; + using var writer = new StringWriter (); + new JcwJavaSourceGenerator ().Generate (peer, writer); + var java = writer.ToString (); + StringAssert.Contains ("public Peer ()", java); + StringAssert.Contains ("super ();", java); + StringAssert.Contains ("mono.android.IGCUserPeer", java); + StringAssert.Contains ("private java.util.ArrayList refList;", java); + StringAssert.DoesNotContain ("__md_methods", java); + + bool hasNativeConstructor = !isAbstract && !deferred; + Assert.AreEqual (hasNativeConstructor, java.Contains ("if (getClass () == Peer.class) nctor_0 ();", StringComparison.Ordinal)); + Assert.AreEqual (hasNativeConstructor, java.Contains ("private native void nctor_0 ();", StringComparison.Ordinal)); + Assert.AreEqual (deferred && hasCallback, java.Contains ("private static boolean __md_natives_registered;", StringComparison.Ordinal)); + Assert.AreEqual (deferred && hasCallback, java.Contains ("private static synchronized void __md_registerNatives ()", StringComparison.Ordinal)); + Assert.AreEqual (deferred && hasCallback, java.Contains ("__md_registerNatives ();", StringComparison.Ordinal)); + Assert.AreEqual (hasCallback, java.Contains ("public native void n_onCallback ();", StringComparison.Ordinal)); + + var generator = new TypeMapAssemblyGenerator (new Version (11, 0)); + var model = generator.CreateModel ([peer], "_Example.TypeMap"); + var proxy = model.ProxyTypes.Single (); + Assert.AreEqual (hasNativeConstructor ? 1 : 0, proxy.UcoConstructors.Count); + string [] expectedRegistrations = hasNativeConstructor + ? (hasCallback ? ["nctor_0", "n_onCallback"] : ["nctor_0"]) + : (hasCallback ? ["n_onCallback"] : []); + CollectionAssert.AreEquivalent (expectedRegistrations, + proxy.NativeRegistrations.Select (registration => registration.JniMethodName)); + Assert.IsNotNull (proxy.ActivationCtor, "Managed peer creation must retain its activation constructor."); + + using var stream = new MemoryStream (); + generator.Generate (model, stream, useSharedTypemapUniverse: false); + stream.Position = 0; + using var assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly (stream); + var emittedProxy = assembly.MainModule.Types.Single (type => type.Name == proxy.TypeName); + Assert.AreEqual (hasNativeConstructor, emittedProxy.Methods.Any (method => method.Name == "nctor_0_uco")); + Assert.IsTrue (emittedProxy.Methods.Any (method => method.Name == "CreateInstance")); + TestContext.Out.WriteLine ($"abstract={isAbstract}, deferred={deferred}, callback={hasCallback}: Java nctor={hasNativeConstructor}, native registrations=[{string.Join (", ", proxy.NativeRegistrations.Select (registration => registration.JniMethodName))}]"); + } + [Test] public void Execute_EmptyAssemblyList_Succeeds () { diff --git a/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/JavaRuntimeTargetsTests.cs b/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/JavaRuntimeTargetsTests.cs new file mode 100644 index 00000000000..1887171251e --- /dev/null +++ b/src/Microsoft.Android.Build.Tasks/Tests/Microsoft.Android.Build.Tasks.Tests/JavaRuntimeTargetsTests.cs @@ -0,0 +1,86 @@ +using System; +using System.IO; +using System.Linq; +using System.Xml.Linq; + +using NUnit.Framework; + +namespace Xamarin.Android.Build.Tests; + +[TestFixture] +public class JavaRuntimeTargetsTests : BaseTest +{ + [TestCase ("Build")] + [TestCase ("Clean")] + public void RetiredArtifactsAreRemovedWithoutRegeneratingRetainedOutputs (string target) + { + string directory = Path.Combine (Root, "temp", TestName); + string output = Path.Combine (directory, "output"); + Directory.CreateDirectory (output); + string targets = Path.Combine (NativeAotBootstrapTestTools.FindRepositoryRoot (), "src", "java-runtime", "java-runtime.targets"); + string project = Path.Combine (directory, "runtime.proj"); + new XDocument ( + new XElement ("Project", + new XElement ("PropertyGroup", + new XElement ("OutputPath", output + Path.DirectorySeparatorChar), + new XElement ("IntermediateOutputPath", Path.Combine (directory, "obj") + Path.DirectorySeparatorChar), + new XElement ("JavaCPath", "unexpected-javac-invocation"), + new XElement ("JavaPath", "unexpected-d8-invocation")), + new XElement ("Import", new XAttribute ("Project", targets)), + new XElement ("Target", new XAttribute ("Name", "Build")), + new XElement ("Target", new XAttribute ("Name", "Clean")))) + .Save (project); + + string [] retired = [ + "java_runtime.jar", "java_runtime.dex", + "java_runtime_fastdev.jar", "java_runtime_fastdev.dex", + "java_runtime_clr.jar", "java_runtime_clr.dex", + "java_runtime_fastdev_clr.jar", "java_runtime_fastdev_clr.dex", + ]; + string [] retained = ["java_runtime_trimmable.jar", "java_runtime_trimmable.dex", "mono_android_Runtime.h", "custom-runtime.jar"]; + DateTime timestamp = new [] { File.GetLastWriteTimeUtc (project), File.GetLastWriteTimeUtc (targets) }.Max ().AddSeconds (2); + foreach (string name in retained) { + string file = Path.Combine (output, name); + File.WriteAllText (file, name); + File.SetLastWriteTimeUtc (file, timestamp); + } + + string dotnet = Environment.GetEnvironmentVariable ("DOTNET_HOST_PATH") ?? "dotnet"; + for (int run = 0; run < 2; run++) { + foreach (string name in retired) { + File.WriteAllText (Path.Combine (output, name), "stale"); + } + var result = NativeAotBootstrapTestTools.Run (dotnet, "msbuild", project, "-t:" + target, "-v:normal", "-nr:false"); + Assert.AreEqual (0, result.ExitCode, result.Output + result.Error); + foreach (string name in retired) { + FileAssert.DoesNotExist (Path.Combine (output, name), $"{target} must remove retired artifact {name} on every run."); + } + foreach (string name in retained) { + string file = Path.Combine (output, name); + if (target == "Clean" && name == "java_runtime_trimmable.jar") { + FileAssert.DoesNotExist (file, "Clean still removes the retained JAR through its existing cleanup target."); + continue; + } + FileAssert.Exists (file, $"{target} must not remove {name} as a retired artifact."); + Assert.AreEqual (name, File.ReadAllText (file)); + Assert.AreEqual (timestamp, File.GetLastWriteTimeUtc (file), "Cleanup must not rewrite retained or unrelated outputs."); + } + if (target == "Build") { + StringAssert.Contains ("Skipping target \"_BuildJavaRuntimeJar\"", result.Output); + StringAssert.Contains ("Skipping target \"_GenerateRuntimeDex16\"", result.Output); + } + } + + if (target == "Build" && !OperatingSystem.IsWindows ()) { + File.WriteAllText (Path.Combine (output, retired [0]), "cannot delete"); + var permissions = File.GetUnixFileMode (output); + try { + File.SetUnixFileMode (output, permissions & ~(UnixFileMode.UserWrite | UnixFileMode.GroupWrite | UnixFileMode.OtherWrite)); + var result = NativeAotBootstrapTestTools.Run (dotnet, "msbuild", project, "-t:Build", "-v:normal", "-nr:false"); + Assert.AreNotEqual (0, result.ExitCode, "A failed retired-artifact deletion must fail the build.\n" + result.Output + result.Error); + } finally { + File.SetUnixFileMode (output, permissions); + } + } + } +} diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JcwJavaSourceGenerator.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JcwJavaSourceGenerator.cs index 7f592364f3b..a1f1e7c4e73 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JcwJavaSourceGenerator.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/JcwJavaSourceGenerator.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; namespace Microsoft.Android.Sdk.TrimmableTypeMap; @@ -143,6 +144,9 @@ static void WriteStaticInitializer (JavaPeerInfo type, TextWriter writer) // emit a lazy one-time __md_registerNatives() helper and call it at the top of // each generated native-method wrapper. if (type.CannotRegisterInStaticConstructor) { + if (!type.MarshalMethods.Any (method => !method.IsConstructor)) { + return; + } writer.Write ($$""" private static boolean __md_natives_registered; private static synchronized void __md_registerNatives () @@ -186,7 +190,7 @@ static void WriteConstructors (JavaPeerInfo type, TextWriter writer) """); - if (!type.CannotRegisterInStaticConstructor) { + if (!type.IsAbstract && !type.CannotRegisterInStaticConstructor) { writer.Write ($$""" if (getClass () == {{simpleClassName}}.class) nctor_{{ctor.ConstructorIndex}} ({{args}}); @@ -201,14 +205,16 @@ static void WriteConstructors (JavaPeerInfo type, TextWriter writer) } // Write native constructor declarations - foreach (var ctor in type.JavaConstructors) { - var nativeCtorParams = JniSignatureHelper.ParseParameters (ctor.JniSignature); - string parameters = FormatParameterList (nativeCtorParams); - writer.WriteLine ($"\tprivate native void nctor_{ctor.ConstructorIndex} ({parameters});"); - } + if (!type.IsAbstract && !type.CannotRegisterInStaticConstructor) { + foreach (var ctor in type.JavaConstructors) { + var nativeCtorParams = JniSignatureHelper.ParseParameters (ctor.JniSignature); + string parameters = FormatParameterList (nativeCtorParams); + writer.WriteLine ($"\tprivate native void nctor_{ctor.ConstructorIndex} ({parameters});"); + } - if (type.JavaConstructors.Count > 0) { - writer.WriteLine (); + if (type.JavaConstructors.Count > 0) { + writer.WriteLine (); + } } } diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ManifestGenerator.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ManifestGenerator.cs index 1e3809a0fb5..b1be581c13f 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ManifestGenerator.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ManifestGenerator.cs @@ -40,7 +40,7 @@ class ManifestGenerator /// /// Generates the application manifest from an optional pre-loaded template. - /// Returns the list of additional content provider names (for ApplicationRegistration.java). + /// Returns the list of additional runtime provider class names to generate. /// public (XDocument Document, IList ProviderNames) Generate ( XDocument? manifestTemplate, diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs index 3c048736ab2..a69560ea61e 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/ModelBuilder.cs @@ -374,10 +374,8 @@ static void BuildUcoConstructors (JavaPeerInfo peer, JavaPeerProxyData proxy) return; } - // Abstract types are never directly instantiated from Java — the ACW - // constructor's getClass() guard prevents activation. Skip generating - // UCO constructor wrappers for them. - if (peer.IsAbstract) { + // Abstract and deferred JCWs do not call native constructor callbacks. + if (peer.IsAbstract || peer.CannotRegisterInStaticConstructor) { return; } diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs index 428b3e989e4..28818971620 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/Scanner/JavaPeerScanner.cs @@ -839,8 +839,7 @@ static void SkipArrayShape (ref BlobReader reader) // Pass 4: detect interface method implementations. // When a type implements a Java interface (e.g., IOnClickListener), the - // implementing method may not have [Register]. The legacy pipeline adds - // these via the interface loop in CecilImporter.cs lines 100-120. + // implementing method may not have [Register]. if (registeredMethodKeys is not null) { CollectInterfaceMethodImplementations (typeDef, index, methods, registeredMethodKeys); } @@ -1083,7 +1082,7 @@ void CollectBasePropertyOverrides (TypeDefinition typeDef, AssemblyIndex index, /// /// Detects methods from implemented Java interfaces that aren't directly [Register]'d - /// on the implementing type. Mirrors the legacy CecilImporter interface loop (lines 100-120): + /// on the implementing type: /// for each implemented interface with [Register], adds its registered methods to the type. /// void CollectInterfaceMethodImplementations (TypeDefinition typeDef, AssemblyIndex index, @@ -1174,7 +1173,6 @@ void CollectInterfaceMethodImplementations (TypeDefinition typeDef, AssemblyInde /// /// Detects Java constructors by chaining from base registered ctors. - /// Mirrors the legacy CecilImporter behavior: /// 1. Walk the base type hierarchy collecting registered ctors (stopping at DoNotGenerateAcw) /// 2. Add all base registered ctors as seed constructors (legacy adds them to the wrapper directly) /// 3. For each ctor on this type without [Register], accept it if a base registered ctor @@ -1200,8 +1198,6 @@ void CollectBaseConstructorChain (TypeDefinition typeDef, AssemblyIndex index, } // Add all base registered ctors as seed constructors. - // Legacy CecilImporter processes base types first (ctorTypes is reversed) and adds - // their registered ctors directly to the wrapper's Constructors list. bool hasParameterlessBaseCtor = false; foreach (var baseCtor in baseRegisteredCtors) { var signature = baseCtor.RegisterInfo.Signature; @@ -1253,7 +1249,6 @@ void CollectBaseConstructorChain (TypeDefinition typeDef, AssemblyIndex index, // and compute its JNI signature from the managed parameter types. // The generated Java ctor calls super() (the parameterless base ctor), // then delegates to nctor_N(...) which handles the args on the managed side. - // This matches legacy CecilImporter behavior (CecilImporter.cs:394-397). if (hasParameterlessBaseCtor) { var sig = methodDef.DecodeSignature (index.TypeRefSignatureProvider, index); var jniSignature = BuildJniCtorSignature (sig); @@ -1477,7 +1472,7 @@ static string GetEnumUnderlyingPrimitiveDescriptor (TypeDefinition typeDef, Asse /// /// Walks the base type hierarchy collecting constructors that have [Register] attributes. - /// Stops after the first base type with DoNotGenerateAcw=true (matching legacy CecilImporter). + /// Stops after the first base type with DoNotGenerateAcw=true. /// Returns them ordered from nearest base to furthest ancestor. /// List CollectBaseRegisteredCtors (TypeDefinition typeDef, AssemblyIndex index) @@ -1501,7 +1496,7 @@ List CollectBaseRegisteredCtors (TypeDefinition typeDef, AssemblyI } // Stop after the first MCW base type — its registered ctors are collected above, - // but we don't need to walk further up (matching legacy CecilImporter behavior). + // but we don't need to walk further up. if (baseIndex.RegisterInfoByType.TryGetValue (baseHandle, out var baseRegInfo) && baseRegInfo.DoNotGenerateAcw) { break; } @@ -2208,7 +2203,7 @@ string BuildJniSignatureFromManaged (MethodSignature sig, IReadOnly /// /// Parses an [ExportField] attribute as a marshal method registration. /// [ExportField] methods use the managed method name as the JNI name and have - /// a connector of "__export__" (matching legacy CecilImporter behavior). + /// a connector of "__export__". /// (RegisterInfo registerInfo, ExportInfo exportInfo) ParseExportFieldAsMethod (CustomAttribute ca, MethodDefinition methodDef, AssemblyIndex index) { diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapTypes.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapTypes.cs index 481056740b7..438e7189d6b 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapTypes.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapTypes.cs @@ -40,7 +40,7 @@ public record GeneratedJavaSource (string RelativePath, string Content); /// /// The in-memory result of manifest generation: the application document and -/// any additional content provider class names for ApplicationRegistration.java. +/// any additional runtime provider class names to generate. /// public record GeneratedManifest (XDocument Document, string[] AdditionalProviderSources); diff --git a/src/Mono.Android/Mono.Android.slnf b/src/Mono.Android/Mono.Android.slnf index dc1ead421c5..8b4dc80b3c1 100644 --- a/src/Mono.Android/Mono.Android.slnf +++ b/src/Mono.Android/Mono.Android.slnf @@ -7,7 +7,6 @@ "build-tools\\jnienv-gen\\jnienv-gen.csproj", "external\\Java.Interop\\src\\Java.Interop.NamingCustomAttributes\\Java.Interop.NamingCustomAttributes.shproj", "external\\Java.Interop\\tools\\generator\\generator.csproj", - "external\\Java.Interop\\tools\\jcw-gen\\jcw-gen.csproj", "src\\Mono.Android\\Mono.Android.csproj", "src\\java-runtime\\java-runtime.csproj" ] diff --git a/src/Xamarin.Android.Build.Tasks/Resources/ApplicationRegistration.java b/src/Xamarin.Android.Build.Tasks/Resources/ApplicationRegistration.java deleted file mode 100644 index f53b64bec97..00000000000 --- a/src/Xamarin.Android.Build.Tasks/Resources/ApplicationRegistration.java +++ /dev/null @@ -1,11 +0,0 @@ -package net.dot.android; - -public class ApplicationRegistration { - - public static android.content.Context Context; - - public static void registerApplications () - { - // REGISTER_APPLICATION_AND_INSTRUMENTATION_CLASSES_HERE - } -} diff --git a/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java b/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java index 5660876e513..c761f292a9b 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java +++ b/src/Xamarin.Android.Build.Tasks/Resources/MonoRuntimeProvider.Bundled.java @@ -1,7 +1,5 @@ package mono; -//NOTE: we can't use import, see Generator.GetMonoInitSource - public class MonoRuntimeProvider extends android.content.ContentProvider { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CopyResourceTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CopyResourceTests.cs index 22e25c62f30..feb3bd584c7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CopyResourceTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/CopyResourceTests.cs @@ -48,10 +48,10 @@ public void FilesThatAreExpected (string resourceName) Assert.AreNotEqual (0, new FileInfo (tempFile).Length, "file should be non-empty!"); } - [Test] - public void FileThatDoesNotExist () + [TestCase ("thisdoesnotexist")] + [TestCase ("ApplicationRegistration.java")] + public void FileThatDoesNotExist (string resourceName) { - var resourceName = "thisdoesnotexist"; var task = new CopyResource { BuildEngine = engine, ResourceName = resourceName, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs index 02471052dab..77c739bb453 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Security; using System.Security.Cryptography; @@ -2611,19 +2612,45 @@ public void TrimmableTypeMap_RuntimeArtifacts_ArePackagedInSdk () { var toolsDir = TestEnvironment.AndroidMSBuildDirectory; + foreach (var file in new [] { + "java_runtime_trimmable.jar", + "java_runtime_trimmable.dex", + }) { + FileAssert.Exists (Path.Combine (toolsDir, file), $"{file} should exist in the SDK pack."); + } + foreach (var file in new [] { "java_runtime.jar", "java_runtime.dex", "java_runtime_fastdev.jar", "java_runtime_fastdev.dex", - "java_runtime_trimmable.jar", - "java_runtime_trimmable.dex", "java_runtime_clr.jar", "java_runtime_clr.dex", "java_runtime_fastdev_clr.jar", "java_runtime_fastdev_clr.dex", }) { - FileAssert.Exists (Path.Combine (toolsDir, file), $"{file} should exist in the SDK pack."); + FileAssert.DoesNotExist (Path.Combine (toolsDir, file), $"{file} should not exist in the SDK pack."); + } + + using var runtimeJar = ZipFile.OpenRead (Path.Combine (toolsDir, "java_runtime_trimmable.jar")); + foreach (var entry in new [] { + "mono/android/Runtime.class", + "mono/android/IGCUserPeer.class", + "mono/android/GCUserPeer.class", + "mono/MonoPackageManager.class", + "mono/NativeLibraryHelper.class", + }) { + Assert.IsNotNull (runtimeJar.GetEntry (entry), $"{entry} must remain in the runtime JAR."); + } + foreach (var entry in new [] { + "mono/android/DebugRuntime.class", + "mono/android/BuildConfig.class", + "mono/android/app/XamarinAndroidEnvironmentVariables.class", + "mono/MonoPackageManager_Resources.class", + "net/dot/android/ApplicationRegistration.class", + "classes.dex", + }) { + Assert.IsNull (runtimeJar.GetEntry (entry), $"{entry} must not be packaged in the runtime JAR."); } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index d2845a5c520..5e13286c178 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -165,11 +165,6 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. True - False - True - False diff --git a/src/java-runtime/java-runtime.targets b/src/java-runtime/java-runtime.targets index 116a4921b63..62e22a52159 100644 --- a/src/java-runtime/java-runtime.targets +++ b/src/java-runtime/java-runtime.targets @@ -2,57 +2,32 @@ - <_RuntimeOutput Include="$(OutputPath)java_runtime.jar"> - $(OutputPath)java_runtime.jar - $(OutputPath)java_runtime.dex - $(IntermediateOutputPath)release - $(IntermediateOutputPath)release.txt - java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\clr\MonoPackageManager.java - <_RuntimeOutput Include="$(OutputPath)java_runtime_trimmable.jar"> $(OutputPath)java_runtime_trimmable.jar $(OutputPath)java_runtime_trimmable.dex $(IntermediateOutputPath)release-trimmable $(IntermediateOutputPath)release-trimmable.txt - java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\MonoPackageManager.java - - <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev.jar"> - $(OutputPath)java_runtime_fastdev.jar - $(OutputPath)java_runtime_fastdev.dex - $(IntermediateOutputPath)fastdev - $(IntermediateOutputPath)fastdev.txt - java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\clr\MonoPackageManager.java - - - <_RuntimeOutput Include="$(OutputPath)java_runtime_clr.jar"> - $(OutputPath)java_runtime_clr.jar - $(OutputPath)java_runtime_clr.dex - $(IntermediateOutputPath)release-clr - $(IntermediateOutputPath)release-clr.txt - java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\MonoPackageManager.java - - <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev_clr.jar"> - $(OutputPath)java_runtime_fastdev_clr.jar - $(OutputPath)java_runtime_fastdev_clr.dex - $(IntermediateOutputPath)fastdev-clr - $(IntermediateOutputPath)fastdev-clr.txt - java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\MonoPackageManager.java + + + <_RetiredJavaRuntimeName Include="java_runtime;java_runtime_fastdev;java_runtime_clr;java_runtime_fastdev_clr" /> + <_RetiredJavaRuntimeArtifact Include="@(_RetiredJavaRuntimeName->'$(OutputPath)%(Identity).jar');@(_RetiredJavaRuntimeName->'$(OutputPath)%(Identity).dex')" /> + + + + + - - <_RuntimeSource Include="@(AllRuntimeSource)" /> - <_RuntimeSource Remove="%(_RuntimeOutput.RemoveItems)" /> - <_RuntimeSource Include="%(_RuntimeOutput.AddItems)" Condition=" '%(_RuntimeOutput.AddItems)' != '' " /> - - diff --git a/src/java-runtime/java/mono/android/DebugRuntime.java b/src/java-runtime/java/mono/android/DebugRuntime.java deleted file mode 100644 index 8d42e45e263..00000000000 --- a/src/java-runtime/java/mono/android/DebugRuntime.java +++ /dev/null @@ -1,8 +0,0 @@ -package mono.android; - -public class DebugRuntime { - private DebugRuntime () - {} - - public static native void init (String[] apks, String runtimeLibDir, String[] appDirs, boolean haveSplitApks); -} diff --git a/src/java-runtime/java/mono/android/MonoPackageManager.java b/src/java-runtime/java/mono/android/MonoPackageManager.java deleted file mode 100644 index afbee894eb0..00000000000 --- a/src/java-runtime/java/mono/android/MonoPackageManager.java +++ /dev/null @@ -1,172 +0,0 @@ -package mono; - -import java.io.*; -import java.lang.String; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.util.Calendar; -import java.util.Locale; -import java.util.HashSet; -import java.util.zip.*; -import java.util.Arrays; -import android.content.Context; -import android.content.Intent; -import android.content.pm.ApplicationInfo; -import android.content.res.AssetManager; -import android.os.Build; -import android.util.Log; -import mono.android.Runtime; -import mono.android.DebugRuntime; -import mono.android.BuildConfig; -import net.dot.android.ApplicationRegistration; - -public class MonoPackageManager { - - static Object lock = new Object (); - static boolean initialized; - - public static void LoadApplication (Context context) - { - synchronized (lock) { - android.content.pm.ApplicationInfo runtimePackage = context.getApplicationInfo (); - String[] apks = null; - String[] splitApks = runtimePackage.splitSourceDirs; - if (splitApks != null && splitApks.length > 0) { - apks = new String[splitApks.length + 1]; - apks [0] = runtimePackage.sourceDir; - System.arraycopy (splitApks, 0, apks, 1, splitApks.length); - } else { - apks = new String[] { runtimePackage.sourceDir }; - } - - if (context instanceof android.app.Application) { - ApplicationRegistration.Context = context; - } - if (!initialized) { - Locale locale = Locale.getDefault (); - String language = locale.getLanguage () + "-" + locale.getCountry (); - String filesDir = context.getFilesDir ().getAbsolutePath (); - String cacheDir = context.getCacheDir ().getAbsolutePath (); - String dataDir = getNativeLibraryPath (context); - ClassLoader loader = context.getClassLoader (); - String runtimeDir = getNativeLibraryPath (runtimePackage); - int localDateTimeOffset; - - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - localDateTimeOffset = OffsetDateTime.now().getOffset().getTotalSeconds(); - } - else { - localDateTimeOffset = (Calendar.getInstance ().get (Calendar.ZONE_OFFSET) + Calendar.getInstance ().get (Calendar.DST_OFFSET)) / 1000; - } - - // - // Should the order change here, src/mono/native/runtime-base/shared-constants.hh and - // src/native/clr/include/constants.hh must be updated accordingly - // - String[] appDirs = new String[] {filesDir, cacheDir, dataDir}; - boolean haveSplitApks = runtimePackage.splitSourceDirs != null && runtimePackage.splitSourceDirs.length > 0; - - // - // Preload DSOs libmonodroid.so depends on so that the dynamic - // linker can resolve them when loading monodroid. This is not - // needed in the latest Android versions but is required in at least - // API 16 and since there's no inherent negative effect of doing it, - // we can do it unconditionally. - // - // Additionally, we need to load all the DSOs which depend on libmonosgen-2.0. The reason is that on - // some 64-bit devices running Android 5.{0,1} the dynamic linker fails to find `libmonosgen-2.0.so` - // even though it is in the same directory as the DSO depending on it *and* libmonosgen-2.0 is already - // in memory. This was seen on some devices (Huawei P8) and the x86_64 Android emulator. See the - // following issues: - // - // https://github.com/dotnet/android/issues/4772 - // https://github.com/dotnet/android/issues/4852 - // - // We could limit the preloading to only 64-bit 5.x Android versions but it appears to be more effort - // than necessary as preloading won't hurt performance (much - some libraries might not be needed - // immediately during startup) and there might be other Android builds out there with similar problems. - // - // We need to use our own `BuildConfig` class to detect debug builds here because, - // it seems, ApplicationInfo.flags information is not reliable - in the debug builds - // (with `android:debuggable=true` present on the `` element in the - // manifest) using shared runtime, the `runtimePackage.flags` field does NOT have - // the FLAGS_DEBUGGABLE (0x00000002) set and thus we'd revert to the `else` clause - // below, leading to an error locating the Mono runtime - // - if (BuildConfig.Debug) { - NativeLibraryHelper.loadLibrary ("xamarin-debug-app-helper", runtimePackage, apks); - DebugRuntime.init (apks, runtimeDir, appDirs, haveSplitApks); - } else { - NativeLibraryHelper.loadLibrary ("monosgen-2.0", runtimePackage, apks); - } - NativeLibraryHelper.loadLibrary ("xamarin-app", runtimePackage, apks); - - if (!BuildConfig.DotNetRuntime) { - // .net5+ APKs don't contain `libmono-native.so` - NativeLibraryHelper.loadLibrary ("mono-native", runtimePackage, apks); - } - - NativeLibraryHelper.loadLibrary ("monodroid", runtimePackage, apks); - - Runtime.initInternal ( - language, - apks, - runtimeDir, - appDirs, - localDateTimeOffset, - loader, - MonoPackageManager_Resources.Assemblies, - isEmulator (), - haveSplitApks - ); - - ApplicationRegistration.registerApplications (); - - initialized = true; - } - } - } - - // We need to detect the emulator in order to determine the maximum gref count. - // The official Android emulator requires a much lower maximum than actual - // devices. Hopefully other emulators don't need the treatment. If they do, we - // can add their detection here. We should perform the absolute minimum of - // checking in order to save time. - static boolean isEmulator() - { - String val = Build.HARDWARE; - - // This detects the official Android emulator - if (val.contains ("ranchu") || val.contains ("goldfish")) - return true; - - return false; - } - - public static void setContext (Context context) - { - // Ignore; vestigial - } - - static String getNativeLibraryPath (Context context) - { - return getNativeLibraryPath (context.getApplicationInfo ()); - } - - static String getNativeLibraryPath (ApplicationInfo ainfo) - { - if (android.os.Build.VERSION.SDK_INT >= 9) - return ainfo.nativeLibraryDir; - return ainfo.dataDir + "/lib"; - } - - public static String[] getAssemblies () - { - return MonoPackageManager_Resources.Assemblies; - } - - public static String[] getDependencies () - { - return MonoPackageManager_Resources.Dependencies; - } -} diff --git a/src/java-runtime/java/mono/android/MonoPackageManager_Resources.java b/src/java-runtime/java/mono/android/MonoPackageManager_Resources.java index 82f350bfa6c..a081446fea2 100644 --- a/src/java-runtime/java/mono/android/MonoPackageManager_Resources.java +++ b/src/java-runtime/java/mono/android/MonoPackageManager_Resources.java @@ -7,7 +7,4 @@ public class MonoPackageManager_Resources { public static String[] Assemblies = new String[]{ }; - public static String[] Dependencies = new String[]{ - }; } - diff --git a/src/java-runtime/java/mono/android/Runtime.java b/src/java-runtime/java/mono/android/Runtime.java index 385904a1ec3..9e067334dad 100644 --- a/src/java-runtime/java/mono/android/Runtime.java +++ b/src/java-runtime/java/mono/android/Runtime.java @@ -7,13 +7,11 @@ public class Runtime { static java.lang.Class java_lang_Class = java.lang.Class.class;; static java.lang.Class java_lang_System = java.lang.System.class; static java.lang.Class mono_android_IGCUserPeer = mono.android.IGCUserPeer.class; - static java.lang.Class mono_android_GCUserPeer = mono.android.GCUserPeer.class; static { Thread.setDefaultUncaughtExceptionHandler (new XamarinUncaughtExceptionHandler (Thread.getDefaultUncaughtExceptionHandler ())); } - public static native void init (String lang, String[] runtimeApks, String runtimeDataDir, String[] appDirs, ClassLoader loader, String[] externalStorageDirs, String[] assemblies, String packageName, int apiLevel, String[] environmentVariables); public static native void initInternal ( String lang, String[] runtimeApks, @@ -26,10 +24,6 @@ public static native void initInternal ( boolean haveSplitApks ); public static native void registerNatives (java.lang.Class nativeClass); - public static native int createNewContext (String[] runtimeApks, String[] assemblies, ClassLoader loader); - public static native int createNewContextWithData (String[] runtimeApks, String[] assemblies, byte[][] assembliesBytes, String[] assembliesPaths, ClassLoader loader, boolean forcePreloadAssemblies); - public static native void switchToContext (int contextID); - public static native void destroyContexts (int[] contextIDs); public static native void propagateUncaughtException (Thread javaThread, Throwable javaException); } diff --git a/src/java-runtime/java/mono/android/app/XamarinAndroidEnvironmentVariables.java b/src/java-runtime/java/mono/android/app/XamarinAndroidEnvironmentVariables.java deleted file mode 100644 index 00d41fcdd6d..00000000000 --- a/src/java-runtime/java/mono/android/app/XamarinAndroidEnvironmentVariables.java +++ /dev/null @@ -1,9 +0,0 @@ -package mono.android.app; - -public class XamarinAndroidEnvironmentVariables -{ - // Variables are specified the in "name", "value" pairs - public static final String[] Variables = new String[] { -//@ENVVARS@ - }; -} diff --git a/src/java-runtime/java/mono/android/clr/MonoPackageManager.java b/src/java-runtime/java/mono/android/clr/MonoPackageManager.java index 0f59ebd590c..5ed5b7b43b7 100644 --- a/src/java-runtime/java/mono/android/clr/MonoPackageManager.java +++ b/src/java-runtime/java/mono/android/clr/MonoPackageManager.java @@ -16,8 +16,6 @@ import android.os.Build; import android.util.Log; import mono.android.Runtime; -import mono.android.DebugRuntime; -import mono.android.BuildConfig; import net.dot.android.ApplicationRegistration; public class MonoPackageManager { @@ -100,11 +98,6 @@ static boolean isEmulator() return false; } - public static void setContext (Context context) - { - // Ignore; vestigial - } - static String getNativeLibraryPath (Context context) { return getNativeLibraryPath (context.getApplicationInfo ()); @@ -120,8 +113,4 @@ public static String[] getAssemblies () return MonoPackageManager_Resources.Assemblies; } - public static String[] getDependencies () - { - return MonoPackageManager_Resources.Dependencies; - } } diff --git a/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java b/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java deleted file mode 100644 index e05ba068714..00000000000 --- a/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package mono.android; - -public class BuildConfig { - public static boolean Debug = true; - public static boolean DotNetRuntime = true; -} diff --git a/src/java-runtime/java/mono/android/debug/BuildConfig.java b/src/java-runtime/java/mono/android/debug/BuildConfig.java deleted file mode 100644 index 575b166ca60..00000000000 --- a/src/java-runtime/java/mono/android/debug/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package mono.android; - -public class BuildConfig { - public static boolean Debug = true; - public static boolean DotNetRuntime = false; -} diff --git a/src/java-runtime/java/mono/android/release-net6/BuildConfig.java b/src/java-runtime/java/mono/android/release-net6/BuildConfig.java deleted file mode 100644 index 498a947ff8c..00000000000 --- a/src/java-runtime/java/mono/android/release-net6/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package mono.android; - -public class BuildConfig { - public static boolean Debug = false; - public static boolean DotNetRuntime = true; -} diff --git a/src/java-runtime/java/mono/android/release/BuildConfig.java b/src/java-runtime/java/mono/android/release/BuildConfig.java deleted file mode 100644 index 4070a147bb1..00000000000 --- a/src/java-runtime/java/mono/android/release/BuildConfig.java +++ /dev/null @@ -1,6 +0,0 @@ -package mono.android; - -public class BuildConfig { - public static boolean Debug = false; - public static boolean DotNetRuntime = false; -}