5#include "flutter/shell/platform/windows/flutter_windows_engine.h"
12#include "flutter/fml/logging.h"
13#include "flutter/fml/paths.h"
14#include "flutter/fml/platform/win/wstring_conversion.h"
15#include "flutter/fml/synchronization/waitable_event.h"
16#include "flutter/shell/platform/common/client_wrapper/binary_messenger_impl.h"
17#include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h"
18#include "flutter/shell/platform/common/path_utils.h"
19#include "flutter/shell/platform/embedder/embedder_struct_macros.h"
20#include "flutter/shell/platform/windows/accessibility_bridge_windows.h"
21#include "flutter/shell/platform/windows/compositor_opengl.h"
22#include "flutter/shell/platform/windows/compositor_software.h"
23#include "flutter/shell/platform/windows/flutter_windows_view.h"
24#include "flutter/shell/platform/windows/keyboard_key_channel_handler.h"
25#include "flutter/shell/platform/windows/system_utils.h"
26#include "flutter/shell/platform/windows/task_runner.h"
27#include "flutter/third_party/accessibility/ax/ax_node.h"
39static std::chrono::nanoseconds SnapToNextTick(
40 std::chrono::nanoseconds
value,
41 std::chrono::nanoseconds tick_phase,
42 std::chrono::nanoseconds tick_interval) {
43 std::chrono::nanoseconds
offset = (tick_phase -
value) % tick_interval;
44 if (
offset != std::chrono::nanoseconds::zero())
59 if (!
host->egl_manager()) {
62 return host->egl_manager()->render_context()->MakeCurrent();
66 if (!
host->egl_manager()) {
69 return host->egl_manager()->render_context()->ClearCurrent();
78 const char* what) ->
void* {
79 return reinterpret_cast<void*
>(eglGetProcAddress(what));
83 if (!
host->egl_manager()) {
86 return host->egl_manager()->resource_context()->MakeCurrent();
92 if (!
host->texture_registrar()) {
110 [](
void*
user_data,
const void* allocation,
size_t row_bytes,
136 if (!
info.region.empty()) {
139 if (!
info.script.empty()) {
149 std::shared_ptr<WindowsProcTable> windows_proc_table)
151 windows_proc_table_(
std::move(windows_proc_table)),
152 aot_data_(nullptr, nullptr),
153 views_mutex_(
fml::SharedMutex::
Create()),
155 if (windows_proc_table_ ==
nullptr) {
156 windows_proc_table_ = std::make_shared<WindowsProcTable>();
165 std::make_unique<TaskRunner>(
169 <<
"Cannot post an engine task when engine is not running.";
173 FML_LOG(ERROR) <<
"Failed to post an engine task.";
180 messenger_->SetEngine(
this);
181 plugin_registrar_ = std::make_unique<FlutterDesktopPluginRegistrar>();
182 plugin_registrar_->engine =
this;
185 std::make_unique<BinaryMessengerImpl>(messenger_->ToRef());
186 message_dispatcher_ =
187 std::make_unique<IncomingMessageDispatcher>(messenger_->ToRef());
190 std::make_unique<FlutterWindowsTextureRegistrar>(
this, gl_);
193 auto& switches = project_->GetSwitches();
194 enable_impeller_ =
std::find(switches.begin(), switches.end(),
195 "--enable-impeller=true") != switches.end();
198 window_proc_delegate_manager_ = std::make_unique<WindowProcDelegateManager>();
199 window_proc_delegate_manager_->RegisterTopLevelWindowProcDelegate(
206 return that->lifecycle_manager_->WindowProc(hwnd, msg, wpar, lpar,
209 static_cast<void*
>(
this));
214 internal_plugin_registrar_ =
215 std::make_unique<PluginRegistrar>(plugin_registrar_.get());
217 accessibility_plugin_ = std::make_unique<AccessibilityPlugin>(
this);
219 accessibility_plugin_.get());
222 std::make_unique<CursorHandler>(messenger_wrapper_.get(),
this);
224 std::make_unique<PlatformHandler>(messenger_wrapper_.get(),
this);
225 settings_plugin_ = std::make_unique<SettingsPlugin>(messenger_wrapper_.get(),
229FlutterWindowsEngine::~FlutterWindowsEngine() {
230 messenger_->SetEngine(
nullptr);
234void FlutterWindowsEngine::SetSwitches(
235 const std::vector<std::string>& switches) {
236 project_->SetSwitches(switches);
244 if (!project_->HasValidPaths()) {
245 FML_LOG(
ERROR) <<
"Missing or unresolvable paths to assets.";
248 std::string assets_path_string = project_->assets_path().u8string();
249 std::string icu_path_string = project_->icu_path().u8string();
250 if (embedder_api_.RunsAOTCompiledDartCode()) {
251 aot_data_ = project_->LoadAotData(embedder_api_);
253 FML_LOG(
ERROR) <<
"Unable to start engine without AOT data.";
261 std::string executable_name = GetExecutableName();
262 std::vector<const char*>
argv = {executable_name.c_str()};
263 std::vector<std::string> switches = project_->GetSwitches();
265 switches.begin(), switches.end(), std::back_inserter(
argv),
266 [](
const std::string& arg) ->
const char* { return arg.c_str(); });
268 const std::vector<std::string>& entrypoint_args =
269 project_->dart_entrypoint_arguments();
270 std::vector<const char*> entrypoint_argv;
272 entrypoint_args.begin(), entrypoint_args.end(),
273 std::back_inserter(entrypoint_argv),
274 [](
const std::string& arg) ->
const char* { return arg.c_str(); });
279 platform_task_runner.
user_data = task_runner_.get();
285 uint64_t target_time_nanos,
298 args.shutdown_dart_vm_when_done =
true;
299 args.assets_path = assets_path_string.c_str();
300 args.icu_data_path = icu_path_string.c_str();
301 args.command_line_argc =
static_cast<int>(
argv.size());
302 args.command_line_argv =
argv.empty() ? nullptr :
argv.data();
310 if (!project_->dart_entrypoint().empty() && !entrypoint.empty() &&
311 project_->dart_entrypoint() != entrypoint) {
312 FML_LOG(
ERROR) <<
"Conflicting entrypoints were specified in "
313 "FlutterDesktopEngineProperties.dart_entrypoint and "
314 "FlutterDesktopEngineRun(engine, entry_point). ";
317 if (!entrypoint.empty()) {
318 args.custom_dart_entrypoint = entrypoint.data();
319 }
else if (!project_->dart_entrypoint().empty()) {
320 args.custom_dart_entrypoint = project_->dart_entrypoint().c_str();
322 args.dart_entrypoint_argc =
static_cast<int>(entrypoint_argv.size());
323 args.dart_entrypoint_argv =
324 entrypoint_argv.empty() ? nullptr : entrypoint_argv.data();
325 args.platform_message_callback =
329 return host->HandlePlatformMessage(engine_message);
331 args.vsync_callback = [](
void*
user_data, intptr_t baton) ->
void {
333 host->OnVsync(baton);
337 host->OnPreEngineRestart();
350 auto accessibility_bridge = view->accessibility_bridge().lock();
351 if (!accessibility_bridge) {
355 for (
size_t i = 0;
i <
update->node_count;
i++) {
357 accessibility_bridge->AddFlutterSemanticsNodeUpdate(*node);
360 for (
size_t i = 0;
i <
update->custom_action_count;
i++) {
362 accessibility_bridge->AddFlutterSemanticsCustomActionUpdate(*
action);
365 accessibility_bridge->CommitUpdates();
369 if (
host->root_isolate_create_callback_) {
370 host->root_isolate_create_callback_();
377 std::string channel_name(
update->channel);
378 host->OnChannelUpdate(std::move(channel_name),
383 args.custom_task_runners = &custom_task_runners;
385 if (!platform_view_plugin_) {
386 platform_view_plugin_ = std::make_unique<PlatformViewPlugin>(
387 messenger_wrapper_.get(), task_runner_.get());
390 auto resolver = [](
const char*
name) ->
void* {
391 return reinterpret_cast<void*
>(::eglGetProcAddress(
name));
396 compositor_ = std::make_unique<CompositorOpenGL>(
this, resolver);
398 compositor_ = std::make_unique<CompositorSoftware>();
403 compositor.user_data =
this;
404 compositor.create_backing_store_callback =
409 return host->compositor_->CreateBackingStore(*config, backing_store_out);
412 compositor.collect_backing_store_callback =
416 return host->compositor_->CollectBackingStore(backing_store);
419 compositor.present_view_callback =
425 args.compositor = &compositor;
428 args.aot_data = aot_data_.get();
433 FML_DCHECK(!egl_manager_ || !egl_manager_->HasContextCurrent());
437 if (enable_impeller_) {
441 FML_LOG(
ERROR) <<
"Could not create surface manager. Impeller backend "
442 "does not support software rendering.";
445 renderer_config = GetOpenGLRendererConfig();
448 egl_manager_ ? GetOpenGLRendererConfig() : GetSoftwareRendererConfig();
452 &
args,
this, &engine_);
464 1.0 / (
static_cast<double>(FrameInterval().count()) / 1000000000.0);
466 std::vector<FlutterEngineDisplay> displays = {display};
467 embedder_api_.NotifyDisplayUpdate(engine_,
469 displays.data(), displays.size());
474 settings_plugin_->StartWatching();
475 settings_plugin_->SendSettings();
477 InitializeKeyboard();
482bool FlutterWindowsEngine::Stop() {
484 for (
const auto& [
callback, registrar] :
485 plugin_registrar_destruction_callbacks_) {
495std::unique_ptr<FlutterWindowsView> FlutterWindowsEngine::CreateView(
496 std::unique_ptr<WindowBindingHandler>
window) {
497 auto view_id = next_view_id_;
498 auto view = std::make_unique<FlutterWindowsView>(
499 view_id,
this, std::move(
window), windows_proc_table_);
501 view->CreateRenderSurface();
509 FML_DCHECK(views_.find(view_id) == views_.end());
510 views_[view_id] = view.get();
513 if (!view->IsImplicitView()) {
520 Captures captures = {};
526 info.view_id = view_id;
527 info.view_metrics = &metrics;
528 info.user_data = &captures;
530 Captures* captures =
reinterpret_cast<Captures*
>(
result->user_data);
531 captures->added =
result->added;
532 captures->latch.Signal();
538 <<
"Starting the add view operation failed. FlutterEngineAddView "
539 "returned an unexpected result: "
540 <<
result <<
". This indicates a bug in the Windows embedder.";
550 captures.latch.Wait();
552 if (!captures.added) {
556 FML_LOG(
ERROR) <<
"FlutterEngineAddView failed to add view";
558 views_.erase(view_id);
563 return std::move(view);
577 Captures captures = {};
581 info.view_id = view_id;
582 info.user_data = &captures;
587 Captures* captures =
reinterpret_cast<Captures*
>(
result->user_data);
588 captures->removed =
result->removed;
589 captures->latch.Signal();
594 FML_LOG(
ERROR) <<
"Starting the remove view operation failed. "
595 "FlutterEngineRemoveView "
596 "returned an unexpected result: "
598 <<
". This indicates a bug in the Windows embedder.";
608 captures.latch.Wait();
610 if (!captures.removed) {
613 FML_LOG(
ERROR) <<
"FlutterEngineRemoveView failed to remove view";
623 FML_DCHECK(views_.find(view_id) != views_.end());
624 views_.erase(view_id);
628void FlutterWindowsEngine::OnVsync(intptr_t baton) {
629 std::chrono::nanoseconds current_time =
630 std::chrono::nanoseconds(embedder_api_.GetCurrentTime());
631 std::chrono::nanoseconds frame_interval = FrameInterval();
632 auto next = SnapToNextTick(current_time, start_time_, frame_interval);
633 embedder_api_.OnVsync(engine_, baton,
next.count(),
634 (
next + frame_interval).count());
637std::chrono::nanoseconds FlutterWindowsEngine::FrameInterval() {
638 if (frame_interval_override_.has_value()) {
639 return frame_interval_override_.value();
641 uint64_t interval = 16600000;
643 DWM_TIMING_INFO timing_info = {};
644 timing_info.cbSize =
sizeof(timing_info);
645 HRESULT
result = DwmGetCompositionTimingInfo(NULL, &timing_info);
646 if (
result == S_OK && timing_info.rateRefresh.uiDenominator > 0 &&
647 timing_info.rateRefresh.uiNumerator > 0) {
648 interval =
static_cast<double>(timing_info.rateRefresh.uiDenominator *
650 static_cast<double>(timing_info.rateRefresh.uiNumerator);
653 return std::chrono::nanoseconds(interval);
659 auto iterator = views_.find(view_id);
660 if (iterator == views_.end()) {
664 return iterator->second;
669 return plugin_registrar_.get();
672void FlutterWindowsEngine::AddPluginRegistrarDestructionCallback(
675 plugin_registrar_destruction_callbacks_[
callback] = registrar;
678void FlutterWindowsEngine::SendWindowMetricsEvent(
681 embedder_api_.SendWindowMetricsEvent(engine_, &
event);
687 embedder_api_.SendPointerEvent(engine_, &
event, 1);
699bool FlutterWindowsEngine::SendPlatformMessage(
702 const size_t message_size,
706 if (reply !=
nullptr &&
user_data !=
nullptr) {
708 embedder_api_.PlatformMessageCreateResponseHandle(
709 engine_, reply,
user_data, &response_handle);
725 embedder_api_.SendPlatformMessage(engine_, &platform_message);
726 if (response_handle !=
nullptr) {
727 embedder_api_.PlatformMessageReleaseResponseHandle(engine_,
733void FlutterWindowsEngine::SendPlatformMessageResponse(
736 size_t data_length) {
737 embedder_api_.SendPlatformMessageResponse(engine_, handle,
data, data_length);
740void FlutterWindowsEngine::HandlePlatformMessage(
743 FML_LOG(
ERROR) <<
"Invalid message size received. Expected: "
751 message_dispatcher_->HandleMessage(
message, [
this] {}, [
this] {});
754void FlutterWindowsEngine::ReloadSystemFonts() {
755 embedder_api_.ReloadSystemFonts(engine_);
759 embedder_api_.ScheduleFrame(engine_);
763 next_frame_callback_ = std::move(
callback);
765 embedder_api_.SetNextFrameCallback(
773 self->task_runner_->PostTask(std::move(
self->next_frame_callback_));
779 if (lifecycle_manager_) {
780 lifecycle_manager_->SetLifecycleState(
state);
784void FlutterWindowsEngine::SendSystemLocales() {
785 std::vector<LanguageInfo> languages =
787 std::vector<FlutterLocale> flutter_locales;
788 flutter_locales.reserve(languages.size());
789 for (
const auto&
info : languages) {
790 flutter_locales.push_back(CovertToFlutterLocale(
info));
793 std::vector<const FlutterLocale*> flutter_locale_list;
794 flutter_locale_list.reserve(flutter_locales.size());
796 std::back_inserter(flutter_locale_list),
797 [](
const auto& arg) ->
const auto* { return &arg; });
798 embedder_api_.UpdateLocales(engine_, flutter_locale_list.data(),
799 flutter_locale_list.size());
802void FlutterWindowsEngine::InitializeKeyboard() {
803 auto internal_plugin_messenger = internal_plugin_registrar_->messenger();
804 KeyboardKeyEmbedderHandler::GetKeyStateHandler get_key_state = GetKeyState;
805 KeyboardKeyEmbedderHandler::MapVirtualKeyToScanCode map_vk_to_scan =
807 return MapVirtualKey(virtual_key,
808 extended ? MAPVK_VK_TO_VSC_EX : MAPVK_VK_TO_VSC);
810 keyboard_key_handler_ = std::move(CreateKeyboardKeyHandler(
811 internal_plugin_messenger, get_key_state, map_vk_to_scan));
813 std::move(CreateTextInputPlugin(internal_plugin_messenger));
816std::unique_ptr<KeyboardHandlerBase>
817FlutterWindowsEngine::CreateKeyboardKeyHandler(
821 auto keyboard_key_handler = std::make_unique<KeyboardKeyHandler>(messenger);
822 keyboard_key_handler->AddDelegate(
823 std::make_unique<KeyboardKeyEmbedderHandler>(
828 get_key_state, map_vk_to_scan));
829 keyboard_key_handler->AddDelegate(
830 std::make_unique<KeyboardKeyChannelHandler>(messenger));
831 keyboard_key_handler->InitKeyboardChannel();
832 return keyboard_key_handler;
835std::unique_ptr<TextInputPlugin> FlutterWindowsEngine::CreateTextInputPlugin(
837 return std::make_unique<TextInputPlugin>(messenger,
this);
840bool FlutterWindowsEngine::RegisterExternalTexture(int64_t
texture_id) {
841 return (embedder_api_.RegisterExternalTexture(engine_,
texture_id) ==
845bool FlutterWindowsEngine::UnregisterExternalTexture(int64_t
texture_id) {
846 return (embedder_api_.UnregisterExternalTexture(engine_,
texture_id) ==
850bool FlutterWindowsEngine::MarkExternalTextureFrameAvailable(
852 return (embedder_api_.MarkExternalTextureFrameAvailable(
860 auto captures =
new Captures();
861 captures->callback = std::move(
callback);
862 if (embedder_api_.PostRenderThreadTask(
865 auto captures = reinterpret_cast<Captures*>(opaque);
866 captures->callback();
880 return (embedder_api_.DispatchSemanticsAction(engine_,
target,
action,
885void FlutterWindowsEngine::UpdateSemanticsEnabled(
bool enabled) {
886 if (engine_ && semantics_enabled_ != enabled) {
889 semantics_enabled_ = enabled;
890 embedder_api_.UpdateSemanticsEnabled(engine_, enabled);
891 for (
auto iterator = views_.begin(); iterator != views_.end(); iterator++) {
892 iterator->second->UpdateSemanticsEnabled(enabled);
897void FlutterWindowsEngine::OnPreEngineRestart() {
899 InitializeKeyboard();
902std::string FlutterWindowsEngine::GetExecutableName()
const {
905 const std::string& executable_path =
result.second;
906 size_t last_separator = executable_path.find_last_of(
"/\\");
907 if (last_separator == std::string::npos ||
908 last_separator == executable_path.size() - 1) {
909 return executable_path;
911 return executable_path.substr(last_separator + 1);
916void FlutterWindowsEngine::UpdateAccessibilityFeatures() {
917 UpdateHighContrastMode();
920void FlutterWindowsEngine::UpdateHighContrastMode() {
921 high_contrast_enabled_ = windows_proc_table_->GetHighContrastEnabled();
923 SendAccessibilityFeatures();
924 settings_plugin_->UpdateHighContrastMode(high_contrast_enabled_);
927void FlutterWindowsEngine::SendAccessibilityFeatures() {
930 if (high_contrast_enabled_) {
935 embedder_api_.UpdateAccessibilityFeatures(
939void FlutterWindowsEngine::RequestApplicationQuit(HWND hwnd,
943 platform_handler_->RequestAppExit(hwnd, wparam, lparam, exit_type, 0);
946void FlutterWindowsEngine::OnQuit(std::optional<HWND> hwnd,
947 std::optional<WPARAM> wparam,
948 std::optional<LPARAM> lparam,
950 lifecycle_manager_->Quit(hwnd, wparam, lparam, exit_code);
953void FlutterWindowsEngine::OnDwmCompositionChanged() {
956 for (
auto iterator = views_.begin(); iterator != views_.end(); iterator++) {
957 iterator->second->OnDwmCompositionChanged();
961void FlutterWindowsEngine::OnWindowStateEvent(HWND hwnd,
963 lifecycle_manager_->OnWindowStateEvent(hwnd,
event);
966std::optional<LRESULT> FlutterWindowsEngine::ProcessExternalWindowMessage(
971 if (lifecycle_manager_) {
972 return lifecycle_manager_->ExternalWindowMessage(hwnd,
message, wparam,
978void FlutterWindowsEngine::OnChannelUpdate(std::string
name,
bool listening) {
979 if (
name ==
"flutter/platform" && listening) {
980 lifecycle_manager_->BeginProcessingExit();
981 }
else if (
name ==
"flutter/lifecycle" && listening) {
982 lifecycle_manager_->BeginProcessingLifecycle();
992 auto iterator = views_.find(
info->view_id);
993 if (iterator == views_.end()) {
997 FlutterWindowsView* view = iterator->second;
999 return compositor_->Present(view,
info->layers,
info->layers_count);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static float next(float f)
static sk_sp< Effect > Create()
int find(T *array, int N, T item)
static void SetUp(BinaryMessenger *binary_messenger, AccessibilityPlugin *plugin)
FlutterWindowsEngine(const FlutterProjectBundle &project, std::shared_ptr< WindowsProcTable > windows_proc_table=nullptr)
std::function< SHORT(UINT, bool)> MapVirtualKeyToScanCode
std::function< SHORT(int)> GetKeyStateHandler
static std::unique_ptr< Manager > Create(bool enable_impeller)
static std::shared_ptr< ProcTable > Create()
A Mapping like NonOwnedMapping, but uses Free as its release proc.
FlutterEngineResult FlutterEngineGetProcAddresses(FlutterEngineProcTable *table)
Gets the table of engine function pointers.
FlutterAccessibilityFeature
@ kFlutterAccessibilityFeatureHighContrast
Request that UI be rendered with darker colors.
@ kFlutterEngineDisplaysUpdateTypeStartup
void(* FlutterKeyEventCallback)(bool, void *)
#define FLUTTER_ENGINE_VERSION
#define SAFE_ACCESS(pointer, member, default_value)
FlutterSemanticsFlag flags
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static FlutterDesktopMessage ConvertToDesktopMessage(const FlutterPlatformMessage &engine_message)
void(* FlutterDesktopBinaryReply)(const uint8_t *data, size_t data_size, void *user_data)
void(* FlutterDesktopOnPluginRegistrarDestroyed)(FlutterDesktopPluginRegistrarRef)
static constexpr char kAccessibilityChannelName[]
#define FML_LOG(severity)
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
static constexpr FlutterViewId kImplicitViewId
WindowStateEvent
An event representing a change in window state that may update the.
static void DispatchSemanticsAction(JNIEnv *env, jobject jcaller, jlong shell_holder, jint id, jint action, jobject args, jint args_position)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service host
DEF_SWITCHES_START aot vmservice shared library name
std::vector< LanguageInfo > GetPreferredLanguageInfo()
static void WindowsPlatformThreadPrioritySetter(FlutterThreadPriority priority)
static void ScheduleFrame(JNIEnv *env, jobject jcaller, jlong shell_holder)
std::pair< bool, std::string > GetExecutablePath()
std::function< void()> closure
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
An update to whether a message channel has a listener set or not.
void(* thread_priority_setter)(FlutterThreadPriority)
const FlutterTaskRunnerDescription * platform_task_runner
size_t struct_size
The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
size_t struct_size
This size of this struct. Must be sizeof(FlutterDisplay).
FlutterEngineDisplayId display_id
Function-pointer-based versions of the APIs above.
size_t struct_size
The size of this struct. Must be sizeof(FlutterEngineProcs).
FlutterEngineGetCurrentTimeFnPtr GetCurrentTime
FlutterEngineRunTaskFnPtr RunTask
const char * language_code
size_t struct_size
This size of this struct. Must be sizeof(FlutterLocale).
const char * country_code
ProcResolver gl_proc_resolver
BoolCallback make_current
size_t struct_size
The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
TextureFrameCallback gl_external_texture_frame_callback
bool fbo_reset_after_present
BoolCallback make_resource_current
UIntFrameInfoCallback fbo_with_frame_info_callback
BoolCallback clear_current
FlutterSoftwareRendererConfig software
FlutterOpenGLRendererConfig open_gl
A batch of updates to semantics nodes and custom actions.
size_t struct_size
The size of this struct. Must be sizeof(FlutterSoftwareRendererConfig).
SoftwareSurfacePresentCallback surface_present_callback
size_t struct_size
The size of this struct. Must be sizeof(FlutterTaskRunnerDescription).
BoolCallback runs_task_on_current_thread_callback
FlutterTaskRunnerPostTaskCallback post_task_callback
std::shared_ptr< const fml::Mapping > data
#define BASE_DCHECK(condition)