From 1fe8a4e4e6728b37933bed983cff80d530763b1c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 28 Mar 2023 11:09:48 -0400 Subject: [PATCH 1/9] update webview_flutter instance mangaer --- .../webviewflutter/InstanceManager.java | 83 ++++++++----------- .../webviewflutter/WebViewFlutterPlugin.java | 4 +- .../webviewflutter/DownloadListenerTest.java | 4 +- .../webviewflutter/FileChooserParamsTest.java | 4 +- .../webviewflutter/InstanceManagerTest.java | 80 ++++-------------- .../webviewflutter/JavaObjectHostApiTest.java | 4 +- .../webviewflutter/JavaScriptChannelTest.java | 4 +- .../webviewflutter/WebChromeClientTest.java | 4 +- .../webviewflutter/WebSettingsTest.java | 4 +- .../WebStorageHostApiImplTest.java | 4 +- .../webviewflutter/WebViewClientTest.java | 4 +- .../plugins/webviewflutter/WebViewTest.java | 8 +- 12 files changed, 72 insertions(+), 135 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java index de51ebd0482..bda182c9fff 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java @@ -30,9 +30,6 @@ */ @SuppressWarnings("unchecked") public class InstanceManager { - /// Constant returned from #addHostCreatedInstance() if the manager is closed. - public static final int INSTANCE_CLOSED = -1; - // Identifiers are locked to a specific range to avoid collisions with objects // created simultaneously from Dart. // Host uses identifiers >= 2^16 and Dart is expected to use values n where, @@ -40,7 +37,6 @@ public class InstanceManager { private static final long MIN_HOST_CREATED_IDENTIFIER = 65536; private static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000; private static final String TAG = "InstanceManager"; - private static final String CLOSED_WARNING = "Method was called while the manager was closed."; /** Interface for listening when a weak reference of an instance is removed from the manager. */ public interface FinalizationListener { @@ -59,17 +55,17 @@ public interface FinalizationListener { private final FinalizationListener finalizationListener; private long nextIdentifier = MIN_HOST_CREATED_IDENTIFIER; - private boolean isClosed = false; + private boolean hasFinalizationListenerStopped = false; /** * Instantiate a new manager. * - *

When the manager is no longer needed, {@link #close()} must be called. + *

When the manager is no longer needed, {@link #stopFinalizationListener()} must be called. * * @param finalizationListener the listener for garbage collected weak references. * @return a new `InstanceManager`. */ - public static InstanceManager open(FinalizationListener finalizationListener) { + public static InstanceManager create(FinalizationListener finalizationListener) { return new InstanceManager(finalizationListener); } @@ -85,14 +81,12 @@ private InstanceManager(FinalizationListener finalizationListener) { * * @param identifier the identifier paired to an instance. * @param the expected return type. - * @return the removed instance if the manager contains the given identifier, otherwise null if - * the manager doesn't contain the value or the manager is closed. + * @return the removed instance if the manager contains the given identifier, otherwise `null` if + * the manager doesn't contain the value. */ @Nullable public T remove(long identifier) { - if (assertNotClosed()) { - return null; - } + logWarningIfFinalizationListenerHasStopped(); return (T) strongInstances.remove(identifier); } @@ -110,13 +104,12 @@ public T remove(long identifier) { * * @param instance an instance that may be stored in the manager. * @return the identifier associated with `instance` if the manager contains the value, otherwise - * null if the manager doesn't contain the value or the manager is closed. + * `null` if the manager doesn't contain the value. */ @Nullable public Long getIdentifierForStrongReference(Object instance) { - if (assertNotClosed()) { - return null; - } + logWarningIfFinalizationListenerHasStopped(); + final Long identifier = identifiers.get(instance); if (identifier != null) { strongInstances.put(identifier, instance); @@ -131,16 +124,12 @@ public Long getIdentifierForStrongReference(Object instance) { * allows two objects that are equivalent (e.g. the `equals` method returns true and their * hashcodes are equal) to both be added. * - *

If the manager is closed, the addition is ignored and a warning is logged. - * * @param instance the instance to be stored. * @param identifier the identifier to be paired with instance. This value must be >= 0 and * unique. */ public void addDartCreatedInstance(Object instance, long identifier) { - if (assertNotClosed()) { - return; - } + logWarningIfFinalizationListenerHasStopped(); addInstance(instance, identifier); } @@ -148,13 +137,10 @@ public void addDartCreatedInstance(Object instance, long identifier) { * Adds a new instance that was instantiated from the host platform. * * @param instance the instance to be stored. This must be unique to all other added instances. - * @return the unique identifier stored with instance. If the manager is closed, returns -1. - * Otherwise, returns a value >= 0. + * @return the unique identifier stored with instance. Otherwise, returns a value >= 0. */ public long addHostCreatedInstance(Object instance) { - if (assertNotClosed()) { - return INSTANCE_CLOSED; - } + logWarningIfFinalizationListenerHasStopped(); if (containsInstance(instance)) { throw new IllegalArgumentException( @@ -171,13 +157,11 @@ public long addHostCreatedInstance(Object instance) { * @param identifier the identifier associated with an instance. * @param the expected return type. * @return the instance associated with `identifier` if the manager contains the value, otherwise - * null if the manager doesn't contain the value or the manager is closed. + * `null` if the manager doesn't contain the value. */ @Nullable public T getInstance(long identifier) { - if (assertNotClosed()) { - return null; - } + logWarningIfFinalizationListenerHasStopped(); final WeakReference instance = (WeakReference) weakInstances.get(identifier); if (instance != null) { @@ -190,25 +174,23 @@ public T getInstance(long identifier) { * Returns whether this manager contains the given `instance`. * * @param instance the instance whose presence in this manager is to be tested. - * @return whether this manager contains the given `instance`. If the manager is closed, returns - * `false`. + * @return whether this manager contains the given `instance`. */ public boolean containsInstance(Object instance) { - if (assertNotClosed()) { - return false; - } + logWarningIfFinalizationListenerHasStopped(); return identifiers.containsKey(instance); } /** - * Closes the manager and releases resources. + * Stop the periodic run of the {@link FinalizationListener} for instances that have been garbage + * collected. * - *

Methods called after this one will be ignored and log a warning. + *

The InstanceManager can continue to be used, but the {@link FinalizationListener} will no + * longer be called and methods will log a warning. */ - public void close() { + public void stopFinalizationListener() { handler.removeCallbacks(this::releaseAllFinalizedInstances); - isClosed = true; - clear(); + hasFinalizationListenerStopped = true; } /** @@ -224,15 +206,20 @@ public void clear() { } /** - * Whether the manager has released resources and is no longer usable. + * Whether the {@link FinalizationListener} is still being called for instances that are garbage + * collected. * - *

See {@link #close()}. + *

See {@link #stopFinalizationListener()}. */ - public boolean isClosed() { - return isClosed; + public boolean hasFinalizationListenerStopped() { + return hasFinalizationListenerStopped; } private void releaseAllFinalizedInstances() { + if (hasFinalizationListenerStopped()) { + return; + } + WeakReference reference; while ((reference = (WeakReference) referenceQueue.poll()) != null) { final Long identifier = weakReferencesToIdentifiers.remove(reference); @@ -261,11 +248,9 @@ private void addInstance(Object instance, long identifier) { strongInstances.put(identifier, instance); } - private boolean assertNotClosed() { - if (isClosed()) { - Log.w(TAG, CLOSED_WARNING); - return true; + private void logWarningIfFinalizationListenerHasStopped() { + if (hasFinalizationListenerStopped()) { + Log.w(TAG, "The manager was used after calls to the FinalizationListener have been stopped."); } - return false; } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java index c30e956c893..6c06678584f 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewFlutterPlugin.java @@ -80,7 +80,7 @@ private void setUp( View containerView, FlutterAssetManager flutterAssetManager) { instanceManager = - InstanceManager.open( + InstanceManager.create( identifier -> new GeneratedAndroidWebView.JavaObjectFlutterApi(binaryMessenger) .dispose(identifier, reply -> {})); @@ -152,7 +152,7 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { if (instanceManager != null) { - instanceManager.close(); + instanceManager.stopFinalizationListener(); instanceManager = null; } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/DownloadListenerTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/DownloadListenerTest.java index caffbb9a95e..ae0029648eb 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/DownloadListenerTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/DownloadListenerTest.java @@ -29,7 +29,7 @@ public class DownloadListenerTest { @Before public void setUp() { - instanceManager = InstanceManager.open(identifier -> {}); + instanceManager = InstanceManager.create(identifier -> {}); final DownloadListenerCreator downloadListenerCreator = new DownloadListenerCreator() { @@ -48,7 +48,7 @@ public DownloadListenerImpl createDownloadListener( @After public void tearDown() { - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FileChooserParamsTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FileChooserParamsTest.java index 3172ea4330c..0fb21cc474c 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FileChooserParamsTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FileChooserParamsTest.java @@ -35,12 +35,12 @@ public class FileChooserParamsTest { @Before public void setUp() { - instanceManager = InstanceManager.open(identifier -> {}); + instanceManager = InstanceManager.create(identifier -> {}); } @After public void tearDown() { - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/InstanceManagerTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/InstanceManagerTest.java index 2bda2d12c75..4b4349db1f4 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/InstanceManagerTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/InstanceManagerTest.java @@ -15,7 +15,7 @@ public class InstanceManagerTest { @Test public void addDartCreatedInstance() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object object = new Object(); instanceManager.addDartCreatedInstance(object, 0); @@ -24,12 +24,12 @@ public void addDartCreatedInstance() { assertEquals((Long) 0L, instanceManager.getIdentifierForStrongReference(object)); assertTrue(instanceManager.containsInstance(object)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test public void addHostCreatedInstance() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object object = new Object(); long identifier = instanceManager.addHostCreatedInstance(object); @@ -38,12 +38,12 @@ public void addHostCreatedInstance() { assertEquals(object, instanceManager.getInstance(identifier)); assertTrue(instanceManager.containsInstance(object)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test public void remove() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); Object object = new Object(); instanceManager.addDartCreatedInstance(object, 0); @@ -58,60 +58,12 @@ public void remove() { assertNull(instanceManager.getInstance(0)); - instanceManager.close(); - } - - @Test - public void removeReturnsNullWhenClosed() { - final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); - instanceManager.addDartCreatedInstance(object, 0); - instanceManager.close(); - - assertNull(instanceManager.remove(0)); - } - - @Test - public void getIdentifierForStrongReferenceReturnsNullWhenClosed() { - final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); - instanceManager.addDartCreatedInstance(object, 0); - instanceManager.close(); - - assertNull(instanceManager.getIdentifierForStrongReference(object)); - } - - @Test - public void addHostCreatedInstanceReturnsNegativeOneWhenClosed() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); - instanceManager.close(); - - assertEquals(instanceManager.addHostCreatedInstance(new Object()), -1L); - } - - @Test - public void getInstanceReturnsNullWhenClosed() { - final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); - instanceManager.addDartCreatedInstance(object, 0); - instanceManager.close(); - - assertNull(instanceManager.getInstance(0)); - } - - @Test - public void containsInstanceReturnsFalseWhenClosed() { - final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); - instanceManager.addDartCreatedInstance(object, 0); - instanceManager.close(); - - assertFalse(instanceManager.containsInstance(object)); + instanceManager.stopFinalizationListener(); } @Test public void clear() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object instance = new Object(); @@ -121,12 +73,12 @@ public void clear() { instanceManager.clear(); assertFalse(instanceManager.containsInstance(instance)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test public void canAddSameObjectWithAddDartCreatedInstance() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object instance = new Object(); @@ -138,37 +90,37 @@ public void canAddSameObjectWithAddDartCreatedInstance() { assertEquals(instanceManager.getInstance(0), instance); assertEquals(instanceManager.getInstance(1), instance); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test(expected = IllegalArgumentException.class) public void cannotAddSameObjectsWithAddHostCreatedInstance() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object instance = new Object(); instanceManager.addHostCreatedInstance(instance); instanceManager.addHostCreatedInstance(instance); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test(expected = IllegalArgumentException.class) public void cannotUseIdentifierLessThanZero() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); instanceManager.addDartCreatedInstance(new Object(), -1); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test(expected = IllegalArgumentException.class) public void identifiersMustBeUnique() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); instanceManager.addDartCreatedInstance(new Object(), 0); instanceManager.addDartCreatedInstance(new Object(), 0); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaObjectHostApiTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaObjectHostApiTest.java index 8ac349e7641..88c759d1082 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaObjectHostApiTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaObjectHostApiTest.java @@ -11,7 +11,7 @@ public class JavaObjectHostApiTest { @Test public void dispose() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final JavaObjectHostApiImpl hostApi = new JavaObjectHostApiImpl(instanceManager); @@ -27,6 +27,6 @@ public void dispose() { assertNull(instanceManager.getInstance(0)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaScriptChannelTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaScriptChannelTest.java index 391c6c833e5..0c9647a8cb9 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaScriptChannelTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/JavaScriptChannelTest.java @@ -30,7 +30,7 @@ public class JavaScriptChannelTest { @Before public void setUp() { - instanceManager = InstanceManager.open(identifier -> {}); + instanceManager = InstanceManager.create(identifier -> {}); final JavaScriptChannelCreator javaScriptChannelCreator = new JavaScriptChannelCreator() { @@ -57,7 +57,7 @@ public JavaScriptChannel createJavaScriptChannel( @After public void tearDown() { - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebChromeClientTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebChromeClientTest.java index be301fa49ea..a9387293184 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebChromeClientTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebChromeClientTest.java @@ -45,7 +45,7 @@ public class WebChromeClientTest { @Before public void setUp() { - instanceManager = InstanceManager.open(identifier -> {}); + instanceManager = InstanceManager.create(identifier -> {}); final WebChromeClientCreator webChromeClientCreator = new WebChromeClientCreator() { @@ -64,7 +64,7 @@ public WebChromeClientImpl createWebChromeClient( @After public void tearDown() { - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java index 3abb4247c18..5e24b0ec18e 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebSettingsTest.java @@ -30,7 +30,7 @@ public class WebSettingsTest { @Before public void setUp() { - testInstanceManager = InstanceManager.open(identifier -> {}); + testInstanceManager = InstanceManager.create(identifier -> {}); when(mockWebSettingsCreator.createWebSettings(any())).thenReturn(mockWebSettings); testHostApiImpl = new WebSettingsHostApiImpl(testInstanceManager, mockWebSettingsCreator); @@ -39,7 +39,7 @@ public void setUp() { @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebStorageHostApiImplTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebStorageHostApiImplTest.java index b4f38f1702d..5756ce7a174 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebStorageHostApiImplTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebStorageHostApiImplTest.java @@ -28,7 +28,7 @@ public class WebStorageHostApiImplTest { @Before public void setUp() { - testInstanceManager = InstanceManager.open(identifier -> {}); + testInstanceManager = InstanceManager.create(identifier -> {}); when(mockWebStorageCreator.createWebStorage()).thenReturn(mockWebStorage); testHostApiImpl = new WebStorageHostApiImpl(testInstanceManager, mockWebStorageCreator); @@ -37,7 +37,7 @@ public void setUp() { @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java index f9e836e4510..97bfee3007f 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewClientTest.java @@ -41,7 +41,7 @@ public class WebViewClientTest { @Before public void setUp() { - instanceManager = InstanceManager.open(identifier -> {}); + instanceManager = InstanceManager.create(identifier -> {}); final WebViewClientCreator webViewClientCreator = new WebViewClientCreator() { @@ -59,7 +59,7 @@ public WebViewClient createWebViewClient(WebViewClientFlutterApiImpl flutterApi) @After public void tearDown() { - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java index 28027c30a61..3dffd66df64 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/WebViewTest.java @@ -48,7 +48,7 @@ public class WebViewTest { @Before public void setUp() { - testInstanceManager = InstanceManager.open(identifier -> {}); + testInstanceManager = InstanceManager.create(identifier -> {}); when(mockWebViewProxy.createWebView(mockContext, mockBinaryMessenger, testInstanceManager)) .thenReturn(mockWebView); @@ -60,7 +60,7 @@ public void setUp() { @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); } @Test @@ -319,7 +319,7 @@ public void destroy() { @Test public void flutterApiCreate() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final WebViewFlutterApiImpl flutterApiImpl = new WebViewFlutterApiImpl(mockBinaryMessenger, instanceManager); @@ -333,6 +333,6 @@ public void flutterApiCreate() { Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(mockWebView)); verify(mockFlutterApi).create(eq(instanceIdentifier), any()); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } } From 412036ca58ec71ea489b5ef50869f3d13564092f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:30:25 -0400 Subject: [PATCH 2/9] camerax side of change --- .../camerax/CameraAndroidCameraxPlugin.java | 4 +- .../plugins/camerax/InstanceManager.java | 90 +++++++++---------- .../plugins/camerax/CameraInfoTest.java | 4 +- .../plugins/camerax/CameraSelectorTest.java | 4 +- .../flutter/plugins/camerax/CameraTest.java | 4 +- .../plugins/camerax/ImageCaptureTest.java | 4 +- .../plugins/camerax/InstanceManagerTest.java | 52 +++++------ .../camerax/JavaObjectHostApiTest.java | 4 +- .../flutter/plugins/camerax/PreviewTest.java | 4 +- .../camerax/ProcessCameraProviderTest.java | 4 +- .../webviewflutter/InstanceManager.java | 2 +- 11 files changed, 83 insertions(+), 93 deletions(-) diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java index 08ecc847aa1..d0176a1812c 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java @@ -31,7 +31,7 @@ public CameraAndroidCameraxPlugin() {} void setUp(BinaryMessenger binaryMessenger, Context context, TextureRegistry textureRegistry) { // Set up instance manager. instanceManager = - InstanceManager.open( + InstanceManager.create( identifier -> { new GeneratedCameraXLibrary.JavaObjectFlutterApi(binaryMessenger) .dispose(identifier, reply -> {}); @@ -66,7 +66,7 @@ public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBindin @Override public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { if (instanceManager != null) { - instanceManager.close(); + instanceManager.stopFinalizationListener(); } } diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java index 4e7fa3e9e16..499544b84a3 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java @@ -30,9 +30,6 @@ */ @SuppressWarnings("unchecked") public class InstanceManager { - /// Constant returned from #addHostCreatedInstance() if the manager is closed. - public static final int INSTANCE_CLOSED = -1; - // Identifiers are locked to a specific range to avoid collisions with objects // created simultaneously from Dart. // Host uses identifiers >= 2^16 and Dart is expected to use values n where, @@ -40,7 +37,6 @@ public class InstanceManager { private static final long MIN_HOST_CREATED_IDENTIFIER = 65536; private static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000; private static final String TAG = "InstanceManager"; - private static final String CLOSED_WARNING = "Method was called while the manager was closed."; /** Interface for listening when a weak reference of an instance is removed from the manager. */ public interface FinalizationListener { @@ -59,17 +55,17 @@ public interface FinalizationListener { private final FinalizationListener finalizationListener; private long nextIdentifier = MIN_HOST_CREATED_IDENTIFIER; - private boolean isClosed = false; + private boolean hasFinalizationListenerStopped = false; /** * Instantiate a new manager. * - *

When the manager is no longer needed, {@link #close()} must be called. + *

When the manager is no longer needed, {@link #stopFinalizationListener()} must be called. * * @param finalizationListener the listener for garbage collected weak references. * @return a new `InstanceManager`. */ - public static InstanceManager open(FinalizationListener finalizationListener) { + public static InstanceManager create(FinalizationListener finalizationListener) { return new InstanceManager(finalizationListener); } @@ -85,15 +81,12 @@ private InstanceManager(FinalizationListener finalizationListener) { * * @param identifier the identifier paired to an instance. * @param the expected return type. - * @return the removed instance if the manager contains the given identifier, otherwise null if - * the manager doesn't contain the value or the manager is closed. + * @return the removed instance if the manager contains the given identifier, otherwise `null` if + * the manager doesn't contain the value. */ @Nullable public T remove(long identifier) { - if (isClosed()) { - Log.w(TAG, CLOSED_WARNING); - return null; - } + logWarningIfFinalizationListenerHasStopped(); return (T) strongInstances.remove(identifier); } @@ -111,14 +104,12 @@ public T remove(long identifier) { * * @param instance an instance that may be stored in the manager. * @return the identifier associated with `instance` if the manager contains the value, otherwise - * null if the manager doesn't contain the value or the manager is closed. + * `null` if the manager doesn't contain the value. */ @Nullable public Long getIdentifierForStrongReference(Object instance) { - if (isClosed()) { - Log.w(TAG, CLOSED_WARNING); - return null; - } + logWarningIfFinalizationListenerHasStopped(); + final Long identifier = identifiers.get(instance); if (identifier != null) { strongInstances.put(identifier, instance); @@ -133,17 +124,12 @@ public Long getIdentifierForStrongReference(Object instance) { * allows two objects that are equivalent (e.g. the `equals` method returns true and their * hashcodes are equal) to both be added. * - *

If the manager is closed, the addition is ignored and a warning is logged. - * * @param instance the instance to be stored. * @param identifier the identifier to be paired with instance. This value must be >= 0 and * unique. */ public void addDartCreatedInstance(Object instance, long identifier) { - if (isClosed()) { - Log.w(TAG, CLOSED_WARNING); - return; - } + logWarningIfFinalizationListenerHasStopped(); addInstance(instance, identifier); } @@ -151,14 +137,12 @@ public void addDartCreatedInstance(Object instance, long identifier) { * Adds a new instance that was instantiated from the host platform. * * @param instance the instance to be stored. This must be unique to all other added instances. - * @return the unique identifier (>= 0) stored with instance. If the manager is closed, returns - * -1. + * @return the unique identifier (>= 0) stored with instance. */ public long addHostCreatedInstance(Object instance) { - if (isClosed()) { - Log.w(TAG, CLOSED_WARNING); - return INSTANCE_CLOSED; - } else if (containsInstance(instance)) { + logWarningIfFinalizationListenerHasStopped(); + + if (containsInstance(instance)) { throw new IllegalArgumentException( String.format("Instance of `%s` has already been added.", instance.getClass())); } @@ -173,14 +157,12 @@ public long addHostCreatedInstance(Object instance) { * @param identifier the identifier associated with an instance. * @param the expected return type. * @return the instance associated with `identifier` if the manager contains the value, otherwise - * null if the manager doesn't contain the value or the manager is closed. + * `null` if the manager doesn't contain the value. */ @Nullable public T getInstance(long identifier) { - if (isClosed()) { - Log.w(TAG, CLOSED_WARNING); - return null; - } + logWarningIfFinalizationListenerHasStopped(); + final WeakReference instance = (WeakReference) weakInstances.get(identifier); if (instance != null) { return instance.get(); @@ -192,26 +174,23 @@ public T getInstance(long identifier) { * Returns whether this manager contains the given `instance`. * * @param instance the instance whose presence in this manager is to be tested. - * @return whether this manager contains the given `instance`. If the manager is closed, returns - * `false`. + * @return whether this manager contains the given `instance`. */ public boolean containsInstance(Object instance) { - if (isClosed()) { - Log.w(TAG, CLOSED_WARNING); - return false; - } + logWarningIfFinalizationListenerHasStopped(); return identifiers.containsKey(instance); } /** - * Closes the manager and releases resources. + * Stop the periodic run of the {@link FinalizationListener} for instances that have been garbage + * collected. * - *

Methods called after this one will be ignored and log a warning. + *

The InstanceManager can continue to be used, but the {@link FinalizationListener} will no + * longer be called and methods will log a warning. */ - public void close() { + public void stopFinalizationListener() { handler.removeCallbacks(this::releaseAllFinalizedInstances); - isClosed = true; - clear(); + hasFinalizationListenerStopped = true; } /** @@ -227,15 +206,20 @@ public void clear() { } /** - * Whether the manager has released resources and is no longer usable. + * Whether the {@link FinalizationListener} is still being called for instances that are garbage + * collected. * - *

See {@link #close()}. + *

See {@link #stopFinalizationListener()}. */ - public boolean isClosed() { - return isClosed; + public boolean hasFinalizationListenerStopped() { + return hasFinalizationListenerStopped; } private void releaseAllFinalizedInstances() { + if (hasFinalizationListenerStopped()) { + return; + } + WeakReference reference; while ((reference = (WeakReference) referenceQueue.poll()) != null) { final Long identifier = weakReferencesToIdentifiers.remove(reference); @@ -263,4 +247,10 @@ private void addInstance(Object instance, long identifier) { weakReferencesToIdentifiers.put(weakReference, identifier); strongInstances.put(identifier, instance); } + + private void logWarningIfFinalizationListenerHasStopped() { + if (hasFinalizationListenerStopped()) { + Log.w(TAG, "The manager was used after calls to the FinalizationListener have been stopped."); + } + } } diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraInfoTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraInfoTest.java index 663d0e2f26d..0cd85848e71 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraInfoTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraInfoTest.java @@ -32,12 +32,12 @@ public class CameraInfoTest { @Before public void setUp() { - testInstanceManager = InstanceManager.open(identifier -> {}); + testInstanceManager = InstanceManager.create(identifier -> {}); } @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); } @Test diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraSelectorTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraSelectorTest.java index 2b27e08b579..81ae31f7475 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraSelectorTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraSelectorTest.java @@ -36,12 +36,12 @@ public class CameraSelectorTest { @Before public void setUp() { - testInstanceManager = InstanceManager.open(identifier -> {}); + testInstanceManager = InstanceManager.create(identifier -> {}); } @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); } @Test diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraTest.java index e2135b3945b..af4fb2ce8e6 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraTest.java @@ -30,12 +30,12 @@ public class CameraTest { @Before public void setUp() { - testInstanceManager = InstanceManager.open(identifier -> {}); + testInstanceManager = InstanceManager.create(identifier -> {}); } @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); } @Test diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageCaptureTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageCaptureTest.java index c65bc3d3922..d1881b39a43 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageCaptureTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageCaptureTest.java @@ -48,14 +48,14 @@ public class ImageCaptureTest { @Before public void setUp() throws Exception { - testInstanceManager = spy(InstanceManager.open(identifier -> {})); + testInstanceManager = spy(InstanceManager.create(identifier -> {})); context = mock(Context.class); mockedStaticFile = mockStatic(File.class); } @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); mockedStaticFile.close(); } diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java index 34d8add9fc9..333fa823dc3 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java @@ -15,7 +15,7 @@ public class InstanceManagerTest { @Test public void addDartCreatedInstance() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object object = new Object(); instanceManager.addDartCreatedInstance(object, 0); @@ -24,12 +24,12 @@ public void addDartCreatedInstance() { assertEquals((Long) 0L, instanceManager.getIdentifierForStrongReference(object)); assertTrue(instanceManager.containsInstance(object)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test public void addHostCreatedInstance() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object object = new Object(); long identifier = instanceManager.addHostCreatedInstance(object); @@ -38,12 +38,12 @@ public void addHostCreatedInstance() { assertEquals(object, instanceManager.getInstance(identifier)); assertTrue(instanceManager.containsInstance(object)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test public void removeReturnsRemovedObjectAndClearsIdentifier() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); Object object = new Object(); instanceManager.addDartCreatedInstance(object, 0); @@ -58,15 +58,15 @@ public void removeReturnsRemovedObjectAndClearsIdentifier() { assertNull(instanceManager.getInstance(0)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test public void removeReturnsNullWhenClosed() { final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); instanceManager.addDartCreatedInstance(object, 0); - instanceManager.close(); + instanceManager.stopFinalizationListener(); assertNull(instanceManager.remove(0)); } @@ -74,17 +74,17 @@ public void removeReturnsNullWhenClosed() { @Test public void getIdentifierForStrongReferenceReturnsNullWhenClosed() { final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); instanceManager.addDartCreatedInstance(object, 0); - instanceManager.close(); + instanceManager.stopFinalizationListener(); assertNull(instanceManager.getIdentifierForStrongReference(object)); } @Test public void addHostCreatedInstanceReturnsNegativeOneWhenClosed() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); - instanceManager.close(); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); + instanceManager.stopFinalizationListener(); assertEquals(instanceManager.addHostCreatedInstance(new Object()), -1L); } @@ -92,9 +92,9 @@ public void addHostCreatedInstanceReturnsNegativeOneWhenClosed() { @Test public void getInstanceReturnsNullWhenClosed() { final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); instanceManager.addDartCreatedInstance(object, 0); - instanceManager.close(); + instanceManager.stopFinalizationListener(); assertNull(instanceManager.getInstance(0)); } @@ -102,16 +102,16 @@ public void getInstanceReturnsNullWhenClosed() { @Test public void containsInstanceReturnsFalseWhenClosed() { final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); instanceManager.addDartCreatedInstance(object, 0); - instanceManager.close(); + instanceManager.stopFinalizationListener(); assertFalse(instanceManager.containsInstance(object)); } @Test public void clear() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object instance = new Object(); @@ -121,12 +121,12 @@ public void clear() { instanceManager.clear(); assertFalse(instanceManager.containsInstance(instance)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test public void canAddSameObjectWithAddDartCreatedInstance() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object instance = new Object(); @@ -138,37 +138,37 @@ public void canAddSameObjectWithAddDartCreatedInstance() { assertEquals(instanceManager.getInstance(0), instance); assertEquals(instanceManager.getInstance(1), instance); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test(expected = IllegalArgumentException.class) public void cannotAddSameObjectsWithAddHostCreatedInstance() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final Object instance = new Object(); instanceManager.addHostCreatedInstance(instance); instanceManager.addHostCreatedInstance(instance); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test(expected = IllegalArgumentException.class) public void cannotUseIdentifierLessThanZero() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); instanceManager.addDartCreatedInstance(new Object(), -1); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } @Test(expected = IllegalArgumentException.class) public void identifiersMustBeUnique() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); instanceManager.addDartCreatedInstance(new Object(), 0); instanceManager.addDartCreatedInstance(new Object(), 0); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } } diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/JavaObjectHostApiTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/JavaObjectHostApiTest.java index cce3341aaa8..d05bf5bc46b 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/JavaObjectHostApiTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/JavaObjectHostApiTest.java @@ -11,7 +11,7 @@ public class JavaObjectHostApiTest { @Test public void dispose() { - final InstanceManager instanceManager = InstanceManager.open(identifier -> {}); + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); final JavaObjectHostApiImpl hostApi = new JavaObjectHostApiImpl(instanceManager); @@ -27,6 +27,6 @@ public void dispose() { assertNull(instanceManager.getInstance(0)); - instanceManager.close(); + instanceManager.stopFinalizationListener(); } } diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java index b76a4c91842..abf99257368 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PreviewTest.java @@ -49,12 +49,12 @@ public class PreviewTest { @Before public void setUp() { - testInstanceManager = spy(InstanceManager.open(identifier -> {})); + testInstanceManager = spy(InstanceManager.create(identifier -> {})); } @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); } @Test diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ProcessCameraProviderTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ProcessCameraProviderTest.java index bfe375854c4..f7987143b98 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ProcessCameraProviderTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ProcessCameraProviderTest.java @@ -52,13 +52,13 @@ public class ProcessCameraProviderTest { @Before public void setUp() { - testInstanceManager = InstanceManager.open(identifier -> {}); + testInstanceManager = InstanceManager.create(identifier -> {}); context = ApplicationProvider.getApplicationContext(); } @After public void tearDown() { - testInstanceManager.close(); + testInstanceManager.stopFinalizationListener(); } @Test diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java index bda182c9fff..b311e7d3984 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java @@ -137,7 +137,7 @@ public void addDartCreatedInstance(Object instance, long identifier) { * Adds a new instance that was instantiated from the host platform. * * @param instance the instance to be stored. This must be unique to all other added instances. - * @return the unique identifier stored with instance. Otherwise, returns a value >= 0. + * @return the unique identifier (>= 0) stored with instance. */ public long addHostCreatedInstance(Object instance) { logWarningIfFinalizationListenerHasStopped(); From ee44f2f55929499400805e12ac1a89e28072405e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:32:45 -0400 Subject: [PATCH 3/9] version bump --- packages/webview_flutter/webview_flutter_android/CHANGELOG.md | 4 ++++ packages/webview_flutter/webview_flutter_android/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index 9bb8d8205af..a940f88b048 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.4.4 + +* Updates internal Java InstanceManager to only stop finalization callbacks when engine is detached. + ## 3.4.3 * Updates internal Java InstanceManager to be cleared on hot restart. diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 5ae83c38194..6a25fffa77c 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_android description: A Flutter plugin that provides a WebView widget on Android. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.4.3 +version: 3.4.4 environment: sdk: ">=2.17.0 <4.0.0" From f73f110ea82f3e1fa2a4841575bfc47580e5086f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:35:45 -0400 Subject: [PATCH 4/9] version bump camerax --- packages/camera/camera_android_camerax/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md index f163e831acc..0f075af3e53 100644 --- a/packages/camera/camera_android_camerax/CHANGELOG.md +++ b/packages/camera/camera_android_camerax/CHANGELOG.md @@ -16,3 +16,4 @@ * Fixes instance manager hot restart behavior and fixes Java casting issue. * Implements image capture. * Fixes cast of CameraInfo to fix integration test failure. +* Updates internal Java InstanceManager to only stop finalization callbacks when engine is detached. From c5fe12e4ca6de821d8d5f745d293e61bc8a0488a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:36:20 -0400 Subject: [PATCH 5/9] stopped --- packages/camera/camera_android_camerax/CHANGELOG.md | 2 +- packages/webview_flutter/webview_flutter_android/CHANGELOG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md index 0f075af3e53..bd539829dd8 100644 --- a/packages/camera/camera_android_camerax/CHANGELOG.md +++ b/packages/camera/camera_android_camerax/CHANGELOG.md @@ -16,4 +16,4 @@ * Fixes instance manager hot restart behavior and fixes Java casting issue. * Implements image capture. * Fixes cast of CameraInfo to fix integration test failure. -* Updates internal Java InstanceManager to only stop finalization callbacks when engine is detached. +* Updates internal Java InstanceManager to only stop finalization callbacks when stopped. diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index a940f88b048..a6d0b45120b 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,6 +1,6 @@ ## 3.4.4 -* Updates internal Java InstanceManager to only stop finalization callbacks when engine is detached. +* Updates internal Java InstanceManager to only stop finalization callbacks when stopped. ## 3.4.3 From c42d4da476c6f16123686aa877cb54f4131c0e38 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 28 Mar 2023 12:45:52 -0400 Subject: [PATCH 6/9] add test --- .../plugins/camerax/InstanceManagerTest.java | 14 ++++++++++++++ .../webviewflutter/InstanceManagerTest.java | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java index 333fa823dc3..3feff8bdb30 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java @@ -171,4 +171,18 @@ public void identifiersMustBeUnique() { instanceManager.stopFinalizationListener(); } + + @Test + public void managerIsUsableWhileListenerHasStopped() { + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); + instanceManager.stopFinalizationListener(); + + final Object instance = new Object(); + final long identifier = 0; + + instanceManager.addDartCreatedInstance(instance, identifier); + assertEquals(instanceManager.getInstance(identifier), instance); + assertEquals(instanceManager.getIdentifierForStrongReference(instance), (Long) identifier); + assertTrue(instanceManager.containsInstance(instance)); + } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/InstanceManagerTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/InstanceManagerTest.java index 4b4349db1f4..2f2ea7769dd 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/InstanceManagerTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/InstanceManagerTest.java @@ -123,4 +123,18 @@ public void identifiersMustBeUnique() { instanceManager.stopFinalizationListener(); } + + @Test + public void managerIsUsableWhileListenerHasStopped() { + final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); + instanceManager.stopFinalizationListener(); + + final Object instance = new Object(); + final long identifier = 0; + + instanceManager.addDartCreatedInstance(instance, identifier); + assertEquals(instanceManager.getInstance(identifier), instance); + assertEquals(instanceManager.getIdentifierForStrongReference(instance), (Long) identifier); + assertTrue(instanceManager.containsInstance(instance)); + } } From cb0c128ed9dadef6d6310ec29b109b742fa488af Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 28 Mar 2023 13:38:49 -0400 Subject: [PATCH 7/9] remove tests --- .../plugins/camerax/InstanceManagerTest.java | 48 ------------------- 1 file changed, 48 deletions(-) diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java index 3feff8bdb30..7dd5e62acab 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/InstanceManagerTest.java @@ -61,54 +61,6 @@ public void removeReturnsRemovedObjectAndClearsIdentifier() { instanceManager.stopFinalizationListener(); } - @Test - public void removeReturnsNullWhenClosed() { - final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); - instanceManager.addDartCreatedInstance(object, 0); - instanceManager.stopFinalizationListener(); - - assertNull(instanceManager.remove(0)); - } - - @Test - public void getIdentifierForStrongReferenceReturnsNullWhenClosed() { - final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); - instanceManager.addDartCreatedInstance(object, 0); - instanceManager.stopFinalizationListener(); - - assertNull(instanceManager.getIdentifierForStrongReference(object)); - } - - @Test - public void addHostCreatedInstanceReturnsNegativeOneWhenClosed() { - final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); - instanceManager.stopFinalizationListener(); - - assertEquals(instanceManager.addHostCreatedInstance(new Object()), -1L); - } - - @Test - public void getInstanceReturnsNullWhenClosed() { - final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); - instanceManager.addDartCreatedInstance(object, 0); - instanceManager.stopFinalizationListener(); - - assertNull(instanceManager.getInstance(0)); - } - - @Test - public void containsInstanceReturnsFalseWhenClosed() { - final Object object = new Object(); - final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); - instanceManager.addDartCreatedInstance(object, 0); - instanceManager.stopFinalizationListener(); - - assertFalse(instanceManager.containsInstance(object)); - } - @Test public void clear() { final InstanceManager instanceManager = InstanceManager.create(identifier -> {}); From 2ec0a601fc13872966e2efda58f2b2a1d07f859a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 14 Apr 2023 15:46:06 -0400 Subject: [PATCH 8/9] add integration test --- .../plugins/camerax/InstanceManager.java | 5 ++- .../example/android/app/build.gradle | 3 +- .../cameraxexample/InstanceManagerTest.java | 42 +++++++++++++++++++ .../example/android/build.gradle | 2 +- .../example/pubspec.yaml | 1 + .../webview_flutter_android/CHANGELOG.md | 1 - .../webviewflutter/InstanceManager.java | 4 +- .../InstanceManagerTest.java | 42 +++++++++++++++++++ 8 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 packages/camera/camera_android_camerax/example/android/app/src/androidTest/java/io/flutter/plugins/cameraxexample/InstanceManagerTest.java create mode 100644 packages/webview_flutter/webview_flutter_android/example/android/app/src/androidTest/java/io/flutter/plugins/webviewflutterexample/InstanceManagerTest.java diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java index 499544b84a3..730908a411e 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java @@ -7,7 +7,9 @@ import android.os.Handler; import android.os.Looper; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.HashMap; @@ -35,7 +37,7 @@ public class InstanceManager { // Host uses identifiers >= 2^16 and Dart is expected to use values n where, // 0 <= n < 2^16. private static final long MIN_HOST_CREATED_IDENTIFIER = 65536; - private static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000; + @VisibleForTesting public static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000; private static final String TAG = "InstanceManager"; /** Interface for listening when a weak reference of an instance is removed from the manager. */ @@ -65,6 +67,7 @@ public interface FinalizationListener { * @param finalizationListener the listener for garbage collected weak references. * @return a new `InstanceManager`. */ + @NonNull public static InstanceManager create(FinalizationListener finalizationListener) { return new InstanceManager(finalizationListener); } diff --git a/packages/camera/camera_android_camerax/example/android/app/build.gradle b/packages/camera/camera_android_camerax/example/android/app/build.gradle index 2d59a59a420..e2001f9ab77 100644 --- a/packages/camera/camera_android_camerax/example/android/app/build.gradle +++ b/packages/camera/camera_android_camerax/example/android/app/build.gradle @@ -62,5 +62,6 @@ flutter { dependencies { testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test:runner:1.2.0' - api 'androidx.test:core:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + api 'androidx.test:core:1.4.0' } diff --git a/packages/camera/camera_android_camerax/example/android/app/src/androidTest/java/io/flutter/plugins/cameraxexample/InstanceManagerTest.java b/packages/camera/camera_android_camerax/example/android/app/src/androidTest/java/io/flutter/plugins/cameraxexample/InstanceManagerTest.java new file mode 100644 index 00000000000..826ad2f6e80 --- /dev/null +++ b/packages/camera/camera_android_camerax/example/android/app/src/androidTest/java/io/flutter/plugins/cameraxexample/InstanceManagerTest.java @@ -0,0 +1,42 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.cameraexample; + +import static io.flutter.plugins.camerax.InstanceManager.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import io.flutter.plugins.camerax.InstanceManager; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class InstanceManagerTest { + @Test + public void managerDoesNotTriggerFinalizationListenerWhenStopped() throws InterruptedException { + final boolean[] callbackTriggered = {false}; + final InstanceManager instanceManager = + InstanceManager.create(identifier -> callbackTriggered[0] = true); + instanceManager.stopFinalizationListener(); + + Object object = new Object(); + instanceManager.addDartCreatedInstance(object, 0); + + assertEquals(object, instanceManager.remove(0)); + + // To allow for object to be garbage collected. + //noinspection UnusedAssignment + object = null; + + Runtime.getRuntime().gc(); + + Thread.sleep(CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL); + + assertNull(instanceManager.getInstance(0)); + assertFalse(callbackTriggered[0]); + } +} diff --git a/packages/camera/camera_android_camerax/example/android/build.gradle b/packages/camera/camera_android_camerax/example/android/build.gradle index 7c909c6116c..45cb407e8d0 100644 --- a/packages/camera/camera_android_camerax/example/android/build.gradle +++ b/packages/camera/camera_android_camerax/example/android/build.gradle @@ -26,7 +26,7 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/packages/camera/camera_android_camerax/example/pubspec.yaml b/packages/camera/camera_android_camerax/example/pubspec.yaml index 1a055e7913c..8e6c02572b9 100644 --- a/packages/camera/camera_android_camerax/example/pubspec.yaml +++ b/packages/camera/camera_android_camerax/example/pubspec.yaml @@ -20,6 +20,7 @@ dependencies: video_player: ^2.4.10 dev_dependencies: + espresso: ^0.2.0 flutter_test: sdk: flutter integration_test: diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index d97de80b4db..f63588727f8 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -21,7 +21,6 @@ * Fixes a bug where the native `WebView` wouldn't be traversed for autofill automatically. * Updates minimum Flutter version to 3.3. ->>>>>>> 9852b41ff46771c24bca26919fc345d69bdd0b1a ## 3.4.3 diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java index cb407ce21a0..5a933c43d80 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java @@ -9,6 +9,7 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.HashMap; @@ -36,7 +37,7 @@ public class InstanceManager { // Host uses identifiers >= 2^16 and Dart is expected to use values n where, // 0 <= n < 2^16. private static final long MIN_HOST_CREATED_IDENTIFIER = 65536; - private static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000; + @VisibleForTesting public static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 3000; private static final String TAG = "InstanceManager"; /** Interface for listening when a weak reference of an instance is removed from the manager. */ @@ -66,6 +67,7 @@ public interface FinalizationListener { * @param finalizationListener the listener for garbage collected weak references. * @return a new `InstanceManager`. */ + @NonNull public static InstanceManager create(@NonNull FinalizationListener finalizationListener) { return new InstanceManager(finalizationListener); } diff --git a/packages/webview_flutter/webview_flutter_android/example/android/app/src/androidTest/java/io/flutter/plugins/webviewflutterexample/InstanceManagerTest.java b/packages/webview_flutter/webview_flutter_android/example/android/app/src/androidTest/java/io/flutter/plugins/webviewflutterexample/InstanceManagerTest.java new file mode 100644 index 00000000000..b85d34ed797 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_android/example/android/app/src/androidTest/java/io/flutter/plugins/webviewflutterexample/InstanceManagerTest.java @@ -0,0 +1,42 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins.webviewflutterexample; + +import static io.flutter.plugins.webviewflutter.InstanceManager.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import io.flutter.plugins.webviewflutter.InstanceManager; +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class InstanceManagerTest { + @Test + public void managerDoesNotTriggerFinalizationListenerWhenStopped() throws InterruptedException { + final boolean[] callbackTriggered = {false}; + final InstanceManager instanceManager = + InstanceManager.create(identifier -> callbackTriggered[0] = true); + instanceManager.stopFinalizationListener(); + + Object object = new Object(); + instanceManager.addDartCreatedInstance(object, 0); + + assertEquals(object, instanceManager.remove(0)); + + // To allow for object to be garbage collected. + //noinspection UnusedAssignment + object = null; + + Runtime.getRuntime().gc(); + + Thread.sleep(CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL); + + assertNull(instanceManager.getInstance(0)); + assertFalse(callbackTriggered[0]); + } +} From c55933870b8a499cfb522fe1b2f845f85b64d537 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 14 Apr 2023 16:14:41 -0400 Subject: [PATCH 9/9] make constant private again --- .../java/io/flutter/plugins/camerax/InstanceManager.java | 3 +-- .../flutter/plugins/cameraxexample/InstanceManagerTest.java | 5 +++-- .../io/flutter/plugins/webviewflutter/InstanceManager.java | 3 +-- .../plugins/webviewflutterexample/InstanceManagerTest.java | 5 +++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java index 730908a411e..43004a6aab7 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java @@ -9,7 +9,6 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.HashMap; @@ -37,7 +36,7 @@ public class InstanceManager { // Host uses identifiers >= 2^16 and Dart is expected to use values n where, // 0 <= n < 2^16. private static final long MIN_HOST_CREATED_IDENTIFIER = 65536; - @VisibleForTesting public static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000; + private static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000; private static final String TAG = "InstanceManager"; /** Interface for listening when a weak reference of an instance is removed from the manager. */ diff --git a/packages/camera/camera_android_camerax/example/android/app/src/androidTest/java/io/flutter/plugins/cameraxexample/InstanceManagerTest.java b/packages/camera/camera_android_camerax/example/android/app/src/androidTest/java/io/flutter/plugins/cameraxexample/InstanceManagerTest.java index 826ad2f6e80..5e4454de80d 100644 --- a/packages/camera/camera_android_camerax/example/android/app/src/androidTest/java/io/flutter/plugins/cameraxexample/InstanceManagerTest.java +++ b/packages/camera/camera_android_camerax/example/android/app/src/androidTest/java/io/flutter/plugins/cameraxexample/InstanceManagerTest.java @@ -4,7 +4,6 @@ package io.flutter.plugins.cameraexample; -import static io.flutter.plugins.camerax.InstanceManager.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -34,7 +33,9 @@ public void managerDoesNotTriggerFinalizationListenerWhenStopped() throws Interr Runtime.getRuntime().gc(); - Thread.sleep(CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL); + // Wait for the interval after finalized callbacks are made for garbage collected objects. + // See InstanceManager.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL. + Thread.sleep(30000); assertNull(instanceManager.getInstance(0)); assertFalse(callbackTriggered[0]); diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java index 5a933c43d80..38f4044c51e 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/InstanceManager.java @@ -9,7 +9,6 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.HashMap; @@ -37,7 +36,7 @@ public class InstanceManager { // Host uses identifiers >= 2^16 and Dart is expected to use values n where, // 0 <= n < 2^16. private static final long MIN_HOST_CREATED_IDENTIFIER = 65536; - @VisibleForTesting public static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 3000; + private static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 3000; private static final String TAG = "InstanceManager"; /** Interface for listening when a weak reference of an instance is removed from the manager. */ diff --git a/packages/webview_flutter/webview_flutter_android/example/android/app/src/androidTest/java/io/flutter/plugins/webviewflutterexample/InstanceManagerTest.java b/packages/webview_flutter/webview_flutter_android/example/android/app/src/androidTest/java/io/flutter/plugins/webviewflutterexample/InstanceManagerTest.java index b85d34ed797..54cff982d4b 100644 --- a/packages/webview_flutter/webview_flutter_android/example/android/app/src/androidTest/java/io/flutter/plugins/webviewflutterexample/InstanceManagerTest.java +++ b/packages/webview_flutter/webview_flutter_android/example/android/app/src/androidTest/java/io/flutter/plugins/webviewflutterexample/InstanceManagerTest.java @@ -4,7 +4,6 @@ package io.flutter.plugins.webviewflutterexample; -import static io.flutter.plugins.webviewflutter.InstanceManager.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; @@ -34,7 +33,9 @@ public void managerDoesNotTriggerFinalizationListenerWhenStopped() throws Interr Runtime.getRuntime().gc(); - Thread.sleep(CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL); + // Wait for the interval after finalized callbacks are made for garbage collected objects. + // See InstanceManager.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL. + Thread.sleep(30000); assertNull(instanceManager.getInstance(0)); assertFalse(callbackTriggered[0]);