Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
runtime_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_RUNTIME_RUNTIME_CONTROLLER_H_
6#define FLUTTER_RUNTIME_RUNTIME_CONTROLLER_H_
7
8#include <memory>
9#include <vector>
10
14#include "flutter/fml/macros.h"
15#include "flutter/fml/mapping.h"
29
30namespace flutter {
31
32class Scene;
33class RuntimeDelegate;
34class View;
35class Window;
36
37//------------------------------------------------------------------------------
38/// Represents an instance of a running root isolate with window bindings. In
39/// normal operation, a single instance of this object is owned by the engine
40/// per shell. This object may only be created, used, and collected on the UI
41/// task runner. Window state queried by the root isolate is stored by this
42/// object. In cold-restart scenarios, the engine may collect this before
43/// installing a new runtime controller in its place. The Clone method may be
44/// used by the engine to copy the currently accumulated window state so it can
45/// be referenced by the new runtime controller.
46///
47/// When `RuntimeController` is created, it takes some time before the root
48/// isolate becomes ready. Operation during this gap is stored by
49/// `RuntimeController` and flushed to the Dart VM when the isolate becomes
50/// ready before the entrypoint function. See `PlatformData`.
51///
54 public:
55 /// A callback that's invoked after this `RuntimeController` attempts to
56 /// add a view to the Dart isolate.
57 ///
58 /// If the Dart isolate is not launched yet, this callback will be stored
59 /// and invoked after the isolate is launched.
60 ///
61 /// The `added` parameter is false if the add operation fails or was
62 /// cancelled while pending using `RemoveView`.
63 using AddViewCallback = std::function<void(bool added)>;
64
65 //----------------------------------------------------------------------------
66 /// @brief Creates a new instance of a runtime controller. This is
67 /// usually only done by the engine instance associated with the
68 /// shell.
69 ///
70 /// @param client The runtime delegate. This is
71 /// usually the `Engine` instance.
72 /// @param vm A reference to a running Dart VM.
73 /// The runtime controller must be
74 /// collected before the VM is
75 /// destroyed (this order is
76 /// guaranteed by the shell).
77 /// @param[in] idle_notification_callback The idle notification callback.
78 /// This allows callers to run native
79 /// code in isolate scope when the VM
80 /// is about to be notified that the
81 /// engine is going to be idle.
82 /// @param[in] platform_data The window data (if exists).
83 /// @param[in] isolate_create_callback The isolate create callback. This
84 /// allows callers to run native code
85 /// in isolate scope on the UI task
86 /// runner as soon as the root isolate
87 /// has been created.
88 /// @param[in] isolate_shutdown_callback The isolate shutdown callback.
89 /// This allows callers to run native
90 /// code in isolate scoped on the UI
91 /// task runner just as the root
92 /// isolate is about to be torn down.
93 /// @param[in] persistent_isolate_data Unstructured persistent read-only
94 /// data that the root isolate can
95 /// access in a synchronous manner.
96 /// @param[in] context Engine-owned state which is
97 /// accessed by the root dart isolate.
98 ///
100 RuntimeDelegate& p_client,
101 DartVM* vm,
102 fml::RefPtr<const DartSnapshot> p_isolate_snapshot,
103 const std::function<void(int64_t)>& idle_notification_callback,
104 const PlatformData& platform_data,
105 const fml::closure& isolate_create_callback,
106 const fml::closure& isolate_shutdown_callback,
107 std::shared_ptr<const fml::Mapping> p_persistent_isolate_data,
108 const UIDartState::Context& context);
109
110 //----------------------------------------------------------------------------
111 /// @brief Create a RuntimeController that shares as many resources as
112 /// possible with the calling RuntimeController such that together
113 /// they occupy less memory.
114 /// @return A RuntimeController with a running isolate.
115 /// @see RuntimeController::RuntimeController
116 ///
117 std::unique_ptr<RuntimeController> Spawn(
118 RuntimeDelegate& p_client,
119 const std::string& advisory_script_uri,
120 const std::string& advisory_script_entrypoint,
121 const std::function<void(int64_t)>& idle_notification_callback,
122 const fml::closure& isolate_create_callback,
123 const fml::closure& isolate_shutdown_callback,
124 const std::shared_ptr<const fml::Mapping>& persistent_isolate_data,
125 fml::WeakPtr<IOManager> io_manager,
128 image_generator_registry,
129 fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate) const;
130
131 // |PlatformConfigurationClient|
132 ~RuntimeController() override;
133
134 //----------------------------------------------------------------------------
135 /// @brief Launches the isolate using the window data associated with
136 /// this runtime controller. Before this call, the Dart isolate
137 /// has not been initialized. On successful return, the caller can
138 /// assume that the isolate is in the
139 /// `DartIsolate::Phase::Running` phase.
140 ///
141 /// This call will fail if a root isolate is already running. To
142 /// re-create an isolate with the window data associated with this
143 /// runtime controller, `Clone` this runtime controller and
144 /// Launch an isolate in that runtime controller instead.
145 ///
146 /// @param[in] settings The per engine instance settings.
147 /// @param[in] root_isolate_create_callback A callback invoked before the
148 /// root isolate has launched the Dart
149 /// program, but after it has been
150 /// created. This is called without
151 /// isolate scope, and after any root
152 /// isolate callback in the settings.
153 /// @param[in] dart_entrypoint The dart entrypoint. If
154 /// `std::nullopt` or empty, `main` will
155 /// be attempted.
156 /// @param[in] dart_entrypoint_library The dart entrypoint library. If
157 /// `std::nullopt` or empty, the core
158 /// library will be attempted.
159 /// @param[in] dart_entrypoint_args Arguments passed as a List<String>
160 /// to Dart's entrypoint function.
161 /// @param[in] isolate_configuration The isolate configuration
162 /// @param[in] engine_id. Engine identifier to be passed to the
163 /// platform dispatcher.
164 ///
165 /// @return If the isolate could be launched and guided to the
166 /// `DartIsolate::Phase::Running` phase.
167 ///
168 [[nodiscard]] bool LaunchRootIsolate(
169 const Settings& settings,
170 const fml::closure& root_isolate_create_callback,
171 std::optional<std::string> dart_entrypoint,
172 std::optional<std::string> dart_entrypoint_library,
173 const std::vector<std::string>& dart_entrypoint_args,
174 std::unique_ptr<IsolateConfiguration> isolate_configuration,
175 std::shared_ptr<NativeAssetsManager> native_assets_manager,
176 std::optional<int64_t> engine_id);
177
178 //----------------------------------------------------------------------------
179 /// @brief Clone the runtime controller. Launching an isolate with a
180 /// cloned runtime controller will use the same snapshots and
181 /// copies all window data to the new instance. This is usually
182 /// only used in the debug runtime mode to support the
183 /// cold-restart scenario.
184 ///
185 /// @return A clone of the existing runtime controller.
186 ///
187 std::unique_ptr<RuntimeController> Clone() const;
188
189 //----------------------------------------------------------------------------
190 /// @brief Notify the isolate that a new view is available.
191 ///
192 /// A view must be added before other methods can refer to it,
193 /// including the implicit view. Adding a view that already exists
194 /// is an error.
195 ///
196 /// The `callback` is invoked when the add operation is attempted,
197 /// failed, or is cancelled.
198 ///
199 /// If the isolate is not running, the view add will be queued and
200 /// flushed to the isolate when it starts. Calling `RemoveView`
201 /// before the isolate is launched cancels the add operation.
202 ///
203 /// If the isolate is running, a frame will be scheduled.
204 ///
205 /// @param[in] view_id The ID of the new view.
206 /// @param[in] viewport_metrics The initial viewport metrics for the view.
207 /// @param[in] callback Callback that will be invoked after the add
208 /// operation is attempted or cancelled.
209 ///
210 void AddView(int64_t view_id,
211 const ViewportMetrics& view_metrics,
213
214 //----------------------------------------------------------------------------
215 /// @brief Notify the isolate that a view is no longer available.
216 ///
217 /// Views that are added before the isolate is started are
218 /// queued until the isolate is launched. If one of these
219 /// "pending" views are removed, the view add is cancelled:
220 /// the `AddViewCallback` will be invoked with an `added` of
221 /// false and `RemoveView` will return false.
222 ///
223 /// The implicit view (kFlutterImplicitViewId) should never be
224 /// removed. Doing so triggers an assertion.
225 ///
226 /// @param[in] view_id The ID of the view.
227 ///
228 /// @return If the remove view operation was forwarded to the running
229 /// isolate. False if the view does not exist. If the Dart isolate
230 /// is not running, then the pending view creation (if any) is
231 /// cancelled and the return value is always false.
232 bool RemoveView(int64_t view_id);
233
234 //----------------------------------------------------------------------------
235 /// @brief Notify the isolate that the focus state of a native view has
236 /// changed.
237 ///
238 /// @param[in] event The focus event describing the change.
239 bool SendViewFocusEvent(const ViewFocusEvent& event);
240
241 //----------------------------------------------------------------------------
242 /// @brief Forward the specified viewport metrics to the running isolate.
243 /// If the isolate is not running, these metrics will be saved and
244 /// flushed to the isolate when it starts.
245 ///
246 /// @param[in] view_id The ID for the view that `metrics` describes.
247 /// @param[in] metrics The window's viewport metrics.
248 ///
249 /// @return If the window metrics were forwarded to the running isolate.
250 ///
251 bool SetViewportMetrics(int64_t view_id, const ViewportMetrics& metrics);
252
253 //----------------------------------------------------------------------------
254 /// @brief Forward the specified display metrics to the running isolate.
255 /// If the isolate is not running, these metrics will be saved and
256 /// flushed to the isolate when it starts.
257 ///
258 /// @param[in] displays The available displays.
259 bool SetDisplays(const std::vector<DisplayData>& displays);
260
261 //----------------------------------------------------------------------------
262 /// @brief Forward the specified locale data to the running isolate. If
263 /// the isolate is not running, this data will be saved and
264 /// flushed to the isolate when it starts running.
265 ///
266 /// @deprecated The persistent isolate data must be used for this purpose
267 /// instead.
268 ///
269 /// @param[in] locale_data The locale data. This should consist of groups of
270 /// 4 strings, each group representing a single locale.
271 ///
272 /// @return If the locale data was forwarded to the running isolate.
273 ///
274 bool SetLocales(const std::vector<std::string>& locale_data);
275
276 //----------------------------------------------------------------------------
277 /// @brief Forward the user settings data to the running isolate. If the
278 /// isolate is not running, this data will be saved and flushed to
279 /// the isolate when it starts running.
280 ///
281 /// @deprecated The persistent isolate data must be used for this purpose
282 /// instead.
283 ///
284 /// @param[in] data The user settings data.
285 ///
286 /// @return If the user settings data was forwarded to the running
287 /// isolate.
288 ///
289 bool SetUserSettingsData(const std::string& data);
290
291 //----------------------------------------------------------------------------
292 /// @brief Forward the initial lifecycle state data to the running
293 /// isolate. If the isolate is not running, this data will be
294 /// saved and flushed to the isolate when it starts running.
295 /// After the isolate starts running, the current lifecycle
296 /// state is pushed to it via the "flutter/lifecycle" channel.
297 ///
298 /// @deprecated The persistent isolate data must be used for this purpose
299 /// instead.
300 ///
301 /// @param[in] data The lifecycle state data.
302 ///
303 /// @return If the lifecycle state data was forwarded to the running
304 /// isolate.
305 ///
306 bool SetInitialLifecycleState(const std::string& data);
307
308 //----------------------------------------------------------------------------
309 /// @brief Notifies the running isolate about whether the semantics tree
310 /// should be generated or not. If the isolate is not running,
311 /// this preference will be saved and flushed to the isolate when
312 /// it starts running.
313 ///
314 /// @param[in] enabled Indicates whether to generate the semantics tree.
315 ///
316 /// @return If the semantics tree generation preference was forwarded to
317 /// the running isolate.
318 ///
319 bool SetSemanticsEnabled(bool enabled);
320
321 //----------------------------------------------------------------------------
322 /// @brief Forward the preference of accessibility features that must be
323 /// enabled in the semantics tree to the running isolate. If the
324 /// isolate is not running, this data will be saved and flushed to
325 /// the isolate when it starts running.
326 ///
327 /// @param[in] flags The accessibility features that must be generated in
328 /// the semantics tree.
329 ///
330 /// @return If the preference of accessibility features was forwarded to
331 /// the running isolate.
332 ///
333 bool SetAccessibilityFeatures(int32_t flags);
334
335 //----------------------------------------------------------------------------
336 /// @brief Notifies the running isolate that it should start generating a
337 /// new frame.
338 ///
339 /// @see `Engine::BeginFrame` for more context.
340 ///
341 /// @param[in] frame_time The point at which the current frame interval
342 /// began. May be used by animation interpolators,
343 /// physics simulations, etc.
344 ///
345 /// @return If notification to begin frame rendering was delivered to the
346 /// running isolate.
347 ///
348 bool BeginFrame(fml::TimePoint frame_time, uint64_t frame_number);
349
350 //----------------------------------------------------------------------------
351 /// @brief Dart code cannot fully measure the time it takes for a
352 /// specific frame to be rendered. This is because Dart code only
353 /// runs on the UI task runner. That is only a small part of the
354 /// overall frame workload. The raster task runner frame workload
355 /// is executed on a thread where Dart code cannot run (and hence
356 /// instrument). Besides, due to the pipelined nature of rendering
357 /// in Flutter, there may be multiple frame workloads being
358 /// processed at any given time. However, for non-Timeline based
359 /// profiling, it is useful for trace collection and processing to
360 /// happen in Dart. To do this, the raster task runner frame
361 /// workloads need to be instrumented separately. After a set
362 /// number of these profiles have been gathered, they need to be
363 /// reported back to Dart code. The engine reports this extra
364 /// instrumentation information back to Dart code running on the
365 /// engine by invoking this method at predefined intervals.
366 ///
367 /// @see `Engine::ReportTimings`, `FrameTiming`
368 ///
369 /// @param[in] timings Collection of `FrameTiming::kCount` * `n` timestamps
370 /// for `n` frames whose timings have not been reported
371 /// yet. A collection of integers is reported here for
372 /// easier conversions to Dart objects. The timestamps
373 /// are measured against the system monotonic clock
374 /// measured in microseconds.
375 ///
376 bool ReportTimings(std::vector<int64_t> timings);
377
378 //----------------------------------------------------------------------------
379 /// @brief Notify the Dart VM that no frame workloads are expected on the
380 /// UI task runner till the specified deadline. The VM uses this
381 /// opportunity to perform garbage collection operations is a
382 /// manner that interferes as little as possible with frame
383 /// rendering.
384 ///
385 /// NotifyIdle is advisory. The VM may or may not run a garbage collection
386 /// when this is called, and will eventually perform garbage collections even
387 /// if it is not called or it is called with insufficient deadlines.
388 ///
389 /// The garbage collection mechanism and its thresholds are internal
390 /// implementation details and absolutely no guarantees are made about the
391 /// threshold discussed below. This discussion is also an oversimplification
392 /// but hopefully serves to calibrate expectations about GC behavior:
393 /// * When the Dart VM and its root isolate are initialized, the memory
394 /// consumed upto that point are treated as a baseline.
395 /// * A fixed percentage of the memory consumed (~20%) over the baseline is
396 /// treated as the hard threshold.
397 /// * The memory in play is divided into old space and new space. The new
398 /// space is typically very small and fills up rapidly.
399 /// * The baseline plus the threshold is considered the old space while the
400 /// small new space is a separate region (typically a few pages).
401 /// * The total old space size minus the max new space size is treated as the
402 /// soft threshold.
403 /// * In a world where there is no call to NotifyIdle, when the total
404 /// allocation exceeds the soft threshold, a concurrent mark is initiated in
405 /// the VM. There is a “small” pause that occurs when the concurrent mark is
406 /// initiated and another pause when the mark concludes and a sweep is
407 /// initiated.
408 /// * If the total allocations exceeds the hard threshold, a “big”
409 /// stop-the-world pause is initiated.
410 /// * If after either the sweep after the concurrent mark, or, the
411 /// stop-the-world pause, the consumption returns to be below the soft
412 /// threshold, the dance begins anew.
413 /// * If after both the “small” and “big” pauses, memory usage is still over
414 /// the hard threshold, i.e, the objects are still reachable, that amount of
415 /// memory is treated as the new baseline and a fixed percentage of the new
416 /// baseline over the new baseline is now the new hard threshold.
417 /// * Updating the baseline will continue till memory for the updated old
418 /// space can be allocated from the operating system. These allocations will
419 /// typically fail due to address space exhaustion on 32-bit systems and
420 /// page table exhaustion on 64-bit systems.
421 /// * NotifyIdle initiates the concurrent mark preemptively. The deadline is
422 /// used by the VM to determine if the corresponding sweep can be performed
423 /// within the deadline. This way, jank due to “small” pauses can be
424 /// ameliorated.
425 /// * There is no ability to stop a “big” pause on reaching the hard threshold
426 /// in the old space. The best you can do is release (by making them
427 /// unreachable) objects eagerly so that the are marked as unreachable in
428 /// the concurrent mark initiated by either reaching the soft threshold or
429 /// an explicit NotifyIdle.
430 /// * If you are running out of memory, its because too many large objects
431 /// were allocation and remained reachable such that the old space kept
432 /// growing till it could grow no more.
433 /// * At the edges of allocation thresholds, failures can occur gracefully if
434 /// the instigating allocation was made in the Dart VM or rather gracelessly
435 /// if the allocation is made by some native component.
436 ///
437 /// @see `Dart_TimelineGetMicros`
438 ///
439 /// @bug The `deadline` argument must be converted to `std::chrono`
440 /// instead of a raw integer.
441 ///
442 /// @param[in] deadline The deadline is used by the VM to determine if the
443 /// corresponding sweep can be performed within the deadline.
444 ///
445 /// @return If the idle notification was forwarded to the running isolate.
446 ///
447 virtual bool NotifyIdle(fml::TimeDelta deadline);
448
449 //----------------------------------------------------------------------------
450 /// @brief Returns if the root isolate is running. The isolate must be
451 /// transitioned to the running phase manually. The isolate can
452 /// stop running if it terminates execution on its own.
453 ///
454 /// @return True if root isolate running, False otherwise.
455 ///
456 virtual bool IsRootIsolateRunning() const;
457
458 //----------------------------------------------------------------------------
459 /// @brief Dispatch the specified platform message to running root
460 /// isolate.
461 ///
462 /// @param[in] message The message to dispatch to the isolate.
463 ///
464 /// @return If the message was dispatched to the running root isolate.
465 /// This may fail is an isolate is not running.
466 ///
467 virtual bool DispatchPlatformMessage(
468 std::unique_ptr<PlatformMessage> message);
469
470 //----------------------------------------------------------------------------
471 /// @brief Dispatch the specified pointer data message to the running
472 /// root isolate.
473 ///
474 /// @param[in] packet The pointer data message to dispatch to the isolate.
475 ///
476 /// @return If the pointer data message was dispatched. This may fail is
477 /// an isolate is not running.
478 ///
480
481 //----------------------------------------------------------------------------
482 /// @brief Requests to perform framework hit test from the engine.
483 ///
484 /// @param[in] view_id The identifier of the flutter view that
485 /// should be hit tested.
486 /// @param[in] offset The position in the view that should be hit tested.
487 ///
488 /// @return The hit test response.
489 ///
490 HitTestResponse HitTest(int64_t view_id, const flutter::PointData offset);
491
492 //----------------------------------------------------------------------------
493 /// @brief Dispatch the semantics action to the specified accessibility
494 /// node.
495 ///
496 /// @param[in] view_id The identifier of the view.
497 /// @param[in] node_id The identifier of the accessibility node.
498 /// @param[in] action The semantics action to perform on the specified
499 /// accessibility node.
500 /// @param[in] args Optional data that applies to the specified action.
501 ///
502 /// @return If the semantics action was dispatched. This may fail if an
503 /// isolate is not running.
504 ///
505 bool DispatchSemanticsAction(int64_t view_id,
506 int32_t node_id,
509
510 //----------------------------------------------------------------------------
511 /// @brief Gets the main port identifier of the root isolate.
512 ///
513 /// @return The main port identifier. If no root isolate is running,
514 /// returns `ILLEGAL_PORT`.
515 ///
516 Dart_Port GetMainPort();
517
518 //----------------------------------------------------------------------------
519 /// @brief Gets the debug name of the root isolate. But default, the
520 /// debug name of the isolate is derived from its advisory script
521 /// URI, advisory main entrypoint and its main port name. For
522 /// example, "main.dart$main-1234" where the script URI is
523 /// "main.dart", the entrypoint is "main" and the port name
524 /// "1234". Once launched, the isolate may re-christen itself
525 /// using a name it selects via `setIsolateDebugName` in
526 /// `window.dart`. This name is purely advisory and only used by
527 /// instrumentation and reporting purposes.
528 ///
529 /// @return The debug name of the root isolate.
530 ///
531 std::string GetIsolateName();
532
533 //----------------------------------------------------------------------------
534 /// @brief Returns if the root isolate has any live receive ports.
535 ///
536 /// @return True if there are live receive ports, False otherwise. Return
537 /// False if the root isolate is not running as well.
538 ///
539 bool HasLivePorts();
540
541 //----------------------------------------------------------------------------
542 /// @brief Returns if the root isolate has any pending microtasks.
543 ///
544 /// @return True if there are microtasks that have been queued but not
545 /// run, False otherwise. Return False if the root isolate is not
546 /// running as well.
547 ///
549
550 //----------------------------------------------------------------------------
551 /// @brief Get the last error encountered by the microtask queue.
552 ///
553 /// @return The last error encountered by the microtask queue.
554 ///
556
557 //----------------------------------------------------------------------------
558 /// @brief Get the service ID of the root isolate if the root isolate is
559 /// running.
560 ///
561 /// @return The root isolate service id.
562 ///
563 std::optional<std::string> GetRootIsolateServiceID() const;
564
565 //----------------------------------------------------------------------------
566 /// @brief Get the return code specified by the root isolate (if one is
567 /// present).
568 ///
569 /// @return The root isolate return code if the isolate has specified one.
570 ///
571 std::optional<uint32_t> GetRootIsolateReturnCode();
572
573 //----------------------------------------------------------------------------
574 /// @brief Get an identifier that represents the Dart isolate group the
575 /// root isolate is in.
576 ///
577 /// @return The root isolate group identifier, zero if one can't
578 /// be established.
579 uint64_t GetRootIsolateGroup() const;
580
581 //--------------------------------------------------------------------------
582 /// @brief Loads the Dart shared library into the Dart VM. When the
583 /// Dart library is loaded successfully, the Dart future
584 /// returned by the originating loadLibrary() call completes.
585 ///
586 /// The Dart compiler may generate separate shared libraries
587 /// files called 'loading units' when libraries are imported
588 /// as deferred. Each of these shared libraries are identified
589 /// by a unique loading unit id. Callers should open and resolve
590 /// a SymbolMapping from the shared library. The Mappings should
591 /// be moved into this method, as ownership will be assumed by the
592 /// dart root isolate after successful loading and released after
593 /// shutdown of the root isolate. The loading unit may not be
594 /// used after isolate shutdown. If loading fails, the mappings
595 /// will be released.
596 ///
597 /// This method is paired with a RequestDartDeferredLibrary
598 /// invocation that provides the embedder with the loading unit id
599 /// of the deferred library to load.
600 ///
601 ///
602 /// @param[in] loading_unit_id The unique id of the deferred library's
603 /// loading unit, as passed in by
604 /// RequestDartDeferredLibrary.
605 ///
606 /// @param[in] snapshot_data Dart snapshot data of the loading unit's
607 /// shared library.
608 ///
609 /// @param[in] snapshot_data Dart snapshot instructions of the loading
610 /// unit's shared library.
611 ///
613 intptr_t loading_unit_id,
614 std::unique_ptr<const fml::Mapping> snapshot_data,
615 std::unique_ptr<const fml::Mapping> snapshot_instructions);
616
617 //--------------------------------------------------------------------------
618 /// @brief Indicates to the dart VM that the request to load a deferred
619 /// library with the specified loading unit id has failed.
620 ///
621 /// The dart future returned by the initiating loadLibrary() call
622 /// will complete with an error.
623 ///
624 /// @param[in] loading_unit_id The unique id of the deferred library's
625 /// loading unit, as passed in by
626 /// RequestDartDeferredLibrary.
627 ///
628 /// @param[in] error_message The error message that will appear in the
629 /// dart Future.
630 ///
631 /// @param[in] transient A transient error is a failure due to
632 /// temporary conditions such as no network.
633 /// Transient errors allow the dart VM to
634 /// re-request the same deferred library and
635 /// loading_unit_id again. Non-transient
636 /// errors are permanent and attempts to
637 /// re-request the library will instantly
638 /// complete with an error.
639 virtual void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
640 const std::string error_message,
641 bool transient);
642
643 // |PlatformConfigurationClient|
644 void RequestDartDeferredLibrary(intptr_t loading_unit_id) override;
645
646 // |PlatformConfigurationClient|
647 std::shared_ptr<const fml::Mapping> GetPersistentIsolateData() override;
648
649 // |PlatformConfigurationClient|
650 void UpdateSemantics(int64_t view_id, SemanticsUpdate* update) override;
651
652 // |PlatformConfigurationClient|
653 void SetApplicationLocale(std::string locale) override;
654
655 // |PlatformConfigurationClient|
656 void SetSemanticsTreeEnabled(bool enabled) override;
657
659 return context_.io_manager;
660 }
661
662 virtual DartVM* GetDartVM() const { return vm_; }
663
665 return isolate_snapshot_;
666 }
667
668 const PlatformData& GetPlatformData() const { return platform_data_; }
669
671 return context_.unref_queue;
672 }
673
678
679 std::weak_ptr<const DartIsolate> GetRootIsolate() const {
680 return root_isolate_;
681 }
682
684 if (auto isolate = root_isolate_.lock()) {
685 isolate->FlushMicrotasksNow();
686 }
687 }
688
689 std::shared_ptr<PlatformIsolateManager> GetPlatformIsolateManager() override {
690 return platform_isolate_manager_;
691 }
692
694
695 //--------------------------------------------------------------------------
696 /// @brief Shuts down all registered platform isolates. Must be called
697 /// from the platform thread.
698 ///
700
701 protected:
702 /// Constructor for Mocks.
703 RuntimeController(RuntimeDelegate& p_client, const TaskRunners& task_runners);
704
705 private:
706 struct Locale {
707 Locale(std::string language_code_,
708 std::string country_code_,
709 std::string script_code_,
710 std::string variant_code_);
711
712 ~Locale();
713
714 std::string language_code;
715 std::string country_code;
716 std::string script_code;
717 std::string variant_code;
718 };
719
720 RuntimeDelegate& client_;
721 DartVM* const vm_;
722 fml::RefPtr<const DartSnapshot> isolate_snapshot_;
723 std::function<void(int64_t)> idle_notification_callback_;
724 PlatformData platform_data_;
725 std::weak_ptr<DartIsolate> root_isolate_;
726 std::weak_ptr<DartIsolate> spawning_isolate_;
727 std::optional<uint32_t> root_isolate_return_code_;
728 const fml::closure isolate_create_callback_;
729 const fml::closure isolate_shutdown_callback_;
730 std::shared_ptr<const fml::Mapping> persistent_isolate_data_;
731 UIDartState::Context context_;
732 PointerDataPacketConverter pointer_data_packet_converter_;
733 std::shared_ptr<PlatformIsolateManager> platform_isolate_manager_ =
734 std::shared_ptr<PlatformIsolateManager>(new PlatformIsolateManager());
735 bool has_flushed_runtime_state_ = false;
736
737 // Callbacks when `AddView` was called before the Dart isolate is launched.
738 //
739 // These views will be added when `FlushRuntimeStateToIsolate` is called.
740 // This is no longer used once the Dart isolate starts.
741 std::unordered_map<int64_t, AddViewCallback> pending_add_view_callbacks_;
742
743 // Tracks the views that have been called `Render` during a frame.
744 //
745 // If all views that have been registered by `AddView` have been called
746 // `Render`, then the runtime controller notifies the client of the end of
747 // frame immediately, allowing the client to submit the views to the pipeline
748 // a bit earlier than having to wait for the end of `BeginFrame`. See also
749 // `Animator::OnAllViewsRendered`.
750 //
751 // This mechanism fixes https://github.com/flutter/flutter/issues/144584 with
752 // option 2 and
753 // https://github.com/flutter/engine/pull/51186#issuecomment-1977820525 with
754 // option a in most cases, except if there are multiple views and only part of
755 // them are rendered.
756 // TODO(dkwingsmt): Fix these problems for all cases.
757 std::unordered_set<uint64_t> rendered_views_during_frame_;
758
759 void MarkAsFrameBorder();
760
761 void CheckIfAllViewsRendered();
762
763 PlatformConfiguration* GetPlatformConfigurationIfAvailable();
764
765 bool FlushRuntimeStateToIsolate();
766
767 // |PointerDataPacketConverter::Delegate|
768 bool ViewExists(int64_t view_id) const override;
769
770 // |PlatformConfigurationClient|
771 std::string DefaultRouteName() override;
772
773 // |PlatformConfigurationClient|
774 void ScheduleFrame() override;
775
776 // |PlatformConfigurationClient|
777 void EndWarmUpFrame() override;
778
779 // |PlatformConfigurationClient|
780 void Render(int64_t view_id,
781 Scene* scene,
782 double width,
783 double height) override;
784
785 // |PlatformConfigurationClient|
786 void HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) override;
787
788 // |PlatformConfigurationClient|
789 FontCollection& GetFontCollection() override;
790
791 // |PlatformConfigurationClient|
792 std::shared_ptr<AssetManager> GetAssetManager() override;
793
794 // |PlatformConfigurationClient|
795 void UpdateIsolateDescription(const std::string isolate_name,
796 int64_t isolate_port) override;
797
798 // |PlatformConfigurationClient|
799 void SetNeedsReportTimings(bool value) override;
800
801 // |PlatformConfigurationClient|
802 std::unique_ptr<std::vector<std::string>> ComputePlatformResolvedLocale(
803 const std::vector<std::string>& supported_locale_data) override;
804
805 // |PlatformConfigurationClient|
806 void SendChannelUpdate(std::string name, bool listening) override;
807
808 // |PlatformConfigurationClient|
809 double GetScaledFontSize(double unscaled_font_size,
810 int configuration_id) const override;
811
812 // |PlatformConfigurationClient|
813 void RequestViewFocusChange(const ViewFocusChangeRequest& request) override;
814
815 FML_DISALLOW_COPY_AND_ASSIGN(RuntimeController);
816};
817
818} // namespace flutter
819
820#endif // FLUTTER_RUNTIME_RUNTIME_CONTROLLER_H_
Describes a running instance of the Dart VM. There may only be one running instance of the Dart VM in...
Definition dart_vm.h:61
A client interface that the RuntimeController uses to define handlers for PlatformConfiguration reque...
void AddView(int64_t view_id, const ViewportMetrics &view_metrics, AddViewCallback callback)
Notify the isolate that a new view is available.
bool SetAccessibilityFeatures(int32_t flags)
Forward the preference of accessibility features that must be enabled in the semantics tree to the ru...
void SetSemanticsTreeEnabled(bool enabled) override
Notifies whether Framework starts generating semantics tree.
Dart_Port GetMainPort()
Gets the main port identifier of the root isolate.
bool SetSemanticsEnabled(bool enabled)
Notifies the running isolate about whether the semantics tree should be generated or not....
bool SetViewportMetrics(int64_t view_id, const ViewportMetrics &metrics)
Forward the specified viewport metrics to the running isolate. If the isolate is not running,...
uint64_t GetRootIsolateGroup() const
Get an identifier that represents the Dart isolate group the root isolate is in.
virtual bool NotifyIdle(fml::TimeDelta deadline)
Notify the Dart VM that no frame workloads are expected on the UI task runner till the specified dead...
bool HasPendingMicrotasks()
Returns if the root isolate has any pending microtasks.
std::weak_ptr< const DartIsolate > GetRootIsolate() const
bool DispatchPointerDataPacket(const PointerDataPacket &packet)
Dispatch the specified pointer data message to the running root isolate.
bool SetInitialLifecycleState(const std::string &data)
Forward the initial lifecycle state data to the running isolate. If the isolate is not running,...
std::function< void(bool added)> AddViewCallback
std::shared_ptr< PlatformIsolateManager > GetPlatformIsolateManager() override
bool SetLocales(const std::vector< std::string > &locale_data)
Forward the specified locale data to the running isolate. If the isolate is not running,...
void RequestDartDeferredLibrary(intptr_t loading_unit_id) override
Invoked when the Dart VM requests that a deferred library be loaded. Notifies the engine that the def...
bool SetDisplays(const std::vector< DisplayData > &displays)
Forward the specified display metrics to the running isolate. If the isolate is not running,...
HitTestResponse HitTest(int64_t view_id, const flutter::PointData offset)
Requests to perform framework hit test from the engine.
bool HasLivePorts()
Returns if the root isolate has any live receive ports.
bool RemoveView(int64_t view_id)
Notify the isolate that a view is no longer available.
std::optional< std::string > GetRootIsolateServiceID() const
Get the service ID of the root isolate if the root isolate is running.
const fml::RefPtr< const DartSnapshot > & GetIsolateSnapshot() const
const PlatformData & GetPlatformData() const
virtual bool IsRootIsolateRunning() const
Returns if the root isolate is running. The isolate must be transitioned to the running phase manuall...
bool LaunchRootIsolate(const Settings &settings, const fml::closure &root_isolate_create_callback, std::optional< std::string > dart_entrypoint, std::optional< std::string > dart_entrypoint_library, const std::vector< std::string > &dart_entrypoint_args, std::unique_ptr< IsolateConfiguration > isolate_configuration, std::shared_ptr< NativeAssetsManager > native_assets_manager, std::optional< int64_t > engine_id)
Launches the isolate using the window data associated with this runtime controller....
bool ReportTimings(std::vector< int64_t > timings)
Dart code cannot fully measure the time it takes for a specific frame to be rendered....
const fml::RefPtr< SkiaUnrefQueue > & GetSkiaUnrefQueue() const
const fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > & GetSnapshotDelegate() const
bool DispatchSemanticsAction(int64_t view_id, int32_t node_id, SemanticsAction action, fml::MallocMapping args)
Dispatch the semantics action to the specified accessibility node.
virtual bool DispatchPlatformMessage(std::unique_ptr< PlatformMessage > message)
Dispatch the specified platform message to running root isolate.
tonic::DartErrorHandleType GetLastError()
Get the last error encountered by the microtask queue.
bool SetUserSettingsData(const std::string &data)
Forward the user settings data to the running isolate. If the isolate is not running,...
void LoadDartDeferredLibrary(intptr_t loading_unit_id, std::unique_ptr< const fml::Mapping > snapshot_data, std::unique_ptr< const fml::Mapping > snapshot_instructions)
Loads the Dart shared library into the Dart VM. When the Dart library is loaded successfully,...
std::unique_ptr< RuntimeController > Clone() const
Clone the runtime controller. Launching an isolate with a cloned runtime controller will use the same...
bool SendViewFocusEvent(const ViewFocusEvent &event)
Notify the isolate that the focus state of a native view has changed.
void ShutdownPlatformIsolates()
Shuts down all registered platform isolates. Must be called from the platform thread.
std::unique_ptr< RuntimeController > Spawn(RuntimeDelegate &p_client, const std::string &advisory_script_uri, const std::string &advisory_script_entrypoint, const std::function< void(int64_t)> &idle_notification_callback, const fml::closure &isolate_create_callback, const fml::closure &isolate_shutdown_callback, const std::shared_ptr< const fml::Mapping > &persistent_isolate_data, fml::WeakPtr< IOManager > io_manager, fml::TaskRunnerAffineWeakPtr< ImageDecoder > image_decoder, fml::TaskRunnerAffineWeakPtr< ImageGeneratorRegistry > image_generator_registry, fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > snapshot_delegate) const
Create a RuntimeController that shares as many resources as possible with the calling RuntimeControll...
void UpdateSemantics(int64_t view_id, SemanticsUpdate *update) override
Receives an updated semantics tree from the Framework.
virtual DartVM * GetDartVM() const
bool BeginFrame(fml::TimePoint frame_time, uint64_t frame_number)
Notifies the running isolate that it should start generating a new frame.
std::optional< uint32_t > GetRootIsolateReturnCode()
Get the return code specified by the root isolate (if one is present).
std::shared_ptr< const fml::Mapping > GetPersistentIsolateData() override
The embedder can specify data that the isolate can request synchronously on launch....
const fml::WeakPtr< IOManager > & GetIOManager() const
virtual void LoadDartDeferredLibraryError(intptr_t loading_unit_id, const std::string error_message, bool transient)
Indicates to the dart VM that the request to load a deferred library with the specified loading unit ...
void SetApplicationLocale(std::string locale) override
Framework sets the application locale.
std::string GetIsolateName()
Gets the debug name of the root isolate. But default, the debug name of the isolate is derived from i...
A Mapping like NonOwnedMapping, but uses Free as its release proc.
Definition mapping.h:144
const char * message
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
G_BEGIN_DECLS FlutterViewId view_id
FlutterDesktopBinaryReply callback
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition macros.h:27
DEF_SWITCHES_START aot vmservice shared library name
Definition switch_defs.h:27
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
std::function< void()> closure
Definition closure.h:14
DartErrorHandleType
Definition dart_error.h:67
std::vector< FlutterEngineDisplay > * displays
int32_t height
int32_t width
The subset of state which is owned by the shell or engine and passed through the RuntimeController in...
fml::RefPtr< SkiaUnrefQueue > unref_queue
fml::WeakPtr< IOManager > io_manager
The IO manager used by the isolate for asynchronous texture uploads.
fml::TaskRunnerAffineWeakPtr< SnapshotDelegate > snapshot_delegate