Skip to content

Commit 25d1f00

Browse files
authored
Bump to xamarin/java.interop/main@07c73009 (#8681)
Context: dotnet/java-interop#1165 Context: dotnet/java-interop@005c914 Context: #8543 Context: dotnet/java-interop@07c7300 Context: #8625 Context: https://github.com/xamarin/monodroid/commit/e3e4f123d8e6c7ca34fb6d9b96a6710a3a877eca Context: https://github.com/xamarin/monodroid/commit/a04b73b30e5bbd81b3773865c313a8084f0a21d1 Context: efbec22 Changes: dotnet/java-interop@8b85462...07c7300 * dotnet/java-interop@07c73009: [Java.Interop] Typemap support for JavaObject & `[JniTypeSignature]` (dotnet/java-interop#1181) * dotnet/java-interop@d529f3be: Bump to xamarin/xamarin-android-tools/main@ed102fc (dotnet/java-interop#1182) * dotnet/java-interop@def5bc0d: [ci] Add API Scan job (dotnet/java-interop#1178) * dotnet/java-interop@d5afa0af: [invocation-overhead] Add generated source files (dotnet/java-interop#1175) * dotnet/java-interop@473ef74c: Bump to xamarin/xamarin-android-tools/main@4889bf0 (dotnet/java-interop#1172) * dotnet/java-interop@005c9141: [Java.Interop] Avoid `Type.GetType()` in `ManagedPeer` (dotnet/java-interop#1168) * dotnet/java-interop@0f1efebd: [Java.Interop] Use PublicApiAnalyzers to ensure we do not break API (dotnet/java-interop#1170) (From the "infinite scream" department…) It started with a desire to remove some linker warnings (dotnet/java-interop#1165): external/Java.Interop/src/Java.Interop/Java.Interop/ManagedPeer.cs(93,19,93,112): warning IL2057: Unrecognized value passed to the parameter 'typeName' of method 'System.Type.GetType(String, Boolean)'. It's not possible to guarantee the availability of the target type. dotnet/java-interop@005c9141 attempted to fix this by requiring the use of "typemaps" mapping Java type signatures to managed types, replacing e.g.: Type type = Type.GetType ("Example.Type, AssemblyName", throwOnError: true)!; Type[] parameterTypes = GetParameterTypes ("System.Int32:System.Int32"); ConstructorInfo ctor = type.GetConstructor (ptypes); // ctor=Example.Type(int, int) constructor with (not exactly, but for expository purposes): Type type = GetTypeFromSignature("crc64…/Type"); Type[] parameterTypes = GetConstructorCandidateParameterTypes ("(II)V"); ConstructorInfo ctor = type.GetConstructor (ptypes); // ctor=Example.Type(int, int) constructor among other changes. This was a *significant* change that would alter *Java.Interop* semantics but *not* .NET Android semantics -- .NET Android uses `Java.Interop.TypeManager.n_Activate()` (in this repo) for Java-side "activation" scenarios, not `Java.Interop.ManagedPeer` -- so in an abundance of caution we did a manual integration test in #8543 to make sure nothing broke before merging it. Something was apparently "off" in that integration. (We're still not sure what was off, or why it was completely green.) Ever since dotnet/java-interop@005c9141 was merged, every attempt to bump xamarin/Java.Interop has failed, in a number of ways described below. However, instead of reverting dotnet/java-interop@005c9141 we took this as an opportunity to understand *how and why* things were failing, as apparently we had encountered some *long-standing* corner cases in How Things Work. The oversights and failures include: 1. In order to make the Java.Interop unit tests work in .NET Android, the (largely hand-written) Java.Interop test types *also* need to participate with .NET Android typemap support, so that there is a typemap entry mapping `net/dot/jni/test/GenericHolder` to `Java.InteropTests.GenericHolder<T>` and vice-versa. dotnet/java-interop@07c73009 updates `Java.Interop.Tools.JavaCallableWrappers` to support creating typemap entries for `Java.Interop.JavaObject` subclasses, introducing a new `TypeDefinition.HasJavaPeer()` extension method. 2. (1) meant that, for the first time ever, types in `Java.Interop-Tests` participated in .NET Android type mapping. This *sounds* fine, except that `Java.Interop-Tests` contains "competing bindings" for `java.lang.Object`: [JniTypeSignature ("java/lang/Object", GenerateJavaPeer=false)] partial class JavaLangRemappingTestObject : JavaObject { } 3. (2) means that, for the first time ever, we *could* have the typemap entry for `java/lang/Object` map to `Java.InteropTests.JavaLangRemappingTestObject, Java.Interop-Tests`, *not* `Java.Lang.Object, Mono.Android`. Arguably a bug, arguably "meh", but this setup triggered some never previously encountered error conditions: 4. `EmbeddedAssemblies::typemap_java_to_managed()` within `libmonodroid.so` returns a `System.Type` that corresponds to a JNI type. `typemap_java_to_managed()` has a bug/corner case wherein it will only provide `Type` instances from assemblies which have already been loaded. Early in startup, `Java.Interop-Tests` hasn't been loaded yet, so when `java/lang/Object` was mapped to `Java.InteropTests.JavaLangRemappingTestObject, Java.Interop-Tests`, `typemap_java_to_managed()` would return `null`. This is a bug/corner case, which is being investigated in #8625. 5. Calls to `Java.Lang.Object.GetObject<T>()` call `Java.Interop.TypeManager.CreateInstance()`, which loops through the type and all base types to find a known binding/wrapper. Because of (3)+(4), if (when) we try to find the wrapper for `java/lang/Object`, we would find *no* mapping. This would cause an `JNI DETECTED ERROR IN APPLICATION` *crash*. This was due to a "use after free" bug. See the "TypeManager.CreateInstance() Use After Free Bug" section. 6. Once (5) is fixed we encounter our next issue: the `Java.InteropTests.JnienvTest.NewOpenGenericTypeThrows()` unit test started failing because `crc641855b07eca6dcc03.GenericHolder_1` couldn't be found. This was caused by a bug in `acw-map.txt` parsing within `<R8/>`. See the "`<R8/>` and `acw-map.txt` parsing.`" section. 7. Once (6) was fixed, (3) caused a *new* set of failures: multiple tests started failing because `java/lang/Object` was being mapped to the wrong managed type. (3) becomes less "meh" and more "definitely a bug". See the "Correct `java/lang/Object` mappings" section. *Now* things should work reliably. ~~ TypeManager.CreateInstance() Use After Free Bug ~~ On 2011-Oct-19, xamarin/monodroid@e3e4f123d8 introduced a use-after-free bug within `TypeManager.CreateInstance()`: JNIEnv.DeleteRef (handle, transfer); throw new NotSupportedException ( FormattableString.Invariant ($"Internal error finding wrapper class for '{JNIEnv.GetClassNameFromInstance (handle)}'. (Where is the Java.Lang.Object wrapper?!)"), CreateJavaLocationException ()); `handle` *cannot be used* after `JNIEnv.DeleteRef(handle)`. Failure to do so results in a `JNI DETECTED ERROR IN APPLICATION` crash; with `adb shell setprop debug.mono.log lref+` set, we see: I monodroid-lref: +l+ lrefc 1 handle 0x71/L from thread '(null)'(1) D monodroid-gref: at Android.Runtime.AndroidObjectReferenceManager.CreatedLocalReference(JniObjectReference , Int32& ) D monodroid-gref: at Java.Interop.JniRuntime.JniObjectReferenceManager.CreatedLocalReference(JniEnvironmentInfo , JniObjectReference ) D monodroid-gref: at Java.Interop.JniEnvironment.LogCreateLocalRef(JniObjectReference ) D monodroid-gref: at Java.Interop.JniEnvironment.LogCreateLocalRef(IntPtr ) D monodroid-gref: at Java.Interop.JniEnvironment.InstanceMethods.CallObjectMethod(JniObjectReference , JniMethodInfo ) D monodroid-gref: … … I monodroid-lref: -l- lrefc 0 handle 0x71/L from thread '(null)'(1) D monodroid-gref: at Android.Runtime.AndroidObjectReferenceManager.DeleteLocalReference(JniObjectReference& , Int32& ) D monodroid-gref: at Java.Interop.JniRuntime.JniObjectReferenceManager.DeleteLocalReference(JniEnvironmentInfo , JniObjectReference& ) D monodroid-gref: at Java.Interop.JniObjectReference.Dispose(JniObjectReference& reference) D monodroid-gref: at Android.Runtime.JNIEnv.DeleteLocalRef(IntPtr ) D monodroid-gref: at Android.Runtime.JNIEnv.DeleteRef(IntPtr , JniHandleOwnership ) D monodroid-gref: at Java.Interop.TypeManager.CreateInstance(IntPtr , JniHandleOwnership , Type ) D monodroid-gref: at Java.Lang.Object.GetObject(IntPtr , JniHandleOwnership , Type ) D monodroid-gref: at Java.Lang.Object._GetObject[IIterator](IntPtr , JniHandleOwnership ) D monodroid-gref: at Java.Lang.Object.GetObject[IIterator](IntPtr handle, JniHandleOwnership transfer) D monodroid-gref: … D monodroid-gref: E droid.NET_Test: JNI ERROR (app bug): accessed stale Local 0x71 (index 7 in a table of size 7) F droid.NET_Test: java_vm_ext.cc:570] JNI DETECTED ERROR IN APPLICATION: use of deleted local reference 0x71 … F droid.NET_Test: runtime.cc:630] native: #13 pc 00000000003ce865 /apex/com.android.runtime/lib64/libart.so (art::(anonymous namespace)::CheckJNI::GetObjectClass(_JNIEnv*, _jobject*)+837) The immediate fix is Don't Do That™; use a temporary: class_name = JNIEnv.GetClassNameFromInstance (handle); JNIEnv.DeleteRef (handle, transfer); throw new NotSupportedException ( FormattableString.Invariant ($"Internal error finding wrapper class for '{class_name}'. (Where is the Java.Lang.Object wrapper?!)"), CreateJavaLocationException ()); Unfortunately, *just* fixing the "use-after-free" bug is insufficient; if we throw that `NotSupportedException`, things *will* break elsewhere. We'll just have an "elegant unhandled exception" app crash instead of a "THE WORLD IS ENDING" failed assertion crash. We could go with the simple fix for the crash, but this means that in order to integrate dotnet/java-interop@005c9141 & dotnet/java-interop@07c73009 we'd have to figure out how to *ensure* that `java/lang/Object` is bound as `Java.Lang.Object, Mono.Android`, not `Java.InteropTests.JavaLangRemappingTestObject, Java.Interop-Tests`. (We actually need to do this *anyway*; see the "Correct `java/lang/Object` mappings" section. At the time we I was trying to *avoid* special-casing `Mono.Android.dll`…) There is a*slightly* more complicated approach which fixes (5) while supporting (4) `typemap_java_to_managed()` returning null; consider the `-l-` callstack: at Android.Runtime.JNIEnv.DeleteRef(IntPtr , JniHandleOwnership ) at Java.Interop.TypeManager.CreateInstance(IntPtr , JniHandleOwnership , Type ) at Java.Lang.Object.GetObject(IntPtr , JniHandleOwnership , Type ) at Java.Lang.Object._GetObject[IIterator](IntPtr , JniHandleOwnership ) at Java.Lang.Object.GetObject[IIterator](IntPtr handle, JniHandleOwnership transfer) at Android.Runtime.JavaSet.Iterator() This is part of a generic `Object.GetObject<IIterator>()` invocation! Additionally, because `IIterator` is an interface, in *normal* use the `type` variable within `TypeManager.CreateInstance()` would be `Java.Lang.Object, Mono.Android` and then *immediately discarded* because `Java.Lang.Object` cannot be assigned to `IIterator`. Moving the type compatibility check to *before* the `type == null` check fixes *an* issue with `typemap_java_to_managed()` returning null. ~~ `<R8/>` and `acw-map.txt` parsing.` ~~ There are many ways for Android+Java code to refer to managed types. For example, consider the following View subclass: namespace Example { partial class MyCoolView : Android.Views.View { // … } } Within layout `.axml` files, you can mention an `Android.Views.View` subclass by: * Using the .NET Full Class Name as an element name. <Example.MyCoolView /> * Using the .NET Full Class Name with a *lowercased* namespace name as the element name. <example.MyCoolView /> * Use the Java-side name directly. <crc64….NiftyView /> Within Fragments, you can also use the *assembly-qualified name*: <fragment class="Example.MyCoolView, AssemblyName" /> At build time, all instances of the .NET type names will be *replaced* with the Java type names before the Android toolchain processes the files. The association between .NET type names and Java names is stored within `$(IntermediateOutputPath)acw-map.txt`, which was introduced in xamarin/monodroid@a04b73b3. *Normally* `acw-map.txt` contains three entries: 1. The fully-qualified .NET type name 2. The .NET type name, no assembly 3. (2) with a lowercased namespace name, *or* the `[Register]` value, if provided. For example: Mono.Android_Test.Library.CustomTextView, Mono.Android-Test.Library.NET;crc6456ab8145c81c4100.CustomTextView Mono.Android_Test.Library.CustomTextView;crc6456ab8145c81c4100.CustomTextView mono.android_test.library.CustomTextView;crc6456ab8145c81c4100.CustomTextView Java.InteropTests.GenericHolder`1, Java.Interop-Tests;net.dot.jni.test.tests.GenericHolder Java.InteropTests.GenericHolder`1;net.dot.jni.test.tests.GenericHolder net.dot.jni.test.tests.GenericHolder;net.dot.jni.test.tests.GenericHolder However, when warning XA4214 is emitted (efbec22), there is a "collision" on the .NET side (but *not* the Java side); (2) and (3) are potentially *ambiguous*, so one .NET type is arbitrarily chosen. (Collisions on the Java side result in XA4215 *errors*.) The first line is still possible, because of assembly qualification. Enter ``Java.InteropTests.GenericHolder`1``: this type is present in *both* `Java.Interop-Tests.dll` *and* `Mono.Android-Tests.dll`. dotnet/java-interop@07c73009, this was "fine" because the `GenericHolder<T>` within `Java.Interop-Tests.dll` did not participate in typemap generation. Now it does, resulting in the XA4214 warning. XA4214 *also* means that instead of three lines, it's *one* line: Java.InteropTests.GenericHolder`1, Mono.Android.NET-Tests;crc641855b07eca6dcc03.GenericHolder_1 Enter `<R8/>`, which parses `acw-map.txt` to create a `proguard_project_primary.cfg` file. `<R8/>` did it's *own* parsing of `acw-map.txt`, parsing only *one of every three lines*, on the assumption that *all* entries took three lines. This breaks in the presence of XA4214, because some entries only take one line, not three lines. This in turn meant that `proguard_project_primary.cfg` could *miss* types, which could mean that `r8` would *remove* the unspecified types, resulting in `ClassNotFoundException` at runtime: Java.Lang.ClassNotFoundException : crc641855b07eca6dcc03.GenericHolder_1 ----> Java.Lang.ClassNotFoundException : Didn't find class "crc641855b07eca6dcc03.GenericHolder_1" on path: DexPathList[[zip file "/data/app/Mono.Android.NET_Tests-2stBqO43ov5F6bHfYemJHQ==/base.apk", zip file "/data/app/Mono.Android.NET_Tests-2stBqO43ov5F6bHfYemJHQ==/split_config.x86_64.apk", zip file "/data/app/Mono.Android.NET_Tests-2stBqO43ov5F6bHfYemJHQ==/split_config.xxhdpi.apk"],nativeLibraryDirectories=[/data/app/Mono.Android.NET_Tests-2stBqO43ov5F6bHfYemJHQ==/lib/x86_64, /system/fake-libs64, /data/app/Mono.Android.NET_Tests-2stBqO43ov5F6bHfYemJHQ==/base.apk!/lib/x86_64, /data/app/Mono.Android.NET_Tests-2stBqO43ov5F6bHfYemJHQ==/split_config.x86_64.apk!/lib/x86_64, /data/app/Mono.Android.NET_Tests-2stBqO43ov5F6bHfYemJHQ==/split_config.xxhdpi.apk!/lib/x86_64, /system/lib64, /system/product/lib64]] at Java.Interop.JniEnvironment.StaticMethods.CallStaticObjectMethod(JniObjectReference , JniMethodInfo , JniArgumentValue* ) at Android.Runtime.JNIEnv.FindClass(String ) Update `<R8/>` to instead use `MonoAndroidHelper.LoadMapFile()`, which reads all lines within `acw-map.txt`. This results in a `proguard_project_primary.cfg` file which properly contains a `-keep` entry for XA4214-related types, such as `crc641855b07eca6dcc03.GenericHolder_1`. ~~ Correct `java/lang/Object` mappings ~~` Previous valiant efforts to allow `java/lang/Object` to be mapped to "anything", not just `Java.Lang.Object, Mono.Android`, eventually resulted in lots of unit test failures, e.g.: `Android.RuntimeTests.XmlReaderPullParserTest.ToLocalJniHandle()`: System.NotSupportedException : Unable to activate instance of type Java.InteropTests.JavaLangRemappingTestObject from native handle 0x19 (key_handle 0x2408476). ----> System.MissingMethodException : No constructor found for Java.InteropTests.JavaLangRemappingTestObject::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership) ----> Java.Interop.JavaLocationException : Exception_WasThrown, Java.Interop.JavaLocationException at Java.Interop.TypeManager.CreateInstance(IntPtr , JniHandleOwnership , Type ) at Java.Interop.TypeManager.CreateInstance(IntPtr , JniHandleOwnership ) at Android.Runtime.XmlResourceParserReader.FromNative(IntPtr , JniHandleOwnership ) at Android.Runtime.XmlResourceParserReader.FromJniHandle(IntPtr handle, JniHandleOwnership transfer) at Android.Content.Res.Resources.GetXml(Int32 ) at Android.RuntimeTests.XmlReaderPullParserTest.ToLocalJniHandle() at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args) at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object , BindingFlags ) --MissingMethodException at Java.Interop.TypeManager.CreateProxy(Type , IntPtr , JniHandleOwnership ) at Java.Interop.TypeManager.CreateInstance(IntPtr , JniHandleOwnership , Type ) With a partially heavy heart, we need to special-case typemap entries by processing `Mono.Android.dll` *first*, so that it gets first dibs at bindings for `java/lang/Object` and other types. Update `NativeTypeMappingData` to process types from `Mono.Android` before processing any other module. Note that the special-casing needs to happen in `NativeTypeMappingData` because typemaps were formerly processed in *sorted module order*, in which the sort order is based on the *byte representation* of the module's MVID (a GUID). Additionally, *linking changes the MVID*, which means module order is *effectively random*. Consequently, trying to special case typemap ordering anywhere else is ineffective. ~~ Other ~~ Update `JavaCompileToolTask` to log the contents of its response file. Update LLVM-IR -related types within `src/Xamarin.Android.Build.Tasks/Utilities` to use `TaskLoggingHelper` for logging purposes, *not* `Action<string>`. Update related types to accept `TaskLoggingHelper`, so that we can more easily add diagnostic messages to these types in the future.
1 parent 1858b55 commit 25d1f00

19 files changed

+110
-46
lines changed

external/Java.Interop

src/Mono.Android/Java.Interop/TypeManager.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,16 +286,20 @@ internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership
286286

287287
JNIEnv.DeleteLocalRef (class_ptr);
288288

289+
if (targetType != null &&
290+
(type == null ||
291+
!targetType.IsAssignableFrom (type))) {
292+
type = targetType;
293+
}
294+
289295
if (type == null) {
296+
class_name = JNIEnv.GetClassNameFromInstance (handle);
290297
JNIEnv.DeleteRef (handle, transfer);
291298
throw new NotSupportedException (
292-
FormattableString.Invariant ($"Internal error finding wrapper class for '{JNIEnv.GetClassNameFromInstance (handle)}'. (Where is the Java.Lang.Object wrapper?!)"),
299+
FormattableString.Invariant ($"Internal error finding wrapper class for '{class_name}'. (Where is the Java.Lang.Object wrapper?!)"),
293300
CreateJavaLocationException ());
294301
}
295302

296-
if (targetType != null && !targetType.IsAssignableFrom (type))
297-
type = targetType;
298-
299303
if (type.IsInterface || type.IsAbstract) {
300304
var invokerType = JavaObjectExtensions.GetInvokerType (type);
301305
if (invokerType == null)

src/Xamarin.Android.Build.Tasks/Tasks/GenerateCompressedAssembliesNativeSourceFiles.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void GenerateCompressedAssemblySources ()
7474

7575
void Generate (IDictionary<string, CompressedAssemblyInfo> dict)
7676
{
77-
var composer = new CompressedAssembliesNativeAssemblyGenerator (dict);
77+
var composer = new CompressedAssembliesNativeAssemblyGenerator (Log, dict);
7878
LLVMIR.LlvmIrModule compressedAssemblies = composer.Construct ();
7979

8080
foreach (string abi in SupportedAbis) {

src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ void SaveResource (string resource, string filename, string destDir, Func<string
570570

571571
void WriteTypeMappings (List<JavaType> types, TypeDefinitionCache cache)
572572
{
573-
var tmg = new TypeMapGenerator ((string message) => Log.LogDebugMessage (message), SupportedAbis);
573+
var tmg = new TypeMapGenerator (Log, SupportedAbis);
574574
if (!tmg.Generate (Debug, SkipJniAddNativeMethodRegistrationAttributeScan, types, cache, TypemapOutputDirectory, GenerateNativeAssembly, out ApplicationConfigTaskState appConfState)) {
575575
throw new XamarinAndroidException (4308, Properties.Resources.XA4308);
576576
}

src/Xamarin.Android.Build.Tasks/Tasks/GenerateJniRemappingNativeCode.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public override bool RunTask ()
5454

5555
void GenerateEmpty ()
5656
{
57-
Generate (new JniRemappingAssemblyGenerator (), typeReplacementsCount: 0);
57+
Generate (new JniRemappingAssemblyGenerator (Log), typeReplacementsCount: 0);
5858
}
5959

6060
void Generate ()
@@ -74,7 +74,7 @@ void Generate ()
7474
}
7575
}
7676

77-
Generate (new JniRemappingAssemblyGenerator (typeReplacements, methodReplacements), typeReplacements.Count);
77+
Generate (new JniRemappingAssemblyGenerator (Log, typeReplacements, methodReplacements), typeReplacements.Count);
7878
}
7979

8080
void Generate (JniRemappingAssemblyGenerator jniRemappingComposer, int typeReplacementsCount)

src/Xamarin.Android.Build.Tasks/Tasks/GeneratePackageManagerJava.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -386,13 +386,13 @@ void AddEnvironment ()
386386

387387
if (enableMarshalMethods) {
388388
marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator (
389+
Log,
389390
assemblyCount,
390391
uniqueAssemblyNames,
391-
marshalMethodsState?.MarshalMethods,
392-
Log
392+
marshalMethodsState?.MarshalMethods
393393
);
394394
} else {
395-
marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator (assemblyCount, uniqueAssemblyNames);
395+
marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator (Log, assemblyCount, uniqueAssemblyNames);
396396
}
397397
LLVMIR.LlvmIrModule marshalMethodsModule = marshalMethodsAsmGen.Construct ();
398398

src/Xamarin.Android.Build.Tasks/Tasks/JavaCompileToolTask.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ private void GenerateResponseFile ()
9090
file.Replace (@"\", @"\\").Normalize (NormalizationForm.FormC)));
9191
}
9292
}
93+
Log.LogDebugMessage ($"javac response file contents: {TemporarySourceListFile}");
94+
foreach (var line in File.ReadLines (TemporarySourceListFile)) {
95+
Log.LogDebugMessage ($" {line}");
96+
}
9397
}
9498
}
9599
}

src/Xamarin.Android.Build.Tasks/Tasks/R8.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using Microsoft.Build.Framework;
23
using Microsoft.Build.Utilities;
34
using System.Collections.Generic;
@@ -82,16 +83,15 @@ protected override CommandLineBuilder GetCommandLineBuilder ()
8283

8384
if (EnableShrinking) {
8485
if (!string.IsNullOrEmpty (AcwMapFile)) {
85-
var acwLines = File.ReadAllLines (AcwMapFile);
86+
var acwMap = MonoAndroidHelper.LoadMapFile (BuildEngine4, Path.GetFullPath (AcwMapFile), StringComparer.OrdinalIgnoreCase);
87+
var javaTypes = new List<string> (acwMap.Values.Count);
88+
foreach (var v in acwMap.Values) {
89+
javaTypes.Add (v);
90+
}
91+
javaTypes.Sort (StringComparer.Ordinal);
8692
using (var appcfg = File.CreateText (ProguardGeneratedApplicationConfiguration)) {
87-
for (int i = 0; i + 2 < acwLines.Length; i += 3) {
88-
try {
89-
var line = acwLines [i + 2];
90-
var java = line.Substring (line.IndexOf (';') + 1);
91-
appcfg.WriteLine ("-keep class " + java + " { *; }");
92-
} catch {
93-
// skip invalid lines
94-
}
93+
foreach (var java in javaTypes) {
94+
appcfg.WriteLine ($"-keep class {java} {{ *; }}");
9595
}
9696
}
9797
}

src/Xamarin.Android.Build.Tasks/Utilities/ApplicationConfigNativeAssemblyGenerator.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Java.Interop.Tools.TypeNameMappings;
77
using Microsoft.Build.Framework;
88
using Microsoft.Build.Utilities;
9+
using Microsoft.Android.Build.Tasks;
910
using Xamarin.Android.Tasks.LLVMIR;
1011

1112
namespace Xamarin.Android.Tasks
@@ -135,7 +136,6 @@ sealed class XamarinAndroidBundledAssembly
135136

136137
SortedDictionary <string, string>? environmentVariables;
137138
SortedDictionary <string, string>? systemProperties;
138-
TaskLoggingHelper log;
139139
StructureInstance? application_config;
140140
List<StructureInstance<DSOCacheEntry>>? dsoCache;
141141
List<StructureInstance<XamarinAndroidBundledAssembly>>? xamarinAndroidBundledAssemblies;
@@ -172,6 +172,7 @@ sealed class XamarinAndroidBundledAssembly
172172
public bool MarshalMethodsEnabled { get; set; }
173173

174174
public ApplicationConfigNativeAssemblyGenerator (IDictionary<string, string> environmentVariables, IDictionary<string, string> systemProperties, TaskLoggingHelper log)
175+
: base (log)
175176
{
176177
if (environmentVariables != null) {
177178
this.environmentVariables = new SortedDictionary<string, string> (environmentVariables, StringComparer.Ordinal);
@@ -180,8 +181,6 @@ public ApplicationConfigNativeAssemblyGenerator (IDictionary<string, string> env
180181
if (systemProperties != null) {
181182
this.systemProperties = new SortedDictionary<string, string> (systemProperties, StringComparer.Ordinal);
182183
}
183-
184-
this.log = log;
185184
}
186185

187186
protected override void Construct (LlvmIrModule module)
@@ -322,7 +321,7 @@ List<StructureInstance<DSOCacheEntry>> InitDSOCache ()
322321
continue;
323322
}
324323

325-
dsos.Add ((name, $"dsoName{dsos.Count.ToString (CultureInfo.InvariantCulture)}", ELFHelper.IsEmptyAOTLibrary (log, item.ItemSpec)));
324+
dsos.Add ((name, $"dsoName{dsos.Count.ToString (CultureInfo.InvariantCulture)}", ELFHelper.IsEmptyAOTLibrary (Log, item.ItemSpec)));
326325
}
327326

328327
var dsoCache = new List<StructureInstance<DSOCacheEntry>> ();

src/Xamarin.Android.Build.Tasks/Utilities/CompressedAssembliesNativeAssemblyGenerator.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
22
using System.Collections.Generic;
33

4+
using Microsoft.Build.Utilities;
5+
46
using Xamarin.Android.Tasks.LLVMIR;
57

68
namespace Xamarin.Android.Tasks
@@ -66,7 +68,8 @@ sealed class CompressedAssemblies
6668
StructureInfo compressedAssemblyDescriptorStructureInfo;
6769
StructureInfo compressedAssembliesStructureInfo;
6870

69-
public CompressedAssembliesNativeAssemblyGenerator (IDictionary<string, CompressedAssemblyInfo> assemblies)
71+
public CompressedAssembliesNativeAssemblyGenerator (TaskLoggingHelper log, IDictionary<string, CompressedAssemblyInfo> assemblies)
72+
: base (log)
7073
{
7174
this.assemblies = assemblies;
7275
}

0 commit comments

Comments
 (0)