-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[camera_android_camerax] Force new Surface
for each SurfaceRequest
#9360
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
Draft
camsim99
wants to merge
8
commits into
flutter:main
Choose a base branch
from
camsim99:abandon_2
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 tasks
github-merge-queue bot
pushed a commit
to flutter/flutter
that referenced
this pull request
Jun 20, 2025
…and avoid `SurfaceProducer` returning invalid `Surface` (#169899) > [!NOTE] > For anyone reviewing this PR, see flutter/packages#9360 for how I'd use the `getSurface(boolean forceNewSurface)` method. > [!NOTE] > For anyone coming across this PR post-landing, in the code review process, I renamed `getSurface(boolean forceNewSurface)` to `getForcedNewSurface()`. ### What this does (1) Adds method `getSurface(boolean forceNewSurface)` to `SurfaceProducer` that will force the creation of a new `Surface` when `SurfaceProducer.getSurface()` is called. (2) Fixes `SurfaceProducer` to avoid returning invalid `Surface`s when `SurfaceProducer.getSurface()`/`getSurface(boolean forceNewSurface)` is called. ### Why we should... #### (1) Add `getSurface(boolean forceNewSurface)` My motivation for adding this is directly tied to #155294. The `camera_android_camerax` plugin supports a camera preview use case that requires providing a `Surface` to in order to render the preview. It does so via `SurfaceProducer`; we provide a `Surface` retrieved from `SurfaceProducer.getSurface()` to the CameraX library to render a camera preview, and when the camera preview is done, a callback that we provide is called, reporting that `Surface` as used and that it now should be released/invalidated (see [`SurfaceRequest`](https://developer.android.com/reference/androidx/camera/core/SurfaceRequest), [`SurfaceRequest.Result`](https://developer.android.com/reference/androidx/camera/core/SurfaceRequest#provideSurface(android.view.Surface,java.util.concurrent.Executor,androidx.core.util.Consumer%3Candroidx.camera.core.SurfaceRequest.Result%3E))). However, the CameraX library [makes no guarantees](https://developer.android.com/reference/androidx/camera/core/Preview.SurfaceProvider#onSurfaceRequested(androidx.camera.core.SurfaceRequest):~:text=The%20camera%20may%20repeatedly%20request%20surfaces%20throughout%20usage%20of%20a%20Preview%20use%20case%2C%20but%20only%20a%20single%20request%20will%20be%20active%20at%20a%20time.) about when requests for new `Surface`s are made, so the following race condition can happen: 1. CameraX requests a `Surface` 2. We provide `Surface` A from `SurfaceProducer.getSurface()` 3. The camera preview was paused; CameraX requests a new `Surface` 4. The camera preview is resumed 5. We provide `Surface` A from `SurfaceProducer.getSurface()` because it is still technically valid 6. CameraX calls our callback and now `Surface` A is released/invalid I believe `SurfaceProducer` currently has no way to handle the level of complexity of `Surface` handling required for use cases like the `camera_android_camerax` camera preview, where a `Surface` may be invalidated between calls to `SurfaceProducer.getSurface()`. So, `getSurface(boolean forceNewSurface)` can support these use cases.* `getSurface(boolean forceNewSurface)` simply will force `SurfaceProducer` to return a new `Surface` when `SurfaceProducer.getSurface` is called versus potentially returning the same `Surface` as the previous invocation. For `camera_android_camerax`, see flutter/packages#9360 for an example of how it would be used. *I'd like to note that I also played around with creating new `SurfaceProducer`s to solve the camera problem, which _was_ successful and probably could be generally for that use case, but I think it's cleaner to support this functionality from within the same `SurfaceProducer` since we can 🤷♀️ It also helps avoid the user from needing to create/manage multiple Flutter `Texture`s, from my understanding. #### (2) Fix `SurfaceProducer.getSurface()`/`getSurface(boolean forceNewSurface)` to never return an invalid `Surface`s I noticed that `SurfaceProducer.getSurface()`/`getSurface(boolean forceNewSurface)` does not check for `Surface` validity before returning them while I was working on (1). Honestly, this just feels right? We should ensure that a `Surface` is valid and can be used before returning it and potentially confusing the user. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Surface
for each SurfaceRequest
Surface
for each SurfaceRequest
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Important
flutter/flutter#169899 must be rolled into the engine in order for this fix to land.
Since timing for
Surface
requests cannot be guaranteed, request a newSurface
fromSurfaceProducer.getSurface
each time aSurface
is requested for rendering the camera preview to.Fixes flutter/flutter#155294.
Fixes flutter/flutter#169506.
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