- Notifications
You must be signed in to change notification settings - Fork28.9k
[Android] Add a way to request newSurface
s fromSurfaceProducer
…#172384
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:flutter-3.32-candidate.0
Are you sure you want to change the base?
[Android] Add a way to request newSurface
s fromSurfaceProducer
…#172384
Conversation
…and avoid `SurfaceProducer` returning invalid `Surface` (flutter#169899)> [!NOTE]> For anyone reviewing this PR, seeflutter/packages#9360 for how I'd use the`getSurface(boolean forceNewSurface)` method.> [!NOTE]> For anyone coming across this PR post-landing, in the code reviewprocess, I renamed `getSurface(boolean forceNewSurface)` to`getForcedNewSurface()`.(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)` iscalled.My motivation for adding this is directly tied toflutter#155294. The`camera_android_camerax` plugin supports a camera preview use case thatrequires providing a `Surface` to in order to render the preview. Itdoes so via `SurfaceProducer`; we provide a `Surface` retrieved from`SurfaceProducer.getSurface()` to the CameraX library to render a camerapreview, and when the camera preview is done, a callback that we provideis called, reporting that `Surface` as used and that it now should bereleased/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 noguarantees](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 racecondition 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 resumed5. We provide `Surface` A from `SurfaceProducer.getSurface()` because itis still technically valid6. CameraX calls our callback and now `Surface` A is released/invalidI believe `SurfaceProducer` currently has no way to handle the level ofcomplexity of `Surface` handling required for use cases like the`camera_android_camerax` camera preview, where a `Surface` may beinvalidated 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 thesame `Surface` as the previous invocation.For `camera_android_camerax`, seeflutter/packages#9360 for an example of how itwould be used.*I'd like to note that I also played around with creating new`SurfaceProducer`s to solve the camera problem, which _was_ successfuland probably could be generally for that use case, but I think it'scleaner to support this functionality from within the same`SurfaceProducer` since we can 🤷♀️ It also helps avoid the user fromneeding to create/manage multiple Flutter `Texture`s, from myunderstanding.forceNewSurface)` to never return an invalid `Surface`sI noticed that `SurfaceProducer.getSurface()`/`getSurface(booleanforceNewSurface)` does not check for `Surface` validity before returningthem while I was working on (1). Honestly, this just feels right? Weshould ensure that a `Surface` is valid and can be used before returningit and potentially confusing the user.- [x] I read the [Contributor Guide] and followed the process outlinedthere for submitting PRs.- [x] I read the [Tree Hygiene] wiki page, which explains myresponsibilities.- [x] I read and followed the [Flutter Style Guide], including [Featureswe expect every widget to implement].- [x] I signed the [CLA].- [x] I listed at least one issue that this PR fixes in the descriptionabove.- [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 DrivenFixes] where supported.- [x] All existing and new tests are passing.If you need help, consider asking for advice on the #hackers-new channelon [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
This pull request was opened from and to a release candidate branch. This should only be done as part of the officialFlutter release process. If you are attempting to make a regular contribution to the Flutter project, please close this PR and follow the instructions atTree Hygiene for detailed instructions on contributing to Flutter. Reviewers: Use caution before merging pull requests to release branches. Ensure the proper procedure has been followed. |
Uh oh!
There was an error while loading.Please reload this page.
Cherry-picksc7362b4 to 3.32 stablewithout the changes to the pre-existing
SurfaceProducer.getSurface
method, only the addition ofSurfaceProducer.getForcedNewSurface
.Note that this change is already present in the 3.35 beta.
Issue Link:
What is the link to the issue this cherry-pick is addressing?
#155294,#169506
Changelog Description:
Adds a new method for requesting a new surface from the embedder than any previously returned.
Impact Description:
Developers using
SurfaceProducer.getForcedNewSurface
will receive aSurface
that is different than previous calls toSurfaceProducer.getForcedNewSurface
or pre-existing methodSurfaceProducer.getSurface
.In other words, there is no impact to current users. This is a new method, so there will be a gap between 3.32.0 and 3.32.8, but I think it's worth landing because this would unblock fixing resuming/pausing the camera preview as described by the linked issues.
Workaround:
Working around the need for the new
getForcedSurface
method (like thecamera
issues linked above require) can be done by creating newSurfaceProducer
s; however, this might have other side-effect unbeknownst to me.Risk:
Test Coverage:
Are you confident that your fix is well-tested by automated tests?
Validation Steps:
You can test withflutter/packages#9360 (which I accidentally landed because I forgot this wasn't in stable yet...oops).
Pre-launch Checklist
///
).If you need help, consider asking for advice on the #hackers-new channel onDiscord.