Flutter Engine
flutter::Engine Class Referencefinal

#include <engine.h>

Inheritance diagram for flutter::Engine:
flutter::RuntimeDelegate flutter::HintFreedDelegate flutter::PointerDataDispatcher::Delegate

Classes

class  Delegate
 While the engine operates entirely on the UI task runner, it needs the capabilities of the other components to fulfill the requirements of the root isolate. The shell is the only class that implements this interface as no other component has access to all components in a thread safe manner. The engine delegates these tasks to the shell via this interface. More...
 

Public Types

enum  RunStatus {
  RunStatus::Success,
  RunStatus::FailureAlreadyRunning,
  RunStatus::Failure
}
 Indicates the result of the call to Engine::Run. More...
 

Public Member Functions

 Engine (Delegate &delegate, const PointerDataDispatcherMaker &dispatcher_maker, std::shared_ptr< fml::ConcurrentTaskRunner > image_decoder_task_runner, TaskRunners task_runners, Settings settings, std::unique_ptr< Animator > animator, fml::WeakPtr< IOManager > io_manager, std::unique_ptr< RuntimeController > runtime_controller)
 Creates an instance of the engine with a supplied RuntimeController. Use the other constructor except for tests. More...
 
 Engine (Delegate &delegate, const PointerDataDispatcherMaker &dispatcher_maker, DartVM &vm, fml::RefPtr< const DartSnapshot > isolate_snapshot, TaskRunners task_runners, const PlatformData platform_data, Settings settings, std::unique_ptr< Animator > animator, fml::WeakPtr< IOManager > io_manager, fml::RefPtr< SkiaUnrefQueue > unref_queue, fml::WeakPtr< SnapshotDelegate > snapshot_delegate)
 Creates an instance of the engine. This is done by the Shell on the UI task runner. More...
 
 ~Engine () override
 Destroys the engine engine. Called by the shell on the UI task runner. The running root isolate is terminated and will no longer access the task runner after this call returns. This allows the embedder to tear down the thread immediately if needed. More...
 
fml::WeakPtr< EngineGetWeakPtr () const
 
RunStatus Run (RunConfiguration configuration)
 Moves the root isolate to the DartIsolate::Phase::Running phase on a successful call to this method. More...
 
bool Restart (RunConfiguration configuration)
 Tears down an existing root isolate, reuses the components of that isolate and attempts to launch a new isolate using the given the run configuration. This is only used in the "debug" Flutter runtime mode in the cold-restart scenario. More...
 
void SetupDefaultFontManager ()
 Setup default font manager according to specific platform. More...
 
bool UpdateAssetManager (std::shared_ptr< AssetManager > asset_manager)
 Updates the asset manager referenced by the root isolate of a Flutter application. This happens implicitly in the call to Engine::Run and Engine::Restart as the asset manager is referenced from the run configuration provided to those calls. In addition to the Engine::Run and Engine::Restart calls, the tooling may need to update the assets available to the application as the user adds them to their project. For example, these assets may be referenced by code that is newly patched in after a hot-reload. Neither the shell or the isolate in relaunched in such cases. The tooling usually patches in the new assets in a temporary location and updates the asset manager to point to that location. More...
 
void BeginFrame (fml::TimePoint frame_time)
 Notifies the engine that it is time to begin working on a new frame previously scheduled via a call to Engine::ScheduleFrame. This call originates in the animator. More...
 
void HintFreed (size_t size) override
 Notifies the engine that native bytes might be freed if a garbage collection ran at the next NotifyIdle period. More...
 
void NotifyIdle (int64_t deadline)
 Notifies the engine that the UI task runner is not expected to undertake a new frame workload till a specified timepoint. The timepoint is measured in microseconds against the system's monotonic clock. It is recommended that the clock be accessed via Dart_TimelineGetMicros from dart_api.h for consistency. In reality, the clocks used by Dart, FML and std::steady_clock are all the same and the timepoints can be converted from on clock type to another. More...
 
void ReportTimings (std::vector< int64_t > timings)
 Dart code cannot fully measure the time it takes for a specific frame to be rendered. This is because Dart code only runs on the UI task runner. That is only a small part of the overall frame workload. The GPU task runner frame workload is executed on a thread where Dart code cannot run (and hence instrument). Besides, due to the pipelined nature of rendering in Flutter, there may be multiple frame workloads being processed at any given time. However, for non-Timeline based profiling, it is useful for trace collection and processing to happen in Dart. To do this, the GPU task runner frame workloads need to be instrumented separately. After a set number of these profiles have been gathered, they need to be reported back to Dart code. The shell reports this extra instrumentation information back to Dart code running on the engine by invoking this method at predefined intervals. More...
 
Dart_Port GetUIIsolateMainPort ()
 Gets the main port of the root isolate. Since the isolate is created immediately in the constructor of the engine, it is possible to get its main port immediately (even before a call to Run can be made). This is useful in registering the port in a race free manner with a port nameserver. More...
 
std::string GetUIIsolateName ()
 Gets the debug name of the root isolate. But default, the debug name of the isolate is derived from its advisory script URI, advisory main entrypoint and its main port name. For example, "main.dart$main-1234" where the script URI is "main.dart", the entrypoint is "main" and the port name "1234". Once launched, the isolate may re-christen itself using a name it selects via setIsolateDebugName in platform_dispatcher.dart. This name is purely advisory and only used by instrumentation and reporting purposes. More...
 
bool UIIsolateHasLivePorts ()
 It is an unexpected challenge to determine when a Dart application is "done". The application cannot simply terminate the native process (and perhaps return an exit code) because it does not have that power. After all, Flutter applications reside within a host process that may have other responsibilities besides just running Flutter applications. Also, the main entry-points are run on an event loop and returning from "main" (unlike in C/C++ applications) does not mean termination of the process. Besides, the return value of the main entrypoint is discarded. More...
 
tonic::DartErrorHandleType GetUIIsolateLastError ()
 Errors that are unhandled on the Dart message loop are kept for further inspection till the next unhandled error comes along. This accessor returns the last unhandled error encountered by the root isolate. More...
 
std::optional< uint32_t > GetUIIsolateReturnCode ()
 As described in the discussion for UIIsolateHasLivePorts, the "done-ness" of a Dart application is tricky to ascertain and the return value from the main entrypoint is discarded (because the Dart isolate is still running after the main entrypoint returns). But, the concept of an exit code akin to those returned by native applications is still useful. Short lived Dart applications (usually tests), emulate this by setting a per isolate "return value" and then indicating their "done-ness" (usually via closing all live ports). This accessor returns that "return value" is present. More...
 
void OnOutputSurfaceCreated ()
 Indicates to the Flutter application that it has obtained a rendering surface. This is a good opportunity for the engine to start servicing any outstanding frame requests from the Flutter applications. Flutter application that have no rendering concerns may never get a rendering surface. In such cases, while their root isolate can perform as normal, any frame requests made by them will never be serviced and layer trees produced outside of frame workloads will be dropped. More...
 
void OnOutputSurfaceDestroyed ()
 Indicates to the Flutter application that a previously acquired rendering surface has been lost. Further frame requests will no longer be serviced and any layer tree submitted for rendering will be dropped. If/when a new surface is acquired, a new layer tree must be generated. More...
 
void SetViewportMetrics (const ViewportMetrics &metrics)
 Updates the viewport metrics for the currently running Flutter application. The viewport metrics detail the size of the rendering viewport in texels as well as edge insets if present. More...
 
void DispatchPlatformMessage (fml::RefPtr< PlatformMessage > message)
 Notifies the engine that the embedder has sent it a message. This call originates in the platform view and has been forwarded to the engine on the UI task runner here. More...
 
void DispatchPointerDataPacket (std::unique_ptr< PointerDataPacket > packet, uint64_t trace_flow_id)
 Notifies the engine that the embedder has sent it a pointer data packet. A pointer data packet may contain multiple input events. This call originates in the platform view and the shell has forwarded the same to the engine on the UI task runner here. More...
 
void DispatchSemanticsAction (int id, SemanticsAction action, std::vector< uint8_t > args)
 Notifies the engine that the embedder encountered an accessibility related action on the specified node. This call originates on the platform view and has been forwarded to the engine here on the UI task runner by the shell. More...
 
void SetSemanticsEnabled (bool enabled)
 Notifies the engine that the embedder has expressed an opinion about whether the accessibility tree should be generated or not. This call originates in the platform view and is forwarded to the engine here on the UI task runner by the shell. More...
 
void SetAccessibilityFeatures (int32_t flags)
 Notifies the engine that the embedder has expressed an opinion about where the flags to set on the accessibility tree. This flag originates in the platform view and is forwarded to the engine here on the UI task runner by the shell. More...
 
void ScheduleFrame (bool regenerate_layer_tree) override
 
void ScheduleFrame ()
 
FontCollectionGetFontCollection () override
 
std::shared_ptr< AssetManagerGetAssetManager ()
 
void DoDispatchPacket (std::unique_ptr< PointerDataPacket > packet, uint64_t trace_flow_id) override
 
void ScheduleSecondaryVsyncCallback (const fml::closure &callback) override
 Schedule a secondary callback to be executed right after the main VsyncWaiter::AsyncWaitForVsync callback (which is added by Animator::RequestFrame). More...
 
const std::string & GetLastEntrypoint () const
 Get the last Entrypoint that was used in the RunConfiguration when |Engine::Run| was called. More...
 
const std::string & GetLastEntrypointLibrary () const
 Get the last Entrypoint Library that was used in the RunConfiguration when |Engine::Run| was called. More...
 
const std::string & InitialRoute () const
 Getter for the initial route. This can be set with a platform message. More...
 

Friends

class testing::ShellTest
 

Additional Inherited Members

- Protected Member Functions inherited from flutter::RuntimeDelegate
virtual ~RuntimeDelegate ()
 

Detailed Description

The engine is a component owned by the shell that resides on the UI task runner and is responsible for managing the needs of the root isolate and its runtime. The engine can only be created, accessed and collected on the UI task runner. Each shell owns exactly one instance of the engine.

The root isolate of Flutter application gets "window" bindings. Using these bindings, the application can schedule frames, post layer-trees for rendering, ask to decompress images and upload them to the GPU, etc.. Non-root isolates of the VM do not get any of these capabilities and are run in a VM managed thread pool (so if they did have "window", the threading guarantees needed for engine operation would be violated).

The engine is responsible for the entire life-cycle of the root isolate. When the engine is collected, its owner assumes that the root isolate has been shutdown and appropriate resources collected. While each engine instance can only manage a single instance of a root isolate, it may restart that isolate on request. This is how the cold-restart development scenario is supported.

When the engine instance is initially created, the root isolate is created but it is not in the |DartIsolate::Phase::Running| phase yet. It only moves into that phase when a successful call to Engine::Run is made.

See also
Shell
Note
This name of this class is perhaps a bit unfortunate and has sometimes been the cause of confusion. For a class named "Engine" in the Flutter "Engine" repository, its responsibilities are decidedly unremarkable. But, it does happen to be the primary entry-point used by components higher up in the Flutter tech stack (usually in Dart code) to peer into the lower level functionality. Besides, the authors haven't been able to come up with a more apt name and it does happen to be one of the older classes in the repository.

Definition at line 73 of file engine.h.

Member Enumeration Documentation

◆ RunStatus

Indicates the result of the call to Engine::Run.

Enumerator
Success 

The call to |Engine::Run| was successful and the root isolate is in the DartIsolate::Phase::Running phase with its entry-point invocation already pending in the task queue.

FailureAlreadyRunning 

The engine can only manage a single instance of a root isolate. If a previous call to run the root isolate was successful, subsequent calls to run the isolate (even if the new run configuration is different) will be rejected.

It is up to the caller to decide to re-purpose the running isolate, terminate it, or use another shell to host the new isolate. This is mostly used by embedders which have a fire-and-forget strategy to root isolate launch. For example, the application may try to "launch" and isolate when the embedders launches or resumes from a paused state. That the isolate is running is not necessarily a failure condition for them. But from the engine's perspective, the run configuration was rejected.

Failure 

Used to indicate to the embedder that a root isolate was not already running but the run configuration was not valid and root isolate could not be moved into the DartIsolate::Phase::Running phase.

The caller must attempt the run call again with a valid configuration. The set of all failure modes is massive and can originate from a variety of sub-components. The engine will attempt to log the same when possible. With the aid of logs, the common causes of failure are:

  • AOT assets give to JIT/DBC mode VM's and vice-versa.
  • The assets could not be found in the asset manager. Callers must make sure their run configuration asset managers have been correctly setup.
  • The assets themselves were corrupt or invalid. Callers must make sure their asset delivery mechanisms are sound.
  • The application entry-point or the root library of the entry-point specified in the run configuration was invalid. Callers must make sure that the entry-point is present in the application. If the name of the entrypoint is not "main" in the root library, callers must also ensure that the snapshotting process has not tree-shaken away this entrypoint. This requires the decoration of the entrypoint with the `('vm:entry-point')` directive. This problem will manifest in AOT mode operation of the Dart VM.

Definition at line 80 of file engine.h.

80  {
81  //--------------------------------------------------------------------------
82  /// The call to |Engine::Run| was successful and the root isolate is in the
83  /// `DartIsolate::Phase::Running` phase with its entry-point invocation
84  /// already pending in the task queue.
85  ///
86  Success,
87 
88  //--------------------------------------------------------------------------
89  /// The engine can only manage a single instance of a root isolate. If a
90  /// previous call to run the root isolate was successful, subsequent calls
91  /// to run the isolate (even if the new run configuration is different) will
92  /// be rejected.
93  ///
94  /// It is up to the caller to decide to re-purpose the running isolate,
95  /// terminate it, or use another shell to host the new isolate. This is
96  /// mostly used by embedders which have a fire-and-forget strategy to root
97  /// isolate launch. For example, the application may try to "launch" and
98  /// isolate when the embedders launches or resumes from a paused state. That
99  /// the isolate is running is not necessarily a failure condition for them.
100  /// But from the engine's perspective, the run configuration was rejected.
101  ///
102  FailureAlreadyRunning,
103 
104  //--------------------------------------------------------------------------
105  /// Used to indicate to the embedder that a root isolate was not already
106  /// running but the run configuration was not valid and root isolate could
107  /// not be moved into the `DartIsolate::Phase::Running` phase.
108  ///
109  /// The caller must attempt the run call again with a valid configuration.
110  /// The set of all failure modes is massive and can originate from a variety
111  /// of sub-components. The engine will attempt to log the same when
112  /// possible. With the aid of logs, the common causes of failure are:
113  ///
114  /// * AOT assets give to JIT/DBC mode VM's and vice-versa.
115  /// * The assets could not be found in the asset manager. Callers must make
116  /// sure their run configuration asset managers have been correctly setup.
117  /// * The assets themselves were corrupt or invalid. Callers must make sure
118  /// their asset delivery mechanisms are sound.
119  /// * The application entry-point or the root library of the entry-point
120  /// specified in the run configuration was invalid. Callers must make sure
121  /// that the entry-point is present in the application. If the name of the
122  /// entrypoint is not "main" in the root library, callers must also ensure
123  /// that the snapshotting process has not tree-shaken away this
124  /// entrypoint. This requires the decoration of the entrypoint with the
125  /// `@pragma('vm:entry-point')` directive. This problem will manifest in
126  /// AOT mode operation of the Dart VM.
127  ///
128  Failure,
129  };

Constructor & Destructor Documentation

◆ Engine() [1/2]

flutter::Engine::Engine ( Delegate delegate,
const PointerDataDispatcherMaker dispatcher_maker,
std::shared_ptr< fml::ConcurrentTaskRunner image_decoder_task_runner,
TaskRunners  task_runners,
Settings  settings,
std::unique_ptr< Animator animator,
fml::WeakPtr< IOManager io_manager,
std::unique_ptr< RuntimeController runtime_controller 
)

Creates an instance of the engine with a supplied RuntimeController. Use the other constructor except for tests.

Definition at line 38 of file engine.cc.

47  : delegate_(delegate),
48  settings_(std::move(settings)),
49  animator_(std::move(animator)),
50  runtime_controller_(std::move(runtime_controller)),
51  activity_running_(true),
52  have_surface_(false),
53  image_decoder_(task_runners, image_decoder_task_runner, io_manager),
54  task_runners_(std::move(task_runners)),
55  weak_factory_(this) {
56  pointer_data_dispatcher_ = dispatcher_maker(*this);
57 }

◆ Engine() [2/2]

flutter::Engine::Engine ( Delegate delegate,
const PointerDataDispatcherMaker dispatcher_maker,
DartVM vm,
fml::RefPtr< const DartSnapshot isolate_snapshot,
TaskRunners  task_runners,
const PlatformData  platform_data,
Settings  settings,
std::unique_ptr< Animator animator,
fml::WeakPtr< IOManager io_manager,
fml::RefPtr< SkiaUnrefQueue unref_queue,
fml::WeakPtr< SnapshotDelegate snapshot_delegate 
)

Creates an instance of the engine. This is done by the Shell on the UI task runner.

Parameters
delegateThe object used by the engine to perform tasks that require access to components that cannot be safely accessed by the engine. This is the shell.
dispatcher_makerThe callback provided by PlatformView for engine to create the pointer data dispatcher. Similar to other engine resources, this dispatcher_maker and its returned dispatcher is only safe to be called from the UI thread.
vmAn instance of the running Dart VM.
[in]isolate_snapshotThe snapshot used to create the root isolate. Even though the isolate is not DartIsolate::Phase::Running phase, it is created when the engine is created. This requires access to the isolate snapshot upfront.
[in]task_runnersThe task runners used by the shell that hosts this engine.
[in]settingsThe settings used to initialize the shell and the engine.
[in]animatorThe animator used to schedule frames.
[in]snapshot_delegateThe delegate used to fulfill requests to snapshot a specified scene. The engine cannot snapshot a scene on the UI thread directly because the scene (described via an SkPicture) may reference resources on the GPU and there is no GPU context current on the UI thread. The delegate is a component that has access to all the requisite GPU resources.
[in]io_managerThe IO manager used by this root isolate to schedule tasks that manage resources on the GPU.

Definition at line 59 of file engine.cc.

References flutter::Settings::advisory_script_entrypoint, flutter::Settings::advisory_script_uri, flutter::ImageDecoder::GetWeakPtr(), GetWeakPtr(), flutter::Settings::idle_notification_callback, flutter::Settings::isolate_create_callback, flutter::Settings::isolate_shutdown_callback, flutter::Settings::persistent_isolate_data, and ~Engine().

70  : Engine(delegate,
71  dispatcher_maker,
72  vm.GetConcurrentWorkerTaskRunner(),
73  task_runners,
74  settings,
75  std::move(animator),
76  io_manager,
77  nullptr) {
78  runtime_controller_ = std::make_unique<RuntimeController>(
79  *this, // runtime delegate
80  &vm, // VM
81  std::move(isolate_snapshot), // isolate snapshot
82  task_runners_, // task runners
83  std::move(snapshot_delegate), // snapshot delegate
84  GetWeakPtr(), // hint freed delegate
85  std::move(io_manager), // io manager
86  std::move(unref_queue), // Skia unref queue
87  image_decoder_.GetWeakPtr(), // image decoder
88  settings_.advisory_script_uri, // advisory script uri
89  settings_.advisory_script_entrypoint, // advisory script entrypoint
90  settings_.idle_notification_callback, // idle notification callback
91  platform_data, // platform data
92  settings_.isolate_create_callback, // isolate create callback
93  settings_.isolate_shutdown_callback, // isolate shutdown callback
94  settings_.persistent_isolate_data // persistent isolate data
95  );
96 }
std::string advisory_script_entrypoint
Definition: settings.h:124
fml::closure isolate_shutdown_callback
Definition: settings.h:181
Engine(Delegate &delegate, const PointerDataDispatcherMaker &dispatcher_maker, std::shared_ptr< fml::ConcurrentTaskRunner > image_decoder_task_runner, TaskRunners task_runners, Settings settings, std::unique_ptr< Animator > animator, fml::WeakPtr< IOManager > io_manager, std::unique_ptr< RuntimeController > runtime_controller)
Creates an instance of the engine with a supplied RuntimeController. Use the other constructor except...
Definition: engine.cc:38
std::string advisory_script_uri
Definition: settings.h:121
fml::closure isolate_create_callback
Definition: settings.h:177
fml::WeakPtr< Engine > GetWeakPtr() const
Definition: engine.cc:100
std::shared_ptr< const fml::Mapping > persistent_isolate_data
Definition: settings.h:229
fml::WeakPtr< ImageDecoder > GetWeakPtr() const
std::function< void(int64_t)> idle_notification_callback
Definition: settings.h:195

◆ ~Engine()

flutter::Engine::~Engine ( )
overridedefault

Destroys the engine engine. Called by the shell on the UI task runner. The running root isolate is terminated and will no longer access the task runner after this call returns. This allows the embedder to tear down the thread immediately if needed.

Referenced by Engine().

Member Function Documentation

◆ BeginFrame()

void flutter::Engine::BeginFrame ( fml::TimePoint  frame_time)

Notifies the engine that it is time to begin working on a new frame previously scheduled via a call to Engine::ScheduleFrame. This call originates in the animator.

The frame time given as the argument indicates the point at which the current frame interval began. It is very slightly (because of scheduling overhead) in the past. If a new layer tree is not produced and given to the GPU task runner within one frame interval from this point, the Flutter application will jank.

If a root isolate is running, this method calls the ::_beginFrame method in hooks.dart. If a root isolate is not running, this call does nothing.

This method encapsulates the entire UI thread frame workload. The following (mis)behavior in the functioning of the method will cause the jank in the Flutter application:

  • The time taken by this method to create a layer-tree exceeds on frame interval (for example, 16.66 ms on a 60Hz display).
  • The time take by this method to generate a new layer-tree causes the current layer-tree pipeline depth to change. To illustrate this point, note that maximum pipeline depth used by layer tree in the engine is 2. If both the UI and GPU task runner tasks finish within one frame interval, the pipeline depth is one. If the UI thread happens to be working on a frame when the raster thread is still not done with the previous frame, the pipeline depth is 2. When the pipeline depth changes from 1 to 2, animations and UI interactions that cause the generation of the new layer tree appropriate for (frame_time + one frame interval) will actually end up at (frame_time + two frame intervals). This is not what code running on the UI thread expected would happen. This causes perceptible jank.
Parameters
[in]frame_timeThe point at which the current frame interval began. May be used by animation interpolators, physics simulations, etc..

Definition at line 185 of file engine.cc.

References TRACE_EVENT0.

185  {
186  TRACE_EVENT0("flutter", "Engine::BeginFrame");
187  runtime_controller_->BeginFrame(frame_time);
188 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75

◆ DispatchPlatformMessage()

void flutter::Engine::DispatchPlatformMessage ( fml::RefPtr< PlatformMessage message)

Notifies the engine that the embedder has sent it a message. This call originates in the platform view and has been forwarded to the engine on the UI task runner here.

Parameters
[in]messageThe message sent from the embedder to the Dart application.

Definition at line 255 of file engine.cc.

References args, flutter::PlatformMessage::data(), FML_DLOG, fml::RefPtr< T >::get(), flutter::kNavigationChannel, and ScheduleFrame().

255  {
256  std::string channel = message->channel();
257  if (channel == kLifecycleChannel) {
258  if (HandleLifecyclePlatformMessage(message.get())) {
259  return;
260  }
261  } else if (channel == kLocalizationChannel) {
262  if (HandleLocalizationPlatformMessage(message.get())) {
263  return;
264  }
265  } else if (channel == kSettingsChannel) {
266  HandleSettingsPlatformMessage(message.get());
267  return;
268  } else if (!runtime_controller_->IsRootIsolateRunning() &&
269  channel == kNavigationChannel) {
270  // If there's no runtime_, we may still need to set the initial route.
271  HandleNavigationPlatformMessage(std::move(message));
272  return;
273  }
274 
275  if (runtime_controller_->IsRootIsolateRunning() &&
276  runtime_controller_->DispatchPlatformMessage(std::move(message))) {
277  return;
278  }
279 
280  FML_DLOG(WARNING) << "Dropping platform message on channel: " << channel;
281 }
static constexpr char kSettingsChannel[]
Definition: engine.cc:35
static constexpr char kNavigationChannel[]
Definition: engine.cc:33
T * get() const
Definition: ref_ptr.h:112
#define FML_DLOG(severity)
Definition: logging.h:85
static constexpr char kLocalizationChannel[]
Definition: engine.cc:34
static constexpr char kLifecycleChannel[]
Definition: engine.cc:32

◆ DispatchPointerDataPacket()

void flutter::Engine::DispatchPointerDataPacket ( std::unique_ptr< PointerDataPacket packet,
uint64_t  trace_flow_id 
)

Notifies the engine that the embedder has sent it a pointer data packet. A pointer data packet may contain multiple input events. This call originates in the platform view and the shell has forwarded the same to the engine on the UI task runner here.

Parameters
[in]packetThe pointer data packet containing multiple input events.
[in]trace_flow_idThe trace flow identifier associated with the pointer data packet. The engine uses this trace identifier to connect trace flows in the timeline from the input event event to the frames generated due to those input events. These flows are tagged as "PointerEvent" in the timeline and allow grouping frames and input events into logical chunks.

Definition at line 377 of file engine.cc.

References TRACE_EVENT0, and TRACE_FLOW_STEP.

379  {
380  TRACE_EVENT0("flutter", "Engine::DispatchPointerDataPacket");
381  TRACE_FLOW_STEP("flutter", "PointerEvent", trace_flow_id);
382  pointer_data_dispatcher_->DispatchPacket(std::move(packet), trace_flow_id);
383 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75
#define TRACE_FLOW_STEP(category, name, id)
Definition: trace_event.h:118

◆ DispatchSemanticsAction()

void flutter::Engine::DispatchSemanticsAction ( int  id,
SemanticsAction  action,
std::vector< uint8_t >  args 
)

Notifies the engine that the embedder encountered an accessibility related action on the specified node. This call originates on the platform view and has been forwarded to the engine here on the UI task runner by the shell.

Parameters
[in]idThe identifier of the accessibility node.
[in]actionThe accessibility related action performed on the node of the specified ID.
[in]argsOptional data that applies to the specified action.

Definition at line 385 of file engine.cc.

387  {
388  runtime_controller_->DispatchSemanticsAction(id, action, std::move(args));
389 }
G_BEGIN_DECLS FlValue * args
SemanticsAction action

◆ DoDispatchPacket()

void flutter::Engine::DoDispatchPacket ( std::unique_ptr< PointerDataPacket packet,
uint64_t  trace_flow_id 
)
overridevirtual

Actually dispatch the packet using Engine's animator_ and runtime_controller_.

Implements flutter::PointerDataDispatcher::Delegate.

Definition at line 469 of file engine.cc.

Referenced by ScheduleFrame().

470  {
471  animator_->EnqueueTraceFlowId(trace_flow_id);
472  if (runtime_controller_) {
473  runtime_controller_->DispatchPointerDataPacket(*packet);
474  }
475 }

◆ GetAssetManager()

std::shared_ptr< AssetManager > flutter::Engine::GetAssetManager ( )

Definition at line 109 of file engine.cc.

Referenced by ScheduleFrame().

109  {
110  return asset_manager_;
111 }

◆ GetFontCollection()

FontCollection & flutter::Engine::GetFontCollection ( )
overridevirtual

Implements flutter::RuntimeDelegate.

Definition at line 465 of file engine.cc.

Referenced by ScheduleFrame().

465  {
466  return font_collection_;
467 }

◆ GetLastEntrypoint()

const std::string & flutter::Engine::GetLastEntrypoint ( ) const

Get the last Entrypoint that was used in the RunConfiguration when |Engine::Run| was called.

Definition at line 502 of file engine.cc.

Referenced by ScheduleFrame().

502  {
503  return last_entry_point_;
504 }

◆ GetLastEntrypointLibrary()

const std::string & flutter::Engine::GetLastEntrypointLibrary ( ) const

Get the last Entrypoint Library that was used in the RunConfiguration when |Engine::Run| was called.

Definition at line 506 of file engine.cc.

Referenced by ScheduleFrame().

506  {
507  return last_entry_point_library_;
508 }

◆ GetUIIsolateLastError()

tonic::DartErrorHandleType flutter::Engine::GetUIIsolateLastError ( )

Errors that are unhandled on the Dart message loop are kept for further inspection till the next unhandled error comes along. This accessor returns the last unhandled error encountered by the root isolate.

Returns
The ui isolate last error.

Definition at line 223 of file engine.cc.

223  {
224  return runtime_controller_->GetLastError();
225 }

◆ GetUIIsolateMainPort()

Dart_Port flutter::Engine::GetUIIsolateMainPort ( )

Gets the main port of the root isolate. Since the isolate is created immediately in the constructor of the engine, it is possible to get its main port immediately (even before a call to Run can be made). This is useful in registering the port in a race free manner with a port nameserver.

Returns
The main port of the root isolate.

Definition at line 211 of file engine.cc.

211  {
212  return runtime_controller_->GetMainPort();
213 }

◆ GetUIIsolateName()

std::string flutter::Engine::GetUIIsolateName ( )

Gets the debug name of the root isolate. But default, the debug name of the isolate is derived from its advisory script URI, advisory main entrypoint and its main port name. For example, "main.dart$main-1234" where the script URI is "main.dart", the entrypoint is "main" and the port name "1234". Once launched, the isolate may re-christen itself using a name it selects via setIsolateDebugName in platform_dispatcher.dart. This name is purely advisory and only used by instrumentation and reporting purposes.

Returns
The debug name of the root isolate.

Definition at line 215 of file engine.cc.

215  {
216  return runtime_controller_->GetIsolateName();
217 }

◆ GetUIIsolateReturnCode()

std::optional< uint32_t > flutter::Engine::GetUIIsolateReturnCode ( )

As described in the discussion for UIIsolateHasLivePorts, the "done-ness" of a Dart application is tricky to ascertain and the return value from the main entrypoint is discarded (because the Dart isolate is still running after the main entrypoint returns). But, the concept of an exit code akin to those returned by native applications is still useful. Short lived Dart applications (usually tests), emulate this by setting a per isolate "return value" and then indicating their "done-ness" (usually via closing all live ports). This accessor returns that "return value" is present.

See also
UIIsolateHasLivePorts
Returns
The return code (if specified) by the isolate.

Definition at line 207 of file engine.cc.

207  {
208  return runtime_controller_->GetRootIsolateReturnCode();
209 }

◆ GetWeakPtr()

fml::WeakPtr< Engine > flutter::Engine::GetWeakPtr ( ) const
Returns
The pointer to this instance of the engine. The engine may only be accessed safely on the UI task runner.

Definition at line 100 of file engine.cc.

Referenced by Engine().

100  {
101  return weak_factory_.GetWeakPtr();
102 }

◆ HintFreed()

void flutter::Engine::HintFreed ( size_t  size)
overridevirtual

Notifies the engine that native bytes might be freed if a garbage collection ran at the next NotifyIdle period.

Parameters
[in]sizeThe number of bytes freed. This size adds to any previously supplied value, rather than replacing.

Implements flutter::HintFreedDelegate.

Definition at line 195 of file engine.cc.

References fml::size().

195  {
196  hint_freed_bytes_since_last_idle_ += size;
197 }
constexpr std::size_t size(T(&array)[N])
Definition: size.h:13

◆ InitialRoute()

const std::string& flutter::Engine::InitialRoute ( ) const
inline

Getter for the initial route. This can be set with a platform message.

Definition at line 768 of file engine.h.

References animator_, flutter::ComputePlatformResolvedLocale(), delegate_, name, runtime_controller_, settings_, task_runners_, and value.

768 { return initial_route_; }

◆ NotifyIdle()

void flutter::Engine::NotifyIdle ( int64_t  deadline)

Notifies the engine that the UI task runner is not expected to undertake a new frame workload till a specified timepoint. The timepoint is measured in microseconds against the system's monotonic clock. It is recommended that the clock be accessed via Dart_TimelineGetMicros from dart_api.h for consistency. In reality, the clocks used by Dart, FML and std::steady_clock are all the same and the timepoints can be converted from on clock type to another.

The Dart VM uses this notification to schedule book-keeping tasks that may include a garbage collection. In this way, it is less likely for the VM to perform such (potentially long running) tasks in the middle of a frame workload.

This notification is advisory. That is, not providing this notification does not mean garbage collection is postponed till this call is made. If this notification is not provided, garbage collection will happen based on the usual heuristics used by the Dart VM.

Currently, this idle notification is delivered to the engine at two points. Once, the deadline is calculated based on how much time in the current frame interval is left on the UI task runner. Since the next frame workload cannot begin till at least the next callback from the vsync waiter, this period may be used to used as a "small" idle notification. On the other hand, if no more frames are scheduled, a large (but arbitrary) idle notification deadline is chosen for a "big" idle notification. Again, this notification does not guarantee collection, just gives the Dart VM more hints about opportune moments to perform collections.

Parameters
[in]deadlineThe deadline as a timepoint in microseconds measured against the system monotonic clock. Use Dart_TimelineGetMicros(), for consistency.

Definition at line 199 of file engine.cc.

References TRACE_EVENT1.

199  {
200  auto trace_event = std::to_string(deadline - Dart_TimelineGetMicros());
201  TRACE_EVENT1("flutter", "Engine::NotifyIdle", "deadline_now_delta",
202  trace_event.c_str());
203  runtime_controller_->NotifyIdle(deadline, hint_freed_bytes_since_last_idle_);
204  hint_freed_bytes_since_last_idle_ = 0;
205 }
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
Definition: trace_event.h:79

◆ OnOutputSurfaceCreated()

void flutter::Engine::OnOutputSurfaceCreated ( )

Indicates to the Flutter application that it has obtained a rendering surface. This is a good opportunity for the engine to start servicing any outstanding frame requests from the Flutter applications. Flutter application that have no rendering concerns may never get a rendering surface. In such cases, while their root isolate can perform as normal, any frame requests made by them will never be serviced and layer trees produced outside of frame workloads will be dropped.

Very close to when this call is made, the application can expect the updated viewport metrics. Rendering only begins when the Flutter application gets an output surface and a valid set of viewport metrics.

See also
OnOutputSurfaceDestroyed

Definition at line 227 of file engine.cc.

References ScheduleFrame().

227  {
228  have_surface_ = true;
229  StartAnimatorIfPossible();
230  ScheduleFrame();
231 }
void ScheduleFrame()
Definition: engine.h:737

◆ OnOutputSurfaceDestroyed()

void flutter::Engine::OnOutputSurfaceDestroyed ( )

Indicates to the Flutter application that a previously acquired rendering surface has been lost. Further frame requests will no longer be serviced and any layer tree submitted for rendering will be dropped. If/when a new surface is acquired, a new layer tree must be generated.

See also
OnOutputSurfaceCreated

Definition at line 233 of file engine.cc.

233  {
234  have_surface_ = false;
235  StopAnimator();
236 }

◆ ReportTimings()

void flutter::Engine::ReportTimings ( std::vector< int64_t >  timings)

Dart code cannot fully measure the time it takes for a specific frame to be rendered. This is because Dart code only runs on the UI task runner. That is only a small part of the overall frame workload. The GPU task runner frame workload is executed on a thread where Dart code cannot run (and hence instrument). Besides, due to the pipelined nature of rendering in Flutter, there may be multiple frame workloads being processed at any given time. However, for non-Timeline based profiling, it is useful for trace collection and processing to happen in Dart. To do this, the GPU task runner frame workloads need to be instrumented separately. After a set number of these profiles have been gathered, they need to be reported back to Dart code. The shell reports this extra instrumentation information back to Dart code running on the engine by invoking this method at predefined intervals.

See also
FrameTiming
Parameters
[in]timingsCollection of FrameTiming::kCount * n timestamps for n frames whose timings have not been reported yet. A collection of integers is reported here for easier conversions to Dart objects. The timestamps are measured against the system monotonic clock measured in microseconds.

Definition at line 190 of file engine.cc.

References TRACE_EVENT0.

190  {
191  TRACE_EVENT0("flutter", "Engine::ReportTimings");
192  runtime_controller_->ReportTimings(std::move(timings));
193 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75

◆ Restart()

bool flutter::Engine::Restart ( RunConfiguration  configuration)

Tears down an existing root isolate, reuses the components of that isolate and attempts to launch a new isolate using the given the run configuration. This is only used in the "debug" Flutter runtime mode in the cold-restart scenario.

Attention
This operation must be performed with care as even a non-successful restart will still tear down any existing root isolate. In such cases, the engine and its shell must be discarded.
Parameters
[in]configurationThe configuration used to launch the new isolate.
Returns
Whether the restart was successful. If not, the engine and its shell must be discarded.

Definition at line 135 of file engine.cc.

References FML_LOG, flutter::RunConfiguration::IsValid(), flutter::Engine::Delegate::OnPreEngineRestart(), Run(), Success, TRACE_EVENT0, and UpdateAssetManager().

135  {
136  TRACE_EVENT0("flutter", "Engine::Restart");
137  if (!configuration.IsValid()) {
138  FML_LOG(ERROR) << "Engine run configuration was invalid.";
139  return false;
140  }
141  delegate_.OnPreEngineRestart();
142  runtime_controller_ = runtime_controller_->Clone();
143  UpdateAssetManager(nullptr);
144  return Run(std::move(configuration)) == Engine::RunStatus::Success;
145 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75
#define FML_LOG(severity)
Definition: logging.h:65
virtual void OnPreEngineRestart()=0
Notifies the delegate that the root isolate of the application is about to be discarded and a new iso...
bool UpdateAssetManager(std::shared_ptr< AssetManager > asset_manager)
Updates the asset manager referenced by the root isolate of a Flutter application. This happens implicitly in the call to Engine::Run and Engine::Restart as the asset manager is referenced from the run configuration provided to those calls. In addition to the Engine::Run and Engine::Restart calls, the tooling may need to update the assets available to the application as the user adds them to their project. For example, these assets may be referenced by code that is newly patched in after a hot-reload. Neither the shell or the isolate in relaunched in such cases. The tooling usually patches in the new assets in a temporary location and updates the asset manager to point to that location.
Definition: engine.cc:113
RunStatus Run(RunConfiguration configuration)
Moves the root isolate to the DartIsolate::Phase::Running phase on a successful call to this method...
Definition: engine.cc:147

◆ Run()

Engine::RunStatus flutter::Engine::Run ( RunConfiguration  configuration)

Moves the root isolate to the DartIsolate::Phase::Running phase on a successful call to this method.

The isolate itself is created when the engine is created, but it is not yet in the running phase. This is done to amortize initial time taken to launch the root isolate. The isolate snapshots used to run the isolate can be fetched on another thread while the engine itself is launched on the UI task runner.

Repeated calls to this method after a successful run will be rejected even if the run configuration is valid (with the appropriate error returned).

Parameters
[in]configurationThe configuration used to run the root isolate. The configuration must be valid.
Returns
The result of the call to run the root isolate.

Definition at line 147 of file engine.cc.

References Failure, FailureAlreadyRunning, FML_LOG, flutter::RunConfiguration::GetAssetManager(), flutter::RunConfiguration::GetEntrypoint(), flutter::RunConfiguration::GetEntrypointLibrary(), flutter::RunConfiguration::IsValid(), flutter::kIsolateChannel, Success, flutter::RunConfiguration::TakeIsolateConfiguration(), and UpdateAssetManager().

Referenced by Restart().

147  {
148  if (!configuration.IsValid()) {
149  FML_LOG(ERROR) << "Engine run configuration was invalid.";
150  return RunStatus::Failure;
151  }
152 
153  last_entry_point_ = configuration.GetEntrypoint();
154  last_entry_point_library_ = configuration.GetEntrypointLibrary();
155 
156  UpdateAssetManager(configuration.GetAssetManager());
157 
158  if (runtime_controller_->IsRootIsolateRunning()) {
160  }
161 
162  if (!runtime_controller_->LaunchRootIsolate(
163  settings_, //
164  configuration.GetEntrypoint(), //
165  configuration.GetEntrypointLibrary(), //
166  configuration.TakeIsolateConfiguration()) //
167  ) {
168  return RunStatus::Failure;
169  }
170 
171  auto service_id = runtime_controller_->GetRootIsolateServiceID();
172  if (service_id.has_value()) {
173  fml::RefPtr<PlatformMessage> service_id_message =
174  fml::MakeRefCounted<flutter::PlatformMessage>(
176  std::vector<uint8_t>(service_id.value().begin(),
177  service_id.value().end()),
178  nullptr);
179  HandlePlatformMessage(service_id_message);
180  }
181 
183 }
static constexpr char kIsolateChannel[]
Definition: engine.cc:36
#define FML_LOG(severity)
Definition: logging.h:65
bool UpdateAssetManager(std::shared_ptr< AssetManager > asset_manager)
Updates the asset manager referenced by the root isolate of a Flutter application. This happens implicitly in the call to Engine::Run and Engine::Restart as the asset manager is referenced from the run configuration provided to those calls. In addition to the Engine::Run and Engine::Restart calls, the tooling may need to update the assets available to the application as the user adds them to their project. For example, these assets may be referenced by code that is newly patched in after a hot-reload. Neither the shell or the isolate in relaunched in such cases. The tooling usually patches in the new assets in a temporary location and updates the asset manager to point to that location.
Definition: engine.cc:113

◆ ScheduleFrame() [1/2]

◆ ScheduleFrame() [2/2]

void flutter::Engine::ScheduleFrame ( )
inline

Schedule a frame with the default parameter of regenerating the layer tree.

Definition at line 737 of file engine.h.

References DoDispatchPacket(), GetAssetManager(), GetFontCollection(), GetLastEntrypoint(), GetLastEntrypointLibrary(), ScheduleFrame(), and ScheduleSecondaryVsyncCallback().

Referenced by DispatchPlatformMessage(), OnOutputSurfaceCreated(), ScheduleFrame(), and SetViewportMetrics().

737 { ScheduleFrame(true); }
void ScheduleFrame()
Definition: engine.h:737

◆ ScheduleSecondaryVsyncCallback()

void flutter::Engine::ScheduleSecondaryVsyncCallback ( const fml::closure callback)
overridevirtual

Schedule a secondary callback to be executed right after the main VsyncWaiter::AsyncWaitForVsync callback (which is added by Animator::RequestFrame).

Like the callback in AsyncWaitForVsync, this callback is only scheduled to be called once, and it will be called in the UI thread. If there is no AsyncWaitForVsync callback (Animator::RequestFrame is not called), this secondary callback will still be executed at vsync.

This callback is used to provide the vsync signal needed by SmoothPointerDataDispatcher.

Implements flutter::PointerDataDispatcher::Delegate.

Definition at line 477 of file engine.cc.

Referenced by ScheduleFrame().

477  {
478  animator_->ScheduleSecondaryVsyncCallback(callback);
479 }

◆ SetAccessibilityFeatures()

void flutter::Engine::SetAccessibilityFeatures ( int32_t  flags)

Notifies the engine that the embedder has expressed an opinion about where the flags to set on the accessibility tree. This flag originates in the platform view and is forwarded to the engine here on the UI task runner by the shell.

The engine does not care about the accessibility feature flags as all it does is forward this information from the embedder to the framework. However, curious readers may refer to AccessibilityFeatures in window.dart for currently supported accessibility feature flags.

Parameters
[in]flagsThe features to enable in the accessibility tree.

Definition at line 395 of file engine.cc.

395  {
396  runtime_controller_->SetAccessibilityFeatures(flags);
397 }
DEF_SWITCHES_START snapshot asset Path to the directory containing the four files specified by VmSnapshotInstructions and IsolateSnapshotInstructions vm snapshot The VM instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present isolate snapshot The isolate instructions snapshot that will be memory mapped as read and executable SnapshotAssetPath must be present icu symbol Prefix for the symbols representing ICU data linked into the Flutter library dart flags
Definition: switches.h:66

◆ SetSemanticsEnabled()

void flutter::Engine::SetSemanticsEnabled ( bool  enabled)

Notifies the engine that the embedder has expressed an opinion about whether the accessibility tree should be generated or not. This call originates in the platform view and is forwarded to the engine here on the UI task runner by the shell.

Parameters
[in]enabledWhether the accessibility tree is enabled or disabled.

Definition at line 391 of file engine.cc.

391  {
392  runtime_controller_->SetSemanticsEnabled(enabled);
393 }

◆ SetupDefaultFontManager()

void flutter::Engine::SetupDefaultFontManager ( )

Setup default font manager according to specific platform.

Definition at line 104 of file engine.cc.

References flutter::FontCollection::SetupDefaultFontManager(), and TRACE_EVENT0.

104  {
105  TRACE_EVENT0("flutter", "Engine::SetupDefaultFontManager");
106  font_collection_.SetupDefaultFontManager();
107 }
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:75

◆ SetViewportMetrics()

void flutter::Engine::SetViewportMetrics ( const ViewportMetrics metrics)

Updates the viewport metrics for the currently running Flutter application. The viewport metrics detail the size of the rendering viewport in texels as well as edge insets if present.

See also
ViewportMetrics
Parameters
[in]metricsThe metrics

Definition at line 238 of file engine.cc.

References flutter::ViewportMetrics::device_pixel_ratio, flutter::ViewportMetrics::physical_height, flutter::ViewportMetrics::physical_width, and ScheduleFrame().

238  {
239  bool dimensions_changed =
240  viewport_metrics_.physical_height != metrics.physical_height ||
241  viewport_metrics_.physical_width != metrics.physical_width ||
242  viewport_metrics_.device_pixel_ratio != metrics.device_pixel_ratio;
243  viewport_metrics_ = metrics;
244  runtime_controller_->SetViewportMetrics(viewport_metrics_);
245  if (animator_) {
246  if (dimensions_changed) {
247  animator_->SetDimensionChangePending();
248  }
249  if (have_surface_) {
250  ScheduleFrame();
251  }
252  }
253 }
void ScheduleFrame()
Definition: engine.h:737

◆ UIIsolateHasLivePorts()

bool flutter::Engine::UIIsolateHasLivePorts ( )

It is an unexpected challenge to determine when a Dart application is "done". The application cannot simply terminate the native process (and perhaps return an exit code) because it does not have that power. After all, Flutter applications reside within a host process that may have other responsibilities besides just running Flutter applications. Also, the main entry-points are run on an event loop and returning from "main" (unlike in C/C++ applications) does not mean termination of the process. Besides, the return value of the main entrypoint is discarded.

One technique used by embedders to determine "liveness" is to count the outstanding live ports dedicated to the application. These ports may be live as a result of pending timers, scheduled tasks, pending IO on sockets, channels open with other isolates, etc.. At regular intervals (sometimes as often as after the UI task runner processes any task), embedders may check for the "liveness" of the application and perform teardown of the embedder when no more ports are live.

Returns
Check if the root isolate has any live ports.

Definition at line 219 of file engine.cc.

219  {
220  return runtime_controller_->HasLivePorts();
221 }

◆ UpdateAssetManager()

bool flutter::Engine::UpdateAssetManager ( std::shared_ptr< AssetManager asset_manager)

Updates the asset manager referenced by the root isolate of a Flutter application. This happens implicitly in the call to Engine::Run and Engine::Restart as the asset manager is referenced from the run configuration provided to those calls. In addition to the Engine::Run and Engine::Restart calls, the tooling may need to update the assets available to the application as the user adds them to their project. For example, these assets may be referenced by code that is newly patched in after a hot-reload. Neither the shell or the isolate in relaunched in such cases. The tooling usually patches in the new assets in a temporary location and updates the asset manager to point to that location.

Parameters
[in]asset_managerThe new asset manager to use for the running root isolate.
Returns
If the asset manager was successfully replaced. This may fail if the new asset manager is invalid.

Definition at line 113 of file engine.cc.

References flutter::FontCollection::RegisterFonts(), flutter::FontCollection::RegisterTestFonts(), and flutter::Settings::use_test_fonts.

Referenced by Restart(), and Run().

114  {
115  if (asset_manager_ == new_asset_manager) {
116  return false;
117  }
118 
119  asset_manager_ = new_asset_manager;
120 
121  if (!asset_manager_) {
122  return false;
123  }
124 
125  // Using libTXT as the text engine.
126  font_collection_.RegisterFonts(asset_manager_);
127 
128  if (settings_.use_test_fonts) {
129  font_collection_.RegisterTestFonts();
130  }
131 
132  return true;
133 }
void RegisterFonts(std::shared_ptr< AssetManager > asset_manager)

Friends And Related Function Documentation

◆ testing::ShellTest

friend class testing::ShellTest
friend

Definition at line 836 of file engine.h.


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