mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Supplant the temporary solution https://github.com/flutter/engine/pull/44238 with a more elegant solution with am embedder API callback. The windows engine provides a callback that enables graceful exit and app lifecycle when the platform and lifecycle channels are listened to, respectively. https://github.com/flutter/flutter/issues/131616 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat --------- Co-authored-by: Chris Bracken <chris@bracken.jp>
1041 lines
54 KiB
C++
1041 lines
54 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef SHELL_COMMON_ENGINE_H_
|
|
#define SHELL_COMMON_ENGINE_H_
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "flutter/assets/asset_manager.h"
|
|
#include "flutter/common/task_runners.h"
|
|
#include "flutter/fml/macros.h"
|
|
#include "flutter/fml/mapping.h"
|
|
#include "flutter/fml/memory/weak_ptr.h"
|
|
#include "flutter/lib/ui/painting/image_decoder.h"
|
|
#include "flutter/lib/ui/painting/image_generator_registry.h"
|
|
#include "flutter/lib/ui/semantics/custom_accessibility_action.h"
|
|
#include "flutter/lib/ui/semantics/semantics_node.h"
|
|
#include "flutter/lib/ui/snapshot_delegate.h"
|
|
#include "flutter/lib/ui/text/font_collection.h"
|
|
#include "flutter/lib/ui/volatile_path_tracker.h"
|
|
#include "flutter/lib/ui/window/platform_message.h"
|
|
#include "flutter/lib/ui/window/viewport_metrics.h"
|
|
#include "flutter/runtime/dart_vm.h"
|
|
#include "flutter/runtime/runtime_controller.h"
|
|
#include "flutter/runtime/runtime_delegate.h"
|
|
#include "flutter/shell/common/animator.h"
|
|
#include "flutter/shell/common/display_manager.h"
|
|
#include "flutter/shell/common/platform_view.h"
|
|
#include "flutter/shell/common/pointer_data_dispatcher.h"
|
|
#include "flutter/shell/common/rasterizer.h"
|
|
#include "flutter/shell/common/run_configuration.h"
|
|
#include "flutter/shell/common/shell_io_manager.h"
|
|
|
|
namespace flutter {
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// 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 `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.
|
|
///
|
|
class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
|
public:
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Indicates the result of the call to `Engine::Run`.
|
|
///
|
|
enum class RunStatus {
|
|
//--------------------------------------------------------------------------
|
|
/// 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.
|
|
///
|
|
Success,
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// 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" an
|
|
/// 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.
|
|
///
|
|
FailureAlreadyRunning,
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// 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 were given 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 set
|
|
/// up.
|
|
/// * 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
|
|
/// `@pragma('vm:entry-point')` directive. This problem will manifest in
|
|
/// AOT mode operation of the Dart VM.
|
|
///
|
|
Failure,
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
class Delegate {
|
|
public:
|
|
//--------------------------------------------------------------------------
|
|
/// @brief When the accessibility tree has been updated by the Flutter
|
|
/// application, this new information needs to be conveyed to
|
|
/// the underlying platform. The engine delegates this task to
|
|
/// the shell via this call. The engine cannot access the
|
|
/// underlying platform directly because of threading
|
|
/// considerations. Most platform specific APIs to convey
|
|
/// accessibility information are only safe to access on the
|
|
/// platform task runner while the engine is running on the UI
|
|
/// task runner.
|
|
///
|
|
/// @see `SemanticsNode`, `SemanticsNodeUpdates`,
|
|
/// `CustomAccessibilityActionUpdates`,
|
|
/// `PlatformView::UpdateSemantics`
|
|
///
|
|
/// @param[in] updates A map with the stable semantics node identifier as
|
|
/// key and the node properties as the value.
|
|
/// @param[in] actions A map with the stable semantics node identifier as
|
|
/// key and the custom node action as the value.
|
|
///
|
|
virtual void OnEngineUpdateSemantics(
|
|
SemanticsNodeUpdates updates,
|
|
CustomAccessibilityActionUpdates actions) = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief When the Flutter application has a message to send to the
|
|
/// underlying platform, the message needs to be forwarded to
|
|
/// the platform on the appropriate thread (via the platform
|
|
/// task runner). The engine delegates this task to the shell
|
|
/// via this method.
|
|
///
|
|
/// @see `PlatformView::HandlePlatformMessage`
|
|
///
|
|
/// @param[in] message The message from the Flutter application to send to
|
|
/// the underlying platform.
|
|
///
|
|
virtual void OnEngineHandlePlatformMessage(
|
|
std::unique_ptr<PlatformMessage> message) = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Notifies the delegate that the root isolate of the
|
|
/// application is about to be discarded and a new isolate with
|
|
/// the same runtime started in its place. This should only
|
|
/// happen in the Flutter "debug" runtime mode in the
|
|
/// cold-restart scenario. The embedder may need to reset native
|
|
/// resource in response to the restart.
|
|
///
|
|
/// @see `PlatformView::OnPreEngineRestart`
|
|
///
|
|
virtual void OnPreEngineRestart() = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Notifies the shell that the root isolate is created.
|
|
/// Currently, this information is to add to the service
|
|
/// protocol list of available root isolates running in the VM
|
|
/// and their names so that the appropriate isolate can be
|
|
/// selected in the tools for debugging and instrumentation.
|
|
///
|
|
virtual void OnRootIsolateCreated() = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Notifies the shell of the name of the root isolate and its
|
|
/// port when that isolate is launched, restarted (in the
|
|
/// cold-restart scenario) or the application itself updates the
|
|
/// name of the root isolate (via
|
|
/// `PlatformDispatcher.setIsolateDebugName` in
|
|
/// `platform_dispatcher.dart`). The name of the isolate is
|
|
/// meaningless to the engine but is used in instrumentation and
|
|
/// tooling. Currently, this information is to update the
|
|
/// service protocol list of available root isolates running in
|
|
/// the VM and their names so that the appropriate isolate can
|
|
/// be selected in the tools for debugging and instrumentation.
|
|
///
|
|
/// @param[in] isolate_name The isolate name
|
|
/// @param[in] isolate_port The isolate port
|
|
///
|
|
virtual void UpdateIsolateDescription(const std::string isolate_name,
|
|
int64_t isolate_port) = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Notifies the shell that the application has an opinion about
|
|
/// whether its frame timings need to be reported backed to it.
|
|
/// Due to the asynchronous nature of rendering in Flutter, it
|
|
/// is not possible for the application to determine the total
|
|
/// time it took to render a specific frame. While the
|
|
/// layer-tree is constructed on the UI thread, it needs to be
|
|
/// rendering on the raster thread. Dart code cannot execute on
|
|
/// this thread. So any instrumentation about the frame times
|
|
/// gathered on this thread needs to be aggregated and sent back
|
|
/// to the UI thread for processing in Dart.
|
|
///
|
|
/// When the application indicates that frame times need to be
|
|
/// reported, it collects this information till a specified
|
|
/// number of data points are gathered. Then this information is
|
|
/// sent back to Dart code via `Engine::ReportTimings`.
|
|
///
|
|
/// This option is engine counterpart of the
|
|
/// `Window._setNeedsReportTimings` in `window.dart`.
|
|
///
|
|
/// @param[in] needs_reporting If reporting information should be
|
|
/// collected and send back to Dart.
|
|
///
|
|
virtual void SetNeedsReportTimings(bool needs_reporting) = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Directly invokes platform-specific APIs to compute the
|
|
/// locale the platform would have natively resolved to.
|
|
///
|
|
/// @param[in] supported_locale_data The vector of strings that represents
|
|
/// the locales supported by the app.
|
|
/// Each locale consists of three
|
|
/// strings: languageCode, countryCode,
|
|
/// and scriptCode in that order.
|
|
///
|
|
/// @return A vector of 3 strings languageCode, countryCode, and
|
|
/// scriptCode that represents the locale selected by the
|
|
/// platform. Empty strings mean the value was unassigned. Empty
|
|
/// vector represents a null locale.
|
|
///
|
|
virtual std::unique_ptr<std::vector<std::string>>
|
|
ComputePlatformResolvedLocale(
|
|
const std::vector<std::string>& supported_locale_data) = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Invoked when the Dart VM requests that a deferred library
|
|
/// be loaded. Notifies the engine that the deferred library
|
|
/// identified by the specified loading unit id should be
|
|
/// downloaded and loaded into the Dart VM via
|
|
/// `LoadDartDeferredLibrary`
|
|
///
|
|
/// Upon encountering errors or otherwise failing to load a
|
|
/// loading unit with the specified id, the failure should be
|
|
/// directly reported to dart by calling
|
|
/// `LoadDartDeferredLibraryFailure` to ensure the waiting dart
|
|
/// future completes with an error.
|
|
///
|
|
/// @param[in] loading_unit_id The unique id of the deferred library's
|
|
/// loading unit. This id is to be passed
|
|
/// back into LoadDartDeferredLibrary
|
|
/// in order to identify which deferred
|
|
/// library to load.
|
|
///
|
|
virtual void RequestDartDeferredLibrary(intptr_t loading_unit_id) = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Returns the current fml::TimePoint.
|
|
/// This method is primarily provided to allow tests to control
|
|
/// Any methods that rely on advancing the clock.
|
|
virtual fml::TimePoint GetCurrentTimePoint() = 0;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Returns the delegate object that handles PlatformMessage's from
|
|
/// Flutter to the host platform (and its responses).
|
|
virtual const std::shared_ptr<PlatformMessageHandler>&
|
|
GetPlatformMessageHandler() const = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Invoked when a listener is registered on a platform channel.
|
|
///
|
|
/// @param[in] name The name of the platform channel to which a
|
|
/// listener has been registered or cleared.
|
|
///
|
|
/// @param[in] listening Whether the listener has been set (true) or
|
|
/// cleared (false).
|
|
///
|
|
virtual void OnEngineChannelUpdate(std::string name, bool listening) = 0;
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Synchronously invokes platform-specific APIs to apply the
|
|
/// system text scaling on the given unscaled font size.
|
|
///
|
|
/// Platforms that support this feature (currently it's only
|
|
/// implemented for Android SDK level 34+) will send a valid
|
|
/// configuration_id to potential callers, before this method
|
|
/// can be called.
|
|
///
|
|
/// @param[in] unscaled_font_size The unscaled font size specified by the
|
|
/// app developer. The value is in logical
|
|
/// pixels, and is guaranteed to be finite
|
|
/// and non-negative.
|
|
/// @param[in] configuration_id The unique id of the configuration to
|
|
/// use for computing the scaled font size.
|
|
///
|
|
/// @return The scaled font size in logical pixels, or -1 when the given
|
|
/// configuration_id did not match a valid configuration.
|
|
///
|
|
virtual double GetScaledFontSize(double unscaled_font_size,
|
|
int configuration_id) const = 0;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Creates an instance of the engine with a supplied
|
|
/// `RuntimeController`. Use the other constructor except for
|
|
/// tests.
|
|
///
|
|
Engine(Delegate& delegate,
|
|
const PointerDataDispatcherMaker& dispatcher_maker,
|
|
std::shared_ptr<fml::ConcurrentTaskRunner> image_decoder_task_runner,
|
|
const TaskRunners& task_runners,
|
|
const Settings& settings,
|
|
std::unique_ptr<Animator> animator,
|
|
fml::WeakPtr<IOManager> io_manager,
|
|
const std::shared_ptr<FontCollection>& font_collection,
|
|
std::unique_ptr<RuntimeController> runtime_controller,
|
|
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Creates an instance of the engine. This is done by the Shell
|
|
/// on the UI task runner.
|
|
///
|
|
/// @param delegate The 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.
|
|
/// @param dispatcher_maker The 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.
|
|
/// @param vm An instance of the running Dart VM.
|
|
/// @param[in] isolate_snapshot The 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.
|
|
// TODO(chinmaygarde): This is probably redundant now that the IO manager is
|
|
// it's own object.
|
|
/// @param[in] task_runners The task runners used by the shell that
|
|
/// hosts this engine.
|
|
/// @param[in] settings The settings used to initialize the shell
|
|
/// and the engine.
|
|
/// @param[in] animator The animator used to schedule frames.
|
|
// TODO(chinmaygarde): Move this to `Engine::Delegate`
|
|
/// @param[in] snapshot_delegate The 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
|
|
/// a `DisplayList`) 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.
|
|
/// @param[in] io_manager The IO manager used by this root isolate to
|
|
/// schedule tasks that manage resources on the
|
|
/// GPU.
|
|
///
|
|
Engine(Delegate& delegate,
|
|
const PointerDataDispatcherMaker& dispatcher_maker,
|
|
DartVM& vm,
|
|
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
|
const TaskRunners& task_runners,
|
|
const PlatformData& platform_data,
|
|
const Settings& settings,
|
|
std::unique_ptr<Animator> animator,
|
|
fml::WeakPtr<IOManager> io_manager,
|
|
fml::RefPtr<SkiaUnrefQueue> unref_queue,
|
|
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
|
|
std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
|
|
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Create a Engine that shares as many resources as
|
|
/// possible with the calling Engine such that together
|
|
/// they occupy less memory and be created faster.
|
|
/// @details This should only be called on running Engines.
|
|
/// @return A new Engine with a running isolate.
|
|
/// @see Engine::Engine
|
|
/// @see DartIsolate::SpawnIsolate
|
|
///
|
|
std::unique_ptr<Engine> Spawn(
|
|
Delegate& delegate,
|
|
const PointerDataDispatcherMaker& dispatcher_maker,
|
|
const Settings& settings,
|
|
std::unique_ptr<Animator> animator,
|
|
const std::string& initial_route,
|
|
const fml::WeakPtr<IOManager>& io_manager,
|
|
fml::TaskRunnerAffineWeakPtr<SnapshotDelegate> snapshot_delegate,
|
|
const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) const;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
~Engine() override;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @return The pointer to this instance of the engine. The engine may
|
|
/// only be accessed safely on the UI task runner.
|
|
///
|
|
fml::WeakPtr<Engine> GetWeakPtr() const;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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).
|
|
///
|
|
/// @param[in] configuration The configuration used to run the root isolate.
|
|
/// The configuration must be valid.
|
|
///
|
|
/// @return The result of the call to run the root isolate.
|
|
///
|
|
[[nodiscard]] RunStatus Run(RunConfiguration configuration);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @param[in] configuration The configuration used to launch the new
|
|
/// isolate.
|
|
///
|
|
/// @return Whether the restart was successful. If not, the engine and its
|
|
/// shell must be discarded.
|
|
///
|
|
[[nodiscard]] bool Restart(RunConfiguration configuration);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Setup default font manager according to specific platform.
|
|
///
|
|
void SetupDefaultFontManager();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @param[in] asset_manager The new asset manager to use for the running
|
|
/// root isolate.
|
|
///
|
|
/// @return If the asset manager was successfully replaced. This may fail
|
|
/// if the new asset manager is invalid.
|
|
///
|
|
bool UpdateAssetManager(const std::shared_ptr<AssetManager>& asset_manager);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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 raster 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
|
|
/// one 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.
|
|
///
|
|
/// @param[in] frame_time The point at which the current frame interval
|
|
/// began. May be used by animation interpolators,
|
|
/// physics simulations, etc..
|
|
///
|
|
/// @param[in] frame_number The frame number recorded by the animator. Used
|
|
/// by the framework to associate frame specific
|
|
/// debug information with frame timings and timeline
|
|
/// events.
|
|
void BeginFrame(fml::TimePoint frame_time, uint64_t frame_number);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
///
|
|
/// @param[in] deadline The deadline is used by the VM to determine if the
|
|
/// corresponding sweep can be performed within the
|
|
/// deadline.
|
|
///
|
|
void NotifyIdle(fml::TimeDelta deadline);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Notifies the engine that the attached flutter view has been
|
|
/// destroyed.
|
|
/// This enables the engine to notify the Dart VM so it can do
|
|
/// some cleanp activities.
|
|
void NotifyDestroyed();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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 raster 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 raster 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 `FrameTiming`
|
|
///
|
|
// TODO(chinmaygarde): The use `int64_t` is added for ease of conversion to
|
|
// Dart but hurts readability. The phases and the units of the timepoints are
|
|
// not obvious without some sleuthing. The conversion can happen at the
|
|
// native interface boundary instead.
|
|
///
|
|
/// @param[in] timings Collection 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.
|
|
///
|
|
void ReportTimings(std::vector<int64_t> timings);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @return The main port of the root isolate.
|
|
///
|
|
Dart_Port GetUIIsolateMainPort();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Gets the debug name of the root isolate. By 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.
|
|
///
|
|
/// @return The debug name of the root isolate.
|
|
///
|
|
std::string GetUIIsolateName();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @return Check if the root isolate has any live ports.
|
|
///
|
|
bool UIIsolateHasLivePorts();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @return The ui isolate last error.
|
|
///
|
|
tonic::DartErrorHandleType GetUIIsolateLastError();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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 `UIIsolateHasLivePorts`
|
|
///
|
|
/// @return The return code (if specified) by the isolate.
|
|
///
|
|
std::optional<uint32_t> GetUIIsolateReturnCode();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Notify the Flutter application that a new view is available.
|
|
///
|
|
/// A view must be added before other methods can refer to it,
|
|
/// including the implicit view. Adding a view that already exists
|
|
/// triggers an assertion.
|
|
///
|
|
/// @param[in] view_id The ID of the new view.
|
|
/// @param[in] viewport_metrics The initial viewport metrics for the view.
|
|
///
|
|
void AddView(int64_t view_id, const ViewportMetrics& view_metrics);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Notify the Flutter application that a view is no
|
|
/// longer available.
|
|
///
|
|
/// Removing a view that does not exist triggers an assertion.
|
|
///
|
|
/// The implicit view (kFlutterImplicitViewId) should never be
|
|
/// removed. Doing so triggers an assertion.
|
|
///
|
|
/// @param[in] view_id The ID of the view.
|
|
///
|
|
void RemoveView(int64_t view_id);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Updates the viewport metrics for a view. The viewport metrics
|
|
/// detail the size of the rendering viewport in texels as well as
|
|
/// edge insets if present.
|
|
///
|
|
/// @see `ViewportMetrics`
|
|
///
|
|
/// @param[in] view_id The ID for the view that `metrics` describes.
|
|
/// @param[in] metrics The metrics.
|
|
///
|
|
void SetViewportMetrics(int64_t view_id, const ViewportMetrics& metrics);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Updates the display metrics for the currently running Flutter
|
|
/// application.
|
|
///
|
|
/// @param[in] displays A complete list of displays
|
|
///
|
|
void SetDisplays(const std::vector<DisplayData>& displays);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @param[in] message The message sent from the embedder to the Dart
|
|
/// application.
|
|
///
|
|
void DispatchPlatformMessage(std::unique_ptr<PlatformMessage> message);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @param[in] packet The pointer data packet containing multiple
|
|
/// input events.
|
|
/// @param[in] trace_flow_id The 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 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.
|
|
///
|
|
void DispatchPointerDataPacket(std::unique_ptr<PointerDataPacket> packet,
|
|
uint64_t trace_flow_id);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @param[in] node_id The identifier of the accessibility node.
|
|
/// @param[in] action The accessibility related action performed on the
|
|
/// node of the specified ID.
|
|
/// @param[in] args Optional data that applies to the specified action.
|
|
///
|
|
void DispatchSemanticsAction(int node_id,
|
|
SemanticsAction action,
|
|
fml::MallocMapping args);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @param[in] enabled Whether the accessibility tree is enabled or
|
|
/// disabled.
|
|
///
|
|
void SetSemanticsEnabled(bool enabled);
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief 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.
|
|
///
|
|
/// @param[in] flags The features to enable in the accessibility tree.
|
|
///
|
|
void SetAccessibilityFeatures(int32_t flags);
|
|
|
|
// |RuntimeDelegate|
|
|
void ScheduleFrame(bool regenerate_layer_tree) override;
|
|
|
|
/// Schedule a frame with the default parameter of regenerating the layer
|
|
/// tree.
|
|
void ScheduleFrame() { ScheduleFrame(true); }
|
|
|
|
// |RuntimeDelegate|
|
|
FontCollection& GetFontCollection() override;
|
|
|
|
// |RuntimeDelegate|
|
|
std::shared_ptr<AssetManager> GetAssetManager() override;
|
|
|
|
// Return the weak_ptr of ImageDecoder.
|
|
fml::WeakPtr<ImageDecoder> GetImageDecoderWeakPtr();
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Get the `ImageGeneratorRegistry` associated with the current
|
|
/// engine.
|
|
///
|
|
/// @return The engine's `ImageGeneratorRegistry`.
|
|
///
|
|
fml::WeakPtr<ImageGeneratorRegistry> GetImageGeneratorRegistry();
|
|
|
|
// |PointerDataDispatcher::Delegate|
|
|
void DoDispatchPacket(std::unique_ptr<PointerDataPacket> packet,
|
|
uint64_t trace_flow_id) override;
|
|
|
|
// |PointerDataDispatcher::Delegate|
|
|
void ScheduleSecondaryVsyncCallback(uintptr_t id,
|
|
const fml::closure& callback) override;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Get the last Entrypoint that was used in the RunConfiguration
|
|
/// when |Engine::Run| was called.
|
|
///
|
|
const std::string& GetLastEntrypoint() const;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Get the last Entrypoint Library that was used in the
|
|
/// RunConfiguration when |Engine::Run| was called.
|
|
///
|
|
const std::string& GetLastEntrypointLibrary() const;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Get the last Entrypoint Arguments that was used in the
|
|
/// RunConfiguration when |Engine::Run| was called.This is only
|
|
/// valid in debug mode.
|
|
///
|
|
const std::vector<std::string>& GetLastEntrypointArgs() const;
|
|
|
|
//----------------------------------------------------------------------------
|
|
/// @brief Getter for the initial route. This can be set with a platform
|
|
/// message.
|
|
///
|
|
const std::string& InitialRoute() const { return initial_route_; }
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Loads the Dart shared library into the Dart VM. When the
|
|
/// Dart library is loaded successfully, the Dart future
|
|
/// returned by the originating loadLibrary() call completes.
|
|
///
|
|
/// The Dart compiler may generate separate shared libraries
|
|
/// files called 'loading units' when libraries are imported
|
|
/// as deferred. Each of these shared libraries are identified
|
|
/// by a unique loading unit id. Callers should open and resolve
|
|
/// a SymbolMapping from the shared library. The Mappings should
|
|
/// be moved into this method, as ownership will be assumed by the
|
|
/// dart root isolate after successful loading and released after
|
|
/// shutdown of the root isolate. The loading unit may not be
|
|
/// used after isolate shutdown. If loading fails, the mappings
|
|
/// will be released.
|
|
///
|
|
/// This method is paired with a RequestDartDeferredLibrary
|
|
/// invocation that provides the embedder with the loading unit id
|
|
/// of the deferred library to load.
|
|
///
|
|
///
|
|
/// @param[in] loading_unit_id The unique id of the deferred library's
|
|
/// loading unit, as passed in by
|
|
/// RequestDartDeferredLibrary.
|
|
///
|
|
/// @param[in] snapshot_data Dart snapshot data of the loading unit's
|
|
/// shared library.
|
|
///
|
|
/// @param[in] snapshot_data Dart snapshot instructions of the loading
|
|
/// unit's shared library.
|
|
///
|
|
void LoadDartDeferredLibrary(
|
|
intptr_t loading_unit_id,
|
|
std::unique_ptr<const fml::Mapping> snapshot_data,
|
|
std::unique_ptr<const fml::Mapping> snapshot_instructions);
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Indicates to the dart VM that the request to load a deferred
|
|
/// library with the specified loading unit id has failed.
|
|
///
|
|
/// The dart future returned by the initiating loadLibrary() call
|
|
/// will complete with an error.
|
|
///
|
|
/// @param[in] loading_unit_id The unique id of the deferred library's
|
|
/// loading unit, as passed in by
|
|
/// RequestDartDeferredLibrary.
|
|
///
|
|
/// @param[in] error_message The error message that will appear in the
|
|
/// dart Future.
|
|
///
|
|
/// @param[in] transient A transient error is a failure due to
|
|
/// temporary conditions such as no network.
|
|
/// Transient errors allow the dart VM to
|
|
/// re-request the same deferred library and
|
|
/// loading_unit_id again. Non-transient
|
|
/// errors are permanent and attempts to
|
|
/// re-request the library will instantly
|
|
/// complete with an error.
|
|
void LoadDartDeferredLibraryError(intptr_t loading_unit_id,
|
|
const std::string& error_message,
|
|
bool transient);
|
|
|
|
//--------------------------------------------------------------------------
|
|
/// @brief Accessor for the RuntimeController.
|
|
///
|
|
const RuntimeController* GetRuntimeController() const {
|
|
return runtime_controller_.get();
|
|
}
|
|
|
|
const std::weak_ptr<VsyncWaiter> GetVsyncWaiter() const;
|
|
|
|
private:
|
|
// |RuntimeDelegate|
|
|
std::string DefaultRouteName() override;
|
|
|
|
// |RuntimeDelegate|
|
|
void Render(std::unique_ptr<flutter::LayerTree> layer_tree,
|
|
float device_pixel_ratio) override;
|
|
|
|
// |RuntimeDelegate|
|
|
void UpdateSemantics(SemanticsNodeUpdates update,
|
|
CustomAccessibilityActionUpdates actions) override;
|
|
|
|
// |RuntimeDelegate|
|
|
void HandlePlatformMessage(std::unique_ptr<PlatformMessage> message) override;
|
|
|
|
// |RuntimeDelegate|
|
|
void OnRootIsolateCreated() override;
|
|
|
|
// |RuntimeDelegate|
|
|
void UpdateIsolateDescription(const std::string isolate_name,
|
|
int64_t isolate_port) override;
|
|
|
|
// |RuntimeDelegate|
|
|
std::unique_ptr<std::vector<std::string>> ComputePlatformResolvedLocale(
|
|
const std::vector<std::string>& supported_locale_data) override;
|
|
|
|
// |RuntimeDelegate|
|
|
void RequestDartDeferredLibrary(intptr_t loading_unit_id) override;
|
|
|
|
// |RuntimeDelegate|
|
|
std::weak_ptr<PlatformMessageHandler> GetPlatformMessageHandler()
|
|
const override;
|
|
|
|
// |RuntimeDelegate|
|
|
void SendChannelUpdate(std::string name, bool listening) override;
|
|
|
|
// |RuntimeDelegate|
|
|
double GetScaledFontSize(double unscaled_font_size,
|
|
int configuration_id) const override;
|
|
|
|
void SetNeedsReportTimings(bool value) override;
|
|
|
|
bool HandleLifecyclePlatformMessage(PlatformMessage* message);
|
|
|
|
bool HandleNavigationPlatformMessage(
|
|
std::unique_ptr<PlatformMessage> message);
|
|
|
|
bool HandleLocalizationPlatformMessage(PlatformMessage* message);
|
|
|
|
void HandleSettingsPlatformMessage(PlatformMessage* message);
|
|
|
|
void HandleAssetPlatformMessage(std::unique_ptr<PlatformMessage> message);
|
|
|
|
bool GetAssetAsBuffer(const std::string& name, std::vector<uint8_t>* data);
|
|
|
|
friend class testing::ShellTest;
|
|
|
|
Engine::Delegate& delegate_;
|
|
const Settings settings_;
|
|
std::unique_ptr<Animator> animator_;
|
|
std::unique_ptr<RuntimeController> runtime_controller_;
|
|
|
|
// The pointer_data_dispatcher_ depends on animator_ and runtime_controller_.
|
|
// So it should be defined after them to ensure that pointer_data_dispatcher_
|
|
// is destructed first.
|
|
std::unique_ptr<PointerDataDispatcher> pointer_data_dispatcher_;
|
|
|
|
std::string last_entry_point_;
|
|
std::string last_entry_point_library_;
|
|
std::vector<std::string> last_entry_point_args_;
|
|
std::string initial_route_;
|
|
std::shared_ptr<AssetManager> asset_manager_;
|
|
std::shared_ptr<FontCollection> font_collection_;
|
|
const std::unique_ptr<ImageDecoder> image_decoder_;
|
|
ImageGeneratorRegistry image_generator_registry_;
|
|
TaskRunners task_runners_;
|
|
fml::WeakPtrFactory<Engine> weak_factory_; // Must be the last member.
|
|
FML_DISALLOW_COPY_AND_ASSIGN(Engine);
|
|
};
|
|
|
|
} // namespace flutter
|
|
|
|
#endif // SHELL_COMMON_ENGINE_H_
|