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