Skip to content

Commit e56f235

Browse files
committed
Merge branch 'main' into dev/grendel/clr-host
* main: [Mono.Android] `JNIEnv.FindClass()` uses `JniEnvironment.Types.FindClass()` (#9769) [Mono.Android] `JavaList.Add` should allow duplicates. (#9751) Bump to dotnet/java-interop@6bc87e8b (#9761)
2 parents 2e035de + aba2726 commit e56f235

File tree

10 files changed

+65
-61
lines changed

10 files changed

+65
-61
lines changed

build-tools/Xamarin.Android.Tools.BootstrapTasks/Xamarin.Android.Tools.BootstrapTasks/CheckApiCompatibility.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ public sealed class CheckApiCompatibility : Task
6767
// In case API diffs vary between e.g. Classic MonoAndroid & .NET 6+
6868
public string TargetFramework { get; set; }
6969

70+
// What's missing from acceptableIssuesFile?
71+
public string LinesToAdd { get; set; }
72+
7073
// This Build tasks validates that changes are not breaking Api
7174
public override bool Execute ()
7275
{
@@ -260,6 +263,7 @@ void dataReceived (object sender, DataReceivedEventArgs args)
260263
}
261264

262265
LogError ($"CheckApiCompatibility found nonacceptable Api breakages for ApiLevel: {ApiLevel}.{Environment.NewLine}{string.Join (Environment.NewLine, lines)}");
266+
ReportMissingLines (acceptableIssuesFile.FullName, lines);
263267

264268
var missingItems = CodeGenDiff.GenerateMissingItems (CodeGenPath, contractAssembly.FullName, implementationAssembly.FullName);
265269
if (missingItems.Any ()) {
@@ -285,6 +289,21 @@ void dataReceived (object sender, DataReceivedEventArgs args)
285289
}
286290
}
287291

292+
void ReportMissingLines (string acceptableIssuesFile, List<string> lines)
293+
{
294+
if (string.IsNullOrWhiteSpace (LinesToAdd)) {
295+
return;
296+
}
297+
var known = new HashSet<string> (File.ReadAllLines (acceptableIssuesFile), StringComparer.Ordinal);
298+
using var writer = File.CreateText (LinesToAdd);
299+
foreach (var line in lines) {
300+
if (known.Contains (line)) {
301+
continue;
302+
}
303+
writer.WriteLine (line);
304+
}
305+
}
306+
288307
void LogError (string errorMessage)
289308
{
290309
if (!string.IsNullOrWhiteSpace (compatApiCommand)) {

build-tools/xaprepare/xaprepare/Steps/Step_InstallDotNetPreview.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ protected override async Task<bool> Execute (Context context)
2121
var dotnetPath = Configurables.Paths.DotNetPreviewPath;
2222
dotnetPath = dotnetPath.TrimEnd (new char [] { Path.DirectorySeparatorChar });
2323

24-
if (!await InstallDotNetAsync (context, dotnetPath, BuildToolVersion)) {
24+
if (!await InstallDotNetAsync (context, dotnetPath, BuildToolVersion, useCachedInstallScript: true) &&
25+
!await InstallDotNetAsync (context, dotnetPath, BuildToolVersion, useCachedInstallScript: false)) {
2526
Log.ErrorLine ($"Installation of dotnet SDK '{BuildToolVersion}' failed.");
2627
return false;
2728
}
@@ -77,17 +78,18 @@ protected override async Task<bool> Execute (Context context)
7778
return true;
7879
}
7980

80-
async Task<bool> DownloadDotNetInstallScript (Context context, string dotnetScriptPath, Uri dotnetScriptUrl)
81+
async Task<bool> DownloadDotNetInstallScript (Context context, string dotnetScriptPath, Uri dotnetScriptUrl, bool useCachedInstallScript)
8182
{
8283
string tempDotnetScriptPath = dotnetScriptPath + "-tmp";
8384
Utilities.DeleteFile (tempDotnetScriptPath);
8485

8586
Log.StatusLine ("Downloading dotnet-install script...");
8687

87-
if (File.Exists (dotnetScriptPath)) {
88+
if (useCachedInstallScript && File.Exists (dotnetScriptPath)) {
8889
Log.WarningLine ($"Using cached installation script found in '{dotnetScriptPath}'");
8990
return true;
9091
}
92+
Utilities.DeleteFile (dotnetScriptPath);
9193

9294
Log.StatusLine ($" {context.Characters.Link} {dotnetScriptUrl}", ConsoleColor.White);
9395
await Utilities.Download (dotnetScriptUrl, tempDotnetScriptPath, DownloadStatus.Empty);
@@ -173,7 +175,7 @@ string[] GetInstallationScriptArgs (string version, string dotnetPath, string do
173175
return args.ToArray ();
174176
}
175177

176-
async Task<bool> InstallDotNetAsync (Context context, string dotnetPath, string version, bool runtimeOnly = false)
178+
async Task<bool> InstallDotNetAsync (Context context, string dotnetPath, string version, bool useCachedInstallScript, bool runtimeOnly = false)
177179
{
178180
string cacheDir = context.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory);
179181

@@ -183,7 +185,7 @@ async Task<bool> InstallDotNetAsync (Context context, string dotnetPath, string
183185
Uri dotnetScriptUrl = Configurables.Urls.DotNetInstallScript;
184186
string scriptFileName = Path.GetFileName (dotnetScriptUrl.LocalPath);
185187
string cachedDotnetScriptPath = Path.Combine (cacheDir, scriptFileName);
186-
if (!await DownloadDotNetInstallScript (context, cachedDotnetScriptPath, dotnetScriptUrl)) {
188+
if (!await DownloadDotNetInstallScript (context, cachedDotnetScriptPath, dotnetScriptUrl, useCachedInstallScript)) {
187189
return false;
188190
}
189191

src/Mono.Android/Android.Runtime/JNIEnv.cs

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -280,52 +280,9 @@ public static IntPtr FindClass (System.Type type)
280280
}
281281
}
282282

283-
const int nameBufferLength = 1024;
284-
[ThreadStatic] static char[]? nameBuffer;
285-
286-
static unsafe IntPtr BinaryName (string classname)
283+
public static IntPtr FindClass (string classname)
287284
{
288-
int index = classname.IndexOf ('/');
289-
290-
if (index == -1)
291-
return NewString (classname);
292-
293-
int length = classname.Length;
294-
if (length > nameBufferLength)
295-
return NewString (classname.Replace ('/', '.'));
296-
297-
if (nameBuffer == null)
298-
nameBuffer = new char[nameBufferLength];
299-
300-
fixed (char* src = classname, dst = nameBuffer) {
301-
char* src_ptr = src;
302-
char* dst_ptr = dst;
303-
char* end_ptr = src + length;
304-
while (src_ptr < end_ptr) {
305-
*dst_ptr = (*src_ptr == '/') ? '.' : *src_ptr;
306-
src_ptr++;
307-
dst_ptr++;
308-
}
309-
}
310-
return NewString (nameBuffer, length);
311-
}
312-
313-
public unsafe static IntPtr FindClass (string classname)
314-
{
315-
JniObjectReference local_ref;
316-
317-
IntPtr native_str = BinaryName (classname);
318-
try {
319-
JniArgumentValue* parameters = stackalloc JniArgumentValue [3] {
320-
new JniArgumentValue (native_str),
321-
new JniArgumentValue (true),
322-
new JniArgumentValue (JNIEnvInit.java_class_loader),
323-
};
324-
local_ref = JniEnvironment.StaticMethods.CallStaticObjectMethod (Java.Lang.Class.Members.JniPeerType.PeerReference, JNIEnvInit.mid_Class_forName!, parameters);
325-
} finally {
326-
DeleteLocalRef (native_str);
327-
}
328-
285+
JniObjectReference local_ref = JniEnvironment.Types.FindClass (classname);
329286
IntPtr global_ref = NewGlobalRef (local_ref.Handle);
330287
JniObjectReference.Dispose (ref local_ref);
331288
return global_ref;

src/Mono.Android/Android.Runtime/JNIEnvInit.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ internal struct JnienvInitializeArgs {
2020
public IntPtr grefLoader;
2121
public IntPtr Loader_loadClass;
2222
public IntPtr grefClass; // TODO: remove, not needed anymore
23-
public IntPtr Class_forName;
2423
public uint logCategories;
2524
public int version; // TODO: remove, not needed anymore
2625
public int grefGcThreshold;
@@ -46,7 +45,6 @@ internal struct JnienvInitializeArgs {
4645
internal static IntPtr grefIGCUserPeer_class;
4746
internal static IntPtr grefGCUserPeerable_class;
4847
internal static IntPtr java_class_loader;
49-
internal static JniMethodInfo? mid_Class_forName;
5048

5149
internal static JniRuntime? androidRuntime;
5250

@@ -100,8 +98,6 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args)
10098
MarshalMethodsEnabled = args->marshalMethodsEnabled;
10199
java_class_loader = args->grefLoader;
102100

103-
mid_Class_forName = new JniMethodInfo (args->Class_forName, isStatic: true);
104-
105101
BoundExceptionType = (BoundExceptionType)args->ioExceptionType;
106102
androidRuntime = new AndroidRuntime (args->env, args->javaVm, args->grefLoader, args->Loader_loadClass, args->jniAddNativeMethodRegistrationAttributePresent != 0);
107103
ValueManager = androidRuntime.ValueManager;

src/Mono.Android/Android.Runtime/JavaList.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -546,14 +546,13 @@ public static IntPtr ToLocalJniHandle (IList? items)
546546
//
547547
public virtual bool Add (Java.Lang.Object? item)
548548
{
549-
return Add (0, item);
549+
Add ((object?) item);
550+
return true;
550551
}
551552

552553
public virtual bool Add (int index, Java.Lang.Object? item)
553554
{
554-
if (Contains (item))
555-
return false;
556-
Add ((object?) item);
555+
Insert (index, (object?) item);
557556
return true;
558557
}
559558

src/Mono.Android/Mono.Android.targets

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@
225225
TargetImplementationPath="$(OutputPath)"
226226
ApiCompatibilityPath="$(ApiCompatibilityDir)"
227227
TargetFramework="$(TargetFramework)"
228+
LinesToAdd="$(MSBuildThisFileDirectory)ApiCompatLinesToAdd.txt"
228229
/>
229230
<Touch
230231
Files="$(IntermediateOutputPath)CheckApiCompatibility.stamp"

src/native/mono/monodroid/monodroid-glue-internal.hh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ namespace xamarin::android::internal
8989
jobject grefLoader;
9090
jmethodID Loader_loadClass;
9191
jclass grefClass;
92-
jmethodID Class_forName;
9392
unsigned int logCategories;
9493
int version;
9594
int grefGcThreshold;

src/native/mono/monodroid/monodroid-glue.cc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,6 @@ MonodroidRuntime::init_android_runtime (JNIEnv *env, jclass runtimeClass, jobjec
860860

861861
init.grefClass = RuntimeUtil::get_class_from_runtime_field (env, runtimeClass, "java_lang_Class", true);
862862
Class_getName = env->GetMethodID (init.grefClass, "getName", "()Ljava/lang/String;");
863-
init.Class_forName = env->GetStaticMethodID (init.grefClass, "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;");
864863

865864
MonoAssembly *mono_android_assembly;
866865

tests/Mono.Android-Tests/Java.Interop/JavaListTest.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,38 @@ namespace Java.InteropTests
1515
[SetUp]
1616
public void Setup () => list = new T ();
1717

18+
[Test]
19+
public void Add ()
20+
{
21+
list.Add ("foo");
22+
Assert.AreEqual ("foo", list [0]);
23+
24+
// Ensure duplicates are allowed.
25+
list.Add ("foo");
26+
Assert.AreEqual (2, list.Count);
27+
Assert.AreEqual ("foo", list [1]);
28+
}
29+
30+
[Test]
31+
public void AddWithIndex ()
32+
{
33+
list.Add ("Apple");
34+
list.Add ("Banana");
35+
list.Add ("Cherry");
36+
37+
// Ensure index is respected.
38+
list.Add (3, "Grape");
39+
list.Add (2, "Blueberry");
40+
list.Add (4, "Fig");
41+
42+
Assert.AreEqual ("Apple", list [0]);
43+
Assert.AreEqual ("Banana", list [1]);
44+
Assert.AreEqual ("Blueberry", list [2]);
45+
Assert.AreEqual ("Cherry", list [3]);
46+
Assert.AreEqual ("Fig", list [4]);
47+
Assert.AreEqual ("Grape", list [5]);
48+
}
49+
1850
[Test]
1951
public void Count ()
2052
{

0 commit comments

Comments
 (0)