From 81e404d4cb05cb9508b4c950e8d6e13058328d14 Mon Sep 17 00:00:00 2001
From: Gray Mackall <34871572+gmackall@users.noreply.github.com>
Date: Mon, 3 Aug 2026 14:26:10 -0700
Subject: [PATCH 1/3] Fix incorrect Android platform view technical details
Mostly a follow-up to #13356, which introduced several inaccuracies on
the Hosting native Android views page. The compositing description in
the hybrid composition section predates that PR.
- Thread merging: hybrid composition merges the raster thread into the
platform thread, not "the raster and UI threads". The UI thread (which
runs Dart) and the platform thread (the Android main thread) are
distinct, so describing them as "the UI/platform thread" was also
wrong. See AndroidExternalViewEmbedder::PostPrerollAction, where the
raster tasks end up handled on the platform thread. This also brings
back the detail, lost when platform-view-perf.md was inlined, that the
cost is rasterization competing with other platform thread work.
- Compositing under hybrid composition: the page claimed Flutter content
goes into a texture that SurfaceFlinger then composes with the
platform views. It actually goes into ImageReaders painted by
FlutterImageViews, which live in the same window as the platform
views, so the Android view hierarchy composites them. SurfaceFlinger
only composites whole windows.
Describe both layer kinds, since they behave differently. The main
render surface is swapped for a background FlutterImageView by
FlutterView.convertToImageView once a platform view is added, while
content drawn above a platform view goes into overlay layers
(PlatformOverlayView) that SurfacePool allocates and recycles per
frame.
SurfaceFlinger compositing is instead what distinguishes HCPP, which
drives real SurfaceControl layers by way of PlatformViewsController2.
Attributing it to hybrid composition erased that distinction.
- Implementation matrix: the pipeline listed under hybrid composition
("renders to texture -> uploads to Impeller -> Impeller composites")
actually describes texture layer, so it moves to the texture layer
row, and hybrid composition gets the pipeline described above.
- HCPP requirements: Vulkan is not required for Impeller. Impeller has
an OpenGLES backend and falls back to it when Vulkan is unusable
(emulators, known bad SoCs, and so on). The real constraint is the
reverse: HCPP requires the Vulkan backend specifically, as gated by
PlatformViewAndroid::IsSurfaceControlEnabled.
---
.../android/platform-views.md | 49 +++++++++++++------
1 file changed, 33 insertions(+), 16 deletions(-)
diff --git a/sites/docs/src/content/platform-integration/android/platform-views.md b/sites/docs/src/content/platform-integration/android/platform-views.md
index 7a75c6094f..dfd68e6067 100644
--- a/sites/docs/src/content/platform-integration/android/platform-views.md
+++ b/sites/docs/src/content/platform-integration/android/platform-views.md
@@ -37,8 +37,8 @@ The following matrix summarizes the different implementations and their trade-of
| Mode | Benefits | Considerations | Enabler |
| :--- | :--- | :--- | :--- |
-| **Texture layer** | • Good Flutter performance
• Full widget transforms work | • Janky during quick scrolling
• SurfaceViews lose accessibility and text magnifier breaks | Default behavior or standard `AndroidView` |
-| **Hybrid composition** | • Full native fidelity
• Correct accessibility and SurfaceView support | • Causes thread merging of raster & platform, which degrades Flutter FPS
• Platform View -> Renders to texture -> Uploads to Impeller -> Impeller composites Flutter content and Platform View content |• `PlatformViewLink` with `AndroidViewSurface`
• [`AndroidViewController` builds either a TLHC or an HC Platform View][AC] |
+| **Texture layer** | • Good Flutter performance
• Full widget transforms work | • Janky during quick scrolling
• SurfaceViews lose accessibility and text magnifier breaks
• Platform View -> Renders to texture -> Uploads to Impeller -> Impeller composites Flutter content and Platform View content | Default behavior or standard `AndroidView` |
+| **Hybrid composition** | • Full native fidelity
• Correct accessibility and SurfaceView support | • Causes thread merging of raster & platform, which degrades Flutter FPS
• Platform View -> Renders into the Android view hierarchy as usual, Flutter content renders into `ImageReader`-backed `FlutterImageView`s (a background layer, plus an overlay layer for content drawn above a platform view), the Android view hierarchy composites them together |• `PlatformViewLink` with `AndroidViewSurface`
• [`AndroidViewController` builds either a TLHC or an HC Platform View][AC] |
| **HCPP** (Experimental) | • Full fidelity and performance
• Solves original sync overhead | • Requires Android API 34+, Vulkan support, and use of the Impeller rendering engine
• Platform View -> Renders to native Android Surface, Impeller renders to native Android Surface, SurfaceFlinger composites the two together | • `` in `AndroidManifest.xml`
• `--enable-hcpp` local flag
•[`AndroidViewController` builds either a TLHC or an HC Platform View][AC] |
{:.table .table-striped}
@@ -47,9 +47,18 @@ The following matrix summarizes the different implementations and their trade-of
## Hybrid composition {: #hybrid-composition }
-Platform Views are rendered as they are normally.
-Flutter content is rendered into a texture.
-SurfaceFlinger composes the Flutter content and the platform views.
+Platform views are rendered as they normally are,
+directly in the Android view hierarchy.
+Flutter content is rendered into `ImageReader`s and painted by
+`FlutterImageView`s that sit in the same window as the platform views,
+so the Android view hierarchy composites them together.
+
+Flutter uses two kinds of these layers.
+The main Flutter render surface is swapped for a background
+`FlutterImageView` once a platform view is added.
+Flutter content that draws on top of a platform view
+goes into an additional overlay `FlutterImageView`,
+allocated from a pool and recycled between frames.
## Hybrid composition++ (HCPP) {: #hcpp }
@@ -66,8 +75,10 @@ It is currently available as an opt-in feature.
* **Android API 34 or later**: Required for native transaction
synchronization capabilities.
-* **Vulkan rendering**: The device must be capable of rendering with Vulkan.
- Required for Impeller to be enabled.
+* **Impeller with the Vulkan backend**: The device must be capable of
+ rendering with Vulkan. Impeller also has an OpenGLES backend, and
+ falls back to it on devices without usable Vulkan support.
+ HCPP isn't available in that configuration.
If these requirements are not met on the end-user device,
Flutter will automatically fall back to the existing platform view strategy
@@ -516,15 +527,21 @@ Check out the [existing Platform View issues][] on GitHub.
Platform views in Flutter come with performance trade-offs.
In a typical Flutter app,
-the Flutter UI is composed on a dedicated raster thread,
-while platform code runs on the UI/platform thread.
-This separation keeps Flutter rendering fast and fluid.
-
-However, when a platform view is rendered on Android using hybrid
-composition, Flutter merges the raster and UI threads into a single thread to
-ensure correct synchronization between the native Android views and the Flutter canvas.
-Because of this thread merging, rendering complex Flutter widgets
-alongside a platform view can compete with OS messages and plugin interactions,
+Flutter rasterizes frames on a dedicated raster thread,
+while platform code, such as plugins and Android views,
+runs on the platform thread, which is the Android main thread.
+This separation keeps Flutter rendering fast and fluid,
+as the platform thread is rarely blocked by rasterization work.
+
+However, when a platform view is rendered on Android using
+hybrid composition,
+Flutter merges the raster thread into the platform thread
+to ensure correct synchronization between
+the native Android views and the Flutter canvas.
+Because of this thread merging,
+rasterizing complex Flutter widgets alongside a platform view
+competes with other work on the platform thread,
+such as OS messages and plugin interactions,
potentially causing lower application FPS and frame drops.
Also, prior to Android 10, hybrid composition copied each Flutter frame
From be6d2d4e4159c037c506c82f6545473b4f2599a5 Mon Sep 17 00:00:00 2001
From: Gray Mackall <34871572+gmackall@users.noreply.github.com>
Date: Mon, 10 Aug 2026 16:22:56 -0700
Subject: [PATCH 2/3] Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
---
.../src/content/platform-integration/android/platform-views.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sites/docs/src/content/platform-integration/android/platform-views.md b/sites/docs/src/content/platform-integration/android/platform-views.md
index dfd68e6067..08fc74b83e 100644
--- a/sites/docs/src/content/platform-integration/android/platform-views.md
+++ b/sites/docs/src/content/platform-integration/android/platform-views.md
@@ -531,7 +531,7 @@ Flutter rasterizes frames on a dedicated raster thread,
while platform code, such as plugins and Android views,
runs on the platform thread, which is the Android main thread.
This separation keeps Flutter rendering fast and fluid,
-as the platform thread is rarely blocked by rasterization work.
+as the platform thread is not blocked by rasterization work.
However, when a platform view is rendered on Android using
hybrid composition,
From 6a0a8cc431327e9a219be0692c2eb8c3520351ea Mon Sep 17 00:00:00 2001
From: Gray Mackall <34871572+gmackall@users.noreply.github.com>
Date: Mon, 10 Aug 2026 16:23:04 -0700
Subject: [PATCH 3/3] Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
---
.../src/content/platform-integration/android/platform-views.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sites/docs/src/content/platform-integration/android/platform-views.md b/sites/docs/src/content/platform-integration/android/platform-views.md
index 08fc74b83e..a86de18406 100644
--- a/sites/docs/src/content/platform-integration/android/platform-views.md
+++ b/sites/docs/src/content/platform-integration/android/platform-views.md
@@ -78,7 +78,7 @@ It is currently available as an opt-in feature.
* **Impeller with the Vulkan backend**: The device must be capable of
rendering with Vulkan. Impeller also has an OpenGLES backend, and
falls back to it on devices without usable Vulkan support.
- HCPP isn't available in that configuration.
+ HCPP is not available in that configuration.
If these requirements are not met on the end-user device,
Flutter will automatically fall back to the existing platform view strategy