Skip to content

Commit 6f0ed15

Browse files
authored
[camerax] Shorten interval for releasing weak references to Dart-wrapped native objects (flutter#6493)
This PR: 1. Shortens the `InstanceManager`'s default time interval that it waits to remove references to Dart-wrapped Android native objects. The shortened interval matches `webview_flutter_android`s `InstanceManager`; because it has been tested by that plugin, we expect it not to impact performance and this could help reduce overall memory usage by the plugin. 2. Dynamically shortens that same time interval whenever image streaming is started/stopped to account for the increased memory usage that this camera use case requires. Fixes flutter/flutter#145893.
1 parent d680544 commit 6f0ed15

File tree

4 files changed

+59
-7
lines changed

4 files changed

+59
-7
lines changed

packages/camera/camera_android_camerax/CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 0.6.3
2+
3+
* Shortens default interval that internal Java `InstanceManager` uses to release garbage collected weak references to
4+
native objects.
5+
* Dynamically shortens interval that internal Java `InstanceManager` uses to release garbage collected weak references to
6+
native objects when an `ImageAnalysis.Analyzer` is set/removed to account for increased memory usage of analyzing
7+
images that may cause a crash.
8+
19
## 0.6.2
210

311
* Adds support to control video FPS and bitrate. See `CameraController.withSettings`.

packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ public void setAnalyzer(@NonNull Long identifier, @NonNull Long analyzerIdentifi
6969
throw new IllegalStateException("Context must be set to set an Analyzer.");
7070
}
7171

72+
// Shorten time interval used to define how often the instanceManager removes garbage
73+
// collected weak references to native Android objects that it manages in order to
74+
// account for the increased memory usage that comes from analyzing images with an
75+
// ImageAnalysis.Analyzer.
76+
instanceManager.setClearFinalizedWeakReferencesInterval(
77+
InstanceManager.CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL_FOR_IMAGE_ANALYSIS);
78+
instanceManager.releaseAllFinalizedInstances();
79+
7280
getImageAnalysisInstance(identifier)
7381
.setAnalyzer(
7482
ContextCompat.getMainExecutor(context),
@@ -81,6 +89,13 @@ public void clearAnalyzer(@NonNull Long identifier) {
8189
ImageAnalysis imageAnalysis =
8290
(ImageAnalysis) Objects.requireNonNull(instanceManager.getInstance(identifier));
8391
imageAnalysis.clearAnalyzer();
92+
93+
// Restore the default time interval used to define how often the instanceManager
94+
// removes garbage collected weak references to native Android objects that it
95+
// manages since analyzing images with an ImageAnalysis.Analyzer, which involves
96+
// increased memory usage, is finished.
97+
instanceManager.setClearFinalizedWeakReferencesInterval(
98+
InstanceManager.DEFAULT_CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL);
8499
}
85100

86101
/** Dynamically sets the target rotation of the {@link ImageAnalysis}. */

packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/InstanceManager.java

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,25 @@ public class InstanceManager {
3636
// Host uses identifiers >= 2^16 and Dart is expected to use values n where,
3737
// 0 <= n < 2^16.
3838
private static final long MIN_HOST_CREATED_IDENTIFIER = 65536;
39-
private static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 30000;
4039
private static final String TAG = "InstanceManager";
4140

41+
/**
42+
* The default time interval used to define how often this instance removes garbage collected weak
43+
* references to native Android objects that this instance manages.
44+
*/
45+
public static final long DEFAULT_CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL = 3000;
46+
47+
/**
48+
* The time interval used to define how often this instance removes garbage collected weak
49+
* references to native Android objects that this instance manages, specifically when an {@code
50+
* ImageAnalysis.Analyzer} is set on an {@code ImageAnalysis} instance to support image streaming.
51+
*
52+
* <p>Streaming images with an {@code ImageAnalysis.Analyzer} involves increased memory usage, so
53+
* this interval, which is lower than the default {@link
54+
* DEFAULT_CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL} interval, accommodates this fact.
55+
*/
56+
public static final long CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL_FOR_IMAGE_ANALYSIS = 1000;
57+
4258
/** Interface for listening when a weak reference of an instance is removed from the manager. */
4359
public interface FinalizationListener {
4460
void onFinalize(long identifier);
@@ -58,6 +74,9 @@ public interface FinalizationListener {
5874
private long nextIdentifier = MIN_HOST_CREATED_IDENTIFIER;
5975
private boolean hasFinalizationListenerStopped = false;
6076

77+
private long clearFinalizedWeakReferencesInterval =
78+
DEFAULT_CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL;
79+
6180
/**
6281
* Instantiate a new manager.
6382
*
@@ -73,8 +92,7 @@ public static InstanceManager create(@NonNull FinalizationListener finalizationL
7392

7493
private InstanceManager(FinalizationListener finalizationListener) {
7594
this.finalizationListener = finalizationListener;
76-
handler.postDelayed(
77-
this::releaseAllFinalizedInstances, CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL);
95+
handler.postDelayed(this::releaseAllFinalizedInstances, clearFinalizedWeakReferencesInterval);
7896
}
7997

8098
/**
@@ -217,7 +235,19 @@ public boolean hasFinalizationListenerStopped() {
217235
return hasFinalizationListenerStopped;
218236
}
219237

220-
private void releaseAllFinalizedInstances() {
238+
/**
239+
* Modifies the time interval used to define how often this instance removes garbage collected
240+
* weak references to native Android objects that this instance was managing.
241+
*/
242+
public void setClearFinalizedWeakReferencesInterval(long interval) {
243+
clearFinalizedWeakReferencesInterval = interval;
244+
}
245+
246+
/**
247+
* Releases garbage collected weak references to native Android objects that this instance was
248+
* managing.
249+
*/
250+
public void releaseAllFinalizedInstances() {
221251
if (hasFinalizationListenerStopped()) {
222252
return;
223253
}
@@ -231,8 +261,7 @@ private void releaseAllFinalizedInstances() {
231261
finalizationListener.onFinalize(identifier);
232262
}
233263
}
234-
handler.postDelayed(
235-
this::releaseAllFinalizedInstances, CLEAR_FINALIZED_WEAK_REFERENCES_INTERVAL);
264+
handler.postDelayed(this::releaseAllFinalizedInstances, clearFinalizedWeakReferencesInterval);
236265
}
237266

238267
private void addInstance(Object instance, long identifier) {

packages/camera/camera_android_camerax/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: camera_android_camerax
22
description: Android implementation of the camera plugin using the CameraX library.
33
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
5-
version: 0.6.2
5+
version: 0.6.3
66

77
environment:
88
sdk: ^3.1.0

0 commit comments

Comments
 (0)