Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Microsoft.Android.Sdk.ILLink] preserve types with IJniNameProviderAttribute #9099

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions src/Microsoft.Android.Sdk.ILLink/MarkJavaObjects.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
using Mono.Cecil;
using Mono.Linker;
using Mono.Linker.Steps;
using Mono.Tuner;
using Java.Interop.Tools.Cecil;
using Xamarin.Android.Tasks;
using Profile = Microsoft.Android.Sdk.ILLink.Profile;

namespace MonoDroid.Tuner {

Expand All @@ -27,7 +27,14 @@ public override void Initialize (LinkContext context, MarkContext markContext)

bool IsActiveFor (AssemblyDefinition assembly)
{
return assembly.MainModule.HasTypeReference ("System.Net.Http.HttpMessageHandler") || assembly.MainModule.HasTypeReference ("Android.Util.IAttributeSet");
if (Profile.IsSdkAssembly (assembly))
return false;
if (Profile.IsProductAssembly (assembly))
return false;

return assembly.MainModule.HasTypeReference ("System.Net.Http.HttpMessageHandler") ||
assembly.MainModule.HasTypeReference ("Java.Lang.Object") ||
assembly.MainModule.HasTypeReference ("Android.Util.IAttributeSet");
Comment on lines +30 to +37
Copy link
Member Author

Choose a reason for hiding this comment

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

Checking IsSdkAssembly(), IsProductAssembly(), and Java.Lang.Object is what the FixAbstractMethodsStep is already doing, so it seemed appropriate here.

}

public void ProcessAssembly (AssemblyDefinition assembly, string androidHttpClientHandlerType, Dictionary<string, HashSet<string>> customViewMap)
Expand All @@ -47,14 +54,42 @@ public void ProcessAssembly (AssemblyDefinition assembly, string androidHttpClie
}
}

// Custom views in Android .xml files
// Continue if not an IJavaObject
if (!type.ImplementsIJavaObject (cache))
continue;

// Custom views in Android .xml files
if (customViewMap.ContainsKey (type.FullName)) {
Annotations.Mark (type);
PreserveJavaObjectImplementation (type);
continue;
}

// Types with Java.Interop.IJniNameProviderAttribute attributes
if (ShouldPreserveBasedOnAttributes (type)) {
Annotations.Mark (type);
PreserveJavaObjectImplementation (type);
continue;
}
}
}

bool ShouldPreserveBasedOnAttributes (TypeDefinition type)
{
if (!type.HasCustomAttributes)
return false;

foreach (var attr in type.CustomAttributes) {
// Ignore Android.Runtime.RegisterAttribute
if (attr.AttributeType.FullName == "Android.Runtime.RegisterAttribute") {
continue;
}
if (attr.AttributeType.Implements ("Java.Interop.IJniNameProviderAttribute", cache)) {
return true;
}
}

return false;
}

public void ProcessType (TypeDefinition type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,40 @@ public void PreserveIX509TrustManagerSubclasses ([Values(true, false)] bool hasS
}
}

[Test]
public void PreserveServices ()
{
var proj = new XamarinAndroidApplicationProject {
IsRelease = true,
TrimModeRelease = TrimMode.Full,
PackageReferences = {
new Package { Id = "Plugin.Firebase.CloudMessaging", Version = "3.0.0" },
}
};
proj.MainActivity = proj.DefaultMainActivity
.Replace ("//${FIELDS}",
"""
protected override void OnNewIntent (Android.Content.Intent? intent)
{
base.OnNewIntent (intent);
Plugin.Firebase.CloudMessaging.FirebaseCloudMessagingImplementation.OnNewIntent (intent);
}
""")
.Replace ("//${AFTER_ONCREATE}", "Plugin.Firebase.Core.Platforms.Android.CrossFirebase.Initialize (this);");

using var b = CreateApkBuilder ();
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");

var assemblyPath = BuildTest.GetLinkedPath (b, isRelease: true, "Plugin.Firebase.CloudMessaging.dll");
FileAssert.Exists (assemblyPath);
using var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
var types = new [] { "Plugin.Firebase.CloudMessaging.Platforms.Android.MyFirebaseMessagingService" };
foreach (var typeName in types) {
var td = assembly.MainModule.GetType (typeName);
Assert.IsNotNull (td, $"{typeName} should not have been linked out!");
}
}

[Test]
public void DoNotErrorOnPerArchJavaTypeDuplicates ([Values(true, false)] bool enableMarshalMethods)
{
Expand Down
Loading