Skip to content

[camerax] Shorten interval for releasing weak references to Dart-wrapped native objects #6493

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 10, 2024
Merged
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
8 changes: 8 additions & 0 deletions packages/camera/camera_android_camerax/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand All @@ -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}. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
* <p>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);
Expand All @@ -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.
*
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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;
}
Expand All @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera_android_camerax/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down