Flutter iOS Embedder
platform_views_controller.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_PLATFORM_VIEWS_CONTROLLER_H_
6 #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_PLATFORM_VIEWS_CONTROLLER_H_
7 
8 #include <Metal/Metal.h>
9 
10 #include "flutter/flow/surface.h"
11 #include "flutter/fml/memory/weak_ptr.h"
12 #include "flutter/fml/platform/darwin/scoped_nsobject.h"
13 #include "flutter/fml/task_runner.h"
14 #include "flutter/fml/trace_event.h"
15 #include "impeller/base/thread_safety.h"
16 #include "third_party/skia/include/core/SkRect.h"
17 
24 
27 
28 namespace flutter {
29 
30 /// @brief Composites Flutter UI and overlay layers alongside embedded UIViews.
32  public:
34 
35  ~PlatformViewsController() = default;
36 
37  /// @brief Retrieve a weak pointer to this controller.
38  fml::WeakPtr<flutter::PlatformViewsController> GetWeakPtr();
39 
40  /// @brief Set the platform task runner used to post rendering tasks.
41  void SetTaskRunner(const fml::RefPtr<fml::TaskRunner>& platform_task_runner);
42 
43  /// @brief Set the flutter view.
44  void SetFlutterView(UIView* flutter_view) __attribute__((cf_audited_transfer));
45 
46  /// @brief Set the flutter view controller.
47  void SetFlutterViewController(UIViewController<FlutterViewResponder>* flutter_view_controller)
48  __attribute__((cf_audited_transfer));
49 
50  /// @brief Retrieve the view controller.
51  UIViewController<FlutterViewResponder>* GetFlutterViewController()
52  __attribute__((cf_audited_transfer));
53 
54  /// @brief set the factory used to construct embedded UI Views.
56  NSObject<FlutterPlatformViewFactory>* factory,
57  NSString* factoryId,
58  FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy)
59  __attribute__((cf_audited_transfer));
60 
61  /// @brief Mark the beginning of a frame and record the size of the onscreen.
62  void BeginFrame(SkISize frame_size);
63 
64  /// @brief Cancel the current frame, indicating that no platform views are composited.
65  ///
66  /// Additionally, reverts the composition order to its original state at the beginning of the
67  /// frame.
68  void CancelFrame();
69 
70  /// @brief Record a platform view in the layer tree to be rendered, along with the positioning and
71  /// mutator parameters.
72  ///
73  /// Called from the raster thread.
74  void PrerollCompositeEmbeddedView(int64_t view_id,
75  std::unique_ptr<flutter::EmbeddedViewParams> params);
76 
77  /// @brief Returns the`FlutterTouchInterceptingView` with the provided view_id.
78  ///
79  /// Returns nil if there is no platform view with the provided id. Called
80  /// from the platform thread.
82 
83  /// @brief Determine if thread merging is required after prerolling platform views.
84  ///
85  /// Called from the raster thread.
86  PostPrerollResult PostPrerollAction(
87  const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger,
88  bool impeller_enabled);
89 
90  /// @brief Mark the end of a compositor frame.
91  ///
92  /// May determine changes are required to the thread merging state.
93  /// Called from the raster thread.
94  void EndFrame(bool should_resubmit_frame,
95  const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger,
96  bool impeller_enabled);
97 
98  /// @brief Returns the Canvas for the overlay slice for the given platform view.
99  ///
100  /// Called from the raster thread.
101  DlCanvas* CompositeEmbeddedView(int64_t view_id);
102 
103  /// @brief Discards all platform views instances and auxiliary resources.
104  ///
105  /// Called from the raster thread.
106  void Reset();
107 
108  /// @brief Encode rendering for the Flutter overlay views and queue up perform platform view
109  /// mutations.
110  ///
111  /// Called from the raster thread.
112  bool SubmitFrame(GrDirectContext* gr_context,
113  const std::shared_ptr<IOSContext>& ios_context,
114  std::unique_ptr<SurfaceFrame> frame);
115 
116  /// @brief Handler for platform view message channels.
117  void OnMethodCall(FlutterMethodCall* call, FlutterResult result)
118  __attribute__((cf_audited_transfer));
119 
120  /// @brief Returns the platform view id if the platform view (or any of its descendant view) is
121  /// the first responder.
122  ///
123  /// Returns -1 if no such platform view is found.
125 
126  /// @brief Pushes backdrop filter mutation to the mutator stack of each visited platform view.
127  void PushFilterToVisitedPlatformViews(const std::shared_ptr<const DlImageFilter>& filter,
128  const SkRect& filter_rect);
129 
130  /// @brief Pushes the view id of a visted platform view to the list of visied platform views.
131  void PushVisitedPlatformView(int64_t view_id) { visited_platform_views_.push_back(view_id); }
132 
133  // visible for testing.
134  size_t EmbeddedViewCount() const;
135 
136  // visible for testing.
137  size_t LayerPoolSize() const;
138 
139  // visible for testing.
140  // Returns the `FlutterPlatformView`'s `view` object associated with the view_id.
141  //
142  // If the `PlatformViewsController` does not contain any `FlutterPlatformView` object or
143  // a `FlutterPlatformView` object associated with the view_id cannot be found, the method
144  // returns nil.
145  UIView* GetPlatformViewByID(int64_t view_id);
146 
147  // Visible for testing.
148  void CompositeWithParams(int64_t view_id, const EmbeddedViewParams& params);
149 
150  // Visible for testing.
151  const EmbeddedViewParams& GetCompositionParams(int64_t view_id) const {
152  return current_composition_params_.find(view_id)->second;
153  }
154 
155  private:
157  PlatformViewsController& operator=(const PlatformViewsController&) = delete;
158 
159  struct LayerData {
160  SkRect rect;
161  int64_t view_id;
162  int64_t overlay_id;
163  std::shared_ptr<OverlayLayer> layer;
164  };
165 
166  using LayersMap = std::unordered_map<int64_t, LayerData>;
167 
168  // Update the buffers and mutate the platform views in CATransaction.
169  //
170  // Runs on the platform thread.
171  void PerformSubmit(const LayersMap& platform_view_layers,
172  std::unordered_map<int64_t, EmbeddedViewParams>& current_composition_params,
173  const std::unordered_set<int64_t>& views_to_recomposite,
174  const std::vector<int64_t>& composition_order,
175  const std::vector<std::shared_ptr<OverlayLayer>>& unused_layers,
176  const std::vector<std::unique_ptr<SurfaceFrame>>& surface_frames);
177 
178  /// @brief Populate any missing overlay layers.
179  ///
180  /// This requires posting a task to the platform thread and blocking on its completion.
181  void CreateMissingOverlays(GrDirectContext* gr_context,
182  const std::shared_ptr<IOSContext>& ios_context,
183  size_t required_overlay_layers);
184 
185  void OnCreate(FlutterMethodCall* call, FlutterResult result) __attribute__((cf_audited_transfer));
186 
187  void OnDispose(FlutterMethodCall* call, FlutterResult result)
188  __attribute__((cf_audited_transfer));
189 
190  void OnAcceptGesture(FlutterMethodCall* call, FlutterResult result)
191  __attribute__((cf_audited_transfer));
192 
193  void OnRejectGesture(FlutterMethodCall* call, FlutterResult result)
194  __attribute__((cf_audited_transfer));
195 
196  /// @brief Return all views to be disposed on the platform thread.
197  std::vector<UIView*> GetViewsToDispose();
198 
199  void ClipViewSetMaskView(UIView* clipView) __attribute__((cf_audited_transfer));
200 
201  // Applies the mutators in the mutators_stack to the UIView chain that was constructed by
202  // `ReconstructClipViewsChain`
203  //
204  // Clips are applied to the `embedded_view`'s super view(|ChildClippingView|) using a
205  // |FlutterClippingMaskView|. Transforms are applied to `embedded_view`
206  //
207  // The `bounding_rect` is the final bounding rect of the PlatformView
208  // (EmbeddedViewParams::finalBoundingRect). If a clip mutator's rect contains the final bounding
209  // rect of the PlatformView, the clip mutator is not applied for performance optimization.
210  void ApplyMutators(const MutatorsStack& mutators_stack,
211  UIView* embedded_view,
212  const SkRect& bounding_rect) __attribute__((cf_audited_transfer));
213 
214  std::shared_ptr<OverlayLayer> GetExistingLayer();
215 
216  // Runs on the platform thread.
217  void CreateLayer(GrDirectContext* gr_context,
218  const std::shared_ptr<IOSContext>& ios_context,
219  MTLPixelFormat pixel_format);
220 
221  // Removes overlay views and platform views that aren't needed in the current frame.
222  // Must run on the platform thread.
223  void RemoveUnusedLayers(const std::vector<std::shared_ptr<OverlayLayer>>& unused_layers,
224  const std::vector<int64_t>& composition_order);
225 
226  // Appends the overlay views and platform view and sets their z index based on the composition
227  // order.
228  void BringLayersIntoView(const LayersMap& layer_map,
229  const std::vector<int64_t>& composition_order);
230 
231  // Resets the state of the frame.
232  void ResetFrameState();
233 
234  // The pool of reusable view layers. The pool allows to recycle layer in each frame.
235  std::unique_ptr<OverlayLayerPool> layer_pool_;
236 
237  // The platform view's |EmbedderViewSlice| keyed off the view id, which contains any subsequent
238  // operation until the next platform view or the end of the last leaf node in the layer tree.
239  //
240  // The Slices are deleted by the PlatformViewsController.reset().
241  std::unordered_map<int64_t, std::unique_ptr<EmbedderViewSlice>> slices_;
242 
243  fml::scoped_nsobject<FlutterMethodChannel> channel_;
244  fml::scoped_nsobject<UIView> flutter_view_;
245  fml::scoped_nsobject<UIViewController<FlutterViewResponder>> flutter_view_controller_;
246  fml::scoped_nsobject<FlutterClippingMaskViewPool> mask_view_pool_;
247  std::unordered_map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>>
248  factories_;
249 
250  // The FlutterPlatformViewGestureRecognizersBlockingPolicy for each type of platform view.
251  std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
252  gesture_recognizers_blocking_policies_;
253 
254  /// The size of the current onscreen surface in physical pixels.
255  SkISize frame_size_;
256 
257  /// The task runner for posting tasks to the platform thread.
258  fml::RefPtr<fml::TaskRunner> platform_task_runner_;
259 
260  /// Each of the following structs stores part of the platform view hierarchy according to its
261  /// ID.
262  ///
263  /// This data must only be accessed on the platform thread.
264  struct PlatformViewData {
265  fml::scoped_nsobject<NSObject<FlutterPlatformView>> view;
266  fml::scoped_nsobject<FlutterTouchInterceptingView> touch_interceptor;
267  fml::scoped_nsobject<UIView> root_view;
268  };
269 
270  /// This data must only be accessed on the platform thread.
271  std::unordered_map<int64_t, PlatformViewData> platform_views_;
272 
273  /// The composition parameters for each platform view.
274  ///
275  /// This state is only modified on the raster thread.
276  std::unordered_map<int64_t, EmbeddedViewParams> current_composition_params_;
277 
278  /// Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on
279  /// the next frame.
280  ///
281  /// This state is modified on both the platform and raster thread.
282  std::unordered_set<int64_t> views_to_dispose_;
283 
284  /// view IDs in composition order.
285  ///
286  /// This state is only modified on the raster thread.
287  std::vector<int64_t> composition_order_;
288 
289  /// platform view IDs visited during layer tree composition.
290  ///
291  /// This state is only modified on the raster thread.
292  std::vector<int64_t> visited_platform_views_;
293 
294  /// Only composite platform views in this set.
295  ///
296  /// This state is only modified on the raster thread.
297  std::unordered_set<int64_t> views_to_recomposite_;
298 
299 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
300  /// A set to keep track of embedded views that do not have (0, 0) origin.
301  /// An insertion triggers a warning message about non-zero origin logged on the debug console.
302  /// See https://github.com/flutter/flutter/issues/109700 for details.
303  std::unordered_set<int64_t> non_zero_origin_views_;
304 #endif
305 
306  /// @brief The composition order from the previous thread.
307  ///
308  /// Only accessed from the platform thread.
309  std::vector<int64_t> previous_composition_order_;
310 
311  /// Whether the previous frame had any platform views in active composition order.
312  ///
313  /// This state is tracked so that the first frame after removing the last platform view
314  /// runs through the platform view rendering code path, giving us a chance to remove the
315  /// platform view from the UIView hierarchy.
316  ///
317  /// Only accessed from the raster thread.
318  bool had_platform_views_ = false;
319 
320  // WeakPtrFactory must be the last member.
321  std::unique_ptr<fml::WeakPtrFactory<PlatformViewsController>> weak_factory_;
322 };
323 
324 } // namespace flutter
325 
326 #endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_PLATFORM_VIEWS_CONTROLLER_H_
flutter::PlatformViewsController::FindFirstResponderPlatformViewId
long FindFirstResponderPlatformViewId()
Returns the platform view id if the platform view (or any of its descendant view) is the first respon...
Definition: platform_views_controller.mm:389
flutter::PlatformViewsController::PostPrerollAction
PostPrerollResult PostPrerollAction(const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger, bool impeller_enabled)
Determine if thread merging is required after prerolling platform views.
Definition: platform_views_controller.mm:291
flutter::PlatformViewsController::SetTaskRunner
void SetTaskRunner(const fml::RefPtr< fml::TaskRunner > &platform_task_runner)
Set the platform task runner used to post rendering tasks.
Definition: platform_views_controller.mm:120
flutter::PlatformViewsController::EndFrame
void EndFrame(bool should_resubmit_frame, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger, bool impeller_enabled)
Mark the end of a compositor frame.
Definition: platform_views_controller.mm:326
FlutterPlatformViews.h
flutter::PlatformViewsController::PlatformViewsController
PlatformViewsController()
Definition: platform_views_controller.mm:113
flutter::PlatformViewsController::SetFlutterView
void SetFlutterView(UIView *flutter_view) __attribute__((cf_audited_transfer))
Set the flutter view.
Definition: platform_views_controller.mm:129
flutter::PlatformViewsController::LayerPoolSize
size_t LayerPoolSize() const
Definition: platform_views_controller.mm:373
flutter::PlatformViewsController::~PlatformViewsController
~PlatformViewsController()=default
FlutterChannels.h
flutter::PlatformViewsController::CompositeEmbeddedView
DlCanvas * CompositeEmbeddedView(int64_t view_id)
Returns the Canvas for the overlay slice for the given platform view.
Definition: platform_views_controller.mm:579
flutter::PlatformViewsController::EmbeddedViewCount
size_t EmbeddedViewCount() const
Definition: platform_views_controller.mm:369
flutter::PlatformViewsController::PrerollCompositeEmbeddedView
void PrerollCompositeEmbeddedView(int64_t view_id, std::unique_ptr< flutter::EmbeddedViewParams > params)
Record a platform view in the layer tree to be rendered, along with the positioning and mutator param...
Definition: platform_views_controller.mm:350
FlutterPlugin.h
FlutterViewResponder.h
FlutterMethodCall
Definition: FlutterCodecs.h:220
flutter::PlatformViewsController::GetFlutterViewController
UIViewController< FlutterViewResponder > * GetFlutterViewController() __attribute__((cf_audited_transfer))
Retrieve the view controller.
Definition: platform_views_controller.mm:138
flutter::PlatformViewsController::SubmitFrame
bool SubmitFrame(GrDirectContext *gr_context, const std::shared_ptr< IOSContext > &ios_context, std::unique_ptr< SurfaceFrame > frame)
Encode rendering for the Flutter overlay views and queue up perform platform view mutations.
Definition: platform_views_controller.mm:603
flutter
Definition: accessibility_bridge.h:28
flutter::PlatformViewsController::Reset
void Reset()
Discards all platform views instances and auxiliary resources.
Definition: platform_views_controller.mm:583
flutter::PlatformViewsController::BeginFrame
void BeginFrame(SkISize frame_size)
Mark the beginning of a frame and record the size of the onscreen.
Definition: platform_views_controller.mm:282
FlutterResult
void(^ FlutterResult)(id _Nullable result)
Definition: FlutterChannels.h:194
FlutterPlatformViewGestureRecognizersBlockingPolicy
FlutterPlatformViewGestureRecognizersBlockingPolicy
Definition: FlutterPlugin.h:252
flutter::PlatformViewsController::GetCompositionParams
const EmbeddedViewParams & GetCompositionParams(int64_t view_id) const
Definition: platform_views_controller.h:151
FlutterClippingMaskViewPool
Definition: FlutterPlatformViews_Internal.h:66
flutter::PlatformViewsController::RegisterViewFactory
void RegisterViewFactory(NSObject< FlutterPlatformViewFactory > *factory, NSString *factoryId, FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy) __attribute__((cf_audited_transfer))
set the factory used to construct embedded UI Views.
Definition: platform_views_controller.mm:272
flutter::PlatformViewsController::SetFlutterViewController
void SetFlutterViewController(UIViewController< FlutterViewResponder > *flutter_view_controller) __attribute__((cf_audited_transfer))
Set the flutter view controller.
Definition: platform_views_controller.mm:133
overlay_layer_pool.h
flutter::PlatformViewsController::PushFilterToVisitedPlatformViews
void PushFilterToVisitedPlatformViews(const std::shared_ptr< const DlImageFilter > &filter, const SkRect &filter_rect)
Pushes backdrop filter mutation to the mutator stack of each visited platform view.
Definition: platform_views_controller.mm:340
flutter::PlatformViewsController::GetPlatformViewByID
UIView * GetPlatformViewByID(int64_t view_id)
Definition: platform_views_controller.mm:377
flutter::PlatformViewsController::OnMethodCall
void OnMethodCall(FlutterMethodCall *call, FlutterResult result) __attribute__((cf_audited_transfer))
Handler for platform view message channels.
Definition: platform_views_controller.mm:142
flutter::PlatformViewsController::PushVisitedPlatformView
void PushVisitedPlatformView(int64_t view_id)
Pushes the view id of a visted platform view to the list of visied platform views.
Definition: platform_views_controller.h:131
flutter::PlatformViewsController
Composites Flutter UI and overlay layers alongside embedded UIViews.
Definition: platform_views_controller.h:31
flutter::PlatformViewsController::CompositeWithParams
void CompositeWithParams(int64_t view_id, const EmbeddedViewParams &params)
Definition: platform_views_controller.mm:540
flutter::PlatformViewsController::GetFlutterTouchInterceptingViewByID
FlutterTouchInterceptingView * GetFlutterTouchInterceptingViewByID(int64_t view_id)
Returns theFlutterTouchInterceptingView with the provided view_id.
Definition: platform_views_controller.mm:381
ios_context.h
flutter::PlatformViewsController::GetWeakPtr
fml::WeakPtr< flutter::PlatformViewsController > GetWeakPtr()
Retrieve a weak pointer to this controller.
Definition: platform_views_controller.mm:125
FlutterTouchInterceptingView
Definition: FlutterPlatformViews_Internal.h:138
flutter::PlatformViewsController::CancelFrame
void CancelFrame()
Cancel the current frame, indicating that no platform views are composited.
Definition: platform_views_controller.mm:287