From b45de0ac7b4ac34ad9574cb875a0c063526d4bb5 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 23 Jul 2019 14:45:29 -0400 Subject: [PATCH 01/21] [Mono.Android-Tests] Run Java.Interop tests as well. Context: https://github.com/xamarin/java.interop/pull/454 Context: https://github.com/xamarin/monodroid/commit/e318861e Context: https://github.com/xamarin/xamarin-android/commit/7d32ef3e6 Context: https://github.com/xamarin/xamarin-android/commit/1a2eb953af76b76b2443b744894523ddfe239ecf When use of `Java.Interop.dll` was originally added in xamarin/monodroid@e318861e, it didn't implement the "full" `JniRuntime` abstraction, which meant that until xamarin/xamarin-android@1a2eb953, trying to instantiate a `JavaInt32Array` instance would result in a `NotImplementedException`, because `Android.Runtime.AndroidValueManager.AddPeer()` threw a `NotImplementedException`. Commit xamarin/xamarin-android@1a2eb953 removed the exception but didn't *implement* `JniRuntime.JniValueManager.AddPeer()`, meaning even though a `JavaInt32Array` could be *instantiated*, it wouldn't *work* "properly", e.g. `JniRuntime.JniValueManager.PeekPeer()` wouldn't *find* the `JavaInt32Array` when given the same handle. This in turn "happened" because `Mono.Android-Tests.dll` never *executed* the unit tests for `Java.Interop.dll`, which it *couldn't* do, because it didn't fully support the semantics. Add the `Java.Interop.dll` unit tests to `Mono.Android-Tests.dll`, and fix `Mono.Android.dll` and company so that they can actually *pass*: * Add a new `Java.Interop-Tests.csproj` project to "host" the Java.Interop unit tests in a MonoAndroid-profile project. * Add `java-interop.jar` to the `javac` command line generated by `Jar.targets`, so that e.g. `com.xamarin.java_interop.ManagedPeer` can be used. * Update `Mono.Android.dll` so that the Java.Interop unit tests work. This includes "migrating" the (jobject => instance) mapping previously accessible via `Java.Lang.Object.GetObject()` into `Android.Runtime.AndroidValueManager`. * `AndroidRuntime.GetExceptionForThrowable()` will now "unwrap" a `Java.Interop.JavaProxyThrowable` instance. * `AndroidTypeManager.GetSimpleReferences()` can't use `JNIEnv.GetJniName()` because that always returns `java/lang/Object`, even if a type can't be found, which breaks several Java.Interop unit tests. Use `JNIEnv.monodroid_typemap_managed_to_java()` instead. * `AndroidTypeManager.RegisterNativeMembers()` will now invoke `JniRuntime.JniTypeManager.RegisterNativeMembers()` when `methods` is empty, so that classes can handle their own registration. This was needed so that `Java.InteropTests.CallVirtualFromConstructorDerived` could actually be properly instantiated and participate in tests. * `Java.Interop.TypeManager.CreateProxy()` now supports Java.Interop-style `(ref JniObjectReference, JniObjectReferenceOptions)` constructors. * `Java.Interop.JavaObject` and `Java.Interop.JavaException` are now bridgeable types, and can participate in GC's. This means that e.g. `JavaInt32Array` instances won't be prematurely collected. TODO: * `Java.Lang.Object` should be updated to inherit from `Java.Interop.JavaObject` * `Java.Lang.Throwable` should be updated to inherit from `Java.Interop.JavaException` * `generator` needs to be updated to begin *avoiding* the `JNIEnv` methods, so that non-`Java.Lang.*`-inheriting types can be used. --- Xamarin.Android-Tests.sln | 24 ++ build-tools/scripts/Jar.targets | 9 +- .../Scenarios/Scenario_PrepareExternal.cs | 23 ++ .../xaprepare/xaprepare/xaprepare.csproj | 1 + .../Android.Runtime/AndroidRuntime.cs | 351 +++++++++++++++++- .../Android.Runtime/InputStreamInvoker.cs | 4 +- src/Mono.Android/Android.Runtime/JNIEnv.cs | 3 + .../Android.Runtime/JavaCollection.cs | 4 +- .../Android.Runtime/JavaDictionary.cs | 4 +- src/Mono.Android/Android.Runtime/JavaList.cs | 4 +- src/Mono.Android/Android.Runtime/JavaSet.cs | 4 +- .../Android.Runtime/OutputStreamInvoker.cs | 4 +- .../Android.Runtime/XmlPullParserReader.cs | 8 +- src/Mono.Android/Java.Interop/JavaConvert.cs | 4 +- .../Java.Interop/JavaObjectExtensions.cs | 2 +- src/Mono.Android/Java.Interop/Runtime.cs | 9 +- src/Mono.Android/Java.Interop/TypeManager.cs | 38 +- src/Mono.Android/Java.Lang/Object.cs | 236 +----------- src/Mono.Android/Java.Lang/Throwable.cs | 25 +- .../Test/Java.Interop-Tests/.gitignore | 1 + .../Java.Interop-Tests.csproj | 86 +++++ .../Java.Interop-Tests.targets | 24 ++ .../JavaInterop_Tests_Reference.cs | 9 + .../Properties/AssemblyInfo.cs | 30 ++ .../Resources/AboutResources.txt | 44 +++ .../Test/Mono.Android-Tests.csproj | 4 + .../NUnitInstrumentation.cs | 5 +- .../TestInstrumentation.cs | 1 + src/monodroid/jni/monodroid-glue.cc | 11 +- src/monodroid/jni/osbridge.cc | 12 +- src/monodroid/jni/osbridge.hh | 16 +- .../Mono.Android-TestsMultiDex.csproj | 4 + tests/TestRunner.Core/TestRunner.Core.csproj | 5 +- .../TestRunner.NUnit/TestRunner.NUnit.csproj | 5 +- 34 files changed, 714 insertions(+), 300 deletions(-) create mode 100644 build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs create mode 100644 src/Mono.Android/Test/Java.Interop-Tests/.gitignore create mode 100644 src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj create mode 100644 src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.targets create mode 100644 src/Mono.Android/Test/Java.Interop-Tests/Java.InteropTests/JavaInterop_Tests_Reference.cs create mode 100644 src/Mono.Android/Test/Java.Interop-Tests/Properties/AssemblyInfo.cs create mode 100644 src/Mono.Android/Test/Java.Interop-Tests/Resources/AboutResources.txt diff --git a/Xamarin.Android-Tests.sln b/Xamarin.Android-Tests.sln index 0d6de66b5dc..ee7d94b987e 100644 --- a/Xamarin.Android-Tests.sln +++ b/Xamarin.Android-Tests.sln @@ -90,6 +90,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android-Test.Library", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android-TestsMultiDex", "tests\Runtime-MultiDex\Mono.Android-TestsMultiDex.csproj", "{9ECBEA14-B79F-4F92-9266-495C03A32571}" EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Interop-Tests", "external\Java.Interop\src\Java.Interop\Tests\Interop-Tests.shproj", "{0ADB8D72-7479-49AF-8809-E03AE4A4EAE2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Linq.Expressions", "external\Java.Interop\lib\mono.linq.expressions\Mono.Linq.Expressions.csproj", "{0C001D50-4176-45AE-BDC8-BA626508B0CC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop.GenericMarshaler", "external\Java.Interop\src\Java.Interop.GenericMarshaler\Java.Interop.GenericMarshaler.csproj", "{D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop-Tests", "src\Mono.Android\Test\Java.Interop-Tests\Java.Interop-Tests.csproj", "{6CB00820-A66B-43E5-8785-ED456C6E9F39}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{0ab4956e-6fb9-4da0-9d49-ab65a3ff403a}*SharedItemsImports = 13 @@ -249,6 +257,18 @@ Global {9ECBEA14-B79F-4F92-9266-495C03A32571}.Release|Any CPU.ActiveCfg = Release|Any CPU {9ECBEA14-B79F-4F92-9266-495C03A32571}.Release|Any CPU.Build.0 = Release|Any CPU {9ECBEA14-B79F-4F92-9266-495C03A32571}.Release|Any CPU.Deploy.0 = Release|Any CPU + {0C001D50-4176-45AE-BDC8-BA626508B0CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C001D50-4176-45AE-BDC8-BA626508B0CC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C001D50-4176-45AE-BDC8-BA626508B0CC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C001D50-4176-45AE-BDC8-BA626508B0CC}.Release|Any CPU.Build.0 = Release|Any CPU + {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}.Release|Any CPU.Build.0 = Release|Any CPU + {6CB00820-A66B-43E5-8785-ED456C6E9F39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CB00820-A66B-43E5-8785-ED456C6E9F39}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CB00820-A66B-43E5-8785-ED456C6E9F39}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CB00820-A66B-43E5-8785-ED456C6E9F39}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -284,6 +304,10 @@ Global {0AB4956E-6FB9-4DA0-9D49-AB65A3FF403A} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {8CB5FF58-FF95-43B9-9064-9ACE9525866F} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {9ECBEA14-B79F-4F92-9266-495C03A32571} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} + {0ADB8D72-7479-49AF-8809-E03AE4A4EAE2} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} + {0C001D50-4176-45AE-BDC8-BA626508B0CC} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} + {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} + {6CB00820-A66B-43E5-8785-ED456C6E9F39} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8643CD20-B195-4919-8135-27549488237E} diff --git a/build-tools/scripts/Jar.targets b/build-tools/scripts/Jar.targets index 327013349b9..107b118a7cf 100644 --- a/build-tools/scripts/Jar.targets +++ b/build-tools/scripts/Jar.targets @@ -25,10 +25,15 @@ <_Jar>"$(JarPath)" <_Targets>-source $(_JavacSourceVersion) -target $(_JavacTargetVersion) <_DestDir>$(IntermediateOutputPath)__CreateTestJarFile-bin - <_AndroidJar>-cp "$(AndroidSdkDirectory)\platforms\android-$(_AndroidApiLevelName)\android.jar" + <_AndroidJar>-bootclasspath "$(AndroidSdkDirectory)\platforms\android-$(_AndroidApiLevelName)\android.jar" + <_JIJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java-interop.jar + <_JIJar_System>$(MSBuildExtensionsPath)\Xamarin\Android\java-interop.jar + <_JIJar Condition=" Exists ($(_JIJar_InTree)) ">$(_JIJar_InTree) + <_JIJar Condition=" '$(_JIJar)' == '' ">$(_JIJar_System) + <_CP>-cp "$(_JIJar)" - + + diff --git a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs index f0fc6bd0f22..4953d5ab785 100644 --- a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs +++ b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs @@ -36,14 +36,23 @@ public override string GetCurrentManagedThreadStackTrace (int skipFrames, bool f .ToString (); } - public override Exception GetExceptionForThrowable (ref JniObjectReference value, JniObjectReferenceOptions transfer) + public override Exception GetExceptionForThrowable (ref JniObjectReference reference, JniObjectReferenceOptions options) { - var throwable = Java.Lang.Object.GetObject(value.Handle, JniHandleOwnership.DoNotTransfer); - JniObjectReference.Dispose (ref value, transfer); - var p = throwable as JavaProxyThrowable; - if (p != null) - return p.InnerException; - return throwable; + if (!reference.IsValid) + return null; + var peeked = JNIEnv.AndroidValueManager.PeekPeer (reference); + var peekedExc = peeked as Exception; + if (peekedExc == null) { + var throwable = Java.Lang.Object.GetObject (reference.Handle, JniHandleOwnership.DoNotTransfer); + JniObjectReference.Dispose (ref reference, options); + return throwable; + } + JniObjectReference.Dispose (ref reference, options); + var unwrapped = JNIEnv.AndroidValueManager.UnboxException (peeked); + if (unwrapped != null) { + return unwrapped; + } + return peekedExc; } public override void RaisePendingException (Exception pendingException) @@ -222,11 +231,12 @@ protected override IEnumerable GetTypesForSimpleReference (string jniSimpl protected override IEnumerable GetSimpleReferences (Type type) { - var j = JNIEnv.GetJniName (type); - if (j == null) + var j = JNIEnv.monodroid_typemap_managed_to_java (type.FullName + ", " + type.Assembly.GetName ().Name); + if (j == IntPtr.Zero) return base.GetSimpleReferences (type); + var s = Marshal.PtrToStringAnsi (j); return base.GetSimpleReferences (type) - .Concat (Enumerable.Repeat (j, 1)); + .Concat (new [] { s }); } delegate Delegate GetCallbackHandler (); @@ -318,17 +328,21 @@ static bool CallRegisterMethodByIndex (JniNativeMethodRegistrationArguments argu } } - public override void RegisterNativeMembers (JniType jniType, Type type, string methods) + public override void RegisterNativeMembers (JniType nativeClass, Type type, string methods) { - if (FastRegisterNativeMembers (jniType, type, methods)) + if (FastRegisterNativeMembers (nativeClass, type, methods)) return; - if (methods == null) + if (string.IsNullOrEmpty (methods)) { + base.RegisterNativeMembers (nativeClass, type, methods); return; + } string[] members = methods.Split ('\n'); - if (members.Length == 0) + if (members.Length < 2) { + base.RegisterNativeMembers (nativeClass, type, methods); return; + } JniNativeMethodRegistration[] natives = new JniNativeMethodRegistration [members.Length-1]; for (int i = 0; i < members.Length; ++i) { @@ -351,41 +365,344 @@ public override void RegisterNativeMembers (JniType jniType, Type type, string m natives [i] = new JniNativeMethodRegistration (toks [0], toks [1], callback); } - JniEnvironment.Types.RegisterNatives (jniType.PeerReference, natives, natives.Length); + JniEnvironment.Types.RegisterNatives (nativeClass.PeerReference, natives, natives.Length); } } class AndroidValueManager : JniRuntime.JniValueManager { + Dictionary instances = new Dictionary (); + public override void WaitForGCBridgeProcessing () { JNIEnv.WaitForBridgeProcessing (); } + public override IJavaPeerable CreatePeer (ref JniObjectReference reference, JniObjectReferenceOptions options, Type targetType) + { + if (!reference.IsValid) + return null; + + var peer = Java.Interop.TypeManager.CreateInstance (reference.Handle, JniHandleOwnership.DoNotTransfer, targetType) as IJavaPeerable; + JniObjectReference.Dispose (ref reference, options); + return peer; + } + public override void AddPeer (IJavaPeerable value) { + if (value == null) + throw new ArgumentNullException (nameof (value)); + if (!value.PeerReference.IsValid) + throw new ArgumentException ("Must have a valid JNI object reference!", nameof (value)); + + var reference = value.PeerReference; + var hash = JNIEnv.IdentityHash (reference.Handle); + + AddPeer (value, reference, hash); + } + + internal void AddPeer (IJavaPeerable value, JniObjectReference reference, IntPtr hash) + { + lock (instances) { + IdentityHashTargets targets; + if (!instances.TryGetValue (hash, out targets)) { + targets = new IdentityHashTargets (value); + instances.Add (hash, targets); + return; + } + bool found = false; + for (int i = 0; i < targets.Count; ++i) { + IJavaPeerable target; + var wref = targets [i]; + if (ShouldReplaceMapping (wref, reference, out target)) { + found = true; + targets [i] = IdentityHashTargets.CreateWeakReference (value); + break; + } + if (JniEnvironment.Types.IsSameObject (value.PeerReference, target.PeerReference)) { + found = true; + if (Logger.LogGlobalRef) { + Logger.Log (LogLevel.Info, "monodroid-gref", + string.Format ("warning: not replacing previous registered handle {0} with handle {1} for key_handle 0x{2}", + target.PeerReference.ToString (), reference.ToString (), hash.ToString ("x"))); + } + } + } + if (!found) { + targets.Add (value); + } + } + } + + internal void AddPeer (IJavaPeerable value, IntPtr handle, JniHandleOwnership transfer, out IntPtr handleField) + { + if (handle == IntPtr.Zero) { + handleField = handle; + return; + } + + var transferType = transfer & (JniHandleOwnership.DoNotTransfer | JniHandleOwnership.TransferLocalRef | JniHandleOwnership.TransferGlobalRef); + switch (transferType) { + case JniHandleOwnership.DoNotTransfer: + handleField = JNIEnv.NewGlobalRef (handle); + break; + case JniHandleOwnership.TransferLocalRef: + handleField = JNIEnv.NewGlobalRef (handle); + JNIEnv.DeleteLocalRef (handle); + break; + case JniHandleOwnership.TransferGlobalRef: + handleField = handle; + break; + default: + throw new ArgumentOutOfRangeException ("transfer", transfer, + "Invalid `transfer` value: " + transfer + " on type " + value.GetType ()); + } + if (handleField == IntPtr.Zero) + throw new InvalidOperationException ("Unable to allocate Global Reference for object '" + value.ToString () + "'!"); + + IntPtr hash = JNIEnv.IdentityHash (handleField); + value.SetJniIdentityHashCode ((int) hash); + if ((transfer & JniHandleOwnership.DoNotRegister) == 0) { + AddPeer (value, new JniObjectReference (handleField, JniObjectReferenceType.Global), hash); + } + + if (Logger.LogGlobalRef) { + JNIEnv._monodroid_gref_log ("handle 0x" + handleField.ToString ("x") + + "; key_handle 0x" + hash.ToString ("x") + + ": Java Type: `" + JNIEnv.GetClassNameFromInstance (handleField) + "`; " + + "MCW type: `" + value.GetType ().FullName + "`\n"); + } + } + + bool ShouldReplaceMapping (WeakReference current, JniObjectReference reference, out IJavaPeerable target) + { + target = null; + + if (current == null) + return true; + + // Target has been GC'd; see also FIXME, above, in finalizer + if (!current.TryGetTarget (out target) || target == null) + return true; + + // It's possible that the instance was GC'd, but the finalizer + // hasn't executed yet, so the `instances` entry is stale. + if (!target.PeerReference.IsValid) + return true; + + if (!JniEnvironment.Types.IsSameObject (target.PeerReference, reference)) + return false; + + // JNIEnv.NewObject/JNIEnv.CreateInstance() compatibility. + // When two MCW's are created for one Java instance [0], + // we want the 2nd MCW to replace the 1st, as the 2nd is + // the one the dev created; the 1st is an implicit intermediary. + // + // [0]: If Java ctor invokes overridden virtual method, we'll + // transition into managed code w/o a registered instance, and + // thus will create an "intermediary" via + // (IntPtr, JniHandleOwnership) .ctor. + if ((target.JniManagedPeerState & JniManagedPeerStates.Replaceable) == JniManagedPeerStates.Replaceable) + return true; + + return false; } public override void RemovePeer (IJavaPeerable value) { + if (value == null) + throw new ArgumentNullException (nameof (value)); + if (!value.PeerReference.IsValid) + throw new ArgumentException ("Must have a valid JNI object reference!", nameof (value)); + + var reference = value.PeerReference; + var hash = JNIEnv.IdentityHash (reference.Handle); + + RemovePeer (value, hash); + } + + internal void RemovePeer (IJavaPeerable value, IntPtr hash) + { + lock (instances) { + IdentityHashTargets targets; + if (!instances.TryGetValue (hash, out targets)) { + return; + } + for (int i = targets.Count - 1; i >= 0; i--) { + var wref = targets [i]; + if (!wref.TryGetTarget (out IJavaPeerable target)) { + // wref is invalidated; remove it. + targets.RemoveAt (i); + continue; + } + if (!object.ReferenceEquals (target, value)) { + continue; + } + targets.RemoveAt (i); + } + if (targets.Count == 0) { + instances.Remove (hash); + } + } } public override IJavaPeerable PeekPeer (JniObjectReference reference) { - return (IJavaPeerable) Java.Lang.Object.GetObject (reference.Handle, JniHandleOwnership.DoNotTransfer); + if (!reference.IsValid) + return null; + + var hash = JNIEnv.IdentityHash (reference.Handle); + lock (instances) { + IdentityHashTargets targets; + if (instances.TryGetValue (hash, out targets)) { + for (int i = targets.Count - 1; i >= 0; i--) { + var wref = targets [i]; + if (!wref.TryGetTarget (out var result) || !result.PeerReference.IsValid) { + targets.RemoveAt (i); + continue; + } + if (!JniEnvironment.Types.IsSameObject (reference, result.PeerReference)) + continue; + return result; + } + } + } + return null; + } + + protected override bool TryUnboxPeerObject (IJavaPeerable value, out object result) + { + var proxy = value as JavaProxyThrowable; + if (proxy != null) { + result = proxy.InnerException; + return true; + } + return base.TryUnboxPeerObject (value, out result); + } + + internal Exception UnboxException (IJavaPeerable value) + { + object r; + if (TryUnboxPeerObject (value, out r) && r is Exception e) { + return e; + } + return null; } public override void CollectPeers () { + GC.Collect (); } public override void FinalizePeer (IJavaPeerable value) { + if (value == null) + throw new ArgumentNullException (nameof (value)); + + if (Logger.LogGlobalRef) { + JNIEnv._monodroid_gref_log ($"Finalizing handle {value.PeerReference}\n"); + } + + // FIXME: need hash cleanup mechanism. + // Finalization occurs after a test of java persistence. If the + // handle still contains a java reference, we can't finalize the + // object and should "resurrect" it. + if (value.PeerReference.IsValid) { + GC.ReRegisterForFinalize (value); + } else { + RemovePeer (value, (IntPtr) value.JniIdentityHashCode); + value.SetPeerReference (new JniObjectReference ()); + value.Finalized (); + } } public override List GetSurfacedPeers () { - return null; + lock (instances) { + var surfacedPeers = new List (instances.Count); + foreach (var e in instances) { + for (int i = 0; i < e.Value.Count; i++) { + var value = e.Value [i]; + surfacedPeers.Add (new JniSurfacedPeerInfo (e.Key.ToInt32 (), value)); + } + } + return surfacedPeers; + } + } + } + + class InstancesKeyComparer : IEqualityComparer + { + + public bool Equals (IntPtr x, IntPtr y) + { + return x == y; + } + + public int GetHashCode (IntPtr value) + { + return value.GetHashCode (); + } + } + + class IdentityHashTargets { + WeakReference first; + List> rest; + + public static WeakReference CreateWeakReference (IJavaPeerable value) + { + return new WeakReference (value, trackResurrection: true); + } + + public IdentityHashTargets (IJavaPeerable value) + { + first = CreateWeakReference (value); + } + + public int Count => (first != null ? 1 : 0) + (rest != null ? rest.Count : 0); + + public WeakReference this [int index] { + get { + if (index == 0) + return first; + index -= 1; + if (rest == null || index >= rest.Count) + return null; + return rest [index]; + } + set { + if (index == 0) { + first = value; + return; + } + index -= 1; + rest [index] = value; + } + } + + public void Add (IJavaPeerable value) + { + if (first == null) { + first = CreateWeakReference (value); + return; + } + if (rest == null) + rest = new List> (); + rest.Add (CreateWeakReference (value)); + } + + public void RemoveAt (int index) + { + if (index == 0) { + first = null; + if (rest?.Count > 0) { + first = rest [0]; + rest.RemoveAt (0); + } + return; + } + index -= 1; + rest.RemoveAt (index); } } } diff --git a/src/Mono.Android/Android.Runtime/InputStreamInvoker.cs b/src/Mono.Android/Android.Runtime/InputStreamInvoker.cs index 484f70207a7..da48df7bda8 100644 --- a/src/Mono.Android/Android.Runtime/InputStreamInvoker.cs +++ b/src/Mono.Android/Android.Runtime/InputStreamInvoker.cs @@ -122,10 +122,10 @@ public static Stream FromJniHandle (IntPtr handle, JniHandleOwnership transfer) if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) - inst = Java.Interop.TypeManager.CreateInstance (handle, transfer); + inst = (IJavaObject) Java.Interop.TypeManager.CreateInstance (handle, transfer); else JNIEnv.DeleteRef (handle, transfer); diff --git a/src/Mono.Android/Android.Runtime/JNIEnv.cs b/src/Mono.Android/Android.Runtime/JNIEnv.cs index 98a78239cc9..fe7a10aae70 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnv.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnv.cs @@ -61,6 +61,8 @@ public static partial class JNIEnv { static AndroidRuntime androidRuntime; static BoundExceptionType BoundExceptionType; + internal static AndroidValueManager AndroidValueManager; + [DllImport ("__Internal", CallingConvention = CallingConvention.Cdecl)] extern static void monodroid_log (LogLevel level, LogCategories category, string message); @@ -166,6 +168,7 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args) BoundExceptionType = (BoundExceptionType)args->ioExceptionType; androidRuntime = new AndroidRuntime (args->env, args->javaVm, androidSdkVersion > 10, args->grefLoader, args->Loader_loadClass); + AndroidValueManager = (AndroidValueManager) androidRuntime.ValueManager; AllocObjectSupported = androidSdkVersion > 10; IsRunningOnDesktop = args->isRunningOnDesktop == 1; diff --git a/src/Mono.Android/Android.Runtime/JavaCollection.cs b/src/Mono.Android/Android.Runtime/JavaCollection.cs index 8a0a83cb20f..7eedb3f4ae5 100644 --- a/src/Mono.Android/Android.Runtime/JavaCollection.cs +++ b/src/Mono.Android/Android.Runtime/JavaCollection.cs @@ -178,7 +178,7 @@ public static ICollection FromJniHandle (IntPtr handle, JniHandleOwnership trans if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) inst = new JavaCollection (handle, transfer); else @@ -397,7 +397,7 @@ public static ICollection FromJniHandle (IntPtr handle, JniHandleOwnership tr if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) inst = new JavaCollection (handle, transfer); else diff --git a/src/Mono.Android/Android.Runtime/JavaDictionary.cs b/src/Mono.Android/Android.Runtime/JavaDictionary.cs index 49f618ea7c2..4593d334779 100644 --- a/src/Mono.Android/Android.Runtime/JavaDictionary.cs +++ b/src/Mono.Android/Android.Runtime/JavaDictionary.cs @@ -359,7 +359,7 @@ public static IDictionary FromJniHandle (IntPtr handle, JniHandleOwnership trans if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) inst = new JavaDictionary (handle, transfer); else @@ -630,7 +630,7 @@ public static IDictionary FromJniHandle (IntPtr handle, JniHandleOwnership if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) inst = new JavaDictionary (handle, transfer); else diff --git a/src/Mono.Android/Android.Runtime/JavaList.cs b/src/Mono.Android/Android.Runtime/JavaList.cs index b260b101e78..f771ef8f6f0 100644 --- a/src/Mono.Android/Android.Runtime/JavaList.cs +++ b/src/Mono.Android/Android.Runtime/JavaList.cs @@ -480,7 +480,7 @@ public static IList FromJniHandle (IntPtr handle, JniHandleOwnership transfer) if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) inst = new JavaList (handle, transfer); else @@ -936,7 +936,7 @@ public static IList FromJniHandle (IntPtr handle, JniHandleOwnership transfer if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle, typeof (IList)); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle, typeof (IList)); if (inst == null) inst = new JavaList (handle, transfer); else diff --git a/src/Mono.Android/Android.Runtime/JavaSet.cs b/src/Mono.Android/Android.Runtime/JavaSet.cs index d01d4eca4bf..ccf9a03a985 100644 --- a/src/Mono.Android/Android.Runtime/JavaSet.cs +++ b/src/Mono.Android/Android.Runtime/JavaSet.cs @@ -243,7 +243,7 @@ public static ICollection FromJniHandle (IntPtr handle, JniHandleOwnership trans if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) inst = new JavaSet (handle, transfer); else @@ -429,7 +429,7 @@ public static ICollection FromJniHandle (IntPtr handle, JniHandleOwnership tr if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) inst = new JavaSet (handle, transfer); else diff --git a/src/Mono.Android/Android.Runtime/OutputStreamInvoker.cs b/src/Mono.Android/Android.Runtime/OutputStreamInvoker.cs index 4a15b45df6c..b192cf607fa 100644 --- a/src/Mono.Android/Android.Runtime/OutputStreamInvoker.cs +++ b/src/Mono.Android/Android.Runtime/OutputStreamInvoker.cs @@ -136,10 +136,10 @@ internal static Stream FromNative (IntPtr handle, JniHandleOwnership transfer) if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) - inst = Java.Interop.TypeManager.CreateInstance (handle, transfer); + inst = (IJavaObject) Java.Interop.TypeManager.CreateInstance (handle, transfer); else JNIEnv.DeleteRef (handle, transfer); diff --git a/src/Mono.Android/Android.Runtime/XmlPullParserReader.cs b/src/Mono.Android/Android.Runtime/XmlPullParserReader.cs index 1bc5102633a..32a5f525bad 100644 --- a/src/Mono.Android/Android.Runtime/XmlPullParserReader.cs +++ b/src/Mono.Android/Android.Runtime/XmlPullParserReader.cs @@ -35,9 +35,9 @@ static XmlResourceParserReader FromNative (IntPtr handle, JniHandleOwnership tra { if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) - inst = Java.Interop.TypeManager.CreateInstance (handle, transfer); + inst = (IJavaObject) Java.Interop.TypeManager.CreateInstance (handle, transfer); else JNIEnv.DeleteRef (handle, transfer); return new XmlResourceParserReader (inst.JavaCast ()); @@ -392,9 +392,9 @@ static XmlReader FromNative (IntPtr handle, JniHandleOwnership transfer) { if (handle == IntPtr.Zero) return null; - IJavaObject inst = Java.Lang.Object.PeekObject (handle); + IJavaObject inst = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (inst == null) - inst = Java.Interop.TypeManager.CreateInstance (handle, transfer); + inst = (IJavaObject) Java.Interop.TypeManager.CreateInstance (handle, transfer); else JNIEnv.DeleteRef (handle, transfer); return new XmlPullParserReader (inst.JavaCast ()); diff --git a/src/Mono.Android/Java.Interop/JavaConvert.cs b/src/Mono.Android/Java.Interop/JavaConvert.cs index fb1a3c76e01..399a59a18ec 100644 --- a/src/Mono.Android/Java.Interop/JavaConvert.cs +++ b/src/Mono.Android/Java.Interop/JavaConvert.cs @@ -104,7 +104,7 @@ public static T FromJniHandle(IntPtr handle, JniHandleOwnership transfer, out return default (T); } - IJavaObject interned = Java.Lang.Object.PeekObject (handle); + IJavaObject interned = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (interned != null) { T r = FromJavaObject(interned, out set); if (set) { @@ -138,7 +138,7 @@ public static object FromJniHandle (IntPtr handle, JniHandleOwnership transfer, return null; } - IJavaObject interned = Java.Lang.Object.PeekObject (handle); + IJavaObject interned = (IJavaObject) Java.Lang.Object.PeekObject (handle); if (interned != null) { var unwrapped = FromJavaObject (interned, targetType); if (unwrapped != null) { diff --git a/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs b/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs index 2a67b624367..90516e0ba0a 100644 --- a/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs +++ b/src/Mono.Android/Java.Interop/JavaObjectExtensions.cs @@ -109,7 +109,7 @@ internal static IJavaObject JavaCast (IJavaObject instance, Type resultType) return CastClass (instance, resultType); } else if (resultType.IsInterface) { - return Java.Lang.Object.GetObject (instance.Handle, JniHandleOwnership.DoNotTransfer, resultType); + return (IJavaObject) Java.Lang.Object.GetObject (instance.Handle, JniHandleOwnership.DoNotTransfer, resultType); } else throw new NotSupportedException (string.Format ("Unable to convert type '{0}' to '{1}'.", diff --git a/src/Mono.Android/Java.Interop/Runtime.cs b/src/Mono.Android/Java.Interop/Runtime.cs index b4e28f584fa..50703a35925 100644 --- a/src/Mono.Android/Java.Interop/Runtime.cs +++ b/src/Mono.Android/Java.Interop/Runtime.cs @@ -8,9 +8,16 @@ namespace Java.Interop { public static class Runtime { + [Obsolete ("Please use Java.Interop.JniEnvironment.Runtime.ValueManager.GetSurfacedPeers()")] public static List GetSurfacedObjects () { - return Java.Lang.Object.GetSurfacedObjects_ForDiagnosticsOnly (); + var peers = JNIEnv.AndroidValueManager.GetSurfacedPeers (); + var r = new List (peers.Count); + foreach (var p in peers) { + if (p.SurfacedPeer.TryGetTarget (out var target)) + r.Add (new WeakReference (target, trackResurrection: true)); + } + return r; } [DllImport ("__Internal", CallingConvention = CallingConvention.Cdecl)] diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs index 98efa0c5a09..0cf4265f62c 100644 --- a/src/Mono.Android/Java.Interop/TypeManager.cs +++ b/src/Mono.Android/Java.Interop/TypeManager.cs @@ -236,12 +236,12 @@ internal static Type GetJavaToManagedType (string class_name) return null; } - internal static IJavaObject CreateInstance (IntPtr handle, JniHandleOwnership transfer) + internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership transfer) { return CreateInstance (handle, transfer, null); } - internal static IJavaObject CreateInstance (IntPtr handle, JniHandleOwnership transfer, Type targetType) + internal static IJavaPeerable CreateInstance (IntPtr handle, JniHandleOwnership transfer, Type targetType) { Type type = null; IntPtr class_ptr = JNIEnv.GetObjectClass (handle); @@ -284,13 +284,13 @@ internal static IJavaObject CreateInstance (IntPtr handle, JniHandleOwnership tr } - IJavaObject result = null; + IJavaPeerable result = null; try { - result = (IJavaObject) CreateProxy (type, handle, transfer); - var ex = result as IJavaObjectEx; - if (Runtime.IsGCUserPeer (result) && ex != null) - ex.IsProxy = true; + result = (IJavaPeerable) CreateProxy (type, handle, transfer); + if (Runtime.IsGCUserPeer (result.PeerReference.Handle)) { + result.SetJniManagedPeerState (JniManagedPeerStates.Replaceable); + } } catch (MissingMethodException e) { var key_handle = JNIEnv.IdentityHash (handle); JNIEnv.DeleteRef (handle, transfer); @@ -302,18 +302,30 @@ internal static IJavaObject CreateInstance (IntPtr handle, JniHandleOwnership tr return result; } + static readonly Type[] XAConstructorSignature = new Type [] { typeof (IntPtr), typeof (JniHandleOwnership) }; + static readonly Type[] JIConstructorSignature = new Type [] { typeof (JniObjectReference).MakeByRefType (), typeof (JniObjectReferenceOptions) }; + internal static object CreateProxy (Type type, IntPtr handle, JniHandleOwnership transfer) { // Skip Activator.CreateInstance() as that requires public constructors, // and we want to hide some constructors for sanity reasons. BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; - ConstructorInfo c = type.GetConstructor (flags, null, new[]{typeof (IntPtr), typeof (JniHandleOwnership)}, null); - if (c == null) { - throw new MissingMethodException ( - "No constructor found for " + type.FullName + "::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership)", - CreateJavaLocationException ()); + ConstructorInfo c = type.GetConstructor (flags, null, XAConstructorSignature, null); + if (c != null) { + return c.Invoke (new object [] { handle, transfer }); + } + c = type.GetConstructor (flags, null, JIConstructorSignature, null); + if (c != null) { + JniObjectReference r = new JniObjectReference (handle); + JniObjectReferenceOptions o = JniObjectReferenceOptions.Copy; + var peer = (IJavaPeerable) c.Invoke (new object [] { r, o }); + JNIEnv.DeleteRef (handle, transfer); + peer.SetJniManagedPeerState (peer.JniManagedPeerState | JniManagedPeerStates.Replaceable); + return peer; } - return c.Invoke (new object[]{handle, transfer}); + throw new MissingMethodException ( + "No constructor found for " + type.FullName + "::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership)", + CreateJavaLocationException ()); } public static void RegisterType (string java_class, Type t) diff --git a/src/Mono.Android/Java.Lang/Object.cs b/src/Mono.Android/Java.Lang/Object.cs index 496a235b1ce..142b6cf1383 100644 --- a/src/Mono.Android/Java.Lang/Object.cs +++ b/src/Mono.Android/Java.Lang/Object.cs @@ -15,9 +15,6 @@ public partial class Object : IDisposable, IJavaObject, IJavaObjectEx , IJavaPeerable #endif // JAVA_INTEROP { - - static Dictionary> instances = new Dictionary> (new InstancesKeyComparer ()); - IntPtr key_handle; IntPtr weak_handle; JObjectRefType handle_type; @@ -52,21 +49,12 @@ IntPtr IJavaObjectEx.ToLocalJniHandle () ~Object () { - if (Logger.LogGlobalRef) { - JNIEnv._monodroid_gref_log ( - string.Format ("Finalizing handle 0x{0}\n", handle.ToString ("x"))); - } // FIXME: need hash cleanup mechanism. // Finalization occurs after a test of java persistence. If the // handle still contains a java reference, we can't finalize the // object and should "resurrect" it. refs_added = 0; - if (handle != IntPtr.Zero) - GC.ReRegisterForFinalize (this); - else { - Dispose (false); - DeregisterInstance (this, key_handle); - } + JniEnvironment.Runtime.ValueManager.FinalizePeer (this); } public Object (IntPtr handle, JniHandleOwnership transfer) @@ -163,17 +151,17 @@ void IJavaPeerable.DisposeUnlessReferenced () public void UnregisterFromRuntime () { - DeregisterInstance (this, key_handle); + JNIEnv.AndroidValueManager.RemovePeer (this, key_handle); } void IJavaPeerable.Disposed () { - throw new NotSupportedException (); + Dispose (disposing: true); } void IJavaPeerable.Finalized () { - throw new NotSupportedException (); + Dispose (disposing: false); } void IJavaPeerable.SetJniIdentityHashCode (int value) @@ -200,16 +188,14 @@ void IJavaPeerable.SetPeerReference (JniObjectReference reference) public void Dispose () { - Dispose (true); - Dispose (this, ref handle, key_handle, handle_type); - GC.SuppressFinalize (this); + JNIEnv.AndroidValueManager.DisposePeer (this); } protected virtual void Dispose (bool disposing) { } - internal static void Dispose (object instance, ref IntPtr handle, IntPtr key_handle, JObjectRefType handle_type) + internal static void Dispose (IJavaPeerable instance, ref IntPtr handle, IntPtr key_handle, JObjectRefType handle_type) { if (handle == IntPtr.Zero) return; @@ -219,7 +205,7 @@ internal static void Dispose (object instance, ref IntPtr handle, IntPtr key_han string.Format ("Disposing handle 0x{0}\n", handle.ToString ("x"))); } - DeregisterInstance (instance, key_handle); + JNIEnv.AndroidValueManager.RemovePeer (instance, key_handle); switch (handle_type) { case JObjectRefType.Global: @@ -242,174 +228,18 @@ internal static void Dispose (object instance, ref IntPtr handle, IntPtr key_han protected void SetHandle (IntPtr value, JniHandleOwnership transfer) { - RegisterInstance (this, value, transfer, out handle); + JNIEnv.AndroidValueManager.AddPeer (this, value, transfer, out handle); handle_type = JObjectRefType.Global; } - internal static void RegisterInstance (IJavaObject instance, IntPtr value, JniHandleOwnership transfer, out IntPtr handle) - { - if (value == IntPtr.Zero) { - handle = value; - return; - } - - var transferType = transfer & (JniHandleOwnership.DoNotTransfer | JniHandleOwnership.TransferLocalRef | JniHandleOwnership.TransferGlobalRef); - switch (transferType) { - case JniHandleOwnership.DoNotTransfer: - handle = JNIEnv.NewGlobalRef (value); - break; - case JniHandleOwnership.TransferLocalRef: - handle = JNIEnv.NewGlobalRef (value); - JNIEnv.DeleteLocalRef (value); - break; - case JniHandleOwnership.TransferGlobalRef: - handle = value; - break; - default: - throw new ArgumentOutOfRangeException ("transfer", transfer, - "Invalid `transfer` value: " + transfer + " on type " + instance.GetType ()); - } - if (handle == IntPtr.Zero) - throw new InvalidOperationException ("Unable to allocate Global Reference for object '" + instance.ToString () + "'!"); - - IntPtr key = JNIEnv.IdentityHash (handle); - if ((transfer & JniHandleOwnership.DoNotRegister) == 0) { - _RegisterInstance (instance, key, handle); - } - var ex = instance as IJavaObjectEx; - if (ex != null) - ex.KeyHandle = key; - - if (Logger.LogGlobalRef) { - JNIEnv._monodroid_gref_log ("handle 0x" + handle.ToString ("x") + - "; key_handle 0x" + key.ToString ("x") + - ": Java Type: `" + JNIEnv.GetClassNameFromInstance (handle) + "`; " + - "MCW type: `" + instance.GetType ().FullName + "`\n"); - } - } - - static void _RegisterInstance (IJavaObject instance, IntPtr key, IntPtr handle) - { - lock (instances) { - List wrefs; - if (!instances.TryGetValue (key, out wrefs)) { - wrefs = new List (1) { - new WeakReference (instance, true), - }; - instances.Add (key, wrefs); - } - else { - bool found = false; - for (int i = 0; i < wrefs.Count; ++i) { - var wref = wrefs [i]; - if (ShouldReplaceMapping (wref, handle)) { - found = true; - wrefs.Remove (wref); - wrefs.Add (new WeakReference (instance, true)); - break; - } - var cur = wref == null ? null : (IJavaObject) wref.Target; - var _c = cur == null ? IntPtr.Zero : cur.Handle; - if (_c != IntPtr.Zero && JNIEnv.IsSameObject (handle, _c)) { - found = true; - if (Logger.LogGlobalRef) { - Logger.Log (LogLevel.Info, "monodroid-gref", - string.Format ("warning: not replacing previous registered handle 0x{0} with handle 0x{1} for key_handle 0x{2}", - _c.ToString ("x"), handle.ToString ("x"), key.ToString ("x"))); - } - break; - } - } - if (!found) { - wrefs.Add (new WeakReference (instance, true)); - } - } - } - } - - static bool ShouldReplaceMapping (WeakReference current, IntPtr handle) + internal static IJavaPeerable PeekObject (IntPtr handle, Type requiredType = null) { - if (current == null) - return true; - - // Target has been GC'd; see also FIXME, above, in finalizer - object target = current.Target; - if (target == null) - return true; - - // It's possible that the instance was GC'd, but the finalizer - // hasn't executed yet, so the `instances` entry is stale. - var ijo = (IJavaObject) target; - if (ijo.Handle == IntPtr.Zero) - return true; - - if (!JNIEnv.IsSameObject (ijo.Handle, handle)) - return false; - - // JNIEnv.NewObject/JNIEnv.CreateInstance() compatibility. - // When two MCW's are created for one Java instance [0], - // we want the 2nd MCW to replace the 1st, as the 2nd is - // the one the dev created; the 1st is an implicit intermediary. - // - // [0]: If Java ctor invokes overridden virtual method, we'll - // transition into managed code w/o a registered instance, and - // thus will create an "intermediary" via - // (IntPtr, JniHandleOwnership) .ctor. - var ex = target as IJavaObjectEx; - if (ex != null && ex.IsProxy) - return true; - - return false; - } - - internal static void DeregisterInstance (object instance, IntPtr key_handle) - { - lock (instances) { - List wrefs; - if (instances.TryGetValue (key_handle, out wrefs)) { - for (int i = wrefs.Count-1; i >= 0; --i) { - var wref = wrefs [i]; - if (wref.Target == null || wref.Target == instance) { - wrefs.RemoveAt (i); - } - } - if (wrefs.Count == 0) - instances.Remove (key_handle); - } - } - } - - internal static List GetSurfacedObjects_ForDiagnosticsOnly () - { - lock (instances) { - var surfaced = new List (instances.Count); - foreach (var e in instances) { - surfaced.AddRange (e.Value); - } - return surfaced; - } - } - - internal static IJavaObject PeekObject (IntPtr handle, Type requiredType = null) - { - if (handle == IntPtr.Zero) + var peeked = JNIEnv.AndroidValueManager.PeekPeer (new JniObjectReference (handle)); + if (peeked == null) return null; - - lock (instances) { - List wrefs; - if (instances.TryGetValue (JNIEnv.IdentityHash (handle), out wrefs)) { - for (int i = 0; i < wrefs.Count; ++i) { - var wref = wrefs [i]; - IJavaObject res = wref.Target as IJavaObject; - if (res != null && res.Handle != IntPtr.Zero && JNIEnv.IsSameObject (handle, res.Handle)) { - if (requiredType != null && !requiredType.IsAssignableFrom (res.GetType ())) - return null; - return res; - } - } - } - } - return null; + if (requiredType != null && !requiredType.IsAssignableFrom (peeked.GetType ())) + return null; + return peeked; } internal static T PeekObject (IntPtr handle) @@ -438,30 +268,15 @@ internal static T _GetObject (IntPtr handle, JniHandleOwnership transfer) return (T) GetObject (handle, transfer, typeof (T)); } - internal static IJavaObject GetObject (IntPtr handle, JniHandleOwnership transfer, Type type = null) + internal static IJavaPeerable GetObject (IntPtr handle, JniHandleOwnership transfer, Type type = null) { if (handle == IntPtr.Zero) return null; - lock (instances) { - List wrefs; - if (instances.TryGetValue (JNIEnv.IdentityHash (handle), out wrefs)) { - for (int i = 0; i < wrefs.Count; ++i) { - var wref = wrefs [i]; - var result = wref.Target as IJavaObject; - var exists = result != null && result.Handle != IntPtr.Zero && JNIEnv.IsSameObject (handle, result.Handle); - if (exists) { - if (type == null ? true : type.IsAssignableFrom (result.GetType ())) { - JNIEnv.DeleteRef (handle, transfer); - return result; - } - /* - Logger.Log (LogLevel.Warn, "*jonp*", "# jonp: Object.GetObject: handle=0x" + handle.ToString ("x") + " found but is of type '" + result.GetType ().FullName + - "' and not the required targetType of '" + type + "'."); - */ - } - } - } + var r = PeekObject (handle, type); + if (r != null) { + JNIEnv.DeleteRef (handle, transfer); + return r; } return Java.Interop.TypeManager.CreateInstance (handle, transfer, type); @@ -725,17 +540,4 @@ public static explicit operator string[] (Java.Lang.Object value) return value.ToArray(); } } - - class InstancesKeyComparer : IEqualityComparer { - - public bool Equals (IntPtr x, IntPtr y) - { - return x == y; - } - - public int GetHashCode (IntPtr value) - { - return value.GetHashCode (); - } - } } diff --git a/src/Mono.Android/Java.Lang/Throwable.cs b/src/Mono.Android/Java.Lang/Throwable.cs index d562565096d..8554c637764 100644 --- a/src/Mono.Android/Java.Lang/Throwable.cs +++ b/src/Mono.Android/Java.Lang/Throwable.cs @@ -226,7 +226,7 @@ public unsafe Java.Lang.Class Class { protected void SetHandle (IntPtr value, JniHandleOwnership transfer) { - Java.Lang.Object.RegisterInstance (this, value, transfer, out handle); + JNIEnv.AndroidValueManager.AddPeer (this, value, transfer, out handle); handle_type = JObjectRefType.Global; } @@ -251,18 +251,8 @@ public static System.Exception ToException (Throwable e) ~Throwable () { - if (Logger.LogGlobalRef) { - JNIEnv._monodroid_gref_log ( - string.Format ("Finalizing Throwable handle 0x{0}\n", handle.ToString ("x"))); - } - refs_added = 0; - if (handle != IntPtr.Zero) - GC.ReRegisterForFinalize (this); - else { - Dispose (false); - Object.DeregisterInstance (this, key_handle); - } + JniEnvironment.Runtime.ValueManager.FinalizePeer (this); } #if JAVA_INTEROP @@ -288,17 +278,17 @@ void IJavaPeerable.DisposeUnlessReferenced () public void UnregisterFromRuntime () { - Object.DeregisterInstance (this, key_handle); + JNIEnv.AndroidValueManager.RemovePeer (this, key_handle); } void IJavaPeerable.Disposed () { - throw new NotSupportedException (); + Dispose (disposing: true); } void IJavaPeerable.Finalized () { - throw new NotSupportedException (); + Dispose (disposing: false); } void IJavaPeerable.SetJniIdentityHashCode (int value) @@ -324,10 +314,7 @@ void IJavaPeerable.SetPeerReference (JniObjectReference reference) public void Dispose () { - Dispose (true); - Java.Lang.Object.Dispose (this, ref handle, key_handle, handle_type); - key_handle = IntPtr.Zero; - GC.SuppressFinalize (this); + JNIEnv.AndroidValueManager.DisposePeer (this); } protected virtual void Dispose (bool disposing) diff --git a/src/Mono.Android/Test/Java.Interop-Tests/.gitignore b/src/Mono.Android/Test/Java.Interop-Tests/.gitignore new file mode 100644 index 00000000000..d996c0b7286 --- /dev/null +++ b/src/Mono.Android/Test/Java.Interop-Tests/.gitignore @@ -0,0 +1 @@ +Jars diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj new file mode 100644 index 00000000000..5009aa123f1 --- /dev/null +++ b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj @@ -0,0 +1,86 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {6CB00820-A66B-43E5-8785-ED456C6E9F39} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {9ef11e43-1701-4396-8835-8392d57abb70} + Library + Properties + Java.Interop_Tests + Java.Interop-Tests + 512 + Resources\Resource.designer.cs + Off + v9.0 + true + + + + $(AndroidFrameworkVersion) + true + portable + false + bin\Debug\ + DEBUG;TRACE;NO_MARSHAL_MEMBER_BUILDER_SUPPORT + prompt + 4 + + + $(AndroidFrameworkVersion) + + true + bin\Release\ + TRACE;NO_MARSHAL_MEMBER_BUILDER_SUPPORT + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF} + Java.Interop.GenericMarshaler + + + {0C001D50-4176-45AE-BDC8-BA626508B0CC} + Mono.Linq.Expressions + + + + + + + + BuildTestJarFile; + _CopyTestJarFiles; + $(BuildDependsOn) + + + + + CleanTestJarFile; + $(CleanDependsOn); + CleanLocal; + + + \ No newline at end of file diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.targets b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.targets new file mode 100644 index 00000000000..e4804b6d206 --- /dev/null +++ b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.targets @@ -0,0 +1,24 @@ + + + + + + + + + Jars\Mono.Android-Test-classes.jar + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Java.InteropTests/JavaInterop_Tests_Reference.cs b/src/Mono.Android/Test/Java.Interop-Tests/Java.InteropTests/JavaInterop_Tests_Reference.cs new file mode 100644 index 00000000000..e0a898e5cd8 --- /dev/null +++ b/src/Mono.Android/Test/Java.Interop-Tests/Java.InteropTests/JavaInterop_Tests_Reference.cs @@ -0,0 +1,9 @@ +using System; + +namespace Java.InteropTests +{ + // Exists for "easy" reference by Mono.Android-Tests.dll + public class JavaInterop_Tests_Reference + { + } +} diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Properties/AssemblyInfo.cs b/src/Mono.Android/Test/Java.Interop-Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..887802784b2 --- /dev/null +++ b/src/Mono.Android/Test/Java.Interop-Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,30 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Java.Interop_Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Java.Interop_Tests")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Resources/AboutResources.txt b/src/Mono.Android/Test/Java.Interop-Tests/Resources/AboutResources.txt new file mode 100644 index 00000000000..c2bca974c48 --- /dev/null +++ b/src/Mono.Android/Test/Java.Interop-Tests/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/src/Mono.Android/Test/Mono.Android-Tests.csproj b/src/Mono.Android/Test/Mono.Android-Tests.csproj index 0d018ae3ea2..b81d2a5d537 100644 --- a/src/Mono.Android/Test/Mono.Android-Tests.csproj +++ b/src/Mono.Android/Test/Mono.Android-Tests.csproj @@ -87,6 +87,10 @@ {CB2335CB-0050-4020-8A05-E9614EDAA05E} TestRunner.NUnit + + {6CB00820-A66B-43E5-8785-ED456C6E9F39} + Java.Interop-Tests + {8CB5FF58-FF95-43B9-9064-9ACE9525866F} Mono.Android-Test.Library diff --git a/src/Mono.Android/Test/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs b/src/Mono.Android/Test/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs index 2da4d177c7b..0a58cd6bc81 100644 --- a/src/Mono.Android/Test/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs +++ b/src/Mono.Android/Test/Xamarin.Android.RuntimeTests/NUnitInstrumentation.cs @@ -30,10 +30,13 @@ protected NUnitInstrumentation(IntPtr handle, JniHandleOwnership transfer) protected override IList GetTestAssemblies() { Assembly asm = Assembly.GetExecutingAssembly(); + Assembly ji = typeof (Java.InteropTests.JavaInterop_Tests_Reference).Assembly; + return new List() { - new TestAssemblyInfo(asm, asm.Location ?? String.Empty) + new TestAssemblyInfo (asm, asm.Location ?? String.Empty), + new TestAssemblyInfo (ji, ji.Location ?? String.Empty), }; } } diff --git a/src/Mono.Android/Test/Xamarin.Android.RuntimeTests/TestInstrumentation.cs b/src/Mono.Android/Test/Xamarin.Android.RuntimeTests/TestInstrumentation.cs index e3dbc895242..1dfae2ed6af 100644 --- a/src/Mono.Android/Test/Xamarin.Android.RuntimeTests/TestInstrumentation.cs +++ b/src/Mono.Android/Test/Xamarin.Android.RuntimeTests/TestInstrumentation.cs @@ -21,6 +21,7 @@ public TestInstrumentation (IntPtr handle, JniHandleOwnership transfer) protected override void AddTests () { AddTest (Assembly.GetExecutingAssembly ()); + AddTest (typeof (Java.InteropTests.JavaInterop_Tests_Reference).Assembly); } } } diff --git a/src/monodroid/jni/monodroid-glue.cc b/src/monodroid/jni/monodroid-glue.cc index b7420ccff6e..f296bf9ed86 100644 --- a/src/monodroid/jni/monodroid-glue.cc +++ b/src/monodroid/jni/monodroid-glue.cc @@ -932,7 +932,9 @@ MonodroidRuntime::init_android_runtime (MonoDomain *domain, JNIEnv *env, jclass MonoAssembly *assm = utils.monodroid_load_assembly (domain, "Mono.Android"); MonoImage *image = mono_assembly_get_image (assm); - for (uint32_t i = 0; i < OSBridge::NUM_GC_BRIDGE_TYPES; ++i) { + uint32_t i = 0; + + for ( ; i < OSBridge::NUM_XA_GC_BRIDGE_TYPES; ++i) { lookup_bridge_info (domain, image, &osBridge.get_java_gc_bridge_type (i), &osBridge.get_java_gc_bridge_info (i)); } @@ -944,6 +946,13 @@ MonodroidRuntime::init_android_runtime (MonoDomain *domain, JNIEnv *env, jclass log_fatal (LOG_DEFAULT, "INTERNAL ERROR: Unable to find Android.Runtime.JNIEnv.Initialize!"); exit (FATAL_EXIT_MISSING_INIT); } + + MonoAssembly *ji_assm = utils.monodroid_load_assembly (domain, "Java.Interop"); + MonoImage *ji_image = mono_assembly_get_image (ji_assm); + for ( ; i < OSBridge::NUM_XA_GC_BRIDGE_TYPES + OSBridge::NUM_JI_GC_BRIDGE_TYPES; ++i) { + lookup_bridge_info (domain, ji_image, &osBridge.get_java_gc_bridge_type (i), &osBridge.get_java_gc_bridge_info (i)); + } + /* If running on desktop, we may be swapping in a new Mono.Android image when calling this * so always make sure we have the freshest handle to the method. */ diff --git a/src/monodroid/jni/osbridge.cc b/src/monodroid/jni/osbridge.cc index b3b72c45d92..dcbe73c131a 100644 --- a/src/monodroid/jni/osbridge.cc +++ b/src/monodroid/jni/osbridge.cc @@ -37,17 +37,25 @@ FILE *lref_log; using namespace xamarin::android; using namespace xamarin::android::internal; -const OSBridge::MonoJavaGCBridgeType OSBridge::mono_java_gc_bridge_types[] = { +const OSBridge::MonoJavaGCBridgeType OSBridge::mono_xa_gc_bridge_types[] = { { "Java.Lang", "Object" }, { "Java.Lang", "Throwable" }, }; +const OSBridge::MonoJavaGCBridgeType OSBridge::mono_ji_gc_bridge_types[] = { + { "Java.Interop", "JavaObject" }, + { "Java.Interop", "JavaException" }, +}; + const OSBridge::MonoJavaGCBridgeType OSBridge::empty_bridge_type = { "", "" }; -const uint32_t OSBridge::NUM_GC_BRIDGE_TYPES = (sizeof (mono_java_gc_bridge_types)/sizeof (mono_java_gc_bridge_types [0])); +const uint32_t OSBridge::NUM_XA_GC_BRIDGE_TYPES = (sizeof (mono_xa_gc_bridge_types)/sizeof (mono_xa_gc_bridge_types [0])); +const uint32_t OSBridge::NUM_JI_GC_BRIDGE_TYPES = (sizeof (mono_ji_gc_bridge_types)/sizeof (mono_ji_gc_bridge_types [0])); +const uint32_t OSBridge::NUM_GC_BRIDGE_TYPES = NUM_XA_GC_BRIDGE_TYPES + NUM_JI_GC_BRIDGE_TYPES; + OSBridge::MonoJavaGCBridgeInfo OSBridge::mono_java_gc_bridge_info [NUM_GC_BRIDGE_TYPES]; OSBridge::MonoJavaGCBridgeInfo OSBridge::empty_bridge_info = { diff --git a/src/monodroid/jni/osbridge.hh b/src/monodroid/jni/osbridge.hh index 0452314e2a7..3c2e99b5568 100644 --- a/src/monodroid/jni/osbridge.hh +++ b/src/monodroid/jni/osbridge.hh @@ -55,11 +55,14 @@ namespace xamarin::android::internal using MonodroidGCTakeRefFunc = mono_bool (OSBridge::*) (JNIEnv *env, MonoObject *obj); static const MonoJavaGCBridgeType empty_bridge_type; - static const MonoJavaGCBridgeType mono_java_gc_bridge_types[]; + static const MonoJavaGCBridgeType mono_xa_gc_bridge_types[]; + static const MonoJavaGCBridgeType mono_ji_gc_bridge_types[]; static MonoJavaGCBridgeInfo empty_bridge_info; static MonoJavaGCBridgeInfo mono_java_gc_bridge_info []; public: + static const uint32_t NUM_XA_GC_BRIDGE_TYPES; + static const uint32_t NUM_JI_GC_BRIDGE_TYPES; static const uint32_t NUM_GC_BRIDGE_TYPES; public: @@ -73,10 +76,15 @@ namespace xamarin::android::internal const MonoJavaGCBridgeType& get_java_gc_bridge_type (uint32_t index) { - if (index >= NUM_GC_BRIDGE_TYPES) - return empty_bridge_type; // Not ideal... + if (index < NUM_XA_GC_BRIDGE_TYPES) + return mono_xa_gc_bridge_types [index]; + + index -= NUM_XA_GC_BRIDGE_TYPES; + if (index < NUM_JI_GC_BRIDGE_TYPES) + return mono_ji_gc_bridge_types [index]; - return mono_java_gc_bridge_types [index]; + index -= NUM_JI_GC_BRIDGE_TYPES; + return empty_bridge_type; // Not ideal... } MonoJavaGCBridgeInfo& get_java_gc_bridge_info (uint32_t index) diff --git a/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj b/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj index 560945d0980..bbaad338f39 100644 --- a/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj +++ b/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj @@ -97,6 +97,10 @@ {CB2335CB-0050-4020-8A05-E9614EDAA05E} TestRunner.NUnit + + {6CB00820-A66B-43E5-8785-ED456C6E9F39} + Java.Interop-Tests + {8CB5FF58-FF95-43B9-9064-9ACE9525866F} Mono.Android-Test.Library diff --git a/tests/TestRunner.Core/TestRunner.Core.csproj b/tests/TestRunner.Core/TestRunner.Core.csproj index b7627a66dae..6e0b2cdb5a5 100644 --- a/tests/TestRunner.Core/TestRunner.Core.csproj +++ b/tests/TestRunner.Core/TestRunner.Core.csproj @@ -8,15 +8,15 @@ Library Xamarin.Android.UnitTests TestRunner.Core - v8.1 + v9.0 Resources\Resource.designer.cs Resource Resources Assets - true + $(AndroidFrameworkVersion) true false bin\Debug @@ -26,6 +26,7 @@ None + $(AndroidFrameworkVersion) true true bin\Release diff --git a/tests/TestRunner.NUnit/TestRunner.NUnit.csproj b/tests/TestRunner.NUnit/TestRunner.NUnit.csproj index 9a162b00004..e85d234a57d 100644 --- a/tests/TestRunner.NUnit/TestRunner.NUnit.csproj +++ b/tests/TestRunner.NUnit/TestRunner.NUnit.csproj @@ -8,15 +8,15 @@ Library Xamarin.Android.UnitTests.NUnit TestRunner.NUnit - v8.1 + v9.0 Resources\Resource.designer.cs Resource Resources Assets - true + $(AndroidFrameworkVersion) true false bin\Debug @@ -26,6 +26,7 @@ None + $(AndroidFrameworkVersion) true true bin\Release From 818136b4e0fc497d5aaccb1958e3d8fb2714d836 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Mon, 9 Sep 2019 21:18:32 -0400 Subject: [PATCH 02/21] Come up with an alternate way for java-interop.jar path detection Context: https://xamarinhq.slack.com/archives/C03CEGRUW/p1568076852178100 Using `$(MSBuildExtensionsPath)` didn't work, as it just took the "first" path, which isn't valid, resulting in attempts to use: /Library/Frameworks/Mono.framework/Versions/6.0.0/lib/mono/xbuild/Xamarin/Android/java-interop.jar which does not exist. --- build-tools/scripts/Jar.targets | 20 +++++++++++++------ .../Xamarin.Android.Common.props.in | 1 + 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/build-tools/scripts/Jar.targets b/build-tools/scripts/Jar.targets index 107b118a7cf..91552910d10 100644 --- a/build-tools/scripts/Jar.targets +++ b/build-tools/scripts/Jar.targets @@ -11,8 +11,20 @@ $(JavaSdkDirectory)\bin\javac + + + <_JIJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java-interop.jar + <_JIJar_System Condition=" '$(_XamarinAndroidMSBuildDirectory)' != '' ">$(_XamarinAndroidMSBuildDirectory)\java-interop.jar + <_JavaInteropJarPath Condition=" Exists($(_JIJar_InTree)) ">$(_JIJar_InTree) + <_JavaInteropJarPath Condition=" '$(_JavaInteropJarPath)' == '' ">$(_JIJar_System) + + + @@ -26,11 +38,7 @@ <_Targets>-source $(_JavacSourceVersion) -target $(_JavacTargetVersion) <_DestDir>$(IntermediateOutputPath)__CreateTestJarFile-bin <_AndroidJar>-bootclasspath "$(AndroidSdkDirectory)\platforms\android-$(_AndroidApiLevelName)\android.jar" - <_JIJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java-interop.jar - <_JIJar_System>$(MSBuildExtensionsPath)\Xamarin\Android\java-interop.jar - <_JIJar Condition=" Exists ($(_JIJar_InTree)) ">$(_JIJar_InTree) - <_JIJar Condition=" '$(_JIJar)' == '' ">$(_JIJar_System) - <_CP>-cp "$(_JIJar)" + <_CP>-cp "$(_JavaInteropJarPath)" diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in index c03391c09b3..1277d2b5aac 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.props.in @@ -19,6 +19,7 @@ 26.1.1 16.1 @BUNDLETOOL_VERSION@ + <_XamarinAndroidMSBuildDirectory>$(MSBuildThisFileDirectory) true From a9c6230f2154afb9f30b284a22479a8e195b56b9 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Sat, 9 Nov 2019 19:04:28 -0700 Subject: [PATCH 03/21] More diagnostics? Context: https://github.com/xamarin/xamarin-android/pull Trying to build things on Windows fails: ...s\external\Java.Interop\src\Java.Interop\Java.Interop.targets(37,5): error MSB3073: The command """ -source 1.6 -target 1.6 -bootclasspath "" -d "obj\Debug\netstandard2.0\ji-classes" java\com\xamarin\java_interop\internal\JavaProxyObject.java java\com\xamarin\java_interop\internal\JavaProxyThrowable.java java\com\xamarin\java_interop\GCUserPeerable.java java\com\xamarin\java_interop\ManagedPeer.java" exited with code 9009. The problem is that `javac` isn't being used. Why? To help answer *that* question, it would be handy to have `bin/TestRelease/msbuild-build-tests.binlog`... which isn't uploaded. Update `reuslt-packaging.targets` so that we actually capture the `bin/Test$(Configuration)` files. Question: should this be in the build zip, or the tests zip? However, this does introduce a hypothesis: the build order! Xamarin.Android-Tests.sln -> Mono.Android-Tests.csproj Java.Interop-Tests.csproj Java.Interop.csproj `Java.Interop.csproj` is not in `Xamarin.Android-Tests.sln`, and thus it *appears* to be building it in the *Debug* configuration, while it should be using the *Release* configuration, so that it can find `external/Java.Interop/bin/BuildRelease/JdkInfo.props` (which is generated as part of build prep). This would explain why `$(JavaCPath)` isn't set! However, this in turn suggests a *different* issue: Insert @jonathanpeppers' PR for re-doing the build system, which we might need first. ...plus an equivalent in Java.Interop! We need to entirely separate tests from non-tests, for various reasons (TODO: lookup commit & msbuild file sharing & ....!) Java.Interop will need to follow suite, which in turn means that `Java.Interop-Tests.csproj` MUST NOT reference `Java.Interop.csproj`. Removing that "connection point" should allow things to work sanely. --- .../result-packaging.targets | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build-tools/Xamarin.Android.Tools.BootstrapTasks/result-packaging.targets b/build-tools/Xamarin.Android.Tools.BootstrapTasks/result-packaging.targets index 4a555505ced..52daf68165d 100644 --- a/build-tools/Xamarin.Android.Tools.BootstrapTasks/result-packaging.targets +++ b/build-tools/Xamarin.Android.Tools.BootstrapTasks/result-packaging.targets @@ -12,6 +12,14 @@ <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\*.projitems" /> <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\*.cmake" /> <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Build$(Configuration)\*.targets" /> + <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Test$(Configuration)\XABuildConfig.cs" Condition="Exists('$(XamarinAndroidSourcePath)bin\Test$(Configuration)\XABuildConfig.cs')" /> + <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Test$(Configuration)\*.binlog" /> + <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Test$(Configuration)\prepare*.log" /> + <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Test$(Configuration)\*.mk" /> + <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Test$(Configuration)\*.projitems" /> + <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Test$(Configuration)\*.cmake" /> + <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)bin\Test$(Configuration)\*.targets" /> + <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)external\Java.Interop\bin\Build$(Configuration)\*.props" /> <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)**\ThirdPartyNotices.txt" /> <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)**\config.log" /> <_BuildStatusFiles Include="$(XamarinAndroidSourcePath)**\config.status" /> From 9a77467d71ed08dd3b313c55cd4ef18b872f7649 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Mon, 11 Nov 2019 12:54:39 +0100 Subject: [PATCH 04/21] Add Java.Interop.csproj to Xamarin.Android-Tests.sln To test the hypothesis in 3828d572, add `Java.Interop.csproj` to `Xamarin.Android-Tests.sln`. This will hopefully *prevent* `Java.Interop.csproj` from being built in the deug configuration, which in turn should allow Windows to *build*. --- Xamarin.Android-Tests.sln | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Xamarin.Android-Tests.sln b/Xamarin.Android-Tests.sln index ee7d94b987e..068c92bb1cf 100644 --- a/Xamarin.Android-Tests.sln +++ b/Xamarin.Android-Tests.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27428.2037 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29411.108 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android-Tests", "src\Mono.Android\Test\Mono.Android-Tests.csproj", "{40EAD437-216B-4DF4-8258-3F47E1672C3A}" EndProject @@ -94,14 +94,18 @@ Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Interop-Tests", "external\J EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Linq.Expressions", "external\Java.Interop\lib\mono.linq.expressions\Mono.Linq.Expressions.csproj", "{0C001D50-4176-45AE-BDC8-BA626508B0CC}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop.GenericMarshaler", "external\Java.Interop\src\Java.Interop.GenericMarshaler\Java.Interop.GenericMarshaler.csproj", "{D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Java.Interop.GenericMarshaler", "external\Java.Interop\src\Java.Interop.GenericMarshaler\Java.Interop.GenericMarshaler.csproj", "{D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop-Tests", "src\Mono.Android\Test\Java.Interop-Tests\Java.Interop-Tests.csproj", "{6CB00820-A66B-43E5-8785-ED456C6E9F39}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Java.Interop", "external\Java.Interop\src\Java.Interop\Java.Interop.csproj", "{94BD81F7-B06F-4295-9636-F8A3B6BDC762}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{0ab4956e-6fb9-4da0-9d49-ab65a3ff403a}*SharedItemsImports = 13 + external\Java.Interop\src\Java.Interop\Tests\Interop-Tests.projitems*{0adb8d72-7479-49af-8809-e03ae4a4eae2}*SharedItemsImports = 13 src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{40ead437-216b-4df4-8258-3f47e1672c3a}*SharedItemsImports = 4 + external\Java.Interop\src\Java.Interop\Tests\Interop-Tests.projitems*{6cb00820-a66b-43e5-8785-ed456c6e9f39}*SharedItemsImports = 4 src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{9ecbea14-b79f-4f92-9266-495c03a32571}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -119,6 +123,10 @@ Global {2305B00D-DE81-4744-B0DA-357835CAFE5A}.Debug|Any CPU.Build.0 = Debug|Any CPU {2305B00D-DE81-4744-B0DA-357835CAFE5A}.Release|Any CPU.ActiveCfg = Release|Any CPU {2305B00D-DE81-4744-B0DA-357835CAFE5A}.Release|Any CPU.Build.0 = Release|Any CPU + {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2}.Release|Any CPU.Build.0 = Release|Any CPU {05768F39-7BAF-43E6-971E-712F5771E88E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {05768F39-7BAF-43E6-971E-712F5771E88E}.Debug|Any CPU.Build.0 = Debug|Any CPU {05768F39-7BAF-43E6-971E-712F5771E88E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -231,18 +239,6 @@ Global {056ED976-618F-4A3E-910E-AA25230C2296}.Debug|Any CPU.Build.0 = Debug|Any CPU {056ED976-618F-4A3E-910E-AA25230C2296}.Release|Any CPU.ActiveCfg = Release|Any CPU {056ED976-618F-4A3E-910E-AA25230C2296}.Release|Any CPU.Build.0 = Release|Any CPU - {B160F0E7-799A-4EB9-92B8-D71623C7674A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B160F0E7-799A-4EB9-92B8-D71623C7674A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B160F0E7-799A-4EB9-92B8-D71623C7674A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B160F0E7-799A-4EB9-92B8-D71623C7674A}.Release|Any CPU.Build.0 = Release|Any CPU - {FA8EEC88-CA3C-4D69-B206-54B392570DC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FA8EEC88-CA3C-4D69-B206-54B392570DC6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FA8EEC88-CA3C-4D69-B206-54B392570DC6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FA8EEC88-CA3C-4D69-B206-54B392570DC6}.Release|Any CPU.Build.0 = Release|Any CPU - {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2}.Release|Any CPU.Build.0 = Release|Any CPU {8B5E63B7-8C18-4BA7-BAAB-A1955B257F5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8B5E63B7-8C18-4BA7-BAAB-A1955B257F5E}.Debug|Any CPU.Build.0 = Debug|Any CPU {8B5E63B7-8C18-4BA7-BAAB-A1955B257F5E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -269,6 +265,10 @@ Global {6CB00820-A66B-43E5-8785-ED456C6E9F39}.Debug|Any CPU.Build.0 = Debug|Any CPU {6CB00820-A66B-43E5-8785-ED456C6E9F39}.Release|Any CPU.ActiveCfg = Release|Any CPU {6CB00820-A66B-43E5-8785-ED456C6E9F39}.Release|Any CPU.Build.0 = Release|Any CPU + {94BD81F7-B06F-4295-9636-F8A3B6BDC762}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94BD81F7-B06F-4295-9636-F8A3B6BDC762}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94BD81F7-B06F-4295-9636-F8A3B6BDC762}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94BD81F7-B06F-4295-9636-F8A3B6BDC762}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -276,6 +276,7 @@ Global GlobalSection(NestedProjects) = preSolution {40EAD437-216B-4DF4-8258-3F47E1672C3A} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {2305B00D-DE81-4744-B0DA-357835CAFE5A} = {43A4FB09-279A-4138-8027-EC1E1CED2E8A} + {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2} = {43A4FB09-279A-4138-8027-EC1E1CED2E8A} {05768F39-7BAF-43E6-971E-712F5771E88E} = {D6BFEDF6-2F48-44B2-9553-F2F6F92531BD} {9D5C83B5-70D5-4CC2-9DB7-78B23DC8F255} = {D6BFEDF6-2F48-44B2-9553-F2F6F92531BD} {EF798EB3-D639-4E09-9DB0-233E67F727B0} = {2EFFECF5-1CCA-4005-AE62-1D6F01C88DF4} @@ -300,7 +301,6 @@ Global {F4DAFD78-BE76-46C9-A1AD-85D8C91CD77B} = {9B63992C-2201-4BB0-BD00-D637B481A995} {2DD1EE75-6D8D-4653-A800-0A24367F7F38} = {9B63992C-2201-4BB0-BD00-D637B481A995} {37CAA28C-40BE-4253-BA68-CC5D7316A617} = {68B8E272-5B12-47AA-8923-550B9CE535C7} - {6BE66B30-9346-4DA6-B09A-0CDC1DFE33C2} = {43A4FB09-279A-4138-8027-EC1E1CED2E8A} {0AB4956E-6FB9-4DA0-9D49-AB65A3FF403A} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {8CB5FF58-FF95-43B9-9064-9ACE9525866F} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {9ECBEA14-B79F-4F92-9266-495C03A32571} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} @@ -308,6 +308,7 @@ Global {0C001D50-4176-45AE-BDC8-BA626508B0CC} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {6CB00820-A66B-43E5-8785-ED456C6E9F39} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} + {94BD81F7-B06F-4295-9636-F8A3B6BDC762} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8643CD20-B195-4919-8135-27549488237E} From 1addc715cf88fcc94424575ff505b8302e272e5e Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 13 Nov 2019 11:38:37 +0100 Subject: [PATCH 05/21] [xaprepare] Split out Java.Interop prep logic Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3232168&view=logs&j=8556562a-ae5f-5bd1-7c4d-bf1af4b6f1e1&t=5076e147-fc66-561e-6c69-3aa777afefc5 The unit tests are failing go build: /Users/runner/runners/2.160.0/work/1/s/external/Java.Interop/src/Java.Interop/Tests/Interop-Tests.projitems(11,3): error MSB4019: The imported project "/Users/runner/runners/2.160.0/work/1/s/external/Java.Interop/bin/BuildRelease/JdkInfo.props" was not found. Confirm that the path in the declaration is correct, and that the file exists on disk. The problem is that for the "APK Instrumentation - macOS" job doesn't create `external/Java.Interop/bin/BuildRelease/JdkInfo.props`. Add a new `Step_PrepareExternalJavaInterop` step which creates `JdkInfo.props`, which should allow things to build. Move the previous `JdkInfo.props` generation logic out of `Step_PrepareExternal`, so that the `xaprepare -s:Required` can just build the required Java.Interop bits, and not "lots". --- .../Scenarios/Scenario_PrepareExternal.cs | 1 + .../xaprepare/Scenarios/Scenario_Required.cs | 1 + .../xaprepare/Scenarios/Scenario_Standard.cs | 1 + .../Steps/Step_PrepareExternal.Unix.cs | 25 ----------- .../Step_PrepareExternalJavaInterop.Unix.cs | 42 +++++++++++++++++++ ...Step_PrepareExternalJavaInterop.Windows.cs | 14 +++++++ .../Steps/Step_PrepareExternalJavaInterop.cs | 18 ++++++++ .../xaprepare/xaprepare/xaprepare.csproj | 3 ++ 8 files changed, 80 insertions(+), 25 deletions(-) create mode 100644 build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.Unix.cs create mode 100644 build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.Windows.cs create mode 100644 build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.cs diff --git a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs index 33ca4306991..e3df02297a0 100644 --- a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs +++ b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs @@ -12,6 +12,7 @@ public Scenario_PrepareExternal () protected override void AddSteps (Context context) { Steps.Add (new Step_PrepareExternal ()); + Steps.Add (new Step_PrepareExternalJavaInterop ()); // disable installation of missing programs... context.SetCondition (KnownConditions.AllowProgramInstallation, false); diff --git a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs index 3bce5d807b4..e41eee5ab6a 100644 --- a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs +++ b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Required.cs @@ -15,6 +15,7 @@ protected override void AddSteps (Context context) throw new ArgumentNullException (nameof (context)); Steps.Add (new Step_GenerateFiles (atBuildStart: true, onlyRequired: true)); + Steps.Add (new Step_PrepareExternalJavaInterop ()); } } } diff --git a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs index f0dbc864d67..d58aaae5a85 100644 --- a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs +++ b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_Standard.cs @@ -20,6 +20,7 @@ protected override void AddSteps (Context context) Steps.Add (new Step_GenerateFiles (atBuildStart: true)); Steps.Add (new Step_PrepareProps ()); Steps.Add (new Step_PrepareExternal ()); + Steps.Add (new Step_PrepareExternalJavaInterop ()); Steps.Add (new Step_PrepareLocal ()); Steps.Add (new Step_DownloadMonoArchive ()); AddRequiredOSSpecificSteps (true); diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternal.Unix.cs b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternal.Unix.cs index 67fb768e128..52609f6300d 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternal.Unix.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternal.Unix.cs @@ -24,31 +24,6 @@ async Task ExecuteOSSpecific (Context context, NuGetRunner nuget) if (!result) return false; - string javaInteropDir = context.Properties.GetRequiredValue (KnownProperties.JavaInteropFullPath); - Log.StatusLine (); - result = await make.Run ( - logTag: "java-interop-prepare", - workingDirectory: javaInteropDir, - arguments: new List { - "prepare", - $"CONFIGURATION={context.Configuration}", - $"JAVA_HOME={context.OS.JavaHome}", - $"JI_MAX_JDK={Configurables.Defaults.MaxJDKVersion}", - } - ); - if (!result) - return false; - - Log.StatusLine (); - result = await make.Run ( - logTag: "java-interop-props", - workingDirectory: javaInteropDir, - arguments: new List { - $"bin/Build{context.Configuration}/JdkInfo.props", - $"CONFIGURATION={context.Configuration}", - $"JI_MAX_JDK={Configurables.Defaults.MaxJDKVersion}", - } - ); return result; } } diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.Unix.cs b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.Unix.cs new file mode 100644 index 00000000000..2da742d8e1c --- /dev/null +++ b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.Unix.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace Xamarin.Android.Prepare +{ + partial class Step_PrepareExternalJavaInterop + { + async Task ExecuteOSSpecific (Context context) + { + string javaInteropDir = context.Properties.GetRequiredValue (KnownProperties.JavaInteropFullPath); + Log.StatusLine (); + var make = new MakeRunner (context) { + NoParallelJobs = true + }; + var result = await make.Run ( + logTag: "java-interop-prepare", + workingDirectory: javaInteropDir, + arguments: new List { + "prepare", + $"CONFIGURATION={context.Configuration}", + $"JAVA_HOME={context.OS.JavaHome}", + $"JI_MAX_JDK={Configurables.Defaults.MaxJDKVersion}", + } + ); + if (!result) + return false; + + Log.StatusLine (); + result = await make.Run ( + logTag: "java-interop-props", + workingDirectory: javaInteropDir, + arguments: new List { + $"bin/Build{context.Configuration}/JdkInfo.props", + $"CONFIGURATION={context.Configuration}", + $"JI_MAX_JDK={Configurables.Defaults.MaxJDKVersion}", + } + ); + return result; + } + } +} diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.Windows.cs b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.Windows.cs new file mode 100644 index 00000000000..e341c97cb89 --- /dev/null +++ b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.Windows.cs @@ -0,0 +1,14 @@ +using System.IO; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Xamarin.Android.Prepare +{ + partial class Step_PrepareExternalJavaInterop + { + async Task ExecuteOSSpecific (Context context) + { + return true; + } + } +} diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.cs b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.cs new file mode 100644 index 00000000000..e57193610e1 --- /dev/null +++ b/build-tools/xaprepare/xaprepare/Steps/Step_PrepareExternalJavaInterop.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace Xamarin.Android.Prepare +{ + partial class Step_PrepareExternalJavaInterop : Step + { + public Step_PrepareExternalJavaInterop () + : base ("Preparing external/Java.Interop") + {} + + protected override async Task Execute (Context context) + { + return await ExecuteOSSpecific (context); + } + } +} diff --git a/build-tools/xaprepare/xaprepare/xaprepare.csproj b/build-tools/xaprepare/xaprepare/xaprepare.csproj index cf88a0dd7cd..81d59485f1e 100644 --- a/build-tools/xaprepare/xaprepare/xaprepare.csproj +++ b/build-tools/xaprepare/xaprepare/xaprepare.csproj @@ -143,6 +143,7 @@ + @@ -197,6 +198,7 @@ + @@ -260,6 +262,7 @@ + From 0c28baa202b19f00516821339e23a63b0f09b95b Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 14 Nov 2019 10:56:54 +0100 Subject: [PATCH 06/21] Preserve required Java.Interop fields It finally built and started running tests! https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3239656&view=logs&s=859b8d9a-8fd6-5a5c-6f5e-f84f1990894e&j=8556562a-ae5f-5bd1-7c4d-bf1af4b6f1e1 It crashes! #00 pc 001eb93c /data/app/Mono.Android_Tests-kS0jLDcPe9huyCD5kHs-cQ==/lib/x86/libmonosgen-2.0.so (mono_field_get_value+60) That's all the stack trace we get. :-( Hypothesis -- because I don't want to try building locally, ugh -- is that our types are missing required fields. Looking at `Mono.Android_Tests-Signed.apk`, and this hypothesis appears to be correct: `Java.Interop.JavaObject` lacks `refs_added` and `weak_handle` fields, while `Java.Lang.Object` contains them. Update src/monodroid to assert that the required fields exist, so that we can at minimum get a better error message. Update Xamarin.Android.Build.Tasks so that we add a linker XML file to explicitly preserve the required fields within JavaObject & JavaException. --- .../Linker/PreserveLists/Java.Interop.xml | 17 +++++++++++++++++ .../Xamarin.Android.Build.Tasks.csproj | 3 +++ src/monodroid/jni/monodroid-glue.cc | 10 ++++++++++ 3 files changed, 30 insertions(+) create mode 100644 src/Xamarin.Android.Build.Tasks/Linker/PreserveLists/Java.Interop.xml diff --git a/src/Xamarin.Android.Build.Tasks/Linker/PreserveLists/Java.Interop.xml b/src/Xamarin.Android.Build.Tasks/Linker/PreserveLists/Java.Interop.xml new file mode 100644 index 00000000000..bfb2cfa1802 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Linker/PreserveLists/Java.Interop.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 104bf1c41f2..75de516c1b7 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -625,6 +625,9 @@ MonoRuntimeProvider.Shared.20.java + + Java.Interop.xml + mscorlib.xml diff --git a/src/monodroid/jni/monodroid-glue.cc b/src/monodroid/jni/monodroid-glue.cc index f296bf9ed86..34874dbb143 100644 --- a/src/monodroid/jni/monodroid-glue.cc +++ b/src/monodroid/jni/monodroid-glue.cc @@ -903,6 +903,16 @@ MonodroidRuntime::lookup_bridge_info (MonoDomain *domain, MonoImage *image, cons info->handle_type = mono_class_get_field_from_name (info->klass, const_cast ("handle_type")); info->refs_added = mono_class_get_field_from_name (info->klass, const_cast ("refs_added")); info->weak_handle = mono_class_get_field_from_name (info->klass, const_cast ("weak_handle")); + if (info->klass == NULL || info->handle == NULL || info->handle_type == NULL || + info->refs_added == NULL || info->weak_handle == NULL) { + log_fatal (LOG_DEFAULT, "The type `%s.%s` is missing required instance fields! handle=%p handle_type=%p refs_added=%p weak_handle=%p", + type->_namespace, type->_typename, + info->handle, + info->handle_type, + info->refs_added, + info->weak_handle); + exit (FATAL_EXIT_MONO_MISSING_SYMBOLS); + } } void From 352eb6940f909f47cdac9b35bbfadd493c343156 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 14 Nov 2019 12:55:53 +0100 Subject: [PATCH 07/21] Preserve more fields! Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3243746&view=results Now we have a decent error message! F monodroid: The type `Java.Lang.Throwable` is missing required instance fields! handle=0xd221e690 handle_type=0xd221e6b0 refs_added=0xd221e6c0 weak_handle=0x0 `Java.Lang.Throwable.weak_handle` isn't preserved! I'm not sure why it was (presumably?) previously preserved -- perhaps it wasn't! this needs verification -- but to address this fatal error and see if we can actually complete things, treat `Java.Lang.Object` and `Java.Lang.Throwable` the same way we treat `Java.Interop.JavaObject` and `Java.Interop.JavaException`. --- .../Linker/PreserveLists/Mono.Android.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Linker/PreserveLists/Mono.Android.xml b/src/Xamarin.Android.Build.Tasks/Linker/PreserveLists/Mono.Android.xml index c6da83bffdf..3c4d22fbfe0 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/PreserveLists/Mono.Android.xml +++ b/src/Xamarin.Android.Build.Tasks/Linker/PreserveLists/Mono.Android.xml @@ -47,6 +47,18 @@ --> + + + + + + + + + + + + From 48b3113eefa642c639186ce9d228b9f24a20278e Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Fri, 15 Nov 2019 09:53:48 +0100 Subject: [PATCH 08/21] Preserve required types Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3243934&view=ms.vss-test-web.build-test-results-tab&runId=9758256&resultId=100726&paneView=debug The tests are now able to build and run without crashing! Yay! Unfortunately many tests fail, e.g. Java.Lang.ClassNotFoundException : com.xamarin.java_interop.internal.JavaProxyObject Huh? Turns out that `Mono.Android-Tests` is using `$(AndroidLinkTool)`=r8, which links more Java code, which caused `com.xamarin.java_interop.internal.JavaProxyObject` and other types to be linked away! Oops! Update `proguard_xamarin.cfg` so that the `com.xamarin.java_interop.**` types are preserved. Add a new `src/Mono.Android/Test/proguard.cfg` file so that the Java types required by the unit tests are also preserved. --- src/Mono.Android/Test/Mono.Android-Tests.csproj | 3 +++ src/Mono.Android/Test/proguard.cfg | 3 +++ src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg | 1 + 3 files changed, 7 insertions(+) create mode 100644 src/Mono.Android/Test/proguard.cfg diff --git a/src/Mono.Android/Test/Mono.Android-Tests.csproj b/src/Mono.Android/Test/Mono.Android-Tests.csproj index b81d2a5d537..96118c34a18 100644 --- a/src/Mono.Android/Test/Mono.Android-Tests.csproj +++ b/src/Mono.Android/Test/Mono.Android-Tests.csproj @@ -60,6 +60,9 @@ + + + diff --git a/src/Mono.Android/Test/proguard.cfg b/src/Mono.Android/Test/proguard.cfg new file mode 100644 index 00000000000..cbc69c8bebe --- /dev/null +++ b/src/Mono.Android/Test/proguard.cfg @@ -0,0 +1,3 @@ +# Need to preserve the contents of Mono.Android-Test-classes.jar + +-keep class com.xamarin.interop.** { *; (); } diff --git a/src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg b/src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg index 695f410aa22..4629e018dd5 100644 --- a/src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg +++ b/src/Xamarin.Android.Build.Tasks/Resources/proguard_xamarin.cfg @@ -3,6 +3,7 @@ -dontobfuscate -keep class android.support.multidex.MultiDexApplication { (); } +-keep class com.xamarin.java_interop.** { *; (); } -keep class mono.MonoRuntimeProvider { *; (...); } -keep class mono.MonoPackageManager { *; (...); } -keep class mono.MonoPackageManager_Resources { *; (...); } From 295d9e75375c1c74cd208256402201f70ce2a3aa Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Fri, 22 Nov 2019 10:41:39 -0500 Subject: [PATCH 09/21] [Mono.Android] Include JavaNativeTypeManager.ToJniName() Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3261114&view=logs&j=65486226-8c87-5153-e73a-d57909d6ac16&t=0c4ab8a2-b502-54b1-2c2d-58f1af7b0279 The Designer tests failed! System.NotSupportedException: Cannot create instance of type 'Android.Runtime.UncaughtExceptionHandler': no Java peer type found. at Java.Interop.JniPeerMembers+JniInstanceMethods..ctor (System.Type declaringType) [0x00046] in <9cb9a310e5034526b407c7688775bf95>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.GetConstructorsForType (System.Type declaringType) [0x00031] in <9cb9a310e5034526b407c7688775bf95>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.StartCreateInstance (System.String constructorSignature, System.Type declaringType, Java.Interop.JniArgumentValue* parameters) [0x00038] in <9cb9a310e5034526b407c7688775bf95>:0 at Java.Lang.Object..ctor () [0x0001f] in /Users/runner/runners/2.160.1/work/1/s/src/Mono.Android/obj/Release/android-28/mcw/Java.Lang.Object.cs:30 at Android.Runtime.UncaughtExceptionHandler..ctor (Java.Lang.Thread+IUncaughtExceptionHandler defaultHandler) [0x00000] in /Users/runner/runners/2.160.1/work/1/s/src/Mono.Android/Android.Runtime/UncaughtExceptionHandler.cs:14 at Android.Runtime.JNIEnv.Initialize (Android.Runtime.JnienvInitializeArgs* args) [0x00159] in /Users/runner/runners/2.160.1/work/1/s/src/Mono.Android/Android.Runtime/JNIEnv.cs:156 ...which was rather odd. Why couldn't the Java peer type be found? The answer is that `AndroidRuntime.GetSimpleReferences()` *used to* call `JNIEnv.GetJniName(Type)`, which in turn would call `JavaNativeTypeManager.ToJniName(Type)`, which was really only useful on Desktop environments. The "updated" `AndroidRuntime.GetSimpleReferences()` stopped calling `JNIEnv.GetJniName()`, in order to fix one of the Java.Interop unit tests, which also meant that it stopped calling `JavaNativeTypeManager.ToJniName()`. This is why `UncaughtExceptionHandler` could not be found. When on desktop, continue calling `JavaNativeTypeManager.ToJniName()`. --- src/Mono.Android/Android.Runtime/AndroidRuntime.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs index 4953d5ab785..93a5fc0e9de 100644 --- a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs +++ b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs @@ -231,12 +231,16 @@ protected override IEnumerable GetTypesForSimpleReference (string jniSimpl protected override IEnumerable GetSimpleReferences (Type type) { + foreach (var simpleRef in base.GetSimpleReferences (type)) { + yield return simpleRef; + } var j = JNIEnv.monodroid_typemap_managed_to_java (type.FullName + ", " + type.Assembly.GetName ().Name); - if (j == IntPtr.Zero) - return base.GetSimpleReferences (type); - var s = Marshal.PtrToStringAnsi (j); - return base.GetSimpleReferences (type) - .Concat (new [] { s }); + if (j != IntPtr.Zero) { + yield return Marshal.PtrToStringAnsi (j); + } + if (JNIEnv.IsRunningOnDesktop) { + yield return JavaNativeTypeManager.ToJniName (type); + } } delegate Delegate GetCallbackHandler (); From bdeba28a6d11f0f39af44c148f4b253710d03909 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Mon, 25 Nov 2019 09:13:20 -0500 Subject: [PATCH 10/21] [Mono.Android] Don't use JniEnvironment.Runtime in finalizers Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object at Java.Interop.JniEnvironmentInfo..ctor () at Java.Interop.JniEnvironment+<>c.<.cctor>b__35_0 () at System.Threading.ThreadLocal`1[T].GetValueSlow () at System.Threading.ThreadLocal`1[T].get_Value () at Java.Interop.JniEnvironment.get_CurrentInfo () at Java.Interop.JniEnvironment.get_Runtime () at Java.Lang.Object.Finalize () Finalization order is indeterminate, and when the process is shutting down it's entirely plausible that a `Java.Lang.Object` instance will be finalized *after* the `JniRuntime` instance has been finalized (as `JniRuntime.Dispose()` will "dispose" all known `JniEnvironment` instances), at which point things will Faill Horribly. Update the `Java.Lang.Object` and `Java.Lang.Throwable` finalizers so that `JniEnvironment.Runtime` is not accessed when `Environment.HasShutdownStarted` is true. --- src/Mono.Android/Java.Lang/Object.cs | 3 +++ src/Mono.Android/Java.Lang/Throwable.cs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/Mono.Android/Java.Lang/Object.cs b/src/Mono.Android/Java.Lang/Object.cs index 142b6cf1383..b9a084788ce 100644 --- a/src/Mono.Android/Java.Lang/Object.cs +++ b/src/Mono.Android/Java.Lang/Object.cs @@ -54,6 +54,9 @@ IntPtr IJavaObjectEx.ToLocalJniHandle () // handle still contains a java reference, we can't finalize the // object and should "resurrect" it. refs_added = 0; + if (Environment.HasShutdownStarted) { + return; + } JniEnvironment.Runtime.ValueManager.FinalizePeer (this); } diff --git a/src/Mono.Android/Java.Lang/Throwable.cs b/src/Mono.Android/Java.Lang/Throwable.cs index 8554c637764..504b658b08b 100644 --- a/src/Mono.Android/Java.Lang/Throwable.cs +++ b/src/Mono.Android/Java.Lang/Throwable.cs @@ -252,6 +252,9 @@ public static System.Exception ToException (Throwable e) ~Throwable () { refs_added = 0; + if (Environment.HasShutdownStarted) { + return; + } JniEnvironment.Runtime.ValueManager.FinalizePeer (this); } From cb2659d8b7e1d08d8807ea4977be52cbb0097b39 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 27 Nov 2019 15:23:24 -0500 Subject: [PATCH 11/21] [Mono.Android-Tests] Deal with xamarin/java.interop@dec2e390 xamarin/java.interop@dec2e390 changed how unit tests are structured and removed the shared projects which were previously used. --- Xamarin.Android-Tests.sln | 4 ---- .../Test/Java.Interop-Tests/Java.Interop-Tests.csproj | 8 ++++++-- .../Test/Java.Interop-Tests/Java.Interop-Tests.targets | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Xamarin.Android-Tests.sln b/Xamarin.Android-Tests.sln index 068c92bb1cf..6c014954ba0 100644 --- a/Xamarin.Android-Tests.sln +++ b/Xamarin.Android-Tests.sln @@ -90,8 +90,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android-Test.Library", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android-TestsMultiDex", "tests\Runtime-MultiDex\Mono.Android-TestsMultiDex.csproj", "{9ECBEA14-B79F-4F92-9266-495C03A32571}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Interop-Tests", "external\Java.Interop\src\Java.Interop\Tests\Interop-Tests.shproj", "{0ADB8D72-7479-49AF-8809-E03AE4A4EAE2}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Linq.Expressions", "external\Java.Interop\lib\mono.linq.expressions\Mono.Linq.Expressions.csproj", "{0C001D50-4176-45AE-BDC8-BA626508B0CC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Java.Interop.GenericMarshaler", "external\Java.Interop\src\Java.Interop.GenericMarshaler\Java.Interop.GenericMarshaler.csproj", "{D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}" @@ -103,7 +101,6 @@ EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{0ab4956e-6fb9-4da0-9d49-ab65a3ff403a}*SharedItemsImports = 13 - external\Java.Interop\src\Java.Interop\Tests\Interop-Tests.projitems*{0adb8d72-7479-49af-8809-e03ae4a4eae2}*SharedItemsImports = 13 src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{40ead437-216b-4df4-8258-3f47e1672c3a}*SharedItemsImports = 4 external\Java.Interop\src\Java.Interop\Tests\Interop-Tests.projitems*{6cb00820-a66b-43e5-8785-ed456c6e9f39}*SharedItemsImports = 4 src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{9ecbea14-b79f-4f92-9266-495c03a32571}*SharedItemsImports = 4 @@ -304,7 +301,6 @@ Global {0AB4956E-6FB9-4DA0-9D49-AB65A3FF403A} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {8CB5FF58-FF95-43B9-9064-9ACE9525866F} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {9ECBEA14-B79F-4F92-9266-495C03A32571} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} - {0ADB8D72-7479-49AF-8809-E03AE4A4EAE2} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {0C001D50-4176-45AE-BDC8-BA626508B0CC} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {6CB00820-A66B-43E5-8785-ED456C6E9F39} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj index 5009aa123f1..5fd18417c3c 100644 --- a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj +++ b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj @@ -15,7 +15,7 @@ 512 Resources\Resource.designer.cs Off - v9.0 + v10.0 true @@ -53,6 +53,11 @@ + + + + + @@ -66,7 +71,6 @@ Mono.Linq.Expressions - diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.targets b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.targets index e4804b6d206..c6a3371fcc7 100644 --- a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.targets +++ b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.targets @@ -10,7 +10,7 @@ - + Date: Wed, 11 Dec 2019 13:56:05 -0500 Subject: [PATCH 12/21] [Mono.Android-Tests] Make debuggable in release config --- src/Mono.Android/Test/Properties/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mono.Android/Test/Properties/AndroidManifest.xml b/src/Mono.Android/Test/Properties/AndroidManifest.xml index d15674daf9a..a67c4caa579 100644 --- a/src/Mono.Android/Test/Properties/AndroidManifest.xml +++ b/src/Mono.Android/Test/Properties/AndroidManifest.xml @@ -1,7 +1,7 @@  - + From fb97766bd48ee464a9f32a9bee788e8a55dea425 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 11 Dec 2019 20:54:25 -0500 Subject: [PATCH 13/21] Bump to xamarin/Java.Interop/jonp-fix-JniTypeTest@f54a7bc5 Context: https://github.com/xamarin/java.interop/pull/538 Should fix the `JNI DETECTED ERROR IN APPLICATION` crash which was preventing the unit tests from completing successfully. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 68edcd73aaa..8659954e821 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,7 +13,7 @@ [submodule "external/Java.Interop"] path = external/Java.Interop url = https://github.com/xamarin/java.interop.git - branch = master + branch = jonp-fix-JniTypeTest [submodule "external/mman-win32"] path = external/mman-win32 url = https://github.com/witwall/mman-win32.git From dabd00e845739e42b004c6e849c37695641d6b2c Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 12 Dec 2019 09:11:53 -0500 Subject: [PATCH 14/21] Bump to xamarin/Java.Interop/master@f3553f41 https://github.com/xamarin/java.interop/pull/538 was merged, so d80020fc is no longer necessary. --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 8659954e821..68edcd73aaa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,7 +13,7 @@ [submodule "external/Java.Interop"] path = external/Java.Interop url = https://github.com/xamarin/java.interop.git - branch = jonp-fix-JniTypeTest + branch = master [submodule "external/mman-win32"] path = external/mman-win32 url = https://github.com/witwall/mman-win32.git From 32dd518c74225bd4b6460519d8eb721e84fd34e4 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 12 Dec 2019 11:33:24 -0500 Subject: [PATCH 15/21] Remove Mono.Linq.Expressions Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3315048&view=logs&jobId=96fd57f5-f69e-53c7-3d47-f67e6cf9b93e&j=8556562a-ae5f-5bd1-7c4d-bf1af4b6f1e1&t=5076e147-fc66-561e-6c69-3aa777afefc5 xamarin/Java.Interop@76d6e6dc removed Mono.Linq.Expressions as a submodule and replaced it with a NuGet package. Remove the `Mono.Linq.Expressions.csproj` references and replace with a `@(PackageReference)`. This change will hopefully allow tests to build now: Java.Interop/tests/Java.Interop-Tests/Java.Interop/JniValueMarshalerContractTests.cs(10,12): error CS0234: The type or namespace name 'Linq' does not exist in the namespace 'Mono' (are you missing an assembly reference?) --- Xamarin.Android-Tests.sln | 7 ------- .../xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs | 8 ++++---- .../Test/Java.Interop-Tests/Java.Interop-Tests.csproj | 7 +++---- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/Xamarin.Android-Tests.sln b/Xamarin.Android-Tests.sln index 6c014954ba0..e3837f554ba 100644 --- a/Xamarin.Android-Tests.sln +++ b/Xamarin.Android-Tests.sln @@ -90,8 +90,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android-Test.Library", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Android-TestsMultiDex", "tests\Runtime-MultiDex\Mono.Android-TestsMultiDex.csproj", "{9ECBEA14-B79F-4F92-9266-495C03A32571}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Linq.Expressions", "external\Java.Interop\lib\mono.linq.expressions\Mono.Linq.Expressions.csproj", "{0C001D50-4176-45AE-BDC8-BA626508B0CC}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Java.Interop.GenericMarshaler", "external\Java.Interop\src\Java.Interop.GenericMarshaler\Java.Interop.GenericMarshaler.csproj", "{D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Java.Interop-Tests", "src\Mono.Android\Test\Java.Interop-Tests\Java.Interop-Tests.csproj", "{6CB00820-A66B-43E5-8785-ED456C6E9F39}" @@ -250,10 +248,6 @@ Global {9ECBEA14-B79F-4F92-9266-495C03A32571}.Release|Any CPU.ActiveCfg = Release|Any CPU {9ECBEA14-B79F-4F92-9266-495C03A32571}.Release|Any CPU.Build.0 = Release|Any CPU {9ECBEA14-B79F-4F92-9266-495C03A32571}.Release|Any CPU.Deploy.0 = Release|Any CPU - {0C001D50-4176-45AE-BDC8-BA626508B0CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0C001D50-4176-45AE-BDC8-BA626508B0CC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0C001D50-4176-45AE-BDC8-BA626508B0CC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0C001D50-4176-45AE-BDC8-BA626508B0CC}.Release|Any CPU.Build.0 = Release|Any CPU {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}.Debug|Any CPU.Build.0 = Debug|Any CPU {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -301,7 +295,6 @@ Global {0AB4956E-6FB9-4DA0-9D49-AB65A3FF403A} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {8CB5FF58-FF95-43B9-9064-9ACE9525866F} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {9ECBEA14-B79F-4F92-9266-495C03A32571} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} - {0C001D50-4176-45AE-BDC8-BA626508B0CC} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {6CB00820-A66B-43E5-8785-ED456C6E9F39} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} {94BD81F7-B06F-4295-9636-F8A3B6BDC762} = {EFBC4DC0-DBFF-4DAA-B0B8-6D0CB02A25F5} diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs index b9fa35b9076..ca4bcd82c9e 100644 --- a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs +++ b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/Java.Interop.cs @@ -13,7 +13,7 @@ class JavaInterop_External_Dependencies_Group : ThirdPartyNoticeGroup new JavaInterop_xamarin_Java_Interop_TPN (), new JavaInterop_gityf_crc_TPN (), new JavaInterop_xamarin_mono_cecil_TPN (), - new JavaInterop_jonpryor_mono_linq_expressions_TPN (), + new JavaInterop_jbevain_mono_linq_expressions_TPN (), new JavaInterop_mono_csharp_TPN (), new JavaInterop_mono_LineEditor_TPN (), new JavaInterop_mono_Options_TPN (), @@ -82,12 +82,12 @@ class JavaInterop_xamarin_mono_cecil_TPN : ThirdPartyNotice public override string LicenseText => null; } - class JavaInterop_jonpryor_mono_linq_expressions_TPN : ThirdPartyNotice + class JavaInterop_jbevain_mono_linq_expressions_TPN : ThirdPartyNotice { - static readonly Uri url = new Uri ("https://github.com/jonpryor/mono.linq.expressions/"); + static readonly Uri url = new Uri ("https://github.com/jbevain/mono.linq.expressions/"); public override string LicenseFile => null; - public override string Name => "jonpryor/mono.linq.expressions"; + public override string Name => "jbevain/mono.linq.expressions"; public override Uri SourceUrl => url; public override string LicenseText => @" diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj index 5fd18417c3c..aac904803ff 100644 --- a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj +++ b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj @@ -66,10 +66,9 @@ {D1243BAB-23CA-4566-A2A3-3ADA2C2DC3AF} Java.Interop.GenericMarshaler - - {0C001D50-4176-45AE-BDC8-BA626508B0CC} - Mono.Linq.Expressions - + + + From 93a7bb05f99a59f271effdea3892299c5b32a82a Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 12 Dec 2019 21:13:18 -0500 Subject: [PATCH 16/21] [tests] Invoke Restore target as part of unit test build. Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3317420&view=logs&jobId=cac0e8d3-0ef5-5d2b-b57e-e8fde7204df3&j=8556562a-ae5f-5bd1-7c4d-bf1af4b6f1e1&t=5076e147-fc66-561e-6c69-3aa777afefc5 Remember the "Remove Mono.Linq.Expressions" commit? The fix didn't fix things; we're still failing in the same way: .../Xamarin.Android.Common.targets(1694,2): error XA2002: Can not resolve reference: `Mono.Linq.Expressions`, referenced by `Java.Interop-Tests`. Please add a NuGet package or assembly reference for `Mono.Linq.Expressions`, or remove the reference to `Java.Interop-Tests`. Why? Because by moving to `@(PackageReference)`, we're now reliant on NuGet, and [NuGet Restore is failing][0] (?!) /Library/Frameworks/Mono.framework/Versions/Current/Commands/mono /Users/runner/hostedtoolcache/NuGet/5.4.0/x64/nuget.exe restore /Users/runner/runners/2.162.0/work/1/s/Xamarin.Android-Tests.sln -Verbosity Detailed -NonInteractive -ConfigFile /Users/runner/runners/2.162.0/work/1/Nuget/tempNuGet_3317420.config NuGet Version: 5.4.0.6315 MSBuild auto-detection: using msbuild version '15.0' from '/Library/Frameworks/Mono.framework/Versions/6.8.0/lib/mono/msbuild/15.0/bin'. Use option -MSBuildVersion to force nuget to use a specific version of MSBuild. MSBuild P2P timeout [ms]: 228000 /Library/Frameworks/Mono.framework/Versions/Current/Commands/msbuild "/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/NuGetScratch/m9ak7i1i.nw0.nugetinputs.targets" /t:GenerateRestoreGraphFile /nologo /nr:false /v:q /p:NuGetRestoreTargets="/var/folders/24/8k48jl6d249_n_qfxwsl6xvm0000gn/T/NuGetScratch/6znzw9b3.kvw.nugetrestore.targets" /p:RestoreUseCustomAfterTargets="True" /p:RestoreTaskAssemblyFile="/Users/runner/hostedtoolcache/NuGet/5.4.0/x64/nuget.exe" /p:RestoreSolutionDirectory="/Users/runner/runners/2.162.0/work/1/s/" /p:RestoreConfigFile="/Users/runner/runners/2.162.0/work/1/Nuget/tempNuGet_3317420.config" /p:SolutionDir="/Users/runner/runners/2.162.0/work/1/s/" /p:SolutionName="Xamarin.Android-Tests" /p:RestoreBuildInParallel="False" /p:RestoreUseSkipNonexistentTargets="False" /Users/runner/runners/2.162.0/work/1/s/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/Xamarin.Android.Bcl-Tests.targets(9,3): error MSB4019: The imported project "/Users/runner/runners/2.162.0/work/1/s/bin/Debug/bcl-tests/ProfileAssemblies.projitems" was not found. Confirm that the expression in the Import declaration "../../../bin/Debug/bcl-tests/ProfileAssemblies.projitems" is correct, and that the file exists on disk. [/Users/runner/runners/2.162.0/work/1/s/tests/BCL-Tests/Xamarin.Android.Bcl-Tests/Xamarin.Android.Bcl-Tests.csproj] /Users/runner/runners/2.162.0/work/1/s/build-tools/scripts/XAVersionInfo.targets(9,3): error MSB4019: The imported project "/Users/runner/runners/2.162.0/work/1/s/bin/BuildDebug/MonoGitHash.props" was not found. Confirm that the expression in the Import declaration "../../bin/BuildDebug/MonoGitHash.props" is correct, and that the file exists on disk. [/Users/runner/runners/2.162.0/work/1/s/build-tools/timing/timing.csproj] Of interest is the MSB4019 error...which is ignored, as the overall AzDO step is green. Best I can easily figure, `Java.Interop-Tests.csproj` is failing to build because it can't find `Mono.Linq.Expressions`: .../Xamarin.Android.Common.targets(1694,2): error XA2002: Can not resolve reference: `Mono.Linq.Expressions`, referenced by `Java.Interop-Tests`. Please add a NuGet package or assembly reference for `Mono.Linq.Expressions`, or remove the reference to `Java.Interop-Tests`. [/Users/runner/runners/2.162.0/work/1/s/src/Mono.Android/Test/Mono.Android-Tests.csproj] ...and it can't find `Mono.Linq.Expressions`, presumably, because the NuGet restore process didn't fully complete. Square this circle by adding a `/t:Restore` invocation as part of the `Mono.Android-Tests` invocation, so that (hopefully) the `Mono.Linq.Expressions` NuGet package will be installed & used. [0]: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3317420&view=logs&jobId=cac0e8d3-0ef5-5d2b-b57e-e8fde7204df3&j=8556562a-ae5f-5bd1-7c4d-bf1af4b6f1e1&t=b9294726-b793-5321-dfc7-34d7e8d44bdd --- build-tools/automation/yaml-templates/apk-instrumentation.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-tools/automation/yaml-templates/apk-instrumentation.yaml b/build-tools/automation/yaml-templates/apk-instrumentation.yaml index b45b649601f..fb3d0743c6f 100644 --- a/build-tools/automation/yaml-templates/apk-instrumentation.yaml +++ b/build-tools/automation/yaml-templates/apk-instrumentation.yaml @@ -17,7 +17,7 @@ steps: solution: ${{ parameters.project }} configuration: ${{ parameters.configuration }} msbuildArguments: > - /t:AcquireAndroidTarget,SignAndroidPackage,DeployTest${{ parameters.packageType }}s,RunTestApks,UndeployTestApks,RenameApkTestCases,ReportComponentFailures + /t:Restore,AcquireAndroidTarget,SignAndroidPackage,DeployTest${{ parameters.packageType }}s,RunTestApks,UndeployTestApks,RenameApkTestCases,ReportComponentFailures /bl:$(System.DefaultWorkingDirectory)/bin/Test${{ parameters.configuration }}/run${{ parameters.testName }}.binlog ${{ parameters.extraBuildArgs }} condition: ${{ parameters.condition }} From c7c1b5adfedc4b53c67700382b9d5bf5a82f89f6 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Mon, 16 Dec 2019 20:06:18 -0500 Subject: [PATCH 17/21] [Java.Interop-Tests] Use legacy nuget reference Attempting to use `@(PackageReference)` for `Mono.Linq.Expressions` continues to fail, even after PR #3995. Looking at the `msbuild Xamarin.Android /t:Prepare` output [^0], I see that there is a `nuget restore Xamarin.Android-Tests.sln`, and it does not always, and it restores numerous NuGet packages...but not Mono.Linq.Expressions. In the interest of any form of progress, use the "legacy" `packages.config`-style nuget reference, and see if that changes anything. [^0]: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3318737&view=logs&j=cac0e8d3-0ef5-5d2b-b57e-e8fde7204df3&t=b0ec5c6c-f5a1-5ebf-2068-57a5c78a6a85 --- Xamarin.Android-Tests.sln | 1 - .../Test/Java.Interop-Tests/Java.Interop-Tests.csproj | 7 ++++--- src/Mono.Android/Test/Java.Interop-Tests/packages.config | 4 ++++ 3 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 src/Mono.Android/Test/Java.Interop-Tests/packages.config diff --git a/Xamarin.Android-Tests.sln b/Xamarin.Android-Tests.sln index e3837f554ba..5b2db998e1b 100644 --- a/Xamarin.Android-Tests.sln +++ b/Xamarin.Android-Tests.sln @@ -100,7 +100,6 @@ Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{0ab4956e-6fb9-4da0-9d49-ab65a3ff403a}*SharedItemsImports = 13 src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{40ead437-216b-4df4-8258-3f47e1672c3a}*SharedItemsImports = 4 - external\Java.Interop\src\Java.Interop\Tests\Interop-Tests.projitems*{6cb00820-a66b-43e5-8785-ed456c6e9f39}*SharedItemsImports = 4 src\Mono.Android\Test\Mono.Android-Test.Shared.projitems*{9ecbea14-b79f-4f92-9266-495c03a32571}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj index aac904803ff..a587304a775 100644 --- a/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj +++ b/src/Mono.Android/Test/Java.Interop-Tests/Java.Interop-Tests.csproj @@ -47,6 +47,9 @@ + + ..\..\..\..\packages\mono.linq.expressions.2.0.0\lib\netstandard2.0\Mono.Linq.Expressions.dll + @@ -60,6 +63,7 @@ + @@ -67,9 +71,6 @@ Java.Interop.GenericMarshaler - - - diff --git a/src/Mono.Android/Test/Java.Interop-Tests/packages.config b/src/Mono.Android/Test/Java.Interop-Tests/packages.config new file mode 100644 index 00000000000..1c3a8d1b1f6 --- /dev/null +++ b/src/Mono.Android/Test/Java.Interop-Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From e20e9deeea3a367f01fa3479cacc7097d19354ac Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 17 Dec 2019 17:49:18 -0500 Subject: [PATCH 18/21] [Mono.Android-TestsAppBundle] Fix the build Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3328422&view=logs&j=8556562a-ae5f-5bd1-7c4d-bf1af4b6f1e1&t=edd3bdba-6ec4-5961-ea81-8c75bc7c9371 The build failed: .../src/Mono.Android/Test/Xamarin.Android.RuntimeTests/TestInstrumentation.cs(24,39): error CS0234: The type or namespace name 'JavaInterop_Tests_Reference' does not exist in the namespace 'Java.InteropTests' (are you missing an assembly reference?) Add an appropriate `@(ProjectReference)`. --- tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj b/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj index 3122174af9b..f6a11f9baa6 100644 --- a/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj +++ b/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj @@ -118,6 +118,10 @@ {CB2335CB-0050-4020-8A05-E9614EDAA05E} TestRunner.NUnit + + {6CB00820-A66B-43E5-8785-ED456C6E9F39} + Java.Interop-Tests + {8CB5FF58-FF95-43B9-9064-9ACE9525866F} Mono.Android-Test.Library From 0873940bc6d40458ebd7db02bcf31c06d484b743 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 17 Dec 2019 17:50:45 -0500 Subject: [PATCH 19/21] Set `$(AndroidLinkMode)`=r8 This is for consistency with `Mono.Android-Tests.csproj`; see also: 4bb4b2e93c832203c1b84aefd2a00e48a5a572ac --- tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj | 1 + tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj b/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj index f6a11f9baa6..3f5f1ec0866 100644 --- a/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj +++ b/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj @@ -46,6 +46,7 @@ 4 false true + r8 diff --git a/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj b/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj index bbaad338f39..bebb3e28a13 100644 --- a/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj +++ b/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj @@ -45,6 +45,7 @@ 4 false true + r8 From 24e81234a4bcdc7a97866c9982fd7d3e727f0293 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Wed, 18 Dec 2019 16:12:57 -0500 Subject: [PATCH 20/21] [tests] Preserve Java.Interop-Tests types! See also the "Preserve required types" commit. `Mono.Android_TestMultiDex` and `Mono.Android_TestsAppBundle` are failing because they can't resolve some Java types: Java.Lang.ClassNotFoundException : com.xamarin.interop.CallVirtualFromConstructorDerived at Java.Interop.JniEnvironment+Types.FindClass (System.String classname) at Java.Interop.JniType..ctor (System.String classname) at Java.Interop.JniType.GetCachedJniType (Java.Interop.JniType& cachedType, System.String classname) at Java.Interop.JniPeerMembers.get_JniPeerType () at Java.Interop.JniPeerMembers+JniStaticMethods.GetMethodInfo (System.String encodedMember) at Java.Interop.JniPeerMembers+JniStaticMethods.InvokeObjectMethod (System.String encodedMember, Java.Interop.JniArgumentValue* parameters) at Java.InteropTests.CallVirtualFromConstructorDerived.NewInstance (System.Int32 value) at Java.InteropTests.InvokeVirtualFromConstructorTests.ActivationConstructor () at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&) at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) --- End of managed Java.Lang.ClassNotFoundException stack trace --- java.lang.ClassNotFoundException: com.xamarin.interop.CallVirtualFromConstructorDerived at crc64f295cabbf85394f5.TestSuiteInstrumentation.n_onStart(Native Method) at crc64f295cabbf85394f5.TestSuiteInstrumentation.onStart(Unknown Source:0) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189) Add a `@(ProguardConfiguration)` entry to the appropriate projects so that these required types are preserved. --- tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj | 3 +++ tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj | 3 +++ 2 files changed, 6 insertions(+) diff --git a/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj b/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj index 3f5f1ec0866..793fa8b7d00 100644 --- a/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj +++ b/tests/Runtime-AppBundle/Mono.Android-TestsAppBundle.csproj @@ -65,6 +65,9 @@ + + + Resources\drawable\Icon.png diff --git a/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj b/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj index bebb3e28a13..39810986789 100644 --- a/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj +++ b/tests/Runtime-MultiDex/Mono.Android-TestsMultiDex.csproj @@ -64,6 +64,9 @@ + + + From 21c2a18955147235ff6300c8b2d24a292cf34ee3 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Thu, 19 Dec 2019 15:22:00 -0500 Subject: [PATCH 21/21] Cleanup! Address questions on the PR Also bump "back" to Java.Interop/master, as that has the needed fixes. --- .../automation/yaml-templates/apk-instrumentation.yaml | 2 +- .../xaprepare/Scenarios/Scenario_PrepareExternal.cs | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/build-tools/automation/yaml-templates/apk-instrumentation.yaml b/build-tools/automation/yaml-templates/apk-instrumentation.yaml index fb3d0743c6f..b45b649601f 100644 --- a/build-tools/automation/yaml-templates/apk-instrumentation.yaml +++ b/build-tools/automation/yaml-templates/apk-instrumentation.yaml @@ -17,7 +17,7 @@ steps: solution: ${{ parameters.project }} configuration: ${{ parameters.configuration }} msbuildArguments: > - /t:Restore,AcquireAndroidTarget,SignAndroidPackage,DeployTest${{ parameters.packageType }}s,RunTestApks,UndeployTestApks,RenameApkTestCases,ReportComponentFailures + /t:AcquireAndroidTarget,SignAndroidPackage,DeployTest${{ parameters.packageType }}s,RunTestApks,UndeployTestApks,RenameApkTestCases,ReportComponentFailures /bl:$(System.DefaultWorkingDirectory)/bin/Test${{ parameters.configuration }}/run${{ parameters.testName }}.binlog ${{ parameters.extraBuildArgs }} condition: ${{ parameters.condition }} diff --git a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs index e3df02297a0..8ed907324f3 100644 --- a/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs +++ b/build-tools/xaprepare/xaprepare/Scenarios/Scenario_PrepareExternal.cs @@ -13,12 +13,6 @@ protected override void AddSteps (Context context) { Steps.Add (new Step_PrepareExternal ()); Steps.Add (new Step_PrepareExternalJavaInterop ()); - - // disable installation of missing programs... - context.SetCondition (KnownConditions.AllowProgramInstallation, false); - - // ...but do not signal an error when any are missing - context.SetCondition (KnownConditions.IgnoreMissingPrograms, true); } } }