Flutter Engine
flutter::AndroidExternalViewEmbedder Class Referencefinal

#include <external_view_embedder.h>

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

Public Member Functions

 AndroidExternalViewEmbedder (const 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
 
void Teardown () 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 ( const 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 258 of file external_view_embedder.cc.

References fml::RasterThreadMerger::IsOnPlatformThread().

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

◆ CancelFrame()

void flutter::AndroidExternalViewEmbedder::CancelFrame ( )
overridevirtual

Implements flutter::ExternalViewEmbedder.

Definition at line 281 of file external_view_embedder.cc.

Referenced by PostPrerollAction().

281  {
282  Reset();
283 }

◆ 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 286 of file external_view_embedder.cc.

References fml::RasterThreadMerger::IsOnPlatformThread().

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

◆ 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 245 of file external_view_embedder.cc.

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

◆ 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 213 of file external_view_embedder.cc.

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

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

◆ 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, 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  sk_sp<RTree> rtree = view_rtrees_.at(view_id);
104  SkRect joined_rect = SkRect::MakeEmpty();
105 
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 
119  // Limit the number of native views, so it doesn't grow forever.
120  //
121  // In this case, the rects are merged into a single one that is the union
122  // of all the rects.
123  for (const SkRect& rect : intersection_rects) {
124  joined_rect.join(rect);
125  }
126  }
127  if (!joined_rect.isEmpty()) {
128  // Subpixels in the platform may not align with the canvas subpixels.
129  //
130  // To workaround it, round the floating point bounds and make the rect
131  // slightly larger.
132  //
133  // For example, {0.3, 0.5, 3.1, 4.7} becomes {0, 0, 4, 5}.
134  joined_rect.set(joined_rect.roundOut());
135  overlay_layers.insert({view_id, joined_rect});
136  // Clip the background canvas, so it doesn't contain any of the pixels
137  // drawn on the overlay layer.
138  background_canvas->clipRect(joined_rect, SkClipOp::kDifference);
139  }
140  background_canvas->drawPicture(pictures.at(view_id));
141  }
142  // Submit the background canvas frame before switching the GL context to
143  // the overlay surfaces.
144  //
145  // Skip a frame if the embedding is switching surfaces, and indicate in
146  // `PostPrerollAction` that this frame must be resubmitted.
147  auto should_submit_current_frame = previous_frame_view_count_ > 0;
148  if (should_submit_current_frame) {
149  frame->Submit();
150  }
151 
152  for (int64_t view_id : composition_order_) {
153  SkRect view_rect = GetViewRect(view_id);
154  const EmbeddedViewParams& params = view_params_.at(view_id);
155  // Display the platform view. If it's already displayed, then it's
156  // just positioned and sized.
157  jni_facade_->FlutterViewOnDisplayPlatformView(
158  view_id, //
159  view_rect.x(), //
160  view_rect.y(), //
161  view_rect.width(), //
162  view_rect.height(), //
163  params.sizePoints().width() * device_pixel_ratio_,
164  params.sizePoints().height() * device_pixel_ratio_,
165  params.mutatorsStack() //
166  );
167  std::unordered_map<int64_t, SkRect>::const_iterator overlay =
168  overlay_layers.find(view_id);
169  if (overlay == overlay_layers.end()) {
170  continue;
171  }
172  std::unique_ptr<SurfaceFrame> frame =
173  CreateSurfaceIfNeeded(context, //
174  view_id, //
175  pictures.at(view_id), //
176  overlay->second //
177  );
178  if (should_submit_current_frame) {
179  frame->Submit();
180  }
181  }
182 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
#define FML_CHECK(condition)
Definition: logging.h:68

◆ SupportsDynamicThreadMerging()

bool flutter::AndroidExternalViewEmbedder::SupportsDynamicThreadMerging ( )
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 297 of file external_view_embedder.cc.

297  {
298  return true;
299 }

◆ Teardown()

void flutter::AndroidExternalViewEmbedder::Teardown ( )
overridevirtual

Reimplemented from flutter::ExternalViewEmbedder.

Definition at line 302 of file external_view_embedder.cc.

302  {
303  surface_pool_->DestroyLayers(jni_facade_);
304 }

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