Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Android.App;
using System;
using Android.App;
using Android.Content;
using Android.Util;
using Android.Views;
Expand Down Expand Up @@ -44,6 +45,47 @@ public void UpperAndLowerCaseCustomWidget_FromLibrary_ShouldNotThrowInflateExcep
inflater.Inflate (Resource.Layout.upper_lower_custom, null);
}, "Regression test for widgets with uppercase and lowercase namespace (bug #23880) failed.");
}

// https://github.com/dotnet/android/issues/11101
[Test]
public void InflateCustomView_ShouldNotLeakGlobalRefs ()
{
var inflater = (LayoutInflater) Application.Context.GetSystemService (Context.LayoutInflaterService);
Assert.IsNotNull (inflater);

// Warm up: inflate once to populate caches and type mappings,
// and let any background thread activity from previous tests settle.
inflater.Inflate (Resource.Layout.lowercase_custom, null);
CollectGarbage (times: 3);

int grefBefore = Java.Interop.Runtime.GlobalReferenceCount;

// Use a large number of inflations so that a real leak (3+ global refs
// per inflate) produces a delta far above any background noise from
// Android system services, GC bridge processing, or finalizer threads.
const int inflateCount = 100;
for (int i = 0; i < inflateCount; i++) {
inflater.Inflate (Resource.Layout.lowercase_custom, null);
}

CollectGarbage (times: 3);

int grefAfter = Java.Interop.Runtime.GlobalReferenceCount;
int delta = grefAfter - grefBefore;

// A real leak would produce delta >= 300 (3 leaked refs per inflate).
// Use a generous threshold to tolerate background noise on real devices.
Assert.IsTrue (delta <= 100,
$"Global reference leak detected: {delta} extra global refs after inflating/GC'ing {inflateCount} custom views. Before={grefBefore}, After={grefAfter}");

static void CollectGarbage (int times)
{
for (int i = 0; i < times; i++) {
GC.Collect ();
GC.WaitForPendingFinalizers ();
}
}
}
}

public class CustomButton : Button
Expand Down