diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md index f271e906158..f719078b681 100644 --- a/packages/camera/camera_android_camerax/CHANGELOG.md +++ b/packages/camera/camera_android_camerax/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.6.3 + +* Shortens default interval that internal Java `InstanceManager` uses to release garbage collected weak references to + native objects. +* Dynamically shortens interval that internal Java `InstanceManager` uses to release garbage collected weak references to + native objects when an `ImageAnalysis.Analyzer` is set/removed to account for increased memory usage of analyzing + images that may cause a crash. + ## 0.6.2 * Adds support to control video FPS and bitrate. See `CameraController.withSettings`. diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java index 95b2cd46798..8774adc9def 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java @@ -69,6 +69,14 @@ public void setAnalyzer(@NonNull Long identifier, @NonNull Long analyzerIdentifi throw new IllegalStateException("Context must be set to set an Analyzer."); } + // Shorten time interval used to define how often the instanceManager removes garbage + // collected weak references to native Android objects that it manages in order to + // account for the increased memory usage that comes from analyzing images with an + // ImageAnalysis.Analyzer. + instanceManager.setClearFinalizedWeakReferencesInterval( + InstanceManager.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL_FOR_IMAGE_ANALYSIS); + instanceManager.releaseAllFinalizedInstances(); + getImageAnalysisInstance(identifier) .setAnalyzer( ContextCompat.getMainExecutor(context), @@ -81,6 +89,13 @@ public void clearAnalyzer(@NonNull Long identifier) { ImageAnalysis imageAnalysis = (ImageAnalysis) Objects.requireNonNull(instanceManager.getInstance(identifier)); imageAnalysis.clearAnalyzer(); + + // Restore the default time interval used to define how often the instanceManager + // removes garbage collected weak references to native Android objects that it + // manages since analyzing images with an ImageAnalysis.Analyzer, which involves + // increased memory usage, is finished. + instanceManager.setClearFinalizedWeakReferencesInterval( + InstanceManager.DEFAULT_CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL); } /** Dynamically sets the target rotation of the {@link ImageAnalysis}. */ 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 97ab805370d..a8a25daa1fa 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 @@ -36,9 +36,25 @@ 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; private static final String TAG = "InstanceManager"; + /** + * The default time interval used to define how often this instance removes garbage collected weak + * references to native Android objects that this instance manages. + */ + public static final long DEFAULT_CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 3000; + + /** + * The time interval used to define how often this instance removes garbage collected weak + * references to native Android objects that this instance manages, specifically when an {@code + * ImageAnalysis.Analyzer} is set on an {@code ImageAnalysis} instance to support image streaming. + * + *
Streaming images with an {@code ImageAnalysis.Analyzer} involves increased memory usage, so + * this interval, which is lower than the default {@link + * DEFAULT_CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL} interval, accommodates this fact. + */ + public static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL_FOR_IMAGE_ANALYSIS = 1000; + /** Interface for listening when a weak reference of an instance is removed from the manager. */ public interface FinalizationListener { void onFinalize(long identifier); @@ -58,6 +74,9 @@ public interface FinalizationListener { private long nextIdentifier = MIN_HOST_CREATED_IDENTIFIER; private boolean hasFinalizationListenerStopped = false; + private long clearFinalizedWeakReferencesInterval = + DEFAULT_CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL; + /** * Instantiate a new manager. * @@ -73,8 +92,7 @@ public static InstanceManager create(@NonNull FinalizationListener finalizationL private InstanceManager(FinalizationListener finalizationListener) { this.finalizationListener = finalizationListener; - handler.postDelayed( - this::releaseAllFinalizedInstances, CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL); + handler.postDelayed(this::releaseAllFinalizedInstances, clearFinalizedWeakReferencesInterval); } /** @@ -217,7 +235,19 @@ public boolean hasFinalizationListenerStopped() { return hasFinalizationListenerStopped; } - private void releaseAllFinalizedInstances() { + /** + * Modifies the time interval used to define how often this instance removes garbage collected + * weak references to native Android objects that this instance was managing. + */ + public void setClearFinalizedWeakReferencesInterval(long interval) { + clearFinalizedWeakReferencesInterval = interval; + } + + /** + * Releases garbage collected weak references to native Android objects that this instance was + * managing. + */ + public void releaseAllFinalizedInstances() { if (hasFinalizationListenerStopped()) { return; } @@ -231,8 +261,7 @@ private void releaseAllFinalizedInstances() { finalizationListener.onFinalize(identifier); } } - handler.postDelayed( - this::releaseAllFinalizedInstances, CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL); + handler.postDelayed(this::releaseAllFinalizedInstances, clearFinalizedWeakReferencesInterval); } private void addInstance(Object instance, long identifier) { diff --git a/packages/camera/camera_android_camerax/pubspec.yaml b/packages/camera/camera_android_camerax/pubspec.yaml index dfc6f93a496..b3ce1dfca29 100644 --- a/packages/camera/camera_android_camerax/pubspec.yaml +++ b/packages/camera/camera_android_camerax/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_android_camerax description: Android implementation of the camera plugin using the CameraX library. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.6.2 +version: 0.6.3 environment: sdk: ^3.1.0