Flutter Engine
flutter::AndroidExternalViewEmbedder Class Referencefinal

#include <external_view_embedder.h>

Inheritance diagram for flutter::AndroidExternalViewEmbedder:
flutter::ExternalViewEmbedder

Public Member Functions

 AndroidExternalViewEmbedder (std::shared_ptr< AndroidContext > android_context, std::shared_ptr< PlatformViewAndroidJNI > jni_facade, std::shared_ptr< AndroidSurfaceFactory > surface_factory)
 
void PrerollCompositeEmbeddedView (int view_id, std::unique_ptr< flutter::EmbeddedViewParams > params) override
 
SkCanvas * CompositeEmbeddedView (int view_id) override
 
std::vector< SkCanvas * > GetCurrentCanvases () override
 
void SubmitFrame (GrDirectContext *context, std::unique_ptr< SurfaceFrame > frame) override
 
PostPrerollResult PostPrerollAction (fml::RefPtr< fml::RasterThreadMerger > raster_thread_merger) override
 
SkCanvas * GetRootCanvas () override
 
void BeginFrame (SkISize frame_size, GrDirectContext *context, double device_pixel_ratio, fml::RefPtr< fml::RasterThreadMerger > raster_thread_merger) override
 
void CancelFrame () override
 
void EndFrame (bool should_resubmit_frame, fml::RefPtr< fml::RasterThreadMerger > raster_thread_merger) override
 
bool SupportsDynamicThreadMerging () override
 
SkRect GetViewRect (int view_id) const
 
- Public Member Functions inherited from flutter::ExternalViewEmbedder
 ExternalViewEmbedder ()=default
 
virtual ~ExternalViewEmbedder ()=default
 
virtual void PrerollCompositeEmbeddedView (int view_id, std::unique_ptr< EmbeddedViewParams > params)=0
 
 FML_DISALLOW_COPY_AND_ASSIGN (ExternalViewEmbedder)
 

Detailed Description

Allows to embed Android views into a Flutter application.

This class calls Java methods via |PlatformViewAndroidJNI| to manage the lifecycle of the Android view corresponding to |flutter::PlatformViewLayer|.

It also orchestrates overlay surfaces. These are Android views that render above (by Z order) the Android view corresponding to |flutter::PlatformViewLayer|.

Definition at line 30 of file external_view_embedder.h.

Constructor & Destructor Documentation

◆ AndroidExternalViewEmbedder()

flutter::AndroidExternalViewEmbedder::AndroidExternalViewEmbedder ( std::shared_ptr< AndroidContext android_context,
std::shared_ptr< PlatformViewAndroidJNI jni_facade,
std::shared_ptr< AndroidSurfaceFactory surface_factory 
)

Definition at line 12 of file external_view_embedder.cc.

17  android_context_(android_context),
18  jni_facade_(jni_facade),
19  surface_factory_(surface_factory),
20  surface_pool_(std::make_unique<SurfacePool>()) {}

Member Function Documentation

◆ BeginFrame()

void flutter::AndroidExternalViewEmbedder::BeginFrame ( SkISize  frame_size,
GrDirectContext *  context,
double  device_pixel_ratio,
fml::RefPtr< fml::RasterThreadMerger raster_thread_merger 
)
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 260 of file external_view_embedder.cc.

References fml::RasterThreadMerger::IsOnPlatformThread().

264  {
265  Reset();
266 
267  // The surface size changed. Therefore, destroy existing surfaces as
268  // the existing surfaces in the pool can't be recycled.
269  if (frame_size_ != frame_size && raster_thread_merger->IsOnPlatformThread()) {
270  surface_pool_->DestroyLayers(jni_facade_);
271  }
272  surface_pool_->SetFrameSize(frame_size);
273  // JNI method must be called on the platform thread.
274  if (raster_thread_merger->IsOnPlatformThread()) {
275  jni_facade_->FlutterViewBeginFrame();
276  }
277 
278  frame_size_ = frame_size;
279  device_pixel_ratio_ = device_pixel_ratio;
280 }

◆ CancelFrame()

void flutter::AndroidExternalViewEmbedder::CancelFrame ( )
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 283 of file external_view_embedder.cc.

Referenced by PostPrerollAction().

283  {
284  Reset();
285 }

◆ CompositeEmbeddedView()

SkCanvas * flutter::AndroidExternalViewEmbedder::CompositeEmbeddedView ( int  view_id)
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 46 of file external_view_embedder.cc.

46  {
47  if (picture_recorders_.count(view_id) == 1) {
48  return picture_recorders_.at(view_id)->getRecordingCanvas();
49  }
50  return nullptr;
51 }

◆ EndFrame()

void flutter::AndroidExternalViewEmbedder::EndFrame ( bool  should_resubmit_frame,
fml::RefPtr< fml::RasterThreadMerger raster_thread_merger 
)
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 288 of file external_view_embedder.cc.

References fml::RasterThreadMerger::IsOnPlatformThread().

290  {
291  surface_pool_->RecycleLayers();
292  // JNI method must be called on the platform thread.
293  if (raster_thread_merger->IsOnPlatformThread()) {
294  jni_facade_->FlutterViewEndFrame();
295  }
296 }

◆ GetCurrentCanvases()

std::vector< SkCanvas * > flutter::AndroidExternalViewEmbedder::GetCurrentCanvases ( )
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 54 of file external_view_embedder.cc.

54  {
55  std::vector<SkCanvas*> canvases;
56  for (size_t i = 0; i < composition_order_.size(); i++) {
57  int64_t view_id = composition_order_[i];
58  canvases.push_back(picture_recorders_.at(view_id)->getRecordingCanvas());
59  }
60  return canvases;
61 }

◆ GetRootCanvas()

SkCanvas * flutter::AndroidExternalViewEmbedder::GetRootCanvas ( )
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 247 of file external_view_embedder.cc.

247  {
248  // On Android, the root surface is created from the on-screen render target.
249  return nullptr;
250 }

◆ GetViewRect()

SkRect flutter::AndroidExternalViewEmbedder::GetViewRect ( int  view_id) const

Definition at line 63 of file external_view_embedder.cc.

References flutter::EmbeddedViewParams::finalBoundingRect().

Referenced by SubmitFrame().

63  {
64  const EmbeddedViewParams& params = view_params_.at(view_id);
65  // TODO(egarciad): The rect should be computed from the mutator stack.
66  // (Clipping is missing)
67  // https://github.com/flutter/flutter/issues/59821
68  return SkRect::MakeXYWH(params.finalBoundingRect().x(), //
69  params.finalBoundingRect().y(), //
70  params.finalBoundingRect().width(), //
71  params.finalBoundingRect().height() //
72  );
73 }

◆ PostPrerollAction()

PostPrerollResult flutter::AndroidExternalViewEmbedder::PostPrerollAction ( fml::RefPtr< fml::RasterThreadMerger raster_thread_merger)
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 215 of file external_view_embedder.cc.

References CancelFrame(), fml::RasterThreadMerger::ExtendLeaseTo(), fml::RasterThreadMerger::IsMerged(), flutter::kResubmitFrame, flutter::kSkipAndRetryFrame, flutter::kSuccess, and fml::RasterThreadMerger::MergeWithLease().

216  {
217  if (!FrameHasPlatformLayers()) {
219  }
220  if (!raster_thread_merger->IsMerged()) {
221  // The raster thread merger may be disabled if the rasterizer is being
222  // created or teared down.
223  //
224  // In such cases, the current frame is dropped, and a new frame is attempted
225  // with the same layer tree.
226  //
227  // Eventually, the frame is submitted once this method returns `kSuccess`.
228  // At that point, the raster tasks are handled on the platform thread.
229  raster_thread_merger->MergeWithLease(kDefaultMergedLeaseDuration);
230  CancelFrame();
232  }
233  raster_thread_merger->ExtendLeaseTo(kDefaultMergedLeaseDuration);
234  // Surface switch requires to resubmit the frame.
235  // TODO(egarciad): https://github.com/flutter/flutter/issues/65652
236  if (previous_frame_view_count_ == 0) {
238  }
240 }
void MergeWithLease(size_t lease_term)
void ExtendLeaseTo(size_t lease_term)

◆ PrerollCompositeEmbeddedView()

void flutter::AndroidExternalViewEmbedder::PrerollCompositeEmbeddedView ( int  view_id,
std::unique_ptr< flutter::EmbeddedViewParams params 
)
override

Definition at line 23 of file external_view_embedder.cc.

References TRACE_EVENT0.

25  {
26  TRACE_EVENT0("flutter",
27  "AndroidExternalViewEmbedder::PrerollCompositeEmbeddedView");
28 
29  auto rtree_factory = RTreeFactory();
30  view_rtrees_.insert_or_assign(view_id, rtree_factory.getInstance());
31 
32  auto picture_recorder = std::make_unique<SkPictureRecorder>();
33  picture_recorder->beginRecording(SkRect::Make(frame_size_), &rtree_factory);
34 
35  picture_recorders_.insert_or_assign(view_id, std::move(picture_recorder));
36  composition_order_.push_back(view_id);
37  // Update params only if they changed.
38  if (view_params_.count(view_id) == 1 &&
39  view_params_.at(view_id) == *params.get()) {
40  return;
41  }
42  view_params_.insert_or_assign(view_id, EmbeddedViewParams(*params.get()));
43 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75

◆ SubmitFrame()

void flutter::AndroidExternalViewEmbedder::SubmitFrame ( GrDirectContext *  context,
std::unique_ptr< SurfaceFrame frame 
)
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 76 of file external_view_embedder.cc.

References FML_CHECK, GetViewRect(), flutter::EmbeddedViewParams::mutatorsStack(), flutter::EmbeddedViewParams::sizePoints(), and TRACE_EVENT0.

78  {
79  TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder::SubmitFrame");
80 
81  if (!FrameHasPlatformLayers()) {
82  frame->Submit();
83  return;
84  }
85 
86  std::unordered_map<int64_t, std::list<SkRect>> overlay_layers;
87  std::unordered_map<int64_t, sk_sp<SkPicture>> pictures;
88  SkCanvas* background_canvas = frame->SkiaCanvas();
89  auto current_frame_view_count = composition_order_.size();
90 
91  // Restore the clip context after exiting this method since it's changed
92  // below.
93  SkAutoCanvasRestore save(background_canvas, /*doSave=*/true);
94 
95  for (size_t i = 0; i < current_frame_view_count; i++) {
96  int64_t view_id = composition_order_[i];
97 
98  sk_sp<SkPicture> picture =
99  picture_recorders_.at(view_id)->finishRecordingAsPicture();
100  FML_CHECK(picture);
101  pictures.insert({view_id, picture});
102 
103  overlay_layers.insert({view_id, {}});
104 
105  sk_sp<RTree> rtree = view_rtrees_.at(view_id);
106  // Determinate if Flutter UI intersects with any of the previous
107  // platform views stacked by z position.
108  //
109  // This is done by querying the r-tree that holds the records for the
110  // picture recorder corresponding to the flow layers added after a platform
111  // view layer.
112  for (ssize_t j = i; j >= 0; j--) {
113  int64_t current_view_id = composition_order_[j];
114  SkRect current_view_rect = GetViewRect(current_view_id);
115  // Each rect corresponds to a native view that renders Flutter UI.
116  std::list<SkRect> intersection_rects =
117  rtree->searchNonOverlappingDrawnRects(current_view_rect);
118  auto allocation_size = intersection_rects.size();
119 
120  // Limit the number of native views, so it doesn't grow forever.
121  //
122  // In this case, the rects are merged into a single one that is the union
123  // of all the rects.
124  if (allocation_size > kMaxLayerAllocations) {
125  SkRect joined_rect;
126  for (const SkRect& rect : intersection_rects) {
127  joined_rect.join(rect);
128  }
129  intersection_rects.clear();
130  intersection_rects.push_back(joined_rect);
131  }
132  for (SkRect& intersection_rect : intersection_rects) {
133  // Subpixels in the platform may not align with the canvas subpixels.
134  //
135  // To workaround it, round the floating point bounds and make the rect
136  // slighly larger. For example, {0.3, 0.5, 3.1, 4.7} becomes {0, 0, 4,
137  // 5}.
138  intersection_rect.set(intersection_rect.roundOut());
139  overlay_layers.at(view_id).push_back(intersection_rect);
140  // Clip the background canvas, so it doesn't contain any of the pixels
141  // drawn on the overlay layer.
142  background_canvas->clipRect(intersection_rect, SkClipOp::kDifference);
143  }
144  }
145  background_canvas->drawPicture(pictures.at(view_id));
146  }
147  // Submit the background canvas frame before switching the GL context to
148  // the overlay surfaces.
149  //
150  // Skip a frame if the embedding is switching surfaces, and indicate in
151  // `PostPrerollAction` that this frame must be resubmitted.
152  auto should_submit_current_frame = previous_frame_view_count_ > 0;
153  if (should_submit_current_frame) {
154  frame->Submit();
155  }
156 
157  for (int64_t view_id : composition_order_) {
158  SkRect view_rect = GetViewRect(view_id);
159  const EmbeddedViewParams& params = view_params_.at(view_id);
160  // Display the platform view. If it's already displayed, then it's
161  // just positioned and sized.
162  jni_facade_->FlutterViewOnDisplayPlatformView(
163  view_id, //
164  view_rect.x(), //
165  view_rect.y(), //
166  view_rect.width(), //
167  view_rect.height(), //
168  params.sizePoints().width() * device_pixel_ratio_,
169  params.sizePoints().height() * device_pixel_ratio_,
170  params.mutatorsStack() //
171  );
172  for (const SkRect& overlay_rect : overlay_layers.at(view_id)) {
173  std::unique_ptr<SurfaceFrame> frame =
174  CreateSurfaceIfNeeded(context, //
175  view_id, //
176  pictures.at(view_id), //
177  overlay_rect //
178  );
179  if (should_submit_current_frame) {
180  frame->Submit();
181  }
182  }
183  }
184 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75
#define FML_CHECK(condition)
Definition: logging.h:68

◆ SupportsDynamicThreadMerging()

bool flutter::AndroidExternalViewEmbedder::SupportsDynamicThreadMerging ( )
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 299 of file external_view_embedder.cc.

299  {
300  return true;
301 }

The documentation for this class was generated from the following files: