-
Notifications
You must be signed in to change notification settings - Fork 3.4k
[camera_android] Use WeakReference to prevent startImageStream OOM error when main thread hangs (flutter#166533) #9571
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
Conversation
…read paused (flutter#166533) When streaming images using CameraController.startImageStream(), images are being post()-ed to the main looper even if it's halted. This is common when debugging. This quickly results in an OOM and the app crashes abruptly. The fix is done by counting the number of images that have been posted to the main thread but have not yet arrived. If too many images are in transit (I arbitrarily chose 3 as the maximum allowable amount) subsequent frames are dropped, until the main thread receives the pending images. A log message is emitted for each dropped frame. Fixes flutter/flutter#166533 That issue also provides a demo program.
…read paused (flutter#166533) When streaming images using CameraController.startImageStream(), images are being `post()`-ed to the main looper even if it's hanging or paused. This will happen, for instance, if the debugger is paused or the main thread is busy. This can quickly result in the OS killing the app abruptly with an OOM (out-of-memory) error. This fixes it by using a `WeakReference` rather than a hard reference to the image data. If too much memory is used up, the runtime may release image frames that have not yet been processed. A log message is emitted for each frame that was evicted before it was processed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@camsim99 can you spend extra time validating that you are happy with the test coverage of this new behavior. Async testing is tricky and we dont want to regress this feature.
import java.nio.ByteBuffer; | ||
|
||
public class ImageStreamReaderTestUtils { | ||
public static Image getImage(int imageWidth, int imageHeight, int padding, int imageFormat) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add java doc for this method
boolean postResult = | ||
handler.post( | ||
new Runnable() { | ||
// a public field is required in order to test this code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: This comment can be removed it does not add anything over the @visibleForTesing annotation.
@Override | ||
public void run() { | ||
final Map<String, Object> imageBuffer = weakImageBuffer.get(); | ||
if (imageBuffer == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is correct but can you add a comment here about why garbage collected image buffer is neither and error or success?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope the comment I added is sufficient?
Hey @reidbaker thanks for the review. I've addressed the comments, hopefully correctly. I also merged main. Let me know if there's anything else. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I can tell, the test covers the cases well. LGTM!
…eam OOM error when main thread hangs (flutter#166533) (flutter/packages#9571)
…eam OOM error when main thread hangs (flutter#166533) (flutter/packages#9571)
…eam OOM error when main thread hangs (flutter#166533) (flutter/packages#9571)
…eam OOM error when main thread hangs (flutter#166533) (flutter/packages#9571)
…eam OOM error when main thread hangs (flutter#166533) (flutter/packages#9571)
flutter/packages@4a231ae...cb8fef6 2025-07-17 49699333+dependabot[bot]@users.noreply.github.com [dependabot]: Bump androidx.activity:activity from 1.9.3 to 1.10.1 in /packages/image_picker/image_picker_android/android (flutter/packages#8725) 2025-07-17 stuartmorgan@google.com [webview_flutter] Update androidx.webkit to 1.14.0 (flutter/packages#9638) 2025-07-17 engine-flutter-autoroll@skia.org Roll Flutter from c2739f0 to 9c626d9 (18 revisions) (flutter/packages#9641) 2025-07-17 engine-flutter-autoroll@skia.org Roll Flutter (stable) from 077b4a4 to d7b523b (3 revisions) (flutter/packages#9640) 2025-07-17 stuartmorgan@google.com Fix Gemini note wrapping (flutter/packages#9639) 2025-07-17 49699333+dependabot[bot]@users.noreply.github.com [dependabot]: Bump com.google.android.gms:play-services-maps from 18.2.0 to 19.2.0 in /packages/google_maps_flutter/google_maps_flutter_android/android (flutter/packages#9120) 2025-07-17 49699333+dependabot[bot]@users.noreply.github.com [dependabot]: Bump androidx.fragment:fragment from 1.6.2 to 1.8.8 in /packages/local_auth/local_auth_android/android (flutter/packages#9406) 2025-07-16 stuartmorgan@google.com [ci] Add Gemini Code Assist review config (flutter/packages#9632) 2025-07-16 engine-flutter-autoroll@skia.org Roll Flutter from cc3110c to c2739f0 (15 revisions) (flutter/packages#9633) 2025-07-16 105786499+syedaniq@users.noreply.github.com [image_picker] redesign example app (flutter/packages#9625) 2025-07-16 robert.odrowaz@leancode.pl [camera_avfoundation] Implementation swift migration - part 7 (flutter/packages#9595) 2025-07-15 10687576+bparrishMines@users.noreply.github.com [webview_flutter_wkwebview] Replace Flutter method failure assertion with nslog (flutter/packages#9587) 2025-07-15 engine-flutter-autoroll@skia.org Roll Flutter from a930ec1 to cc3110c (24 revisions) (flutter/packages#9631) 2025-07-15 stuartmorgan@google.com [webview_flutter] Add setMixedContentMode for Android (flutter/packages#9586) 2025-07-15 stuartmorgan@google.com [google_sign_in] Add exception info to migration guide (flutter/packages#9574) 2025-07-14 392199+kwikwag@users.noreply.github.com [camera_android] Use WeakReference to prevent startImageStream OOM error when main thread hangs (#166533) (flutter/packages#9571) 2025-07-14 jason-simmons@users.noreply.github.com [quick_actions] Restore the appShortcutLaunchActivityAfterStarting test in quick_actions_android (flutter/packages#9508) 2025-07-14 engine-flutter-autoroll@skia.org Roll Flutter from 35f197f to a930ec1 (3 revisions) (flutter/packages#9624) 2025-07-14 49699333+dependabot[bot]@users.noreply.github.com [dependabot]: Bump com.android.tools.build:gradle from 8.9.1 to 8.11.1 in /packages/pigeon/platform_tests/test_plugin/android (flutter/packages#9618) 2025-07-12 engine-flutter-autoroll@skia.org Roll Flutter from 43657f3 to 35f197f (39 revisions) (flutter/packages#9602) 2025-07-11 stuartmorgan@google.com Replace popularity badges (flutter/packages#9594) 2025-07-11 1961493+harryterkelsen@users.noreply.github.com [rfw] Update test to not depend on toString() (flutter/packages#9590) 2025-07-11 robert.odrowaz@leancode.pl [camera_avfoundation] Implementation swift migration - part 6 (flutter/packages#9588) 2025-07-10 52160996+FMorschel@users.noreply.github.com [url_launcher] Fixes new unnecessary boolean operations warnings (flutter/packages#9409) 2025-07-10 stuartmorgan@google.com [google_sign_in] Add troubleshooting to Android README (flutter/packages#9581) 2025-07-10 engine-flutter-autoroll@skia.org Roll Flutter from ac12f66 to 43657f3 (25 revisions) (flutter/packages#9589) 2025-07-10 32538273+ValentinVignal@users.noreply.github.com [go_router_builder] Update case sensitive test to `go_router` 16.0.0 (flutter/packages#9482) 2025-07-09 737941+loic-sharma@users.noreply.github.com [rfw] Remove the RFW WASM example (flutter/packages#9551) 2025-07-09 engine-flutter-autoroll@skia.org Roll Flutter (stable) from fcf2c11 to 077b4a4 (5 revisions) (flutter/packages#9585) 2025-07-09 engine-flutter-autoroll@skia.org Roll Flutter from adffe24 to ac12f66 (28 revisions) (flutter/packages#9584) 2025-07-09 malo.allee@gmail.com [video_player] Add html 5 video poster support (thumbnail) as a VideoPlayerWebOptions (flutter/packages#8940) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC flutter-ecosystem@google.com on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
This is an alternative solution to the pull request #8998
When streaming images using
CameraController.startImageStream()
, images are beingpost()
-ed to the main looper in the Android implementation, even if it's hanging or paused. This will happen, for instance, when the Flutter debugger is paused or when the main thread is very busy. This can quickly result in an OOM (out-of-memory) error due to many images pending in queue, and the Android OS will kill the app abruptly.This version of the fix is done by keep the frames (except for the latest one) as
WeakReference
s. When memory pressur is on, the runtime can free weak references, therefore dropping frames. A log message is emitted for each dropped frame. As opposed to the back-pressure solution, there is no hard limit to how many frames are kept in queue - this means that if the main thread is delayed in processing frames for some reason, they will pile up as long as the memory can sustain them.Fixes flutter/flutter#166533 That issue also provides a demo program for testing the behavior.
Some more data and considerations are listed in the original pull request.
Pre-Review Checklist
[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or I have commented below to indicate which version change exemption this PR falls under1.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style, or I have commented below to indicate which CHANGELOG exemption this PR falls under1.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.
Footnotes
Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. ↩ ↩2 ↩3