[embedder] Copy code from workstation.git.

This gives us a basic embedder executable
and some build rules to run a Flutter sample app.
However the app crashes on startup with the
product bundle workflow due to not having
an ambient_mark_vmo_exec allowlist entry. We
are talking with security to figure out how to handle
this.

In addition I added a script to sync Engine artifacts
to a new revision since copying changes over was a pain.

Bug: 46971
Change-Id: Ic7f361862b878cee9faddffafbd89fce64dca403
diff --git a/.gitmodules b/.gitmodules
index 1c3bf7f..d0ea17e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,5 +1,5 @@
 [submodule "sdk-integration"]
-	path = sdk-integration
+	path = third_party/sdk-integration
 	url = https://fuchsia.googlesource.com/sdk-integration
 [submodule "third_party/googletest"]
 	path = third_party/googletest
diff --git a/README.md b/README.md
index 7d6f469..3048563 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
 flutter-embedder.git
 =======================================
 
-The Flutter & Dart embedders (FDE) repo holds the source code for
-building the Fuchsia-specific Flutter & Dart embedders outside of
-fuchsia.git.
+The Flutter Embedder for Fuchsia is a new in-progress runtime for Flutter apps
+on Fuchsia. This runtime is built on top of Flutter's
+[embedder platform](https://github.com/flutter/flutter/wiki/Custom-Flutter-Engine-Embedders).
 
 This repository is a work in progress and should be considered
 experimental.
@@ -16,40 +16,82 @@
 
 2. Make sure this repository has the required submodules:
 
-   ```
+   ```sh
    git submodule update --recursive --init
    ```
 
 3. Ensure that there are Fuchsia SSH keys in your host machine. You will need
    them for running the Fuchsia emulator.
 
-   ```
+   ```sh
     [[ -f "${HOME}/.ssh/fuchsia_ed25519" ]] || ssh-keygen -P "" -t ed25519 -f "${HOME}/.ssh/fuchsia_ed25519" -C "${USER}@$(hostname -f) Shared SSH Key for Fuchsia"
 
     [[ -f "${HOME}/.ssh/fuchsia_authorized_keys" ]] || ssh-keygen -y -f "${HOME}/.ssh/fuchsia_ed25519" > "${HOME}/.ssh/fuchsia_authorized_keys"
    ```
 
+4. You will need [the Flutter tool](https://github.com/flutter/flutter/wiki/Setting-up-the-Framework-development-environment) in
+   your PATH. For example if your Flutter framework source checkout is at `~/flutter`, add the following to
+   your `~/.zprofile` for `zsh` or `~/.bash_profile` for `bash`:
+
+   ```sh
+   export PATH=~/flutter/bin:$PATH
+   ```
+
+   TODO(akbiggs): Get rid of the dependency on the Flutter tool by using Bazel build rules to build the Flutter app instead.
+
 ## Build and package the sample
 
 Now the repository is ready to build the sample.
 
-1. Fetch an emulator image and start an emulator
+1. Fetch an emulator image and start an emulator:
 
    ```
    tools/ffx product-bundle get workstation.qemu-x64
    tools/ffx emu start --headless workstation.qemu-x64
    ```
 
-2. (optional) watch the device log in a separate window
+2. (optional) Watch the device log in a separate window:
 
    ```
    tools/ffx log
    ```
 
-3. Run the hello world component
+3. Run the sample app component:
 
    ```
-   bazel run --config=fuchsia_x64 //src/examples/hello_world_cpp:hello_world_cpp_pkg.component
+   scripts/build_and_run_sample_app.sh
    ```
 
-   Watch that "Hello, World!" is printed in the log.
+TODO(akbiggs): Currently the component crashes on startup with an `ambient_mark_vmo_exec`
+allowlist issue. We are talking to security to figure out how to handle this.
+
+## Syncing engine artifacts
+
+Occasionally you will need to update the Flutter Engine artifacts (embedder.h and
+libengine_flutter.so) that are used by the embedder to run Flutter apps. A script
+is provided for this workflow.
+
+### Prerequisites
+
+1. You will [need to get the Flutter Engine source code](https://github.com/flutter/flutter/wiki/Setting-up-the-Engine-development-environment). **Note that this is not just cloning
+https://github.com/flutter/engine.**
+2. `$ENGINE_DIR` should be set to the `src` folder of your Flutter Engine checkout, for example
+`~/engine/src`.
+3. `$FUCHSIA_EMBEDDER_DIR` should be set to your flutter-embedder.git checkout, for example
+`~/flutter-embedder`.
+4. `$DEPOT_TOOLS` should be set to your [`depot_tools`](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up) location, for example `~/depot_tools`.
+5. You will need to `git stash` or `git commit` any local changes to the Flutter Engine or the
+script will fail.
+
+### Running the script
+
+You can run the script with a `flutter/engine` Git commit to sync the Engine artifacts to that
+revision.
+
+```sh
+scripts/sync_engine_artifacts_to_revision.sh <ENGINE_COMMIT_SHA>
+```
+
+A common workflow is to sync your Engine commit to your Flutter tool. If your Flutter tool
+lives at `~/flutter/bin/flutter`, you can do `cat ~/flutter/bin/internal/engine.version` to get
+your Flutter tool's Engine commit.
diff --git a/scripts/build_and_run_sample_app.sh b/scripts/build_and_run_sample_app.sh
new file mode 100755
index 0000000..53fb37b
--- /dev/null
+++ b/scripts/build_and_run_sample_app.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# Copyright 2022 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Prerequisites:
+#   1. $FUCHSIA_EMBEDDER_DIR is set to your flutter-embedder.git checkout directory.
+#   2. You are currently running Workstation (`ffx emu start --headless workstation.qemu-x64`).
+#
+# TODO(akbiggs): Port this workflow to Bazel.
+
+set -e # Exit if any program returns an error.
+APP_NAME=flutter_sample_app
+FAR_DEBUG_DIR=/tmp/"${APP_NAME}"_far_contents
+
+function is-stderr-tty {
+  [[ -t 2 ]]
+}
+
+# echo-info prints a line to stderr with a green INFO: prefix.
+function echo-info {
+  if is-stderr-tty; then
+    echo -e >&2 "\033[1;32mINFO:\033[0m $*"
+  else
+    echo -e >&2 "INFO: $*"
+  fi
+}
+
+pushd "${FUCHSIA_EMBEDDER_DIR}"
+
+echo-info "Building Flutter sample app bundle."
+cd "${FUCHSIA_EMBEDDER_DIR}"/src/examples/"${APP_NAME}"
+flutter build bundle
+
+echo-info "Running Flutter sample app."
+cd "${FUCHSIA_EMBEDDER_DIR}"
+bazel run --config=fuchsia_x64 //src/examples/"${APP_NAME}":"${APP_NAME}"_pkg.component
+
+popd
diff --git a/scripts/sync_engine_artifacts_to_revision.sh b/scripts/sync_engine_artifacts_to_revision.sh
new file mode 100755
index 0000000..189d7e7
--- /dev/null
+++ b/scripts/sync_engine_artifacts_to_revision.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+#
+# Usage:
+#   sync_engine_artifacts_to_commit.sh <engine_commit>
+#
+# Prerequisites:
+#   1. $ENGINE_DIR is set to the src/ directory of your flutter/engine checkout.
+#   2. $FUCHSIA_EMBEDDER_DIR is set to your flutter-embedder.git checkout.
+#   3. $DEPOT_TOOLS is set to your depot_tools directory.
+#   4. You don't have any uncommited changes to your Engine code.
+
+# Returns true if colors are supported.
+function is-stderr-tty {
+  [[ -t 2 ]]
+}
+
+# Prints a line to stderr with a green INFO: prefix.
+function echo-info {
+  if is-stderr-tty; then
+    echo -e >&2 "\033[1;32mINFO:\033[0m $*"
+  else
+    echo -e >&2 "INFO: $*"
+  fi
+}
+
+engine_revision=$1
+
+pushd "${ENGINE_DIR}"
+
+echo-info "Syncing ${ENGINE_DIR}/flutter to ${engine_revision}..."
+pushd flutter
+git checkout "${engine_revision}"
+popd
+
+echo-info "Syncing ${ENGINE_DIR} dependencies..."
+gclient sync -D
+
+buildroot_fix=c7deba3773ed645c29f4518cc3990bc02f0f53cd
+pushd build
+if ! git merge-base --is-ancestor "${buildroot_fix}" HEAD
+then
+  echo-info "Cherry-picking https://github.com/flutter/buildroot/pull/552 into ${ENGINE_DIR}/build to fix embedder build for Fuchsia..."
+
+  git remote add akbiggs https://github.com/akbiggs/buildroot
+  git fetch akbiggs
+  git cherry-pick -c "${buildroot_fix}"
+fi
+popd
+
+jit_snapshot_fix=d79531e15a1b04d5e68c7ad87775cb594727d7b0
+pushd flutter
+if ! git merge-base --is-ancestor "${jit_snapshot_fix}" HEAD
+then
+  echo-info "Cherry-picking https://github.com/flutter/engine/pull/33189 into ${ENGINE_DIR}/flutter to work around JIT snapshot loading issue..."
+  git remote add akbiggs https://github.com/akbiggs/engine
+  git fetch akbiggs
+  git cherry-pick -c "${jit_snapshot_fix}"
+fi
+popd
+
+# Fail on any error.
+# We start failing here because the previous commands throw errors even
+# when things are fine.
+set -e
+
+echo-info "Building the Flutter Engine embedding for Fuchsia (libflutter_engine.so)..."
+"${ENGINE_DIR}"/flutter/tools/gn --fuchsia --embedder-for-target --unopt
+out_dir="${ENGINE_DIR}"/out/fuchsia_debug_unopt_x64
+"${DEPOT_TOOLS}"/ninja -C "${out_dir}"
+
+echo-info "Copying Flutter Engine artifacts to ${FUCHSIA_EMBEDDER_DIR}/src/embedder..."
+cp "${out_dir}"/libflutter_engine.so "${FUCHSIA_EMBEDDER_DIR}"/src/embedder/libflutter_engine.so
+cp "${ENGINE_DIR}"/flutter/shell/platform/embedder/embedder.h "${FUCHSIA_EMBEDDER_DIR}"/src/embedder/embedder.h
+echo "${engine_revision}" > "${FUCHSIA_EMBEDDER_DIR}"/src/embedder/engine_revision
+
+echo-info "Done! Engine artifacts updated to ${engine_revision}."
+popd
diff --git a/sdk-integration b/sdk-integration
index 260034b..3dcbad9 160000
--- a/sdk-integration
+++ b/sdk-integration
@@ -1 +1 @@
-Subproject commit 260034bc45542dca829a56606c7e7dbab7639749
+Subproject commit 3dcbad97b1a1ab140caf5ba5b2102a82f3144d6e
diff --git a/src/embedder/BUILD.bazel b/src/embedder/BUILD.bazel
new file mode 100644
index 0000000..c33d100
--- /dev/null
+++ b/src/embedder/BUILD.bazel
@@ -0,0 +1,44 @@
+# Copyright 2022 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# Package for the Flutter embedder for Fuchsia.
+
+load(
+    "@rules_fuchsia//fuchsia:defs.bzl",
+    "fuchsia_cc_binary",
+    "fuchsia_component_manifest",
+    "fuchsia_package_resource",
+)
+
+# ELF binary that takes Flutter app assets and runs a Flutter app.
+fuchsia_cc_binary(
+    name = "embedder",
+    visibility = ["//visibility:public"],
+    srcs = [
+        # ABI-stable interface for the Flutter embedder platform. Copied from the Flutter Engine.
+        "embedder.h",
+        "main.cc",
+        "libflutter_engine.so",
+    ],
+    deps = [
+        "@fuchsia_sdk//pkg/async-loop-default",
+        "@fuchsia_sdk//pkg/async-loop-cpp",
+        "@fuchsia_sdk//pkg/syslog",
+    ],
+)
+
+fuchsia_component_manifest(
+    name = "embedder_manifest",
+    visibility = ["//visibility:public"],
+    src = "meta/embedder.cml",
+    includes = ["@fuchsia_sdk//pkg/syslog:client"],
+)
+
+# The implementation of the embedder platform for the Flutter Engine.
+# TODO(akbiggs): This should come from a CIPD bucket instead.
+fuchsia_package_resource(
+    name = "flutter_engine",
+    visibility = ["//visibility:public"],
+    src = ":libflutter_engine.so",
+    dest = "lib/libflutter_engine.so",
+)
diff --git a/src/embedder/OWNERS b/src/embedder/OWNERS
new file mode 100644
index 0000000..a8c7ae8
--- /dev/null
+++ b/src/embedder/OWNERS
@@ -0,0 +1,2 @@
+akbiggs@google.com
+dworsham@google.com
diff --git a/src/embedder/README.md b/src/embedder/README.md
new file mode 100644
index 0000000..ef35819
--- /dev/null
+++ b/src/embedder/README.md
@@ -0,0 +1,27 @@
+# Flutter Embedder
+
+The Flutter Embedder for Fuchsia is a new in-progress runtime for Flutter apps on Fuchsia. This runtime
+is built on top of Flutter's [embedder platform](https://github.com/flutter/flutter/wiki/Custom-Flutter-Engine-Embedders).
+
+## Code breakdown
+
+### `libflutter_engine.so`
+
+This is an unoptimized build of the Flutter embedder platform built for `OS_FUCHSIA`.
+This build contains a few changes that have not been landed into the Flutter Engine repository:
+
+1. [Add `-fPIC` to Fuchsia builds](https://github.com/flutter/buildroot/pull/552).
+2. [Fix JIT snapshot support for the embedder platform](https://github.com/flutter/flutter/issues/100640).
+
+These changes should be landed and `libflutter_engine.so` should be pulled from a CIPD bucket
+instead.
+
+### `embedder.h`
+
+This is a copy of the Flutter embedder platform header from the Engine repository: https://github.com/flutter/engine/blob/main/shell/platform/embedder/embedder.h
+
+### `engine_revision`
+
+The git hash of [Flutter Engine](https://github.com/flutter/engine) that the Engine artifacts come from.
+Currently, this is purely for developer reference and is not used by any tooling.
+
diff --git a/src/embedder/embedder.h b/src/embedder/embedder.h
new file mode 100644
index 0000000..66a25c7
--- /dev/null
+++ b/src/embedder/embedder.h
@@ -0,0 +1,2611 @@
+// 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 FLUTTER_EMBEDDER_H_
+#define FLUTTER_EMBEDDER_H_
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+// This file defines an Application Binary Interface (ABI), which requires more
+// stability than regular code to remain functional for exchanging messages
+// between different versions of the embedding and the engine, to allow for both
+// forward and backward compatibility.
+//
+// Specifically,
+// - The order, type, and size of the struct members below must remain the same,
+//   and members should not be removed.
+// - New structures that are part of the ABI must be defined with "size_t
+//   struct_size;" as their first member, which should be initialized using
+//   "sizeof(Type)".
+// - Enum values must not change or be removed.
+// - Enum members without explicit values must not be reordered.
+// - Function signatures (names, argument counts, argument order, and argument
+//   type) cannot change.
+// - The core behavior of existing functions cannot change.
+//
+// These changes are allowed:
+// - Adding new struct members at the end of a structure.
+// - Adding new enum members with a new value.
+// - Renaming a struct member as long as its type, size, and intent remain the
+//   same.
+// - Renaming an enum member as long as its value and intent remains the same.
+//
+// It is expected that struct members and implicitly-valued enums will not
+// always be declared in an order that is optimal for the reader, since members
+// will be added over time, and they can't be reordered.
+//
+// Existing functions should continue to appear from the caller's point of view
+// to operate as they did when they were first introduced, so introduce a new
+// function instead of modifying the core behavior of a function (and continue
+// to support the existing function with the previous behavior).
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef FLUTTER_EXPORT
+#define FLUTTER_EXPORT
+#endif  // FLUTTER_EXPORT
+
+#ifdef FLUTTER_API_SYMBOL_PREFIX
+#define FLUTTER_EMBEDDING_CONCAT(a, b) a##b
+#define FLUTTER_EMBEDDING_ADD_PREFIX(symbol, prefix) \
+  FLUTTER_EMBEDDING_CONCAT(prefix, symbol)
+#define FLUTTER_API_SYMBOL(symbol) \
+  FLUTTER_EMBEDDING_ADD_PREFIX(symbol, FLUTTER_API_SYMBOL_PREFIX)
+#else
+#define FLUTTER_API_SYMBOL(symbol) symbol
+#endif
+
+#define FLUTTER_ENGINE_VERSION 1
+
+typedef enum {
+  kSuccess = 0,
+  kInvalidLibraryVersion,
+  kInvalidArguments,
+  kInternalInconsistency,
+} FlutterEngineResult;
+
+typedef enum {
+  kOpenGL,
+  kSoftware,
+  /// Metal is only supported on Darwin platforms (macOS / iOS).
+  /// iOS version >= 10.0 (device), 13.0 (simulator)
+  /// macOS version >= 10.14
+  kMetal,
+  kVulkan,
+} FlutterRendererType;
+
+/// Additional accessibility features that may be enabled by the platform.
+/// Must match the `AccessibilityFeatures` enum in window.dart.
+typedef enum {
+  /// Indicate there is a running accessibility service which is changing the
+  /// interaction model of the device.
+  kFlutterAccessibilityFeatureAccessibleNavigation = 1 << 0,
+  /// Indicate the platform is inverting the colors of the application.
+  kFlutterAccessibilityFeatureInvertColors = 1 << 1,
+  /// Request that animations be disabled or simplified.
+  kFlutterAccessibilityFeatureDisableAnimations = 1 << 2,
+  /// Request that text be rendered at a bold font weight.
+  kFlutterAccessibilityFeatureBoldText = 1 << 3,
+  /// Request that certain animations be simplified and parallax effects
+  /// removed.
+  kFlutterAccessibilityFeatureReduceMotion = 1 << 4,
+  /// Request that UI be rendered with darker colors.
+  kFlutterAccessibilityFeatureHighContrast = 1 << 5,
+  /// Request to show on/off labels inside switches.
+  kFlutterAccessibilityFeatureOnOffSwitchLabels = 1 << 6,
+} FlutterAccessibilityFeature;
+
+/// The set of possible actions that can be conveyed to a semantics node.
+///
+/// Must match the `SemanticsAction` enum in semantics.dart.
+typedef enum {
+  /// The equivalent of a user briefly tapping the screen with the finger
+  /// without moving it.
+  kFlutterSemanticsActionTap = 1 << 0,
+  /// The equivalent of a user pressing and holding the screen with the finger
+  /// for a few seconds without moving it.
+  kFlutterSemanticsActionLongPress = 1 << 1,
+  /// The equivalent of a user moving their finger across the screen from right
+  /// to left.
+  kFlutterSemanticsActionScrollLeft = 1 << 2,
+  /// The equivalent of a user moving their finger across the screen from left
+  /// to
+  /// right.
+  kFlutterSemanticsActionScrollRight = 1 << 3,
+  /// The equivalent of a user moving their finger across the screen from bottom
+  /// to top.
+  kFlutterSemanticsActionScrollUp = 1 << 4,
+  /// The equivalent of a user moving their finger across the screen from top to
+  /// bottom.
+  kFlutterSemanticsActionScrollDown = 1 << 5,
+  /// Increase the value represented by the semantics node.
+  kFlutterSemanticsActionIncrease = 1 << 6,
+  /// Decrease the value represented by the semantics node.
+  kFlutterSemanticsActionDecrease = 1 << 7,
+  /// A request to fully show the semantics node on screen.
+  kFlutterSemanticsActionShowOnScreen = 1 << 8,
+  /// Move the cursor forward by one character.
+  kFlutterSemanticsActionMoveCursorForwardByCharacter = 1 << 9,
+  /// Move the cursor backward by one character.
+  kFlutterSemanticsActionMoveCursorBackwardByCharacter = 1 << 10,
+  /// Set the text selection to the given range.
+  kFlutterSemanticsActionSetSelection = 1 << 11,
+  /// Copy the current selection to the clipboard.
+  kFlutterSemanticsActionCopy = 1 << 12,
+  /// Cut the current selection and place it in the clipboard.
+  kFlutterSemanticsActionCut = 1 << 13,
+  /// Paste the current content of the clipboard.
+  kFlutterSemanticsActionPaste = 1 << 14,
+  /// Indicate that the node has gained accessibility focus.
+  kFlutterSemanticsActionDidGainAccessibilityFocus = 1 << 15,
+  /// Indicate that the node has lost accessibility focus.
+  kFlutterSemanticsActionDidLoseAccessibilityFocus = 1 << 16,
+  /// Indicate that the user has invoked a custom accessibility action.
+  kFlutterSemanticsActionCustomAction = 1 << 17,
+  /// A request that the node should be dismissed.
+  kFlutterSemanticsActionDismiss = 1 << 18,
+  /// Move the cursor forward by one word.
+  kFlutterSemanticsActionMoveCursorForwardByWord = 1 << 19,
+  /// Move the cursor backward by one word.
+  kFlutterSemanticsActionMoveCursorBackwardByWord = 1 << 20,
+  /// Replace the current text in the text field.
+  kFlutterSemanticsActionSetText = 1 << 21,
+} FlutterSemanticsAction;
+
+/// The set of properties that may be associated with a semantics node.
+///
+/// Must match the `SemanticsFlag` enum in semantics.dart.
+typedef enum {
+  /// The semantics node has the quality of either being "checked" or
+  /// "unchecked".
+  kFlutterSemanticsFlagHasCheckedState = 1 << 0,
+  /// Whether a semantics node is checked.
+  kFlutterSemanticsFlagIsChecked = 1 << 1,
+  /// Whether a semantics node is selected.
+  kFlutterSemanticsFlagIsSelected = 1 << 2,
+  /// Whether the semantic node represents a button.
+  kFlutterSemanticsFlagIsButton = 1 << 3,
+  /// Whether the semantic node represents a text field.
+  kFlutterSemanticsFlagIsTextField = 1 << 4,
+  /// Whether the semantic node currently holds the user's focus.
+  kFlutterSemanticsFlagIsFocused = 1 << 5,
+  /// The semantics node has the quality of either being "enabled" or
+  /// "disabled".
+  kFlutterSemanticsFlagHasEnabledState = 1 << 6,
+  /// Whether a semantic node that hasEnabledState is currently enabled.
+  kFlutterSemanticsFlagIsEnabled = 1 << 7,
+  /// Whether a semantic node is in a mutually exclusive group.
+  kFlutterSemanticsFlagIsInMutuallyExclusiveGroup = 1 << 8,
+  /// Whether a semantic node is a header that divides content into sections.
+  kFlutterSemanticsFlagIsHeader = 1 << 9,
+  /// Whether the value of the semantics node is obscured.
+  kFlutterSemanticsFlagIsObscured = 1 << 10,
+  /// Whether the semantics node is the root of a subtree for which a route name
+  /// should be announced.
+  kFlutterSemanticsFlagScopesRoute = 1 << 11,
+  /// Whether the semantics node label is the name of a visually distinct route.
+  kFlutterSemanticsFlagNamesRoute = 1 << 12,
+  /// Whether the semantics node is considered hidden.
+  kFlutterSemanticsFlagIsHidden = 1 << 13,
+  /// Whether the semantics node represents an image.
+  kFlutterSemanticsFlagIsImage = 1 << 14,
+  /// Whether the semantics node is a live region.
+  kFlutterSemanticsFlagIsLiveRegion = 1 << 15,
+  /// The semantics node has the quality of either being "on" or "off".
+  kFlutterSemanticsFlagHasToggledState = 1 << 16,
+  /// If true, the semantics node is "on". If false, the semantics node is
+  /// "off".
+  kFlutterSemanticsFlagIsToggled = 1 << 17,
+  /// Whether the platform can scroll the semantics node when the user attempts
+  /// to move the accessibility focus to an offscreen child.
+  ///
+  /// For example, a `ListView` widget has implicit scrolling so that users can
+  /// easily move the accessibility focus to the next set of children. A
+  /// `PageView` widget does not have implicit scrolling, so that users don't
+  /// navigate to the next page when reaching the end of the current one.
+  kFlutterSemanticsFlagHasImplicitScrolling = 1 << 18,
+  /// Whether the value of the semantics node is coming from a multi-line text
+  /// field.
+  ///
+  /// This is used for text fields to distinguish single-line text fields from
+  /// multi-line ones.
+  kFlutterSemanticsFlagIsMultiline = 1 << 19,
+  /// Whether the semantic node is read only.
+  ///
+  /// Only applicable when kFlutterSemanticsFlagIsTextField flag is on.
+  kFlutterSemanticsFlagIsReadOnly = 1 << 20,
+  /// Whether the semantic node can hold the user's focus.
+  kFlutterSemanticsFlagIsFocusable = 1 << 21,
+  /// Whether the semantics node represents a link.
+  kFlutterSemanticsFlagIsLink = 1 << 22,
+  /// Whether the semantics node represents a slider.
+  kFlutterSemanticsFlagIsSlider = 1 << 23,
+  /// Whether the semantics node represents a keyboard key.
+  kFlutterSemanticsFlagIsKeyboardKey = 1 << 24,
+} FlutterSemanticsFlag;
+
+typedef enum {
+  /// Text has unknown text direction.
+  kFlutterTextDirectionUnknown = 0,
+  /// Text is read from right to left.
+  kFlutterTextDirectionRTL = 1,
+  /// Text is read from left to right.
+  kFlutterTextDirectionLTR = 2,
+} FlutterTextDirection;
+
+/// Valid values for priority of Thread.
+typedef enum {
+  /// Suitable for threads that shouldn't disrupt high priority work.
+  kBackground = 0,
+  /// Default priority level.
+  kNormal = 1,
+  /// Suitable for threads which generate data for the display.
+  kDisplay = 2,
+  /// Suitable for thread which raster data.
+  kRaster = 3,
+} FlutterThreadPriority;
+
+typedef struct _FlutterEngine* FLUTTER_API_SYMBOL(FlutterEngine);
+
+typedef struct {
+  /// horizontal scale factor
+  double scaleX;
+  /// horizontal skew factor
+  double skewX;
+  /// horizontal translation
+  double transX;
+  /// vertical skew factor
+  double skewY;
+  /// vertical scale factor
+  double scaleY;
+  /// vertical translation
+  double transY;
+  /// input x-axis perspective factor
+  double pers0;
+  /// input y-axis perspective factor
+  double pers1;
+  /// perspective scale factor
+  double pers2;
+} FlutterTransformation;
+
+typedef void (*VoidCallback)(void* /* user data */);
+
+typedef enum {
+  /// Specifies an OpenGL texture target type. Textures are specified using
+  /// the FlutterOpenGLTexture struct.
+  kFlutterOpenGLTargetTypeTexture,
+  /// Specifies an OpenGL frame-buffer target type. Framebuffers are specified
+  /// using the FlutterOpenGLFramebuffer struct.
+  kFlutterOpenGLTargetTypeFramebuffer,
+} FlutterOpenGLTargetType;
+
+typedef struct {
+  /// Target texture of the active texture unit (example GL_TEXTURE_2D or
+  /// GL_TEXTURE_RECTANGLE).
+  uint32_t target;
+  /// The name of the texture.
+  uint32_t name;
+  /// The texture format (example GL_RGBA8).
+  uint32_t format;
+  /// User data to be returned on the invocation of the destruction callback.
+  void* user_data;
+  /// Callback invoked (on an engine managed thread) that asks the embedder to
+  /// collect the texture.
+  VoidCallback destruction_callback;
+  /// Optional parameters for texture height/width, default is 0, non-zero means
+  /// the texture has the specified width/height. Usually, when the texture type
+  /// is GL_TEXTURE_RECTANGLE, we need to specify the texture width/height to
+  /// tell the embedder to scale when rendering.
+  /// Width of the texture.
+  size_t width;
+  /// Height of the texture.
+  size_t height;
+} FlutterOpenGLTexture;
+
+typedef struct {
+  /// The target of the color attachment of the frame-buffer. For example,
+  /// GL_TEXTURE_2D or GL_RENDERBUFFER. In case of ambiguity when dealing with
+  /// Window bound frame-buffers, 0 may be used.
+  uint32_t target;
+
+  /// The name of the framebuffer.
+  uint32_t name;
+
+  /// User data to be returned on the invocation of the destruction callback.
+  void* user_data;
+
+  /// Callback invoked (on an engine managed thread) that asks the embedder to
+  /// collect the framebuffer.
+  VoidCallback destruction_callback;
+} FlutterOpenGLFramebuffer;
+
+typedef bool (*BoolCallback)(void* /* user data */);
+typedef FlutterTransformation (*TransformationCallback)(void* /* user data */);
+typedef uint32_t (*UIntCallback)(void* /* user data */);
+typedef bool (*SoftwareSurfacePresentCallback)(void* /* user data */,
+                                               const void* /* allocation */,
+                                               size_t /* row bytes */,
+                                               size_t /* height */);
+typedef void* (*ProcResolver)(void* /* user data */, const char* /* name */);
+typedef bool (*TextureFrameCallback)(void* /* user data */,
+                                     int64_t /* texture identifier */,
+                                     size_t /* width */,
+                                     size_t /* height */,
+                                     FlutterOpenGLTexture* /* texture out */);
+typedef void (*VsyncCallback)(void* /* user data */, intptr_t /* baton */);
+typedef void (*OnPreEngineRestartCallback)(void* /* user data */);
+
+/// A structure to represent the width and height.
+typedef struct {
+  double width;
+  double height;
+} FlutterSize;
+
+/// A structure to represent the width and height.
+///
+/// See: \ref FlutterSize when the value are not integers.
+typedef struct {
+  uint32_t width;
+  uint32_t height;
+} FlutterUIntSize;
+
+/// A structure to represent a rectangle.
+typedef struct {
+  double left;
+  double top;
+  double right;
+  double bottom;
+} FlutterRect;
+
+/// A structure to represent a 2D point.
+typedef struct {
+  double x;
+  double y;
+} FlutterPoint;
+
+/// A structure to represent a rounded rectangle.
+typedef struct {
+  FlutterRect rect;
+  FlutterSize upper_left_corner_radius;
+  FlutterSize upper_right_corner_radius;
+  FlutterSize lower_right_corner_radius;
+  FlutterSize lower_left_corner_radius;
+} FlutterRoundedRect;
+
+/// This information is passed to the embedder when requesting a frame buffer
+/// object.
+///
+/// See: \ref FlutterOpenGLRendererConfig.fbo_with_frame_info_callback.
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterFrameInfo).
+  size_t struct_size;
+  /// The size of the surface that will be backed by the fbo.
+  FlutterUIntSize size;
+} FlutterFrameInfo;
+
+/// Callback for when a frame buffer object is requested.
+typedef uint32_t (*UIntFrameInfoCallback)(
+    void* /* user data */,
+    const FlutterFrameInfo* /* frame info */);
+
+/// This information is passed to the embedder when a surface is presented.
+///
+/// See: \ref FlutterOpenGLRendererConfig.present_with_info.
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterPresentInfo).
+  size_t struct_size;
+  /// Id of the fbo backing the surface that was presented.
+  uint32_t fbo_id;
+} FlutterPresentInfo;
+
+/// Callback for when a surface is presented.
+typedef bool (*BoolPresentInfoCallback)(
+    void* /* user data */,
+    const FlutterPresentInfo* /* present info */);
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
+  size_t struct_size;
+  BoolCallback make_current;
+  BoolCallback clear_current;
+  /// Specifying one (and only one) of `present` or `present_with_info` is
+  /// required. Specifying both is an error and engine initialization will be
+  /// terminated. The return value indicates success of the present call.
+  BoolCallback present;
+  /// Specifying one (and only one) of the `fbo_callback` or
+  /// `fbo_with_frame_info_callback` is required. Specifying both is an error
+  /// and engine intialization will be terminated. The return value indicates
+  /// the id of the frame buffer object that flutter will obtain the gl surface
+  /// from.
+  UIntCallback fbo_callback;
+  /// This is an optional callback. Flutter will ask the emebdder to create a GL
+  /// context current on a background thread. If the embedder is able to do so,
+  /// Flutter will assume that this context is in the same sharegroup as the
+  /// main rendering context and use this context for asynchronous texture
+  /// uploads. Though optional, it is recommended that all embedders set this
+  /// callback as it will lead to better performance in texture handling.
+  BoolCallback make_resource_current;
+  /// By default, the renderer config assumes that the FBO does not change for
+  /// the duration of the engine run. If this argument is true, the
+  /// engine will ask the embedder for an updated FBO target (via an
+  /// fbo_callback invocation) after a present call.
+  bool fbo_reset_after_present;
+  /// The transformation to apply to the render target before any rendering
+  /// operations. This callback is optional.
+  /// @attention      When using a custom compositor, the layer offset and sizes
+  ///                 will be affected by this transformation. It will be
+  ///                 embedder responsibility to render contents at the
+  ///                 transformed offset and size. This is useful for embedders
+  ///                 that want to render transformed contents directly into
+  ///                 hardware overlay planes without having to apply extra
+  ///                 transformations to layer contents (which may necessitate
+  ///                 an expensive off-screen render pass).
+  TransformationCallback surface_transformation;
+  ProcResolver gl_proc_resolver;
+  /// When the embedder specifies that a texture has a frame available, the
+  /// engine will call this method (on an internal engine managed thread) so
+  /// that external texture details can be supplied to the engine for subsequent
+  /// composition.
+  TextureFrameCallback gl_external_texture_frame_callback;
+  /// Specifying one (and only one) of the `fbo_callback` or
+  /// `fbo_with_frame_info_callback` is required. Specifying both is an error
+  /// and engine intialization will be terminated. The return value indicates
+  /// the id of the frame buffer object (fbo) that flutter will obtain the gl
+  /// surface from. When using this variant, the embedder is passed a
+  /// `FlutterFrameInfo` struct that indicates the properties of the surface
+  /// that flutter will acquire from the returned fbo.
+  UIntFrameInfoCallback fbo_with_frame_info_callback;
+  /// Specifying one (and only one) of `present` or `present_with_info` is
+  /// required. Specifying both is an error and engine initialization will be
+  /// terminated. When using this variant, the embedder is passed a
+  /// `FlutterPresentInfo` struct that the embedder can use to release any
+  /// resources. The return value indicates success of the present call.
+  BoolPresentInfoCallback present_with_info;
+} FlutterOpenGLRendererConfig;
+
+/// Alias for id<MTLDevice>.
+typedef const void* FlutterMetalDeviceHandle;
+
+/// Alias for id<MTLCommandQueue>.
+typedef const void* FlutterMetalCommandQueueHandle;
+
+/// Alias for id<MTLTexture>.
+typedef const void* FlutterMetalTextureHandle;
+
+/// Pixel format for the external texture.
+typedef enum {
+  kYUVA,
+  kRGBA,
+} FlutterMetalExternalTexturePixelFormat;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterMetalExternalTexture).
+  size_t struct_size;
+  /// Height of the texture.
+  size_t width;
+  /// Height of the texture.
+  size_t height;
+  /// The pixel format type of the external.
+  FlutterMetalExternalTexturePixelFormat pixel_format;
+  /// Represents the size of the `textures` array.
+  size_t num_textures;
+  /// Supported textures are YUVA and RGBA, in case of YUVA we expect 2 texture
+  /// handles to be provided by the embedder, Y first and UV next. In case of
+  /// RGBA only one should be passed.
+  /// These are individually aliases for id<MTLTexture>. These textures are
+  /// retained by the engine for the period of the composition. Once these
+  /// textures have been unregistered via the
+  /// `FlutterEngineUnregisterExternalTexture`, the embedder has to release
+  /// these textures.
+  FlutterMetalTextureHandle* textures;
+} FlutterMetalExternalTexture;
+
+/// Callback to provide an external texture for a given texture_id.
+/// See: external_texture_frame_callback.
+typedef bool (*FlutterMetalTextureFrameCallback)(
+    void* /* user data */,
+    int64_t /* texture identifier */,
+    size_t /* width */,
+    size_t /* height */,
+    FlutterMetalExternalTexture* /* texture out */);
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterMetalTexture).
+  size_t struct_size;
+  /// Embedder provided unique identifier to the texture buffer. Given that the
+  /// `texture` handle is passed to the engine to render to, the texture buffer
+  /// is itself owned by the embedder. This `texture_id` is then also given to
+  /// the embedder in the present callback.
+  int64_t texture_id;
+  /// Handle to the MTLTexture that is owned by the embedder. Engine will render
+  /// the frame into this texture.
+  FlutterMetalTextureHandle texture;
+  /// A baton that is not interpreted by the engine in any way. It will be given
+  /// back to the embedder in the destruction callback below. Embedder resources
+  /// may be associated with this baton.
+  void* user_data;
+  /// The callback invoked by the engine when it no longer needs this backing
+  /// store.
+  VoidCallback destruction_callback;
+} FlutterMetalTexture;
+
+/// Callback for when a metal texture is requested.
+typedef FlutterMetalTexture (*FlutterMetalTextureCallback)(
+    void* /* user data */,
+    const FlutterFrameInfo* /* frame info */);
+
+/// Callback for when a metal texture is presented. The texture_id here
+/// corresponds to the texture_id provided by the embedder in the
+/// `FlutterMetalTextureCallback` callback.
+typedef bool (*FlutterMetalPresentCallback)(
+    void* /* user data */,
+    const FlutterMetalTexture* /* texture */);
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterMetalRendererConfig).
+  size_t struct_size;
+  /// Alias for id<MTLDevice>.
+  FlutterMetalDeviceHandle device;
+  /// Alias for id<MTLCommandQueue>.
+  FlutterMetalCommandQueueHandle present_command_queue;
+  /// The callback that gets invoked when the engine requests the embedder for a
+  /// texture to render to.
+  FlutterMetalTextureCallback get_next_drawable_callback;
+  /// The callback presented to the embedder to present a fully populated metal
+  /// texture to the user.
+  FlutterMetalPresentCallback present_drawable_callback;
+  /// When the embedder specifies that a texture has a frame available, the
+  /// engine will call this method (on an internal engine managed thread) so
+  /// that external texture details can be supplied to the engine for subsequent
+  /// composition.
+  FlutterMetalTextureFrameCallback external_texture_frame_callback;
+} FlutterMetalRendererConfig;
+
+/// Alias for VkInstance.
+typedef void* FlutterVulkanInstanceHandle;
+
+/// Alias for VkPhysicalDevice.
+typedef void* FlutterVulkanPhysicalDeviceHandle;
+
+/// Alias for VkDevice.
+typedef void* FlutterVulkanDeviceHandle;
+
+/// Alias for VkQueue.
+typedef void* FlutterVulkanQueueHandle;
+
+/// Alias for VkImage.
+typedef uint64_t FlutterVulkanImageHandle;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterVulkanImage).
+  size_t struct_size;
+  /// Handle to the VkImage that is owned by the embedder. The engine will
+  /// bind this image for writing the frame.
+  FlutterVulkanImageHandle image;
+  /// The VkFormat of the image (for example: VK_FORMAT_R8G8B8A8_UNORM).
+  uint32_t format;
+} FlutterVulkanImage;
+
+/// Callback to fetch a Vulkan function pointer for a given instance. Normally,
+/// this should return the results of vkGetInstanceProcAddr.
+typedef void* (*FlutterVulkanInstanceProcAddressCallback)(
+    void* /* user data */,
+    FlutterVulkanInstanceHandle /* instance */,
+    const char* /* name */);
+
+/// Callback for when a VkImage is requested.
+typedef FlutterVulkanImage (*FlutterVulkanImageCallback)(
+    void* /* user data */,
+    const FlutterFrameInfo* /* frame info */);
+
+/// Callback for when a VkImage has been written to and is ready for use by the
+/// embedder.
+typedef bool (*FlutterVulkanPresentCallback)(
+    void* /* user data */,
+    const FlutterVulkanImage* /* image */);
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterVulkanRendererConfig).
+  size_t struct_size;
+
+  /// The Vulkan API version. This should match the value set in
+  /// VkApplicationInfo::apiVersion when the VkInstance was created.
+  uint32_t version;
+  /// VkInstance handle. Must not be destroyed before `FlutterEngineShutdown` is
+  /// called.
+  FlutterVulkanInstanceHandle instance;
+  /// VkPhysicalDevice handle.
+  FlutterVulkanPhysicalDeviceHandle physical_device;
+  /// VkDevice handle. Must not be destroyed before `FlutterEngineShutdown` is
+  /// called.
+  FlutterVulkanDeviceHandle device;
+  /// The queue family index of the VkQueue supplied in the next field.
+  uint32_t queue_family_index;
+  /// VkQueue handle.
+  FlutterVulkanQueueHandle queue;
+  /// The number of instance extensions available for enumerating in the next
+  /// field.
+  size_t enabled_instance_extension_count;
+  /// Array of enabled instance extension names. This should match the names
+  /// passed to `VkInstanceCreateInfo.ppEnabledExtensionNames` when the instance
+  /// was created, but any subset of enabled instance extensions may be
+  /// specified.
+  /// This field is optional; `nullptr` may be specified.
+  /// This memory is only accessed during the call to FlutterEngineInitialize.
+  const char** enabled_instance_extensions;
+  /// The number of device extensions available for enumerating in the next
+  /// field.
+  size_t enabled_device_extension_count;
+  /// Array of enabled logical device extension names. This should match the
+  /// names passed to `VkDeviceCreateInfo.ppEnabledExtensionNames` when the
+  /// logical device was created, but any subset of enabled logical device
+  /// extensions may be specified.
+  /// This field is optional; `nullptr` may be specified.
+  /// This memory is only accessed during the call to FlutterEngineInitialize.
+  /// For example: VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME
+  const char** enabled_device_extensions;
+  /// The callback invoked when resolving Vulkan function pointers.
+  FlutterVulkanInstanceProcAddressCallback get_instance_proc_address_callback;
+  /// The callback invoked when the engine requests a VkImage from the embedder
+  /// for rendering the next frame.
+  /// Not used if a FlutterCompositor is supplied in FlutterProjectArgs.
+  FlutterVulkanImageCallback get_next_image_callback;
+  /// The callback invoked when a VkImage has been written to and is ready for
+  /// use by the embedder. Prior to calling this callback, the engine performs
+  /// a host sync, and so the VkImage can be used in a pipeline by the embedder
+  /// without any additional synchronization.
+  /// Not used if a FlutterCompositor is supplied in FlutterProjectArgs.
+  FlutterVulkanPresentCallback present_image_callback;
+
+} FlutterVulkanRendererConfig;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterSoftwareRendererConfig).
+  size_t struct_size;
+  /// The callback presented to the embedder to present a fully populated buffer
+  /// to the user. The pixel format of the buffer is the native 32-bit RGBA
+  /// format. The buffer is owned by the Flutter engine and must be copied in
+  /// this callback if needed.
+  SoftwareSurfacePresentCallback surface_present_callback;
+} FlutterSoftwareRendererConfig;
+
+typedef struct {
+  FlutterRendererType type;
+  union {
+    FlutterOpenGLRendererConfig open_gl;
+    FlutterSoftwareRendererConfig software;
+    FlutterMetalRendererConfig metal;
+    FlutterVulkanRendererConfig vulkan;
+  };
+} FlutterRendererConfig;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
+  size_t struct_size;
+  /// Physical width of the window.
+  size_t width;
+  /// Physical height of the window.
+  size_t height;
+  /// Scale factor for the physical screen.
+  double pixel_ratio;
+  /// Horizontal physical location of the left side of the window on the screen.
+  size_t left;
+  /// Vertical physical location of the top of the window on the screen.
+  size_t top;
+  /// Top inset of window.
+  double physical_view_inset_top;
+  /// Right inset of window.
+  double physical_view_inset_right;
+  /// Bottom inset of window.
+  double physical_view_inset_bottom;
+  /// Left inset of window.
+  double physical_view_inset_left;
+} FlutterWindowMetricsEvent;
+
+/// The phase of the pointer event.
+typedef enum {
+  kCancel,
+  /// The pointer, which must have been down (see kDown), is now up.
+  ///
+  /// For touch, this means that the pointer is no longer in contact with the
+  /// screen. For a mouse, it means the last button was released. Note that if
+  /// any other buttons are still pressed when one button is released, that
+  /// should be sent as a kMove rather than a kUp.
+  kUp,
+  /// The pointer, which must have been been up, is now down.
+  ///
+  /// For touch, this means that the pointer has come into contact with the
+  /// screen. For a mouse, it means a button is now pressed. Note that if any
+  /// other buttons are already pressed when a new button is pressed, that
+  /// should be sent as a kMove rather than a kDown.
+  kDown,
+  /// The pointer moved while down.
+  ///
+  /// This is also used for changes in button state that don't cause a kDown or
+  /// kUp, such as releasing one of two pressed buttons.
+  kMove,
+  /// The pointer is now sending input to Flutter. For instance, a mouse has
+  /// entered the area where the Flutter content is displayed.
+  ///
+  /// A pointer should always be added before sending any other events.
+  kAdd,
+  /// The pointer is no longer sending input to Flutter. For instance, a mouse
+  /// has left the area where the Flutter content is displayed.
+  ///
+  /// A removed pointer should no longer send events until sending a new kAdd.
+  kRemove,
+  /// The pointer moved while up.
+  kHover,
+  /// A pan/zoom started on this pointer.
+  kPanZoomStart,
+  /// The pan/zoom updated.
+  kPanZoomUpdate,
+  /// The pan/zoom ended.
+  kPanZoomEnd,
+} FlutterPointerPhase;
+
+/// The device type that created a pointer event.
+typedef enum {
+  kFlutterPointerDeviceKindMouse = 1,
+  kFlutterPointerDeviceKindTouch,
+  kFlutterPointerDeviceKindStylus,
+  kFlutterPointerDeviceKindTrackpad,
+} FlutterPointerDeviceKind;
+
+/// Flags for the `buttons` field of `FlutterPointerEvent` when `device_kind`
+/// is `kFlutterPointerDeviceKindMouse`.
+typedef enum {
+  kFlutterPointerButtonMousePrimary = 1 << 0,
+  kFlutterPointerButtonMouseSecondary = 1 << 1,
+  kFlutterPointerButtonMouseMiddle = 1 << 2,
+  kFlutterPointerButtonMouseBack = 1 << 3,
+  kFlutterPointerButtonMouseForward = 1 << 4,
+  /// If a mouse has more than five buttons, send higher bit shifted values
+  /// corresponding to the button number: 1 << 5 for the 6th, etc.
+} FlutterPointerMouseButtons;
+
+/// The type of a pointer signal.
+typedef enum {
+  kFlutterPointerSignalKindNone,
+  kFlutterPointerSignalKindScroll,
+} FlutterPointerSignalKind;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterPointerEvent).
+  size_t struct_size;
+  FlutterPointerPhase phase;
+  /// The timestamp at which the pointer event was generated. The timestamp
+  /// should be specified in microseconds and the clock should be the same as
+  /// that used by `FlutterEngineGetCurrentTime`.
+  size_t timestamp;
+  /// The x coordinate of the pointer event in physical pixels.
+  double x;
+  /// The y coordinate of the pointer event in physical pixels.
+  double y;
+  /// An optional device identifier. If this is not specified, it is assumed
+  /// that the embedder has no multi-touch capability.
+  int32_t device;
+  FlutterPointerSignalKind signal_kind;
+  /// The x offset of the scroll in physical pixels.
+  double scroll_delta_x;
+  /// The y offset of the scroll in physical pixels.
+  double scroll_delta_y;
+  /// The type of the device generating this event.
+  /// Backwards compatibility note: If this is not set, the device will be
+  /// treated as a mouse, with the primary button set for `kDown` and `kMove`.
+  /// If set explicitly to `kFlutterPointerDeviceKindMouse`, you must set the
+  /// correct buttons.
+  FlutterPointerDeviceKind device_kind;
+  /// The buttons currently pressed, if any.
+  int64_t buttons;
+  /// The x offset of the pan/zoom in physical pixels.
+  double pan_x;
+  /// The y offset of the pan/zoom in physical pixels.
+  double pan_y;
+  /// The scale of the pan/zoom, where 1.0 is the initial scale.
+  double scale;
+  /// The rotation of the pan/zoom in radians, where 0.0 is the initial angle.
+  double rotation;
+} FlutterPointerEvent;
+
+typedef enum {
+  kFlutterKeyEventTypeUp = 1,
+  kFlutterKeyEventTypeDown,
+  kFlutterKeyEventTypeRepeat,
+} FlutterKeyEventType;
+
+/// A structure to represent a key event.
+///
+/// Sending `FlutterKeyEvent` via `FlutterEngineSendKeyEvent` results in a
+/// corresponding `FlutterKeyEvent` to be dispatched in the framework. It is
+/// embedder's responsibility to ensure the regularity of sent events, since the
+/// framework only performs simple one-to-one mapping. The events must conform
+/// the following rules:
+///
+///  * Each key press sequence shall consist of one key down event (`kind` being
+///    `kFlutterKeyEventTypeDown`), zero or more repeat events, and one key up
+///    event, representing a physical key button being pressed, held, and
+///    released.
+///  * All events throughout a key press sequence shall have the same `physical`
+///    and `logical`. Having different `character`s is allowed.
+///
+/// A `FlutterKeyEvent` with `physical` 0 and `logical` 0 is an empty event.
+/// This is the only case either `physical` or `logical` can be 0. An empty
+/// event must be sent if a key message should be converted to no
+/// `FlutterKeyEvent`s, for example, when a key down message is received for a
+/// key that has already been pressed according to the record. This is to ensure
+/// some `FlutterKeyEvent` arrives at the framework before raw key message.
+/// See https://github.com/flutter/flutter/issues/87230.
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterKeyEvent).
+  size_t struct_size;
+  /// The timestamp at which the key event was generated. The timestamp should
+  /// be specified in microseconds and the clock should be the same as that used
+  /// by `FlutterEngineGetCurrentTime`.
+  double timestamp;
+  /// The event kind.
+  FlutterKeyEventType type;
+  /// The USB HID code for the physical key of the event.
+  ///
+  /// For the full definition and list of pre-defined physical keys, see
+  /// `PhysicalKeyboardKey` from the framework.
+  ///
+  /// The only case that `physical` might be 0 is when this is an empty event.
+  /// See `FlutterKeyEvent` for introduction.
+  uint64_t physical;
+  /// The key ID for the logical key of this event.
+  ///
+  /// For the full definition and a list of pre-defined logical keys, see
+  /// `LogicalKeyboardKey` from the framework.
+  ///
+  /// The only case that `logical` might be 0 is when this is an empty event.
+  /// See `FlutterKeyEvent` for introduction.
+  uint64_t logical;
+  /// Null-terminated character input from the event. Can be null. Ignored for
+  /// up events.
+  const char* character;
+  /// True if this event does not correspond to a native event.
+  ///
+  /// The embedder is likely to skip events and/or construct new events that do
+  /// not correspond to any native events in order to conform the regularity
+  /// of events (as documented in `FlutterKeyEvent`). An example is when a key
+  /// up is missed due to loss of window focus, on a platform that provides
+  /// query to key pressing status, the embedder might realize that the key has
+  /// been released at the next key event, and should construct a synthesized up
+  /// event immediately before the actual event.
+  ///
+  /// An event being synthesized means that the `timestamp` might greatly
+  /// deviate from the actual time when the event occurs physically.
+  bool synthesized;
+} FlutterKeyEvent;
+
+typedef void (*FlutterKeyEventCallback)(bool /* handled */,
+                                        void* /* user_data */);
+
+struct _FlutterPlatformMessageResponseHandle;
+typedef struct _FlutterPlatformMessageResponseHandle
+    FlutterPlatformMessageResponseHandle;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterPlatformMessage).
+  size_t struct_size;
+  const char* channel;
+  const uint8_t* message;
+  size_t message_size;
+  /// The response handle on which to invoke
+  /// `FlutterEngineSendPlatformMessageResponse` when the response is ready.
+  /// `FlutterEngineSendPlatformMessageResponse` must be called for all messages
+  /// received by the embedder. Failure to call
+  /// `FlutterEngineSendPlatformMessageResponse` will cause a memory leak. It is
+  /// not safe to send multiple responses on a single response object.
+  const FlutterPlatformMessageResponseHandle* response_handle;
+} FlutterPlatformMessage;
+
+typedef void (*FlutterPlatformMessageCallback)(
+    const FlutterPlatformMessage* /* message*/,
+    void* /* user data */);
+
+typedef void (*FlutterDataCallback)(const uint8_t* /* data */,
+                                    size_t /* size */,
+                                    void* /* user data */);
+
+/// The identifier of the platform view. This identifier is specified by the
+/// application when a platform view is added to the scene via the
+/// `SceneBuilder.addPlatformView` call.
+typedef int64_t FlutterPlatformViewIdentifier;
+
+/// `FlutterSemanticsNode` ID used as a sentinel to signal the end of a batch of
+/// semantics node updates.
+FLUTTER_EXPORT
+extern const int32_t kFlutterSemanticsNodeIdBatchEnd;
+
+/// A node that represents some semantic data.
+///
+/// The semantics tree is maintained during the semantics phase of the pipeline
+/// (i.e., during PipelineOwner.flushSemantics), which happens after
+/// compositing. Updates are then pushed to embedders via the registered
+/// `FlutterUpdateSemanticsNodeCallback`.
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterSemanticsNode).
+  size_t struct_size;
+  /// The unique identifier for this node.
+  int32_t id;
+  /// The set of semantics flags associated with this node.
+  FlutterSemanticsFlag flags;
+  /// The set of semantics actions applicable to this node.
+  FlutterSemanticsAction actions;
+  /// The position at which the text selection originates.
+  int32_t text_selection_base;
+  /// The position at which the text selection terminates.
+  int32_t text_selection_extent;
+  /// The total number of scrollable children that contribute to semantics.
+  int32_t scroll_child_count;
+  /// The index of the first visible semantic child of a scroll node.
+  int32_t scroll_index;
+  /// The current scrolling position in logical pixels if the node is
+  /// scrollable.
+  double scroll_position;
+  /// The maximum in-range value for `scrollPosition` if the node is scrollable.
+  double scroll_extent_max;
+  /// The minimum in-range value for `scrollPosition` if the node is scrollable.
+  double scroll_extent_min;
+  /// The elevation along the z-axis at which the rect of this semantics node is
+  /// located above its parent.
+  double elevation;
+  /// Describes how much space the semantics node takes up along the z-axis.
+  double thickness;
+  /// A textual description of the node.
+  const char* label;
+  /// A brief description of the result of performing an action on the node.
+  const char* hint;
+  /// A textual description of the current value of the node.
+  const char* value;
+  /// A value that `value` will have after a kFlutterSemanticsActionIncrease`
+  /// action has been performed.
+  const char* increased_value;
+  /// A value that `value` will have after a kFlutterSemanticsActionDecrease`
+  /// action has been performed.
+  const char* decreased_value;
+  /// The reading direction for `label`, `value`, `hint`, `increasedValue`, and
+  /// `decreasedValue`.
+  FlutterTextDirection text_direction;
+  /// The bounding box for this node in its coordinate system.
+  FlutterRect rect;
+  /// The transform from this node's coordinate system to its parent's
+  /// coordinate system.
+  FlutterTransformation transform;
+  /// The number of children this node has.
+  size_t child_count;
+  /// Array of child node IDs in traversal order. Has length `child_count`.
+  const int32_t* children_in_traversal_order;
+  /// Array of child node IDs in hit test order. Has length `child_count`.
+  const int32_t* children_in_hit_test_order;
+  /// The number of custom accessibility action associated with this node.
+  size_t custom_accessibility_actions_count;
+  /// Array of `FlutterSemanticsCustomAction` IDs associated with this node.
+  /// Has length `custom_accessibility_actions_count`.
+  const int32_t* custom_accessibility_actions;
+  /// Identifier of the platform view associated with this semantics node, or
+  /// -1 if none.
+  FlutterPlatformViewIdentifier platform_view_id;
+} FlutterSemanticsNode;
+
+/// `FlutterSemanticsCustomAction` ID used as a sentinel to signal the end of a
+/// batch of semantics custom action updates.
+FLUTTER_EXPORT
+extern const int32_t kFlutterSemanticsCustomActionIdBatchEnd;
+
+/// A custom semantics action, or action override.
+///
+/// Custom actions can be registered by applications in order to provide
+/// semantic actions other than the standard actions available through the
+/// `FlutterSemanticsAction` enum.
+///
+/// Action overrides are custom actions that the application developer requests
+/// to be used in place of the standard actions in the `FlutterSemanticsAction`
+/// enum.
+typedef struct {
+  /// The size of the struct. Must be sizeof(FlutterSemanticsCustomAction).
+  size_t struct_size;
+  /// The unique custom action or action override ID.
+  int32_t id;
+  /// For overridden standard actions, corresponds to the
+  /// `FlutterSemanticsAction` to override.
+  FlutterSemanticsAction override_action;
+  /// The user-readable name of this custom semantics action.
+  const char* label;
+  /// The hint description of this custom semantics action.
+  const char* hint;
+} FlutterSemanticsCustomAction;
+
+typedef void (*FlutterUpdateSemanticsNodeCallback)(
+    const FlutterSemanticsNode* /* semantics node */,
+    void* /* user data */);
+
+typedef void (*FlutterUpdateSemanticsCustomActionCallback)(
+    const FlutterSemanticsCustomAction* /* semantics custom action */,
+    void* /* user data */);
+
+typedef struct _FlutterTaskRunner* FlutterTaskRunner;
+
+typedef struct {
+  FlutterTaskRunner runner;
+  uint64_t task;
+} FlutterTask;
+
+typedef void (*FlutterTaskRunnerPostTaskCallback)(
+    FlutterTask /* task */,
+    uint64_t /* target time nanos */,
+    void* /* user data */);
+
+/// An interface used by the Flutter engine to execute tasks at the target time
+/// on a specified thread. There should be a 1-1 relationship between a thread
+/// and a task runner. It is undefined behavior to run a task on a thread that
+/// is not associated with its task runner.
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterTaskRunnerDescription).
+  size_t struct_size;
+  void* user_data;
+  /// May be called from any thread. Should return true if tasks posted on the
+  /// calling thread will be run on that same thread.
+  ///
+  /// @attention     This field is required.
+  BoolCallback runs_task_on_current_thread_callback;
+  /// May be called from any thread. The given task should be executed by the
+  /// embedder on the thread associated with that task runner by calling
+  /// `FlutterEngineRunTask` at the given target time. The system monotonic
+  /// clock should be used for the target time. The target time is the absolute
+  /// time from epoch (NOT a delta) at which the task must be returned back to
+  /// the engine on the correct thread. If the embedder needs to calculate a
+  /// delta, `FlutterEngineGetCurrentTime` may be called and the difference used
+  /// as the delta.
+  ///
+  /// @attention     This field is required.
+  FlutterTaskRunnerPostTaskCallback post_task_callback;
+  /// A unique identifier for the task runner. If multiple task runners service
+  /// tasks on the same thread, their identifiers must match.
+  size_t identifier;
+} FlutterTaskRunnerDescription;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
+  size_t struct_size;
+  /// Specify the task runner for the thread on which the `FlutterEngineRun`
+  /// call is made. The same task runner description can be specified for both
+  /// the render and platform task runners. This makes the Flutter engine use
+  /// the same thread for both task runners.
+  const FlutterTaskRunnerDescription* platform_task_runner;
+  /// Specify the task runner for the thread on which the render tasks will be
+  /// run. The same task runner description can be specified for both the render
+  /// and platform task runners. This makes the Flutter engine use the same
+  /// thread for both task runners.
+  const FlutterTaskRunnerDescription* render_task_runner;
+  /// Specify a callback that is used to set the thread priority for embedder
+  /// task runners.
+  void (*thread_priority_setter)(FlutterThreadPriority);
+} FlutterCustomTaskRunners;
+
+typedef struct {
+  /// The type of the OpenGL backing store. Currently, it can either be a
+  /// texture or a framebuffer.
+  FlutterOpenGLTargetType type;
+  union {
+    /// A texture for Flutter to render into.
+    FlutterOpenGLTexture texture;
+    /// A framebuffer for Flutter to render into. The embedder must ensure that
+    /// the framebuffer is complete.
+    FlutterOpenGLFramebuffer framebuffer;
+  };
+} FlutterOpenGLBackingStore;
+
+typedef struct {
+  /// A pointer to the raw bytes of the allocation described by this software
+  /// backing store.
+  const void* allocation;
+  /// The number of bytes in a single row of the allocation.
+  size_t row_bytes;
+  /// The number of rows in the allocation.
+  size_t height;
+  /// A baton that is not interpreted by the engine in any way. It will be given
+  /// back to the embedder in the destruction callback below. Embedder resources
+  /// may be associated with this baton.
+  void* user_data;
+  /// The callback invoked by the engine when it no longer needs this backing
+  /// store.
+  VoidCallback destruction_callback;
+} FlutterSoftwareBackingStore;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterMetalBackingStore).
+  size_t struct_size;
+  union {
+    // A Metal texture for Flutter to render into. Ownership is not transferred
+    // to Flutter; the texture is CFRetained on successfully being passed in and
+    // CFReleased when no longer used.
+    FlutterMetalTexture texture;
+  };
+} FlutterMetalBackingStore;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterVulkanBackingStore).
+  size_t struct_size;
+  /// The image that the layer will be rendered to. This image must already be
+  /// available for the engine to bind for writing when it's given to the engine
+  /// via the backing store creation callback. The engine will perform a host
+  /// sync for all layers prior to calling the compositor present callback, and
+  /// so the written layer images can be freely bound by the embedder without
+  /// any additional synchronization.
+  const FlutterVulkanImage* image;
+  /// A baton that is not interpreted by the engine in any way. It will be given
+  /// back to the embedder in the destruction callback below. Embedder resources
+  /// may be associated with this baton.
+  void* user_data;
+  /// The callback invoked by the engine when it no longer needs this backing
+  /// store.
+  VoidCallback destruction_callback;
+} FlutterVulkanBackingStore;
+
+typedef enum {
+  /// Indicates that the Flutter application requested that an opacity be
+  /// applied to the platform view.
+  kFlutterPlatformViewMutationTypeOpacity,
+  /// Indicates that the Flutter application requested that the platform view be
+  /// clipped using a rectangle.
+  kFlutterPlatformViewMutationTypeClipRect,
+  /// Indicates that the Flutter application requested that the platform view be
+  /// clipped using a rounded rectangle.
+  kFlutterPlatformViewMutationTypeClipRoundedRect,
+  /// Indicates that the Flutter application requested that the platform view be
+  /// transformed before composition.
+  kFlutterPlatformViewMutationTypeTransformation,
+} FlutterPlatformViewMutationType;
+
+typedef struct {
+  /// The type of the mutation described by the subsequent union.
+  FlutterPlatformViewMutationType type;
+  union {
+    double opacity;
+    FlutterRect clip_rect;
+    FlutterRoundedRect clip_rounded_rect;
+    FlutterTransformation transformation;
+  };
+} FlutterPlatformViewMutation;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterPlatformView).
+  size_t struct_size;
+  /// The identifier of this platform view. This identifier is specified by the
+  /// application when a platform view is added to the scene via the
+  /// `SceneBuilder.addPlatformView` call.
+  FlutterPlatformViewIdentifier identifier;
+  /// The number of mutations to be applied to the platform view by the embedder
+  /// before on-screen composition.
+  size_t mutations_count;
+  /// The mutations to be applied by this platform view before it is composited
+  /// on-screen. The Flutter application may transform the platform view but
+  /// these transformations cannot be affected by the Flutter compositor because
+  /// it does not render platform views. Since the embedder is responsible for
+  /// composition of these views, it is also the embedder's responsibility to
+  /// affect the appropriate transformation.
+  ///
+  /// The mutations must be applied in order. The mutations done in the
+  /// collection don't take into account the device pixel ratio or the root
+  /// surface transformation. If these exist, the first mutation in the list
+  /// will be a transformation mutation to make sure subsequent mutations are in
+  /// the correct coordinate space.
+  const FlutterPlatformViewMutation** mutations;
+} FlutterPlatformView;
+
+typedef enum {
+  /// Specifies an OpenGL backing store. Can either be an OpenGL texture or
+  /// framebuffer.
+  kFlutterBackingStoreTypeOpenGL,
+  /// Specified an software allocation for Flutter to render into using the CPU.
+  kFlutterBackingStoreTypeSoftware,
+  /// Specifies a Metal backing store. This is backed by a Metal texture.
+  kFlutterBackingStoreTypeMetal,
+  /// Specifies a Vulkan backing store. This is backed by a Vulkan VkImage.
+  kFlutterBackingStoreTypeVulkan,
+} FlutterBackingStoreType;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterBackingStore).
+  size_t struct_size;
+  /// A baton that is not interpreted by the engine in any way. The embedder may
+  /// use this to associate resources that are tied to the lifecycle of the
+  /// `FlutterBackingStore`.
+  void* user_data;
+  /// Specifies the type of backing store.
+  FlutterBackingStoreType type;
+  /// Indicates if this backing store was updated since the last time it was
+  /// associated with a presented layer.
+  bool did_update;
+  union {
+    /// The description of the OpenGL backing store.
+    FlutterOpenGLBackingStore open_gl;
+    /// The description of the software backing store.
+    FlutterSoftwareBackingStore software;
+    // The description of the Metal backing store.
+    FlutterMetalBackingStore metal;
+    // The description of the Vulkan backing store.
+    FlutterVulkanBackingStore vulkan;
+  };
+} FlutterBackingStore;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterBackingStoreConfig).
+  size_t struct_size;
+  /// The size of the render target the engine expects to render into.
+  FlutterSize size;
+} FlutterBackingStoreConfig;
+
+typedef enum {
+  /// Indicates that the contents of this layer are rendered by Flutter into a
+  /// backing store.
+  kFlutterLayerContentTypeBackingStore,
+  /// Indicates that the contents of this layer are determined by the embedder.
+  kFlutterLayerContentTypePlatformView,
+} FlutterLayerContentType;
+
+typedef struct {
+  /// This size of this struct. Must be sizeof(FlutterLayer).
+  size_t struct_size;
+  /// Each layer displays contents in one way or another. The type indicates
+  /// whether those contents are specified by Flutter or the embedder.
+  FlutterLayerContentType type;
+  union {
+    /// Indicates that the contents of this layer are rendered by Flutter into a
+    /// backing store.
+    const FlutterBackingStore* backing_store;
+    /// Indicates that the contents of this layer are determined by the
+    /// embedder.
+    const FlutterPlatformView* platform_view;
+  };
+  /// The offset of this layer (in physical pixels) relative to the top left of
+  /// the root surface used by the engine.
+  FlutterPoint offset;
+  /// The size of the layer (in physical pixels).
+  FlutterSize size;
+} FlutterLayer;
+
+typedef bool (*FlutterBackingStoreCreateCallback)(
+    const FlutterBackingStoreConfig* config,
+    FlutterBackingStore* backing_store_out,
+    void* user_data);
+
+typedef bool (*FlutterBackingStoreCollectCallback)(
+    const FlutterBackingStore* renderer,
+    void* user_data);
+
+typedef bool (*FlutterLayersPresentCallback)(const FlutterLayer** layers,
+                                             size_t layers_count,
+                                             void* user_data);
+
+typedef struct {
+  /// This size of this struct. Must be sizeof(FlutterCompositor).
+  size_t struct_size;
+  /// A baton that in not interpreted by the engine in any way. If it passed
+  /// back to the embedder in `FlutterCompositor.create_backing_store_callback`,
+  /// `FlutterCompositor.collect_backing_store_callback` and
+  /// `FlutterCompositor.present_layers_callback`
+  void* user_data;
+  /// A callback invoked by the engine to obtain a backing store for a specific
+  /// `FlutterLayer`.
+  ///
+  /// On ABI stability: Callers must take care to restrict access within
+  /// `FlutterBackingStore::struct_size` when specifying a new backing store to
+  /// the engine. This only matters if the embedder expects to be used with
+  /// engines older than the version whose headers it used during compilation.
+  FlutterBackingStoreCreateCallback create_backing_store_callback;
+  /// A callback invoked by the engine to release the backing store. The
+  /// embedder may collect any resources associated with the backing store.
+  FlutterBackingStoreCollectCallback collect_backing_store_callback;
+  /// Callback invoked by the engine to composite the contents of each layer
+  /// onto the screen.
+  FlutterLayersPresentCallback present_layers_callback;
+  /// Avoid caching backing stores provided by this compositor.
+  bool avoid_backing_store_cache;
+} FlutterCompositor;
+
+typedef struct {
+  /// This size of this struct. Must be sizeof(FlutterLocale).
+  size_t struct_size;
+  /// The language code of the locale. For example, "en". This is a required
+  /// field. The string must be null terminated. It may be collected after the
+  /// call to `FlutterEngineUpdateLocales`.
+  const char* language_code;
+  /// The country code of the locale. For example, "US". This is a an optional
+  /// field. The string must be null terminated if present. It may be collected
+  /// after the call to `FlutterEngineUpdateLocales`. If not present, a
+  /// `nullptr` may be specified.
+  const char* country_code;
+  /// The script code of the locale. This is a an optional field. The string
+  /// must be null terminated if present. It may be collected after the call to
+  /// `FlutterEngineUpdateLocales`. If not present, a `nullptr` may be
+  /// specified.
+  const char* script_code;
+  /// The variant code of the locale. This is a an optional field. The string
+  /// must be null terminated if present. It may be collected after the call to
+  /// `FlutterEngineUpdateLocales`. If not present, a `nullptr` may be
+  /// specified.
+  const char* variant_code;
+} FlutterLocale;
+
+/// Callback that returns the system locale.
+///
+/// Embedders that implement this callback should return the `FlutterLocale`
+/// from the `supported_locales` list that most closely matches the
+/// user/device's preferred locale.
+///
+/// This callback does not currently provide the user_data baton.
+/// https://github.com/flutter/flutter/issues/79826
+typedef const FlutterLocale* (*FlutterComputePlatformResolvedLocaleCallback)(
+    const FlutterLocale** /* supported_locales*/,
+    size_t /* Number of locales*/);
+
+/// Display refers to a graphics hardware system consisting of a framebuffer,
+/// typically a monitor or a screen. This ID is unique per display and is
+/// stable until the Flutter application restarts.
+typedef uint64_t FlutterEngineDisplayId;
+
+typedef struct {
+  /// This size of this struct. Must be sizeof(FlutterDisplay).
+  size_t struct_size;
+
+  FlutterEngineDisplayId display_id;
+
+  /// This is set to true if the embedder only has one display. In cases where
+  /// this is set to true, the value of display_id is ignored. In cases where
+  /// this is not set to true, it is expected that a valid display_id be
+  /// provided.
+  bool single_display;
+
+  /// This represents the refresh period in frames per second. This value may be
+  /// zero if the device is not running or unavailable or unknown.
+  double refresh_rate;
+} FlutterEngineDisplay;
+
+/// The update type parameter that is passed to
+/// `FlutterEngineNotifyDisplayUpdate`.
+typedef enum {
+  /// `FlutterEngineDisplay`s that were active during start-up. A display is
+  /// considered active if:
+  ///    1. The frame buffer hardware is connected.
+  ///    2. The display is drawable, e.g. it isn't being mirrored from another
+  ///    connected display or sleeping.
+  kFlutterEngineDisplaysUpdateTypeStartup,
+  kFlutterEngineDisplaysUpdateTypeCount,
+} FlutterEngineDisplaysUpdateType;
+
+typedef int64_t FlutterEngineDartPort;
+
+typedef enum {
+  kFlutterEngineDartObjectTypeNull,
+  kFlutterEngineDartObjectTypeBool,
+  kFlutterEngineDartObjectTypeInt32,
+  kFlutterEngineDartObjectTypeInt64,
+  kFlutterEngineDartObjectTypeDouble,
+  kFlutterEngineDartObjectTypeString,
+  /// The object will be made available to Dart code as an instance of
+  /// Uint8List.
+  kFlutterEngineDartObjectTypeBuffer,
+} FlutterEngineDartObjectType;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterEngineDartBuffer).
+  size_t struct_size;
+  /// An opaque baton passed back to the embedder when the
+  /// buffer_collect_callback is invoked. The engine does not interpret this
+  /// field in any way.
+  void* user_data;
+  /// This is an optional field.
+  ///
+  /// When specified, the engine will assume that the buffer is owned by the
+  /// embedder. When the data is no longer needed by any isolate, this callback
+  /// will be made on an internal engine managed thread. The embedder is free to
+  /// collect the buffer here. When this field is specified, it is the embedders
+  /// responsibility to keep the buffer alive and not modify it till this
+  /// callback is invoked by the engine. The user data specified in the callback
+  /// is the value of `user_data` field in this struct.
+  ///
+  /// When NOT specified, the VM creates an internal copy of the buffer. The
+  /// caller is free to modify the buffer as necessary or collect it immediately
+  /// after the call to `FlutterEnginePostDartObject`.
+  ///
+  /// @attention      The buffer_collect_callback is will only be invoked by the
+  ///                 engine when the `FlutterEnginePostDartObject` method
+  ///                 returns kSuccess. In case of non-successful calls to this
+  ///                 method, it is the embedders responsibility to collect the
+  ///                 buffer.
+  VoidCallback buffer_collect_callback;
+  /// A pointer to the bytes of the buffer. When the buffer is owned by the
+  /// embedder (by specifying the `buffer_collect_callback`), Dart code may
+  /// modify that embedder owned buffer. For this reason, it is important that
+  /// this buffer not have page protections that restrict writing to this
+  /// buffer.
+  uint8_t* buffer;
+  /// The size of the buffer.
+  size_t buffer_size;
+} FlutterEngineDartBuffer;
+
+/// This struct specifies the native representation of a Dart object that can be
+/// sent via a send port to any isolate in the VM that has the corresponding
+/// receive port.
+///
+/// All fields in this struct are copied out in the call to
+/// `FlutterEnginePostDartObject` and the caller is free to reuse or collect
+/// this struct after that call.
+typedef struct {
+  FlutterEngineDartObjectType type;
+  union {
+    bool bool_value;
+    int32_t int32_value;
+    int64_t int64_value;
+    double double_value;
+    /// A null terminated string. This string will be copied by the VM in the
+    /// call to `FlutterEnginePostDartObject` and must be collected by the
+    /// embedder after that call is made.
+    const char* string_value;
+    const FlutterEngineDartBuffer* buffer_value;
+  };
+} FlutterEngineDartObject;
+
+/// This enum allows embedders to determine the type of the engine thread in the
+/// FlutterNativeThreadCallback. Based on the thread type, the embedder may be
+/// able to tweak the thread priorities for optimum performance.
+typedef enum {
+  /// The Flutter Engine considers the thread on which the FlutterEngineRun call
+  /// is made to be the platform thread. There is only one such thread per
+  /// engine instance.
+  kFlutterNativeThreadTypePlatform,
+  /// This is the thread the Flutter Engine uses to execute rendering commands
+  /// based on the selected client rendering API. There is only one such thread
+  /// per engine instance.
+  kFlutterNativeThreadTypeRender,
+  /// This is a dedicated thread on which the root Dart isolate is serviced.
+  /// There is only one such thread per engine instance.
+  kFlutterNativeThreadTypeUI,
+  /// Multiple threads are used by the Flutter engine to perform long running
+  /// background tasks.
+  kFlutterNativeThreadTypeWorker,
+} FlutterNativeThreadType;
+
+/// A callback made by the engine in response to
+/// `FlutterEnginePostCallbackOnAllNativeThreads` on all internal thread.
+typedef void (*FlutterNativeThreadCallback)(FlutterNativeThreadType type,
+                                            void* user_data);
+
+/// AOT data source type.
+typedef enum {
+  kFlutterEngineAOTDataSourceTypeElfPath
+} FlutterEngineAOTDataSourceType;
+
+/// This struct specifies one of the various locations the engine can look for
+/// AOT data sources.
+typedef struct {
+  FlutterEngineAOTDataSourceType type;
+  union {
+    /// Absolute path to an ELF library file.
+    const char* elf_path;
+  };
+} FlutterEngineAOTDataSource;
+
+// Logging callback for Dart application messages.
+//
+// The `tag` parameter contains a null-terminated string containing a logging
+// tag or component name that can be used to identify system log messages from
+// the app. The `message` parameter contains a null-terminated string
+// containing the message to be logged. `user_data` is a user data baton passed
+// in `FlutterEngineRun`.
+typedef void (*FlutterLogMessageCallback)(const char* /* tag */,
+                                          const char* /* message */,
+                                          void* /* user_data */);
+
+/// An opaque object that describes the AOT data that can be used to launch a
+/// FlutterEngine instance in AOT mode.
+typedef struct _FlutterEngineAOTData* FlutterEngineAOTData;
+
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterProjectArgs).
+  size_t struct_size;
+  /// The path to the Flutter assets directory containing project assets. The
+  /// string can be collected after the call to `FlutterEngineRun` returns. The
+  /// string must be NULL terminated.
+  const char* assets_path;
+  /// The path to the Dart file containing the `main` entry point.
+  /// The string can be collected after the call to `FlutterEngineRun` returns.
+  /// The string must be NULL terminated.
+  ///
+  /// @deprecated     As of Dart 2, running from Dart source is no longer
+  ///                 supported. Dart code should now be compiled to kernel form
+  ///                 and will be loaded by from `kernel_blob.bin` in the assets
+  ///                 directory. This struct member is retained for ABI
+  ///                 stability.
+  const char* main_path__unused__;
+  /// The path to the `.packages` file for the project. The string can be
+  /// collected after the call to `FlutterEngineRun` returns. The string must be
+  /// NULL terminated.
+  ///
+  /// @deprecated    As of Dart 2, running from Dart source is no longer
+  ///                supported. Dart code should now be compiled to kernel form
+  ///                and will be loaded by from `kernel_blob.bin` in the assets
+  ///                directory. This struct member is retained for ABI
+  ///                stability.
+  const char* packages_path__unused__;
+  /// The path to the `icudtl.dat` file for the project. The string can be
+  /// collected after the call to `FlutterEngineRun` returns. The string must
+  /// be NULL terminated.
+  const char* icu_data_path;
+  /// The command line argument count used to initialize the project.
+  int command_line_argc;
+  /// The command line arguments used to initialize the project. The strings can
+  /// be collected after the call to `FlutterEngineRun` returns. The strings
+  /// must be `NULL` terminated.
+  ///
+  /// @attention     The first item in the command line (if specified at all) is
+  ///                interpreted as the executable name. So if an engine flag
+  ///                needs to be passed into the same, it needs to not be the
+  ///                very first item in the list.
+  ///
+  /// The set of engine flags are only meant to control
+  /// unstable features in the engine. Deployed applications should not pass any
+  /// command line arguments at all as they may affect engine stability at
+  /// runtime in the presence of un-sanitized input. The list of currently
+  /// recognized engine flags and their descriptions can be retrieved from the
+  /// `switches.h` engine source file.
+  const char* const* command_line_argv;
+  /// The callback invoked by the engine in order to give the embedder the
+  /// chance to respond to platform messages from the Dart application.
+  /// The callback will be invoked on the thread on which the `FlutterEngineRun`
+  /// call is made. The second parameter, `user_data`, is supplied when
+  /// `FlutterEngineRun` or `FlutterEngineInitialize` is called.
+  FlutterPlatformMessageCallback platform_message_callback;
+  /// The VM snapshot data buffer used in AOT operation. This buffer must be
+  /// mapped in as read-only. For more information refer to the documentation on
+  /// the Wiki at
+  /// https://github.com/flutter/flutter/wiki/Flutter-engine-operation-in-AOT-Mode
+  const uint8_t* vm_snapshot_data;
+  /// The size of the VM snapshot data buffer.  If vm_snapshot_data is a symbol
+  /// reference, 0 may be passed here.
+  size_t vm_snapshot_data_size;
+  /// The VM snapshot instructions buffer used in AOT operation. This buffer
+  /// must be mapped in as read-execute. For more information refer to the
+  /// documentation on the Wiki at
+  /// https://github.com/flutter/flutter/wiki/Flutter-engine-operation-in-AOT-Mode
+  const uint8_t* vm_snapshot_instructions;
+  /// The size of the VM snapshot instructions buffer. If
+  /// vm_snapshot_instructions is a symbol reference, 0 may be passed here.
+  size_t vm_snapshot_instructions_size;
+  /// The isolate snapshot data buffer used in AOT operation. This buffer must
+  /// be mapped in as read-only. For more information refer to the documentation
+  /// on the Wiki at
+  /// https://github.com/flutter/flutter/wiki/Flutter-engine-operation-in-AOT-Mode
+  const uint8_t* isolate_snapshot_data;
+  /// The size of the isolate snapshot data buffer.  If isolate_snapshot_data is
+  /// a symbol reference, 0 may be passed here.
+  size_t isolate_snapshot_data_size;
+  /// The isolate snapshot instructions buffer used in AOT operation. This
+  /// buffer must be mapped in as read-execute. For more information refer to
+  /// the documentation on the Wiki at
+  /// https://github.com/flutter/flutter/wiki/Flutter-engine-operation-in-AOT-Mode
+  const uint8_t* isolate_snapshot_instructions;
+  /// The size of the isolate snapshot instructions buffer. If
+  /// isolate_snapshot_instructions is a symbol reference, 0 may be passed here.
+  size_t isolate_snapshot_instructions_size;
+  /// The callback invoked by the engine in root isolate scope. Called
+  /// immediately after the root isolate has been created and marked runnable.
+  VoidCallback root_isolate_create_callback;
+  /// The callback invoked by the engine in order to give the embedder the
+  /// chance to respond to semantics node updates from the Dart application.
+  /// Semantics node updates are sent in batches terminated by a 'batch end'
+  /// callback that is passed a sentinel `FlutterSemanticsNode` whose `id` field
+  /// has the value `kFlutterSemanticsNodeIdBatchEnd`.
+  ///
+  /// The callback will be invoked on the thread on which the `FlutterEngineRun`
+  /// call is made.
+  FlutterUpdateSemanticsNodeCallback update_semantics_node_callback;
+  /// The callback invoked by the engine in order to give the embedder the
+  /// chance to respond to updates to semantics custom actions from the Dart
+  /// application.  Custom action updates are sent in batches terminated by a
+  /// 'batch end' callback that is passed a sentinel
+  /// `FlutterSemanticsCustomAction` whose `id` field has the value
+  /// `kFlutterSemanticsCustomActionIdBatchEnd`.
+  ///
+  /// The callback will be invoked on the thread on which the `FlutterEngineRun`
+  /// call is made.
+  FlutterUpdateSemanticsCustomActionCallback
+      update_semantics_custom_action_callback;
+  /// Path to a directory used to store data that is cached across runs of a
+  /// Flutter application (such as compiled shader programs used by Skia).
+  /// This is optional.  The string must be NULL terminated.
+  ///
+  // This is different from the cache-path-dir argument defined in switches.h,
+  // which is used in `flutter::Settings` as `temp_directory_path`.
+  const char* persistent_cache_path;
+
+  /// If true, the engine would only read the existing cache, but not write new
+  /// ones.
+  bool is_persistent_cache_read_only;
+
+  /// A callback that gets invoked by the engine when it attempts to wait for a
+  /// platform vsync event. The engine will give the platform a baton that needs
+  /// to be returned back to the engine via `FlutterEngineOnVsync`. All batons
+  /// must be retured to the engine before initializing a
+  /// `FlutterEngineShutdown`. Not doing the same will result in a memory leak.
+  /// While the call to `FlutterEngineOnVsync` must occur on the thread that
+  /// made the call to `FlutterEngineRun`, the engine will make this callback on
+  /// an internal engine-managed thread. If the components accessed on the
+  /// embedder are not thread safe, the appropriate re-threading must be done.
+  VsyncCallback vsync_callback;
+
+  /// The name of a custom Dart entrypoint. This is optional and specifying a
+  /// null or empty entrypoint makes the engine look for a method named "main"
+  /// in the root library of the application.
+  ///
+  /// Care must be taken to ensure that the custom entrypoint is not tree-shaken
+  /// away. Usually, this is done using the `@pragma('vm:entry-point')`
+  /// decoration.
+  const char* custom_dart_entrypoint;
+
+  /// Typically the Flutter engine create and manages its internal threads. This
+  /// optional argument allows for the specification of task runner interfaces
+  /// to event loops managed by the embedder on threads it creates.
+  const FlutterCustomTaskRunners* custom_task_runners;
+
+  /// All `FlutterEngine` instances in the process share the same Dart VM. When
+  /// the first engine is launched, it starts the Dart VM as well. It used to be
+  /// the case that it was not possible to shutdown the Dart VM cleanly and
+  /// start it back up in the process in a safe manner. This issue has since
+  /// been patched. Unfortunately, applications already began to make use of the
+  /// fact that shutting down the Flutter engine instance left a running VM in
+  /// the process. Since a Flutter engine could be launched on any thread,
+  /// applications would "warm up" the VM on another thread by launching
+  /// an engine with no isolates and then shutting it down immediately. The main
+  /// Flutter application could then be started on the main thread without
+  /// having to incur the Dart VM startup costs at that time. With the new
+  /// behavior, this "optimization" immediately becomes massive performance
+  /// pessimization as the VM would be started up in the "warm up" phase, shut
+  /// down there and then started again on the main thread. Changing this
+  /// behavior was deemed to be an unacceptable breaking change. Embedders that
+  /// wish to shutdown the Dart VM when the last engine is terminated in the
+  /// process should opt into this behavior by setting this flag to true.
+  bool shutdown_dart_vm_when_done;
+
+  /// Typically, Flutter renders the layer hierarchy into a single root surface.
+  /// However, when embedders need to interleave their own contents within the
+  /// Flutter layer hierarchy, their applications can push platform views within
+  /// the Flutter scene. This is done using the `SceneBuilder.addPlatformView`
+  /// call. When this happens, the Flutter rasterizer divides the effective view
+  /// hierarchy into multiple layers. Each layer gets its own backing store and
+  /// Flutter renders into the same. Once the layers contents have been
+  /// fulfilled, the embedder is asked to composite these layers on-screen. At
+  /// this point, it can interleave its own contents within the effective
+  /// hierarchy. The interface for the specification of these layer backing
+  /// stores and the hooks to listen for the composition of layers on-screen can
+  /// be controlled using this field. This field is completely optional. In its
+  /// absence, platforms views in the scene are ignored and Flutter renders to
+  /// the root surface as normal.
+  const FlutterCompositor* compositor;
+
+  /// Max size of the old gen heap for the Dart VM in MB, or 0 for unlimited, -1
+  /// for default value.
+  ///
+  /// See also:
+  /// https://github.com/dart-lang/sdk/blob/ca64509108b3e7219c50d6c52877c85ab6a35ff2/runtime/vm/flag_list.h#L150
+  int64_t dart_old_gen_heap_size;
+
+  /// The AOT data to be used in AOT operation.
+  ///
+  /// Embedders should instantiate and destroy this object via the
+  /// FlutterEngineCreateAOTData and FlutterEngineCollectAOTData methods.
+  ///
+  /// Embedders can provide either snapshot buffers or aot_data, but not both.
+  FlutterEngineAOTData aot_data;
+
+  /// A callback that computes the locale the platform would natively resolve
+  /// to.
+  ///
+  /// The input parameter is an array of FlutterLocales which represent the
+  /// locales supported by the app. One of the input supported locales should
+  /// be selected and returned to best match with the user/device's preferred
+  /// locale. The implementation should produce a result that as closely
+  /// matches what the platform would natively resolve to as possible.
+  FlutterComputePlatformResolvedLocaleCallback
+      compute_platform_resolved_locale_callback;
+
+  /// The command line argument count for arguments passed through to the Dart
+  /// entrypoint.
+  int dart_entrypoint_argc;
+
+  /// The command line arguments passed through to the Dart entrypoint. The
+  /// strings must be `NULL` terminated.
+  ///
+  /// The strings will be copied out and so any strings passed in here can
+  /// be safely collected after initializing the engine with
+  /// `FlutterProjectArgs`.
+  const char* const* dart_entrypoint_argv;
+
+  // Logging callback for Dart application messages.
+  //
+  // This callback is used by embedder to log print messages from the running
+  // Flutter application. This callback is made on an internal engine managed
+  // thread and embedders must re-thread if necessary. Performing blocking calls
+  // in this callback may introduce application jank.
+  FlutterLogMessageCallback log_message_callback;
+
+  // A tag string associated with application log messages.
+  //
+  // A log message tag string that can be used convey application, subsystem,
+  // or component name to embedder's logger. This string will be passed to to
+  // callbacks on `log_message_callback`. Defaults to "flutter" if unspecified.
+  const char* log_tag;
+
+  // A callback that is invoked right before the engine is restarted.
+  //
+  // This optional callback is typically used to reset states to as if the
+  // engine has just been started, and usually indicates the user has requested
+  // a hot restart (Shift-R in the Flutter CLI.) It is not called the first time
+  // the engine starts.
+  //
+  // The first argument is the `user_data` from `FlutterEngineInitialize`.
+  OnPreEngineRestartCallback on_pre_engine_restart_callback;
+} FlutterProjectArgs;
+
+#ifndef FLUTTER_ENGINE_NO_PROTOTYPES
+
+//------------------------------------------------------------------------------
+/// @brief      Creates the necessary data structures to launch a Flutter Dart
+///             application in AOT mode. The data may only be collected after
+///             all FlutterEngine instances launched using this data have been
+///             terminated.
+///
+/// @param[in]  source    The source of the AOT data.
+/// @param[out] data_out  The AOT data on success. Unchanged on failure.
+///
+/// @return     Returns if the AOT data could be successfully resolved.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineCreateAOTData(
+    const FlutterEngineAOTDataSource* source,
+    FlutterEngineAOTData* data_out);
+
+//------------------------------------------------------------------------------
+/// @brief      Collects the AOT data.
+///
+/// @warning    The embedder must ensure that this call is made only after all
+///             FlutterEngine instances launched using this data have been
+///             terminated, and that all of those instances were launched with
+///             the FlutterProjectArgs::shutdown_dart_vm_when_done flag set to
+///             true.
+///
+/// @param[in]  data   The data to collect.
+///
+/// @return     Returns if the AOT data was successfully collected.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineCollectAOTData(FlutterEngineAOTData data);
+
+//------------------------------------------------------------------------------
+/// @brief      Initialize and run a Flutter engine instance and return a handle
+///             to it. This is a convenience method for the pair of calls to
+///             `FlutterEngineInitialize` and `FlutterEngineRunInitialized`.
+///
+/// @note       This method of running a Flutter engine works well except in
+///             cases where the embedder specifies custom task runners via
+///             `FlutterProjectArgs::custom_task_runners`. In such cases, the
+///             engine may need the embedder to post tasks back to it before
+///             `FlutterEngineRun` has returned. Embedders can only post tasks
+///             to the engine if they have a handle to the engine. In such
+///             cases, embedders are advised to get the engine handle via the
+///             `FlutterInitializeCall`. Then they can call
+///             `FlutterEngineRunInitialized` knowing that they will be able to
+///             service custom tasks on other threads with the engine handle.
+///
+/// @param[in]  version    The Flutter embedder API version. Must be
+///                        FLUTTER_ENGINE_VERSION.
+/// @param[in]  config     The renderer configuration.
+/// @param[in]  args       The Flutter project arguments.
+/// @param      user_data  A user data baton passed back to embedders in
+///                        callbacks.
+/// @param[out] engine_out The engine handle on successful engine creation.
+///
+/// @return     The result of the call to run the Flutter engine.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineRun(size_t version,
+                                     const FlutterRendererConfig* config,
+                                     const FlutterProjectArgs* args,
+                                     void* user_data,
+                                     FLUTTER_API_SYMBOL(FlutterEngine) *
+                                         engine_out);
+
+//------------------------------------------------------------------------------
+/// @brief      Shuts down a Flutter engine instance. The engine handle is no
+///             longer valid for any calls in the embedder API after this point.
+///             Making additional calls with this handle is undefined behavior.
+///
+/// @note       This de-initializes the Flutter engine instance (via an implicit
+///             call to `FlutterEngineDeinitialize`) if necessary.
+///
+/// @param[in]  engine  The Flutter engine instance to collect.
+///
+/// @return     The result of the call to shutdown the Flutter engine instance.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineShutdown(FLUTTER_API_SYMBOL(FlutterEngine)
+                                              engine);
+
+//------------------------------------------------------------------------------
+/// @brief      Initialize a Flutter engine instance. This does not run the
+///             Flutter application code till the `FlutterEngineRunInitialized`
+///             call is made. Besides Flutter application code, no tasks are
+///             scheduled on embedder managed task runners either. This allows
+///             embedders providing custom task runners to the Flutter engine to
+///             obtain a handle to the Flutter engine before the engine can post
+///             tasks on these task runners.
+///
+/// @param[in]  version    The Flutter embedder API version. Must be
+///                        FLUTTER_ENGINE_VERSION.
+/// @param[in]  config     The renderer configuration.
+/// @param[in]  args       The Flutter project arguments.
+/// @param      user_data  A user data baton passed back to embedders in
+///                        callbacks.
+/// @param[out] engine_out The engine handle on successful engine creation.
+///
+/// @return     The result of the call to initialize the Flutter engine.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineInitialize(size_t version,
+                                            const FlutterRendererConfig* config,
+                                            const FlutterProjectArgs* args,
+                                            void* user_data,
+                                            FLUTTER_API_SYMBOL(FlutterEngine) *
+                                                engine_out);
+
+//------------------------------------------------------------------------------
+/// @brief      Stops running the Flutter engine instance. After this call, the
+///             embedder is also guaranteed that no more calls to post tasks
+///             onto custom task runners specified by the embedder are made. The
+///             Flutter engine handle still needs to be collected via a call to
+///             `FlutterEngineShutdown`.
+///
+/// @param[in]  engine    The running engine instance to de-initialize.
+///
+/// @return     The result of the call to de-initialize the Flutter engine.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineDeinitialize(FLUTTER_API_SYMBOL(FlutterEngine)
+                                                  engine);
+
+//------------------------------------------------------------------------------
+/// @brief      Runs an initialized engine instance. An engine can be
+///             initialized via `FlutterEngineInitialize`. An initialized
+///             instance can only be run once. During and after this call,
+///             custom task runners supplied by the embedder are expected to
+///             start servicing tasks.
+///
+/// @param[in]  engine  An initialized engine instance that has not previously
+///                     been run.
+///
+/// @return     The result of the call to run the initialized Flutter
+///             engine instance.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineRunInitialized(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineSendWindowMetricsEvent(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterWindowMetricsEvent* event);
+
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineSendPointerEvent(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterPointerEvent* events,
+    size_t events_count);
+
+//------------------------------------------------------------------------------
+/// @brief      Sends a key event to the engine. The framework will decide
+///             whether to handle this event in a synchronous fashion, although
+///             due to technical limitation, the result is always reported
+///             asynchronously. The `callback` is guaranteed to be called
+///             exactly once.
+///
+/// @param[in]  engine         A running engine instance.
+/// @param[in]  event          The event data to be sent. This function will no
+///                            longer access `event` after returning.
+/// @param[in]  callback       The callback invoked by the engine when the
+///                            Flutter application has decided whether it
+///                            handles this event. Accepts nullptr.
+/// @param[in]  user_data      The context associated with the callback. The
+///                            exact same value will used to invoke `callback`.
+///                            Accepts nullptr.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineSendKeyEvent(FLUTTER_API_SYMBOL(FlutterEngine)
+                                                  engine,
+                                              const FlutterKeyEvent* event,
+                                              FlutterKeyEventCallback callback,
+                                              void* user_data);
+
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineSendPlatformMessage(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterPlatformMessage* message);
+
+//------------------------------------------------------------------------------
+/// @brief     Creates a platform message response handle that allows the
+///            embedder to set a native callback for a response to a message.
+///            This handle may be set on the `response_handle` field of any
+///            `FlutterPlatformMessage` sent to the engine.
+///
+///            The handle must be collected via a call to
+///            `FlutterPlatformMessageReleaseResponseHandle`. This may be done
+///            immediately after a call to `FlutterEngineSendPlatformMessage`
+///            with a platform message whose response handle contains the handle
+///            created using this call. In case a handle is created but never
+///            sent in a message, the release call must still be made. Not
+///            calling release on the handle results in a small memory leak.
+///
+///            The user data baton passed to the data callback is the one
+///            specified in this call as the third argument.
+///
+/// @see       FlutterPlatformMessageReleaseResponseHandle()
+///
+/// @param[in]  engine         A running engine instance.
+/// @param[in]  data_callback  The callback invoked by the engine when the
+///                            Flutter application send a response on the
+///                            handle.
+/// @param[in]  user_data      The user data associated with the data callback.
+/// @param[out] response_out   The response handle created when this call is
+///                            successful.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterDataCallback data_callback,
+    void* user_data,
+    FlutterPlatformMessageResponseHandle** response_out);
+
+//------------------------------------------------------------------------------
+/// @brief      Collects the handle created using
+///             `FlutterPlatformMessageCreateResponseHandle`.
+///
+/// @see        FlutterPlatformMessageCreateResponseHandle()
+///
+/// @param[in]  engine     A running engine instance.
+/// @param[in]  response   The platform message response handle to collect.
+///                        These handles are created using
+///                        `FlutterPlatformMessageCreateResponseHandle()`.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterPlatformMessageResponseHandle* response);
+
+//------------------------------------------------------------------------------
+/// @brief      Send a response from the native side to a platform message from
+///             the Dart Flutter application.
+///
+/// @param[in]  engine       The running engine instance.
+/// @param[in]  handle       The platform message response handle.
+/// @param[in]  data         The data to associate with the platform message
+///                          response.
+/// @param[in]  data_length  The length of the platform message response data.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineSendPlatformMessageResponse(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterPlatformMessageResponseHandle* handle,
+    const uint8_t* data,
+    size_t data_length);
+
+//------------------------------------------------------------------------------
+/// @brief      This API is only meant to be used by platforms that need to
+///             flush tasks on a message loop not controlled by the Flutter
+///             engine.
+///
+/// @deprecated This API will be deprecated and is not part of the stable API.
+///             Please use the custom task runners API by setting an
+///             appropriate `FlutterProjectArgs::custom_task_runners`
+///             interface. This will yield better performance and the
+///             interface is stable.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult __FlutterEngineFlushPendingTasksNow();
+
+//------------------------------------------------------------------------------
+/// @brief      Register an external texture with a unique (per engine)
+///             identifier. Only rendering backends that support external
+///             textures accept external texture registrations. After the
+///             external texture is registered, the application can mark that a
+///             frame is available by calling
+///             `FlutterEngineMarkExternalTextureFrameAvailable`.
+///
+/// @see        FlutterEngineUnregisterExternalTexture()
+/// @see        FlutterEngineMarkExternalTextureFrameAvailable()
+///
+/// @param[in]  engine              A running engine instance.
+/// @param[in]  texture_identifier  The identifier of the texture to register
+///                                 with the engine. The embedder may supply new
+///                                 frames to this texture using the same
+///                                 identifier.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineRegisterExternalTexture(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    int64_t texture_identifier);
+
+//------------------------------------------------------------------------------
+/// @brief      Unregister a previous texture registration.
+///
+/// @see        FlutterEngineRegisterExternalTexture()
+/// @see        FlutterEngineMarkExternalTextureFrameAvailable()
+///
+/// @param[in]  engine              A running engine instance.
+/// @param[in]  texture_identifier  The identifier of the texture for which new
+///                                 frame will not be available.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineUnregisterExternalTexture(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    int64_t texture_identifier);
+
+//------------------------------------------------------------------------------
+/// @brief      Mark that a new texture frame is available for a given texture
+///             identifier.
+///
+/// @see        FlutterEngineRegisterExternalTexture()
+/// @see        FlutterEngineUnregisterExternalTexture()
+///
+/// @param[in]  engine              A running engine instance.
+/// @param[in]  texture_identifier  The identifier of the texture whose frame
+///                                 has been updated.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineMarkExternalTextureFrameAvailable(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    int64_t texture_identifier);
+
+//------------------------------------------------------------------------------
+/// @brief      Enable or disable accessibility semantics.
+///
+/// @param[in]  engine     A running engine instance.
+/// @param[in]  enabled    When enabled, changes to the semantic contents of the
+///                        window are sent via the
+///                        `FlutterUpdateSemanticsNodeCallback` registered to
+///                        `update_semantics_node_callback` in
+///                        `FlutterProjectArgs`.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineUpdateSemanticsEnabled(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    bool enabled);
+
+//------------------------------------------------------------------------------
+/// @brief      Sets additional accessibility features.
+///
+/// @param[in]  engine     A running engine instance
+/// @param[in]  features   The accessibility features to set.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineUpdateAccessibilityFeatures(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterAccessibilityFeature features);
+
+//------------------------------------------------------------------------------
+/// @brief      Dispatch a semantics action to the specified semantics node.
+///
+/// @param[in]  engine       A running engine instance.
+/// @param[in]  identifier   The semantics action identifier.
+/// @param[in]  action       The semantics action.
+/// @param[in]  data         Data associated with the action.
+/// @param[in]  data_length  The data length.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineDispatchSemanticsAction(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    uint64_t id,
+    FlutterSemanticsAction action,
+    const uint8_t* data,
+    size_t data_length);
+
+//------------------------------------------------------------------------------
+/// @brief      Notify the engine that a vsync event occurred. A baton passed to
+///             the platform via the vsync callback must be returned. This call
+///             must be made on the thread on which the call to
+///             `FlutterEngineRun` was made.
+///
+/// @see        FlutterEngineGetCurrentTime()
+///
+/// @attention  That frame timepoints are in nanoseconds.
+///
+/// @attention  The system monotonic clock is used as the timebase.
+///
+/// @param[in]  engine.                  A running engine instance.
+/// @param[in]  baton                    The baton supplied by the engine.
+/// @param[in]  frame_start_time_nanos   The point at which the vsync event
+///                                      occurred or will occur. If the time
+///                                      point is in the future, the engine will
+///                                      wait till that point to begin its frame
+///                                      workload.
+/// @param[in]  frame_target_time_nanos  The point at which the embedder
+///                                      anticipates the next vsync to occur.
+///                                      This is a hint the engine uses to
+///                                      schedule Dart VM garbage collection in
+///                                      periods in which the various threads
+///                                      are most likely to be idle. For
+///                                      example, for a 60Hz display, embedders
+///                                      should add 16.6 * 1e6 to the frame time
+///                                      field.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineOnVsync(FLUTTER_API_SYMBOL(FlutterEngine)
+                                             engine,
+                                         intptr_t baton,
+                                         uint64_t frame_start_time_nanos,
+                                         uint64_t frame_target_time_nanos);
+
+//------------------------------------------------------------------------------
+/// @brief      Reloads the system fonts in engine.
+///
+/// @param[in]  engine.                  A running engine instance.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineReloadSystemFonts(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+
+//------------------------------------------------------------------------------
+/// @brief      A profiling utility. Logs a trace duration begin event to the
+///             timeline. If the timeline is unavailable or disabled, this has
+///             no effect. Must be balanced with an duration end event (via
+///             `FlutterEngineTraceEventDurationEnd`) with the same name on the
+///             same thread. Can be called on any thread. Strings passed into
+///             the function will NOT be copied when added to the timeline. Only
+///             string literals may be passed in.
+///
+/// @param[in]  name  The name of the trace event.
+///
+FLUTTER_EXPORT
+void FlutterEngineTraceEventDurationBegin(const char* name);
+
+//-----------------------------------------------------------------------------
+/// @brief      A profiling utility. Logs a trace duration end event to the
+///             timeline. If the timeline is unavailable or disabled, this has
+///             no effect. This call must be preceded by a trace duration begin
+///             call (via `FlutterEngineTraceEventDurationBegin`) with the same
+///             name on the same thread. Can be called on any thread. Strings
+///             passed into the function will NOT be copied when added to the
+///             timeline. Only string literals may be passed in.
+///
+/// @param[in]  name  The name of the trace event.
+///
+FLUTTER_EXPORT
+void FlutterEngineTraceEventDurationEnd(const char* name);
+
+//-----------------------------------------------------------------------------
+/// @brief      A profiling utility. Logs a trace duration instant event to the
+///             timeline. If the timeline is unavailable or disabled, this has
+///             no effect. Can be called on any thread. Strings passed into the
+///             function will NOT be copied when added to the timeline. Only
+///             string literals may be passed in.
+///
+/// @param[in]  name  The name of the trace event.
+///
+FLUTTER_EXPORT
+void FlutterEngineTraceEventInstant(const char* name);
+
+//------------------------------------------------------------------------------
+/// @brief      Posts a task onto the Flutter render thread. Typically, this may
+///             be called from any thread as long as a `FlutterEngineShutdown`
+///             on the specific engine has not already been initiated.
+///
+/// @param[in]  engine         A running engine instance.
+/// @param[in]  callback       The callback to execute on the render thread.
+/// @param      callback_data  The callback context.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEnginePostRenderThreadTask(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    VoidCallback callback,
+    void* callback_data);
+
+//------------------------------------------------------------------------------
+/// @brief      Get the current time in nanoseconds from the clock used by the
+///             flutter engine. This is the system monotonic clock.
+///
+/// @return     The current time in nanoseconds.
+///
+FLUTTER_EXPORT
+uint64_t FlutterEngineGetCurrentTime();
+
+//------------------------------------------------------------------------------
+/// @brief      Inform the engine to run the specified task. This task has been
+///             given to the engine via the
+///             `FlutterTaskRunnerDescription.post_task_callback`. This call
+///             must only be made at the target time specified in that callback.
+///             Running the task before that time is undefined behavior.
+///
+/// @param[in]  engine     A running engine instance.
+/// @param[in]  task       the task handle.
+///
+/// @return     The result of the call.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine)
+                                             engine,
+                                         const FlutterTask* task);
+
+//------------------------------------------------------------------------------
+/// @brief      Notify a running engine instance that the locale has been
+///             updated. The preferred locale must be the first item in the list
+///             of locales supplied. The other entries will be used as a
+///             fallback.
+///
+/// @param[in]  engine         A running engine instance.
+/// @param[in]  locales        The updated locales in the order of preference.
+/// @param[in]  locales_count  The count of locales supplied.
+///
+/// @return     Whether the locale updates were applied.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine)
+                                                   engine,
+                                               const FlutterLocale** locales,
+                                               size_t locales_count);
+
+//------------------------------------------------------------------------------
+/// @brief      Returns if the Flutter engine instance will run AOT compiled
+///             Dart code. This call has no threading restrictions.
+///
+///             For embedder code that is configured for both AOT and JIT mode
+///             Dart execution based on the Flutter engine being linked to, this
+///             runtime check may be used to appropriately configure the
+///             `FlutterProjectArgs`. In JIT mode execution, the kernel
+///             snapshots must be present in the Flutter assets directory
+///             specified in the `FlutterProjectArgs`. For AOT execution, the
+///             fields `vm_snapshot_data`, `vm_snapshot_instructions`,
+///             `isolate_snapshot_data` and `isolate_snapshot_instructions`
+///             (along with their size fields) must be specified in
+///             `FlutterProjectArgs`.
+///
+/// @return     True, if AOT Dart code is run. JIT otherwise.
+///
+FLUTTER_EXPORT
+bool FlutterEngineRunsAOTCompiledDartCode(void);
+
+//------------------------------------------------------------------------------
+/// @brief      Posts a Dart object to specified send port. The corresponding
+///             receive port for send port can be in any isolate running in the
+///             VM. This isolate can also be the root isolate for an
+///             unrelated engine. The engine parameter is necessary only to
+///             ensure the call is not made when no engine (and hence no VM) is
+///             running.
+///
+///             Unlike the platform messages mechanism, there are no threading
+///             restrictions when using this API. Message can be posted on any
+///             thread and they will be made available to isolate on which the
+///             corresponding send port is listening.
+///
+///             However, it is the embedders responsibility to ensure that the
+///             call is not made during an ongoing call the
+///             `FlutterEngineDeinitialize` or `FlutterEngineShutdown` on
+///             another thread.
+///
+/// @param[in]  engine     A running engine instance.
+/// @param[in]  port       The send port to send the object to.
+/// @param[in]  object     The object to send to the isolate with the
+///                        corresponding receive port.
+///
+/// @return     If the message was posted to the send port.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEnginePostDartObject(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterEngineDartPort port,
+    const FlutterEngineDartObject* object);
+
+//------------------------------------------------------------------------------
+/// @brief      Posts a low memory notification to a running engine instance.
+///             The engine will do its best to release non-critical resources in
+///             response. It is not guaranteed that the resource would have been
+///             collected by the time this call returns however. The
+///             notification is posted to engine subsystems that may be
+///             operating on other threads.
+///
+///             Flutter applications can respond to these notifications by
+///             setting `WidgetsBindingObserver.didHaveMemoryPressure`
+///             observers.
+///
+/// @param[in]  engine     A running engine instance.
+///
+/// @return     If the low memory notification was sent to the running engine
+///             instance.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineNotifyLowMemoryWarning(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+
+//------------------------------------------------------------------------------
+/// @brief      Schedule a callback to be run on all engine managed threads.
+///             The engine will attempt to service this callback the next time
+///             the message loop for each managed thread is idle. Since the
+///             engine manages the entire lifecycle of multiple threads, there
+///             is no opportunity for the embedders to finely tune the
+///             priorities of threads directly, or, perform other thread
+///             specific configuration (for example, setting thread names for
+///             tracing). This callback gives embedders a chance to affect such
+///             tuning.
+///
+/// @attention  This call is expensive and must be made as few times as
+///             possible. The callback must also return immediately as not doing
+///             so may risk performance issues (especially for callbacks of type
+///             kFlutterNativeThreadTypeUI and kFlutterNativeThreadTypeRender).
+///
+/// @attention  Some callbacks (especially the ones of type
+///             kFlutterNativeThreadTypeWorker) may be called after the
+///             FlutterEngine instance has shut down. Embedders must be careful
+///             in handling the lifecycle of objects associated with the user
+///             data baton.
+///
+/// @attention  In case there are multiple running Flutter engine instances,
+///             their workers are shared.
+///
+/// @param[in]  engine     A running engine instance.
+/// @param[in]  callback   The callback that will get called multiple times on
+///                        each engine managed thread.
+/// @param[in]  user_data  A baton passed by the engine to the callback. This
+///                        baton is not interpreted by the engine in any way.
+///
+/// @return     Returns if the callback was successfully posted to all threads.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEnginePostCallbackOnAllNativeThreads(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterNativeThreadCallback callback,
+    void* user_data);
+
+//------------------------------------------------------------------------------
+/// @brief    Posts updates corresponding to display changes to a running engine
+///           instance.
+///
+/// @param[in] update_type      The type of update pushed to the engine.
+/// @param[in] displays         The displays affected by this update.
+/// @param[in] display_count    Size of the displays array, must be at least 1.
+///
+/// @return the result of the call made to the engine.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineNotifyDisplayUpdate(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterEngineDisplaysUpdateType update_type,
+    const FlutterEngineDisplay* displays,
+    size_t display_count);
+
+//------------------------------------------------------------------------------
+/// @brief      Schedule a new frame to redraw the content.
+///
+/// @param[in]  engine     A running engine instance.
+///
+/// @return the result of the call made to the engine.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineScheduleFrame(FLUTTER_API_SYMBOL(FlutterEngine)
+                                                   engine);
+
+#endif  // !FLUTTER_ENGINE_NO_PROTOTYPES
+
+// Typedefs for the function pointers in FlutterEngineProcTable.
+typedef FlutterEngineResult (*FlutterEngineCreateAOTDataFnPtr)(
+    const FlutterEngineAOTDataSource* source,
+    FlutterEngineAOTData* data_out);
+typedef FlutterEngineResult (*FlutterEngineCollectAOTDataFnPtr)(
+    FlutterEngineAOTData data);
+typedef FlutterEngineResult (*FlutterEngineRunFnPtr)(
+    size_t version,
+    const FlutterRendererConfig* config,
+    const FlutterProjectArgs* args,
+    void* user_data,
+    FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
+typedef FlutterEngineResult (*FlutterEngineShutdownFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+typedef FlutterEngineResult (*FlutterEngineInitializeFnPtr)(
+    size_t version,
+    const FlutterRendererConfig* config,
+    const FlutterProjectArgs* args,
+    void* user_data,
+    FLUTTER_API_SYMBOL(FlutterEngine) * engine_out);
+typedef FlutterEngineResult (*FlutterEngineDeinitializeFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+typedef FlutterEngineResult (*FlutterEngineRunInitializedFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+typedef FlutterEngineResult (*FlutterEngineSendWindowMetricsEventFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterWindowMetricsEvent* event);
+typedef FlutterEngineResult (*FlutterEngineSendPointerEventFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterPointerEvent* events,
+    size_t events_count);
+typedef FlutterEngineResult (*FlutterEngineSendKeyEventFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterKeyEvent* event,
+    FlutterKeyEventCallback callback,
+    void* user_data);
+typedef FlutterEngineResult (*FlutterEngineSendPlatformMessageFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterPlatformMessage* message);
+typedef FlutterEngineResult (
+    *FlutterEnginePlatformMessageCreateResponseHandleFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterDataCallback data_callback,
+    void* user_data,
+    FlutterPlatformMessageResponseHandle** response_out);
+typedef FlutterEngineResult (
+    *FlutterEnginePlatformMessageReleaseResponseHandleFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterPlatformMessageResponseHandle* response);
+typedef FlutterEngineResult (*FlutterEngineSendPlatformMessageResponseFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterPlatformMessageResponseHandle* handle,
+    const uint8_t* data,
+    size_t data_length);
+typedef FlutterEngineResult (*FlutterEngineRegisterExternalTextureFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    int64_t texture_identifier);
+typedef FlutterEngineResult (*FlutterEngineUnregisterExternalTextureFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    int64_t texture_identifier);
+typedef FlutterEngineResult (
+    *FlutterEngineMarkExternalTextureFrameAvailableFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    int64_t texture_identifier);
+typedef FlutterEngineResult (*FlutterEngineUpdateSemanticsEnabledFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    bool enabled);
+typedef FlutterEngineResult (*FlutterEngineUpdateAccessibilityFeaturesFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterAccessibilityFeature features);
+typedef FlutterEngineResult (*FlutterEngineDispatchSemanticsActionFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    uint64_t id,
+    FlutterSemanticsAction action,
+    const uint8_t* data,
+    size_t data_length);
+typedef FlutterEngineResult (*FlutterEngineOnVsyncFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    intptr_t baton,
+    uint64_t frame_start_time_nanos,
+    uint64_t frame_target_time_nanos);
+typedef FlutterEngineResult (*FlutterEngineReloadSystemFontsFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+typedef void (*FlutterEngineTraceEventDurationBeginFnPtr)(const char* name);
+typedef void (*FlutterEngineTraceEventDurationEndFnPtr)(const char* name);
+typedef void (*FlutterEngineTraceEventInstantFnPtr)(const char* name);
+typedef FlutterEngineResult (*FlutterEnginePostRenderThreadTaskFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    VoidCallback callback,
+    void* callback_data);
+typedef uint64_t (*FlutterEngineGetCurrentTimeFnPtr)();
+typedef FlutterEngineResult (*FlutterEngineRunTaskFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterTask* task);
+typedef FlutterEngineResult (*FlutterEngineUpdateLocalesFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    const FlutterLocale** locales,
+    size_t locales_count);
+typedef bool (*FlutterEngineRunsAOTCompiledDartCodeFnPtr)(void);
+typedef FlutterEngineResult (*FlutterEnginePostDartObjectFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterEngineDartPort port,
+    const FlutterEngineDartObject* object);
+typedef FlutterEngineResult (*FlutterEngineNotifyLowMemoryWarningFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+typedef FlutterEngineResult (*FlutterEnginePostCallbackOnAllNativeThreadsFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterNativeThreadCallback callback,
+    void* user_data);
+typedef FlutterEngineResult (*FlutterEngineNotifyDisplayUpdateFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine,
+    FlutterEngineDisplaysUpdateType update_type,
+    const FlutterEngineDisplay* displays,
+    size_t display_count);
+typedef FlutterEngineResult (*FlutterEngineScheduleFrameFnPtr)(
+    FLUTTER_API_SYMBOL(FlutterEngine) engine);
+
+/// Function-pointer-based versions of the APIs above.
+typedef struct {
+  /// The size of this struct. Must be sizeof(FlutterEngineProcs).
+  size_t struct_size;
+
+  FlutterEngineCreateAOTDataFnPtr CreateAOTData;
+  FlutterEngineCollectAOTDataFnPtr CollectAOTData;
+  FlutterEngineRunFnPtr Run;
+  FlutterEngineShutdownFnPtr Shutdown;
+  FlutterEngineInitializeFnPtr Initialize;
+  FlutterEngineDeinitializeFnPtr Deinitialize;
+  FlutterEngineRunInitializedFnPtr RunInitialized;
+  FlutterEngineSendWindowMetricsEventFnPtr SendWindowMetricsEvent;
+  FlutterEngineSendPointerEventFnPtr SendPointerEvent;
+  FlutterEngineSendKeyEventFnPtr SendKeyEvent;
+  FlutterEngineSendPlatformMessageFnPtr SendPlatformMessage;
+  FlutterEnginePlatformMessageCreateResponseHandleFnPtr
+      PlatformMessageCreateResponseHandle;
+  FlutterEnginePlatformMessageReleaseResponseHandleFnPtr
+      PlatformMessageReleaseResponseHandle;
+  FlutterEngineSendPlatformMessageResponseFnPtr SendPlatformMessageResponse;
+  FlutterEngineRegisterExternalTextureFnPtr RegisterExternalTexture;
+  FlutterEngineUnregisterExternalTextureFnPtr UnregisterExternalTexture;
+  FlutterEngineMarkExternalTextureFrameAvailableFnPtr
+      MarkExternalTextureFrameAvailable;
+  FlutterEngineUpdateSemanticsEnabledFnPtr UpdateSemanticsEnabled;
+  FlutterEngineUpdateAccessibilityFeaturesFnPtr UpdateAccessibilityFeatures;
+  FlutterEngineDispatchSemanticsActionFnPtr DispatchSemanticsAction;
+  FlutterEngineOnVsyncFnPtr OnVsync;
+  FlutterEngineReloadSystemFontsFnPtr ReloadSystemFonts;
+  FlutterEngineTraceEventDurationBeginFnPtr TraceEventDurationBegin;
+  FlutterEngineTraceEventDurationEndFnPtr TraceEventDurationEnd;
+  FlutterEngineTraceEventInstantFnPtr TraceEventInstant;
+  FlutterEnginePostRenderThreadTaskFnPtr PostRenderThreadTask;
+  FlutterEngineGetCurrentTimeFnPtr GetCurrentTime;
+  FlutterEngineRunTaskFnPtr RunTask;
+  FlutterEngineUpdateLocalesFnPtr UpdateLocales;
+  FlutterEngineRunsAOTCompiledDartCodeFnPtr RunsAOTCompiledDartCode;
+  FlutterEnginePostDartObjectFnPtr PostDartObject;
+  FlutterEngineNotifyLowMemoryWarningFnPtr NotifyLowMemoryWarning;
+  FlutterEnginePostCallbackOnAllNativeThreadsFnPtr
+      PostCallbackOnAllNativeThreads;
+  FlutterEngineNotifyDisplayUpdateFnPtr NotifyDisplayUpdate;
+  FlutterEngineScheduleFrameFnPtr ScheduleFrame;
+} FlutterEngineProcTable;
+
+//------------------------------------------------------------------------------
+/// @brief      Gets the table of engine function pointers.
+///
+/// @param[out] table   The table to fill with pointers. This should be
+///                     zero-initialized, except for struct_size.
+///
+/// @return     Returns whether the table was successfully populated.
+///
+FLUTTER_EXPORT
+FlutterEngineResult FlutterEngineGetProcAddresses(
+    FlutterEngineProcTable* table);
+
+#if defined(__cplusplus)
+}  // extern "C"
+#endif
+
+#endif  // FLUTTER_EMBEDDER_H_
diff --git a/src/embedder/engine_revision b/src/embedder/engine_revision
new file mode 100644
index 0000000..5226470
--- /dev/null
+++ b/src/embedder/engine_revision
@@ -0,0 +1 @@
+6710d67ead813c51e6e6cee4c8df7d208795dd85
diff --git a/src/embedder/libflutter_engine.so b/src/embedder/libflutter_engine.so
new file mode 100755
index 0000000..201dece
--- /dev/null
+++ b/src/embedder/libflutter_engine.so
Binary files differ
diff --git a/src/embedder/main.cc b/src/embedder/main.cc
new file mode 100644
index 0000000..7735348
--- /dev/null
+++ b/src/embedder/main.cc
@@ -0,0 +1,86 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Entrypoint for running a Flutter app on Fuchsia.
+//
+// Usage: ./main <path_to_flutter_asset_bundle>
+
+#include <lib/async-loop/cpp/loop.h>
+#include <lib/async-loop/default.h>
+#include <lib/syslog/global.h>
+#include <string>
+
+#include "embedder.h"
+
+namespace {
+
+constexpr char kLogTag[] = "flutter_embedder";
+
+bool FuchsiaPresentSoftwareSurface(void *user_data, const void *allocation,
+                                   size_t row_bytes, size_t height) {
+  // TODO(akbiggs): Present the surface to the screen.
+  FX_LOGF(ERROR, kLogTag,
+          "surface_present_callback (row_bytes=%lu, height=%lu)", row_bytes,
+          height);
+  return true;
+}
+
+void FuchsiaLogMessage(const char *tag, const char *message, void *user_data) {
+  // TODO(akbiggs): This does not report the file and line number of the Dart
+  // app that the log came from.
+  FX_LOG(INFO, tag, message);
+}
+
+bool RunFlutterApp(const char *assets_path) {
+  FlutterRendererConfig renderer_config = {
+      .type = kSoftware,
+      .software =
+          {
+              .struct_size = sizeof(FlutterSoftwareRendererConfig),
+              .surface_present_callback = FuchsiaPresentSoftwareSurface,
+              // TODO(akbiggs): Add callback for acquiring the software surface.
+          },
+  };
+  FlutterProjectArgs project_args = {
+      .struct_size = sizeof(FlutterProjectArgs),
+      .assets_path = assets_path,
+      .log_message_callback = FuchsiaLogMessage,
+      .log_tag = "flutter_app",
+  };
+
+  // TODO(akbiggs): Store this FlutterEngine instance somewhere instead of
+  // throwing it away.
+  FlutterEngine engine;
+  FlutterEngineResult result = FlutterEngineRun(
+      FLUTTER_ENGINE_VERSION, &renderer_config, &project_args,
+      // user_data is an arbitrary object that we can pass around to engine
+      // callbacks. When we need to make those callbacks change state in our
+      // embedder we should pass a pointer to a collection of our state here.
+      nullptr /* user_data */, &engine);
+
+  if (result != kSuccess || engine == nullptr) {
+    FX_LOGF(ERROR, kLogTag, "Could not run the Flutter Engine. Error code: %d",
+            static_cast<int>(result));
+    return false;
+  }
+
+  return true;
+}
+
+} // namespace
+
+int main(int argc, const char *argv[]) {
+  if (argc != 2) {
+    FX_LOG(ERROR, kLogTag, "usage: executable <path to flutter bundle>");
+    return EXIT_FAILURE;
+  }
+
+  const char *assets_path = argv[1];
+
+  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
+  RunFlutterApp(assets_path);
+  loop.Run();
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/embedder/meta/embedder.cml b/src/embedder/meta/embedder.cml
new file mode 100644
index 0000000..970ac11
--- /dev/null
+++ b/src/embedder/meta/embedder.cml
@@ -0,0 +1,15 @@
+{
+    include: [ "syslog/client.shard.cml" ],
+
+    program: {
+        runner: "elf",
+        binary: "bin/embedder",
+        args: ["/pkg/data/flutter_assets"],
+
+        forward_stdout_to: "log",
+        forward_stderr_to: "log",
+
+        // Required for JIT execution.
+        job_policy_ambient_mark_vmo_exec: "true",
+    },
+}
diff --git a/src/examples/BUILD.bazel b/src/examples/BUILD.bazel
index ee0f6b5..1e2a0d6 100644
--- a/src/examples/BUILD.bazel
+++ b/src/examples/BUILD.bazel
@@ -11,7 +11,7 @@
     name = "examples_repository",
     repo_name = "flutter-embedder-examples.com",
     deps = [
-        "//src/examples/hello_world_cpp:hello_world_cpp_pkg",
+        "//src/examples/flutter_sample_app:flutter_sample_app_pkg",
     ],
 )
 
diff --git a/src/examples/flutter_sample_app/.gitignore b/src/examples/flutter_sample_app/.gitignore
new file mode 100644
index 0000000..9855537
--- /dev/null
+++ b/src/examples/flutter_sample_app/.gitignore
@@ -0,0 +1,31 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
diff --git a/src/examples/flutter_sample_app/.metadata b/src/examples/flutter_sample_app/.metadata
new file mode 100644
index 0000000..166a998
--- /dev/null
+++ b/src/examples/flutter_sample_app/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: c860cba910319332564e1e9d470a17074c1f2dfd
+  channel: stable
+
+project_type: app
diff --git a/src/examples/flutter_sample_app/BUILD.bazel b/src/examples/flutter_sample_app/BUILD.bazel
new file mode 100644
index 0000000..6a5bc1d
--- /dev/null
+++ b/src/examples/flutter_sample_app/BUILD.bazel
@@ -0,0 +1,49 @@
+load(
+    "@rules_fuchsia//fuchsia:defs.bzl",
+    "fuchsia_component",
+    "fuchsia_package",
+)
+
+# To rebuild the Flutter app with new changes:
+#   ~/flutter-embedder $ cd examples/flutter_sample_app
+#   flutter_sample_app $ flutter build bundle
+#
+# TODO(akbiggs): Grab subdirectories and ensure their names are preserved
+# in the output package's data.
+# TODO(akbiggs): Build these assets using a build rule like flutter_application
+# instead of building them using the Flutter tool and then copying them over.
+# TODO(fxbug.dev/96417): Support folders/globs in fuchsia_package_resource.
+filegroup(
+    name = "assets",
+    srcs = glob([
+        "build/flutter_assets/*",
+    ]),
+)
+
+# The embedder manifest specifies that the bundled assets for the Flutter application
+# to run will be located at /pkg/data/flutter_assets. To create a component that
+# runs a specific Flutter app, we package the embedder manifest together with the
+# embedder binary and the assets for the specific Flutter app we want to run.
+#
+# TODO(akbiggs): After writing a few more example apps, simplify into a build rule
+# like flutter_application.
+fuchsia_component(
+    name = "component",
+    manifest = "//src/embedder:embedder_manifest",
+    content = {
+        ":assets": "data/flutter_assets/",
+    },
+    deps = [
+        "//src/embedder",
+    ],
+)
+
+fuchsia_package(
+    name = "flutter_sample_app_pkg",
+    package_name = "flutter_sample_app",
+    visibility = ["//visibility:public"],
+    deps = [
+        ":component",
+        "//src/embedder:flutter_engine",
+    ],
+)
diff --git a/src/examples/flutter_sample_app/README.md b/src/examples/flutter_sample_app/README.md
new file mode 100644
index 0000000..2c33ffc
--- /dev/null
+++ b/src/examples/flutter_sample_app/README.md
@@ -0,0 +1,16 @@
+# flutter_sample_app
+
+A new Flutter project.
+
+## Getting Started
+
+This project is a starting point for a Flutter application.
+
+A few resources to get you started if this is your first Flutter project:
+
+- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
+- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
+
+For help getting started with Flutter, view our
+[online documentation](https://flutter.dev/docs), which offers tutorials,
+samples, guidance on mobile development, and a full API reference.
diff --git a/src/examples/flutter_sample_app/analysis_options.yaml b/src/examples/flutter_sample_app/analysis_options.yaml
new file mode 100644
index 0000000..61b6c4d
--- /dev/null
+++ b/src/examples/flutter_sample_app/analysis_options.yaml
@@ -0,0 +1,29 @@
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+  # The lint rules applied to this project can be customized in the
+  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+  # included above or to enable additional rules. A list of all available lints
+  # and their documentation is published at
+  # https://dart-lang.github.io/linter/lints/index.html.
+  #
+  # Instead of disabling a lint rule for the entire project in the
+  # section below, it can also be suppressed for a single line of code
+  # or a specific dart file by using the `// ignore: name_of_lint` and
+  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+  # producing the lint.
+  rules:
+    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
+    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/src/examples/flutter_sample_app/lib/main.dart b/src/examples/flutter_sample_app/lib/main.dart
new file mode 100644
index 0000000..6e82b47
--- /dev/null
+++ b/src/examples/flutter_sample_app/lib/main.dart
@@ -0,0 +1,117 @@
+import 'package:flutter/material.dart';
+
+void main() {
+  print("Hello from Dart!");
+
+  runApp(const MyApp());
+}
+
+class MyApp extends StatelessWidget {
+  const MyApp({Key? key}) : super(key: key);
+
+  // This widget is the root of your application.
+  @override
+  Widget build(BuildContext context) {
+    return MaterialApp(
+      title: 'Flutter Demo',
+      theme: ThemeData(
+        // This is the theme of your application.
+        //
+        // Try running your application with "flutter run". You'll see the
+        // application has a blue toolbar. Then, without quitting the app, try
+        // changing the primarySwatch below to Colors.green and then invoke
+        // "hot reload" (press "r" in the console where you ran "flutter run",
+        // or simply save your changes to "hot reload" in a Flutter IDE).
+        // Notice that the counter didn't reset back to zero; the application
+        // is not restarted.
+        primarySwatch: Colors.blue,
+      ),
+      home: const MyHomePage(title: 'Flutter Demo Home Page'),
+    );
+  }
+}
+
+class MyHomePage extends StatefulWidget {
+  const MyHomePage({Key? key, required this.title}) : super(key: key);
+
+  // This widget is the home page of your application. It is stateful, meaning
+  // that it has a State object (defined below) that contains fields that affect
+  // how it looks.
+
+  // This class is the configuration for the state. It holds the values (in this
+  // case the title) provided by the parent (in this case the App widget) and
+  // used by the build method of the State. Fields in a Widget subclass are
+  // always marked "final".
+
+  final String title;
+
+  @override
+  State<MyHomePage> createState() => _MyHomePageState();
+}
+
+class _MyHomePageState extends State<MyHomePage> {
+  int _counter = 0;
+
+  void _incrementCounter() {
+    setState(() {
+      // This call to setState tells the Flutter framework that something has
+      // changed in this State, which causes it to rerun the build method below
+      // so that the display can reflect the updated values. If we changed
+      // _counter without calling setState(), then the build method would not be
+      // called again, and so nothing would appear to happen.
+      _counter++;
+    });
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    // This method is rerun every time setState is called, for instance as done
+    // by the _incrementCounter method above.
+    //
+    // The Flutter framework has been optimized to make rerunning build methods
+    // fast, so that you can just rebuild anything that needs updating rather
+    // than having to individually change instances of widgets.
+    return Scaffold(
+      appBar: AppBar(
+        // Here we take the value from the MyHomePage object that was created by
+        // the App.build method, and use it to set our appbar title.
+        title: Text(widget.title),
+      ),
+      body: Center(
+        // Center is a layout widget. It takes a single child and positions it
+        // in the middle of the parent.
+        child: Column(
+          // Column is also a layout widget. It takes a list of children and
+          // arranges them vertically. By default, it sizes itself to fit its
+          // children horizontally, and tries to be as tall as its parent.
+          //
+          // Invoke "debug painting" (press "p" in the console, choose the
+          // "Toggle Debug Paint" action from the Flutter Inspector in Android
+          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
+          // to see the wireframe for each widget.
+          //
+          // Column has various properties to control how it sizes itself and
+          // how it positions its children. Here we use mainAxisAlignment to
+          // center the children vertically; the main axis here is the vertical
+          // axis because Columns are vertical (the cross axis would be
+          // horizontal).
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: <Widget>[
+            const Text(
+              'You have pushed the button this many times:',
+            ),
+            Text(
+              '$_counter',
+              style: Theme.of(context).textTheme.headline4,
+            ),
+          ],
+        ),
+      ),
+      floatingActionButton: FloatingActionButton(
+        onPressed: _incrementCounter,
+        tooltip: 'Increment',
+        child: const Icon(Icons.add),
+      ), // This trailing comma makes auto-formatting nicer for build methods.
+    );
+  }
+}
diff --git a/src/examples/flutter_sample_app/pubspec.lock b/src/examples/flutter_sample_app/pubspec.lock
new file mode 100644
index 0000000..9cee3e9
--- /dev/null
+++ b/src/examples/flutter_sample_app/pubspec.lock
@@ -0,0 +1,167 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+  async:
+    dependency: transitive
+    description:
+      name: async
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.9.0"
+  boolean_selector:
+    dependency: transitive
+    description:
+      name: boolean_selector
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.1.0"
+  characters:
+    dependency: transitive
+    description:
+      name: characters
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.2.0"
+  charcode:
+    dependency: transitive
+    description:
+      name: charcode
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.3.1"
+  clock:
+    dependency: transitive
+    description:
+      name: clock
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.1.0"
+  collection:
+    dependency: transitive
+    description:
+      name: collection
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.16.0"
+  cupertino_icons:
+    dependency: "direct main"
+    description:
+      name: cupertino_icons
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.4"
+  fake_async:
+    dependency: transitive
+    description:
+      name: fake_async
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.3.0"
+  flutter:
+    dependency: "direct main"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  flutter_lints:
+    dependency: "direct dev"
+    description:
+      name: flutter_lints
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.4"
+  flutter_test:
+    dependency: "direct dev"
+    description: flutter
+    source: sdk
+    version: "0.0.0"
+  lints:
+    dependency: transitive
+    description:
+      name: lints
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.0.1"
+  matcher:
+    dependency: transitive
+    description:
+      name: matcher
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.12.11"
+  material_color_utilities:
+    dependency: transitive
+    description:
+      name: material_color_utilities
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.1.4"
+  meta:
+    dependency: transitive
+    description:
+      name: meta
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.7.0"
+  path:
+    dependency: transitive
+    description:
+      name: path
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.8.1"
+  sky_engine:
+    dependency: transitive
+    description: flutter
+    source: sdk
+    version: "0.0.99"
+  source_span:
+    dependency: transitive
+    description:
+      name: source_span
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.8.2"
+  stack_trace:
+    dependency: transitive
+    description:
+      name: stack_trace
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.10.0"
+  stream_channel:
+    dependency: transitive
+    description:
+      name: stream_channel
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.1.0"
+  string_scanner:
+    dependency: transitive
+    description:
+      name: string_scanner
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.1.0"
+  term_glyph:
+    dependency: transitive
+    description:
+      name: term_glyph
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "1.2.0"
+  test_api:
+    dependency: transitive
+    description:
+      name: test_api
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "0.4.9"
+  vector_math:
+    dependency: transitive
+    description:
+      name: vector_math
+      url: "https://pub.dartlang.org"
+    source: hosted
+    version: "2.1.2"
+sdks:
+  dart: ">=2.17.0-0 <3.0.0"
diff --git a/src/examples/flutter_sample_app/pubspec.yaml b/src/examples/flutter_sample_app/pubspec.yaml
new file mode 100644
index 0000000..73305c0
--- /dev/null
+++ b/src/examples/flutter_sample_app/pubspec.yaml
@@ -0,0 +1,89 @@
+name: flutter_sample_app
+description: A new Flutter project.
+
+# The following line prevents the package from being accidentally published to
+# pub.dev using `flutter pub publish`. This is preferred for private packages.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+  sdk: ">=2.16.2 <3.0.0"
+
+# Dependencies specify other packages that your package needs in order to work.
+# To automatically upgrade your package dependencies to the latest versions
+# consider running `flutter pub upgrade --major-versions`. Alternatively,
+# dependencies can be manually updated by changing the version numbers below to
+# the latest version available on pub.dev. To see which dependencies have newer
+# versions available, run `flutter pub outdated`.
+dependencies:
+  flutter:
+    sdk: flutter
+
+
+  # The following adds the Cupertino Icons font to your application.
+  # Use with the CupertinoIcons class for iOS style icons.
+  cupertino_icons: ^1.0.2
+
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+
+  # The "flutter_lints" package below contains a set of recommended lints to
+  # encourage good coding practices. The lint set provided by the package is
+  # activated in the `analysis_options.yaml` file located at the root of your
+  # package. See that file for information about deactivating specific lint
+  # rules and activating additional ones.
+  flutter_lints: ^1.0.0
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+
+# The following section is specific to Flutter.
+flutter:
+
+  # The following line ensures that the Material Icons font is
+  # included with your application, so that you can use the icons in
+  # the material Icons class.
+  uses-material-design: true
+
+  # To add assets to your application, add an assets section, like this:
+  # assets:
+  #   - images/a_dot_burr.jpeg
+  #   - images/a_dot_ham.jpeg
+
+  # An image asset can refer to one or more resolution-specific "variants", see
+  # https://flutter.dev/assets-and-images/#resolution-aware.
+
+  # For details regarding adding assets from package dependencies, see
+  # https://flutter.dev/assets-and-images/#from-packages
+
+  # To add custom fonts to your application, add a fonts section here,
+  # in this "flutter" section. Each entry in this list should have a
+  # "family" key with the font family name, and a "fonts" key with a
+  # list giving the asset and other descriptors for the font. For
+  # example:
+  # fonts:
+  #   - family: Schyler
+  #     fonts:
+  #       - asset: fonts/Schyler-Regular.ttf
+  #       - asset: fonts/Schyler-Italic.ttf
+  #         style: italic
+  #   - family: Trajan Pro
+  #     fonts:
+  #       - asset: fonts/TrajanPro.ttf
+  #       - asset: fonts/TrajanPro_Bold.ttf
+  #         weight: 700
+  #
+  # For details regarding fonts from package dependencies,
+  # see https://flutter.dev/custom-fonts/#from-packages
diff --git a/src/examples/flutter_sample_app/test/widget_test.dart b/src/examples/flutter_sample_app/test/widget_test.dart
new file mode 100644
index 0000000..9fe6f6d
--- /dev/null
+++ b/src/examples/flutter_sample_app/test/widget_test.dart
@@ -0,0 +1,30 @@
+// This is a basic Flutter widget test.
+//
+// To perform an interaction with a widget in your test, use the WidgetTester
+// utility that Flutter provides. For example, you can send tap and scroll
+// gestures. You can also use WidgetTester to find child widgets in the widget
+// tree, read text, and verify that the values of widget properties are correct.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:flutter_sample_app_2/main.dart';
+
+void main() {
+  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
+    // Build our app and trigger a frame.
+    await tester.pumpWidget(const MyApp());
+
+    // Verify that our counter starts at 0.
+    expect(find.text('0'), findsOneWidget);
+    expect(find.text('1'), findsNothing);
+
+    // Tap the '+' icon and trigger a frame.
+    await tester.tap(find.byIcon(Icons.add));
+    await tester.pump();
+
+    // Verify that our counter has incremented.
+    expect(find.text('0'), findsNothing);
+    expect(find.text('1'), findsOneWidget);
+  });
+}
diff --git a/src/examples/hello_world_cpp/BUILD.bazel b/src/examples/hello_world_cpp/BUILD.bazel
deleted file mode 100644
index df96533..0000000
--- a/src/examples/hello_world_cpp/BUILD.bazel
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2021 The Fuchsia Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-load(
-    "@rules_fuchsia//fuchsia:defs.bzl",
-    "fuchsia_cc_binary",
-    "fuchsia_component",
-    "fuchsia_component_manifest",
-    "fuchsia_package",
-)
-
-fuchsia_cc_binary(
-    name = "hello_world_cpp",
-    srcs = [
-        "hello_world.cc",
-    ],
-    deps = ["@fuchsia_sdk//pkg/syslog"],
-)
-
-fuchsia_component_manifest(
-    name = "manifest",
-    src = "meta/hello_world_cpp.cml",
-    includes = ["@fuchsia_sdk//pkg/syslog:client"],
-)
-
-fuchsia_component(
-    name = "component",
-    manifest = ":manifest",
-    deps = [":hello_world_cpp"],
-)
-
-fuchsia_package(
-    name = "hello_world_cpp_pkg",
-    package_name = "hello_world",
-    visibility = ["//visibility:public"],
-    deps = [
-        ":component",
-    ],
-)
diff --git a/src/examples/hello_world_cpp/hello_world.cc b/src/examples/hello_world_cpp/hello_world.cc
deleted file mode 100644
index 36d1fcc..0000000
--- a/src/examples/hello_world_cpp/hello_world.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2021 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <iostream>
-
-int main()
-{
-  std::cout << "Hello, World!" << std::endl;
-  return 0;
-}
diff --git a/src/examples/hello_world_cpp/meta/hello_world_cpp.cml b/src/examples/hello_world_cpp/meta/hello_world_cpp.cml
deleted file mode 100644
index dbd6ebc..0000000
--- a/src/examples/hello_world_cpp/meta/hello_world_cpp.cml
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    include: [ "syslog/client.shard.cml" ],
-
-    program: {
-        runner: "elf",
-        binary: "bin/hello_world_cpp",
-        forward_stderr_to: "log",
-        forward_stdout_to: "log"
-    },
-}