-
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 [email protected] [webview_flutter] Update androidx.webkit to 1.14.0 (flutter/packages#9638) 2025-07-17 [email protected] Roll Flutter from c2739f0 to 9c626d9 (18 revisions) (flutter/packages#9641) 2025-07-17 [email protected] Roll Flutter (stable) from 077b4a4 to d7b523b (3 revisions) (flutter/packages#9640) 2025-07-17 [email protected] 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 [email protected] [ci] Add Gemini Code Assist review config (flutter/packages#9632) 2025-07-16 [email protected] Roll Flutter from cc3110c to c2739f0 (15 revisions) (flutter/packages#9633) 2025-07-16 [email protected] [image_picker] redesign example app (flutter/packages#9625) 2025-07-16 [email protected] [camera_avfoundation] Implementation swift migration - part 7 (flutter/packages#9595) 2025-07-15 [email protected] [webview_flutter_wkwebview] Replace Flutter method failure assertion with nslog (flutter/packages#9587) 2025-07-15 [email protected] Roll Flutter from a930ec1 to cc3110c (24 revisions) (flutter/packages#9631) 2025-07-15 [email protected] [webview_flutter] Add setMixedContentMode for Android (flutter/packages#9586) 2025-07-15 [email protected] [google_sign_in] Add exception info to migration guide (flutter/packages#9574) 2025-07-14 [email protected] [camera_android] Use WeakReference to prevent startImageStream OOM error when main thread hangs (#166533) (flutter/packages#9571) 2025-07-14 [email protected] [quick_actions] Restore the appShortcutLaunchActivityAfterStarting test in quick_actions_android (flutter/packages#9508) 2025-07-14 [email protected] 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 [email protected] Roll Flutter from 43657f3 to 35f197f (39 revisions) (flutter/packages#9602) 2025-07-11 [email protected] Replace popularity badges (flutter/packages#9594) 2025-07-11 [email protected] [rfw] Update test to not depend on toString() (flutter/packages#9590) 2025-07-11 [email protected] [camera_avfoundation] Implementation swift migration - part 6 (flutter/packages#9588) 2025-07-10 [email protected] [url_launcher] Fixes new unnecessary boolean operations warnings (flutter/packages#9409) 2025-07-10 [email protected] [google_sign_in] Add troubleshooting to Android README (flutter/packages#9581) 2025-07-10 [email protected] Roll Flutter from ac12f66 to 43657f3 (25 revisions) (flutter/packages#9589) 2025-07-10 [email protected] [go_router_builder] Update case sensitive test to `go_router` 16.0.0 (flutter/packages#9482) 2025-07-09 [email protected] [rfw] Remove the RFW WASM example (flutter/packages#9551) 2025-07-09 [email protected] Roll Flutter (stable) from fcf2c11 to 077b4a4 (5 revisions) (flutter/packages#9585) 2025-07-09 [email protected] Roll Flutter from adffe24 to ac12f66 (28 revisions) (flutter/packages#9584) 2025-07-09 [email protected] [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 [email protected] 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
…er#172303) 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 [email protected] [webview_flutter] Update androidx.webkit to 1.14.0 (flutter/packages#9638) 2025-07-17 [email protected] Roll Flutter from c2739f0 to 9c626d9 (18 revisions) (flutter/packages#9641) 2025-07-17 [email protected] Roll Flutter (stable) from 077b4a4 to d7b523b (3 revisions) (flutter/packages#9640) 2025-07-17 [email protected] 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 [email protected] [ci] Add Gemini Code Assist review config (flutter/packages#9632) 2025-07-16 [email protected] Roll Flutter from cc3110c to c2739f0 (15 revisions) (flutter/packages#9633) 2025-07-16 [email protected] [image_picker] redesign example app (flutter/packages#9625) 2025-07-16 [email protected] [camera_avfoundation] Implementation swift migration - part 7 (flutter/packages#9595) 2025-07-15 [email protected] [webview_flutter_wkwebview] Replace Flutter method failure assertion with nslog (flutter/packages#9587) 2025-07-15 [email protected] Roll Flutter from a930ec1 to cc3110c (24 revisions) (flutter/packages#9631) 2025-07-15 [email protected] [webview_flutter] Add setMixedContentMode for Android (flutter/packages#9586) 2025-07-15 [email protected] [google_sign_in] Add exception info to migration guide (flutter/packages#9574) 2025-07-14 [email protected] [camera_android] Use WeakReference to prevent startImageStream OOM error when main thread hangs (flutter#166533) (flutter/packages#9571) 2025-07-14 [email protected] [quick_actions] Restore the appShortcutLaunchActivityAfterStarting test in quick_actions_android (flutter/packages#9508) 2025-07-14 [email protected] 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 [email protected] Roll Flutter from 43657f3 to 35f197f (39 revisions) (flutter/packages#9602) 2025-07-11 [email protected] Replace popularity badges (flutter/packages#9594) 2025-07-11 [email protected] [rfw] Update test to not depend on toString() (flutter/packages#9590) 2025-07-11 [email protected] [camera_avfoundation] Implementation swift migration - part 6 (flutter/packages#9588) 2025-07-10 [email protected] [url_launcher] Fixes new unnecessary boolean operations warnings (flutter/packages#9409) 2025-07-10 [email protected] [google_sign_in] Add troubleshooting to Android README (flutter/packages#9581) 2025-07-10 [email protected] Roll Flutter from ac12f66 to 43657f3 (25 revisions) (flutter/packages#9589) 2025-07-10 [email protected] [go_router_builder] Update case sensitive test to `go_router` 16.0.0 (flutter/packages#9482) 2025-07-09 [email protected] [rfw] Remove the RFW WASM example (flutter/packages#9551) 2025-07-09 [email protected] Roll Flutter (stable) from fcf2c11 to 077b4a4 (5 revisions) (flutter/packages#9585) 2025-07-09 [email protected] Roll Flutter from adffe24 to ac12f66 (28 revisions) (flutter/packages#9584) 2025-07-09 [email protected] [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 [email protected] 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