Skip to content

Deprecate Android FlutterRenderer.getBitmap - #41

Open
mboetger wants to merge 5 commits into
flutter:mainfrom
mboetger:rfc-410-deprecate-getbitmap
Open

mboetger wants to merge 5 commits into
flutter:mainfrom
mboetger:rfc-410-deprecate-getbitmap

Conversation

@mboetger

@mboetger mboetger commented Oct 30, 2026 •

Copy link
Copy Markdown

A proposal to deprecate FlutterRenderer.getBitmap

Tracking issue: flutter/flutter#195720

Pre-launch Checklist

  • I read [RFC 000.0001: Taxonomy] and followed the file and path naming and metadata standards.
  • I read [RFC 000.0002: Process] and confirmed this proposal meets the threshold for a full RFC.
  • I read and agree to the [Code of Conduct].
  • I signed the [CLA].
  • I have linked an issue from flutter/flutter with the label design doc.
  • All existing and new tests are passing.
  • I have enabled "Allow edits from maintainers" on this PR so the bot can automatically assign an RFC number (or I will run dart run bin/assign_rfc_number.dart locally when instructed).

@mboetger
mboetger marked this pull request as ready for review October 30, 2026 22:58
@mboetger
mboetger requested a review from camsim99 October 30, 2026 22:58
- **HCPP enabled (the default on master and beta):** Impeller presents through a `SurfaceControl` child layer on API 29+. Nothing reaches the `Surface`, so `getBitmap()` returns `null`, even with no platform views on screen.
- **Hybrid Composition:** Flutter UI drawn over a platform view lives in separate overlay surfaces, so it is dropped.

Android has no public API to read back those layers, so this approach cannot be made complete.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is extremely unfortunate if true... Have we reached out to the Android team to ask if there are workarounds, or if they intend to add these APIs in the future?

This makes me rethink the decision to skip the screenshot embedder API. Assuming there is no workarounds, adding the screenshot embedder API would allow us to continue to support FlutterRenderer.getBitmap().

Copy link
Copy Markdown
Author

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, this is true. I have not reached out to the Android team yet.

Even if we added the embedder API this would still have the same support story for platform views as a Dart framework call (which is to say, the same support story as the current getBitmap call - since they use the same code underneath the covers).

The biggest difference being the framework call does not block the main thread.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gmackall - FYI, https://b.corp.google.com/issues/494307996, I believe the same issue that prevents the Magnifier loupe from working also prevents use from getting the SurfaceControl pixels for screenshots.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The biggest difference being the framework call does not block the main thread.

If we add a screenshot embedder API, I suspect that would be asynchronous. FlutterRenderer.getBitmap() would need to block to maintain backwards compatibility, but we could deprecate it in favor of an asynchronous alternative that doesn't block the platform thread.


### Phase 2: Remove

After the deprecation has shipped in at least one stable release, remove:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the framework allowed breaking changes, we would wait 4 stable releases or 1 year, whichever is longer. I would recommend we wait at least as long.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. That's a long time, also considering the deprecation story for the Embedder API - that could push things back a bit.

…we'd still need to deprecate the old method though)
- In AOSP, compositing and reading back a `SurfaceControl` subtree (`android.window.ScreenCapture.captureLayers`) is `@hide` / `@TestApi` and requires the signature `READ_FRAME_BUFFER` permission because child `SurfaceControl` layers can host cross-process `SurfaceControlViewHost` or `FLAG_SECURE` content.
- Even if a future Android version added a public `ASurfaceControl` readback API, `PixelCopy` would still fail on Android 10–16 (API 29–36), where HCPP is active.
- In AOSP, `AccessibilityInteractionController` composites a window's `SurfaceControl` subtree in-process by calling `android.window.ScreenCapture.captureLayers` on `ViewRootImpl.getSurfaceControl()` with `.setChildrenOnly(false).setUid(Process.myUid())`, but both APIs are `@hide` and blocked by Android's non-SDK interface restrictions (`blacklist`) for callers outside `/system/framework/framework.jar`.
- Android 17 (API 37) adds `AttachedSurfaceControl.createMirror()`, which lets an app mirror its window `SurfaceControl` hierarchy (filtering out layers from other UIDs) into a `VirtualDisplay` and `ImageReader`. However, that path is asynchronous, requires setting up a `VirtualDisplay` and waiting for a composition pass, and does not help on Android 10–16 (API 29–36), where HCPP is active.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm do you mean on 14-16? HCPP is only active on 34+

Or am I misreading this line


- Nothing in `flutter/flutter` or `flutter/packages` calls `getBitmap()`, and it has had no test coverage since 2024.
- The engine implementation blocks the Android main thread for 200–470 ms per call.
- It cannot be reimplemented in the embedder alone. See [Alternatives Considered](#alternatives-considered).

@gmackall gmackall Nov 4, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly I think there are apis that we could use to get each disparate piece (flutter root content in ahb swapchain case and non ahb swapchain case, the platform views, and overlay content) w/o changes to embedder api. But we'd have to get each piece independently and reconstruct, which is a lot of work and seems out of scope. But just noting for completeness

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants