[fuchsia] Migrate integration test to CFv2 (#35318)

diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index ff50b5a..c78b93d 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -2129,18 +2129,6 @@
 FILE: ../../../flutter/shell/platform/fuchsia/flutter/gfx_platform_view.h
 FILE: ../../../flutter/shell/platform/fuchsia/flutter/gfx_session_connection.cc
 FILE: ../../../flutter/shell/platform/fuchsia/flutter/gfx_session_connection.h
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/child_view2.dart
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/meta/child-view2.cmx
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.cc
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.h
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/meta/flutter-embedder-test2.cmx
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/meta/parent-view2.cmx
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/parent_view2.dart
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/base_view.cc
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/base_view.h
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/embedded_view_utils.cc
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/embedded_view_utils.h
-FILE: ../../../flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/math.h
 FILE: ../../../flutter/shell/platform/fuchsia/flutter/isolate_configurator.cc
 FILE: ../../../flutter/shell/platform/fuchsia/flutter/isolate_configurator.h
 FILE: ../../../flutter/shell/platform/fuchsia/flutter/kernel/extract_far.dart
diff --git a/shell/platform/fuchsia/flutter/BUILD.gn b/shell/platform/fuchsia/flutter/BUILD.gn
index 0680f42..01a1f2e 100644
--- a/shell/platform/fuchsia/flutter/BUILD.gn
+++ b/shell/platform/fuchsia/flutter/BUILD.gn
@@ -457,6 +457,34 @@
   product = true
 }
 
+# "OOT" copy of the runner used by tests, to avoid conflicting with the runner
+# in the base fuchsia image.
+# TODO(fxbug.dev/106575): Fix this with subpackages.
+aot_runner("oot_flutter_aot_runner") {
+  product = false
+}
+
+# "OOT" copy of the runner used by tests, to avoid conflicting with the runner
+# in the base fuchsia image.
+# TODO(fxbug.dev/106575): Fix this with subpackages.
+aot_runner("oot_flutter_aot_product_runner") {
+  product = true
+}
+
+# "OOT" copy of the runner used by tests, to avoid conflicting with the runner
+# in the base fuchsia image.
+# TODO(fxbug.dev/106575): Fix this with subpackages.
+jit_runner("oot_flutter_jit_runner") {
+  product = false
+}
+
+# "OOT" copy of the runner used by tests, to avoid conflicting with the runner
+# in the base fuchsia image.
+# TODO(fxbug.dev/106575): Fix this with subpackages.
+jit_runner("oot_flutter_jit_product_runner") {
+  product = true
+}
+
 test_fixtures("flutter_runner_fixtures") {
   fixtures = []
 }
@@ -885,7 +913,7 @@
       ":testing_tests",
       ":txt_tests",
       ":ui_tests",
-      "integration_flutter_tests",
+      "tests/integration",
     ]
   }
 }
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/OWNERS b/shell/platform/fuchsia/flutter/integration_flutter_tests/OWNERS
deleted file mode 100644
index aa90637..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-dworsham@google.com
-sanjayc@google.com
-richkadel@google.com
-
-# COMPONENT: FlutteronFuchsia
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/BUILD.gn b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/BUILD.gn
deleted file mode 100644
index bba0da5..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/BUILD.gn
+++ /dev/null
@@ -1,67 +0,0 @@
-# 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.
-
-assert(is_fuchsia)
-
-import("//build/fuchsia/sdk.gni")
-import("//flutter/tools/fuchsia/fuchsia_archive.gni")
-
-group("tests") {
-  testonly = true
-  deps = [
-    ":flutter-embedder-test2",
-    "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2",
-    "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2",
-  ]
-}
-
-executable("flutter-embedder-test2-bin") {
-  testonly = true
-
-  output_name = "flutter-embedder-test2"
-
-  sources = [
-    "flutter-embedder-test2.cc",
-    "flutter-embedder-test2.h",
-  ]
-
-  # This is needed for //third_party/googletest for linking zircon symbols.
-  libs = [ "$fuchsia_sdk_path/arch/$target_cpu/sysroot/lib/libzircon.so" ]
-
-  include_dirs = [ "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing" ]
-
-  public_deps = [ "//third_party/googletest:gtest" ]
-
-  deps = [
-    "$fuchsia_sdk_root/fidl:fuchsia.sys",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.app",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.input",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.lifecycle",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.policy",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.scenic",
-    "$fuchsia_sdk_root/pkg:async-loop-cpp",
-    "$fuchsia_sdk_root/pkg:async-loop-default",
-    "$fuchsia_sdk_root/pkg:fit",
-    "$fuchsia_sdk_root/pkg:scenic_cpp",
-    "$fuchsia_sdk_root/pkg:sys_cpp",
-    "$fuchsia_sdk_root/pkg:sys_cpp_testing",
-    "$fuchsia_sdk_root/pkg:zx",
-    "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view",
-    "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views",
-    "//third_party/dart/runtime:libdart_jit",
-    "//third_party/googletest:gtest_main",
-  ]
-}
-
-fuchsia_test_archive("flutter-embedder-test2") {
-  deps = [
-    ":flutter-embedder-test2-bin",
-    "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2:package",
-    "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2:package",
-  ]
-
-  binary = "$target_name"
-
-  cmx_file = rebase_path("meta/$target_name.cmx")
-}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/README.md b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/README.md
deleted file mode 100644
index 6b5190b..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/README.md
+++ /dev/null
@@ -1,173 +0,0 @@
-# `flutter scenic embedder tests`
-
-## Configure and build fuchsia
-
-For tests that require scenic, for example, run `fx set` with the required
-targets; for example:
-
-```shell
-$ cd "$FUCHSIA_DIR"
-$ fx set core.x64 \
-    --with //src/ui/scenic \
-    --with //src/ui/bin/root_presenter \
-    --with //src/ui/bin/hardware_display_controller_provider
-$ fx build
-```
-
-Note 1: You could use `--with-base` here, instead of `--with`, but if so, you
-would also need to add `--with-base //garnet/bin/run_test_component`. More on
-this below, under [Start the package servers](#start-the-package-servers).
-
-Note 2: The `fx set` flags, above, offer a minimized fuchsia platform
-configuration to successfully execute the test, but some optional services may
-be missing. Be aware that the Fuchsia system logs may include multiple
-occurrences `WARNING: error resolving ...` messages, such as the following,
-which can be ignored:
-
-```
-[pkg-resolver] WARNING: error resolving fuchsia-pkg://fuchsia.com/fonts/0 ...
-[pkg-resolver] WARNING: error resolving fuchsia-pkg://fuchsia.com/ime_service/0 ...
-[pkg-resolver] WARNING: error resolving fuchsia-pkg://fuchsia.com/intl_property_manager/0 ...
-```
-
-## Restart and reboot your device
-
-_(Optional)_ If developing with the emulator, launch (or shutdown and relaunch)
-the emulator.
-
-```shell
-fx vdl start -N
-```
-
-NOTE: Do _not_ run the default package server. The instructions below describe
-how to launch a flutter-specific package server.
-
-Or if you've rebuilt fuchsia for a device that is already running a version of
-fuchsia, you may be able to reboot without restarting the device:
-
-```shell
-$ fx reboot -r
-```
-
-If you are building a device that launches the UI at startup, you will likely
-need to kill Scenic before running the test.
-
-```shell
-$ fx shell killall scenic.cmx
-```
-
-## Build the test
-
-You can specify the test's package target to build only the test package, with
-its dependencies. This will also build the required runner.
-
-```shell
-$ cd "$FLUTTER_ENGINE_DIR/src"
-$ ./flutter/tools/gn --fuchsia <flags> \
-      # for example: --goma --fuchsia-cpu=x64 --runtime-mode=debug
-$ ninja -C out/fuchsia_debug_x64 \
-    flutter/shell/platform/fuchsia/flutter/integration_flutter_tests
-```
-
-## Publish the test packages to the Fuchsia package server
-
-The tests currently specify the Fuchsia package server's standard domain,
-`fuchsia.com`, as the server to use to resolve (locate and load) the test
-packages. So, before running the test, the most recently built `.far` files
-need to be published to the Fuchsia package repo:
-
-```shell
-$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
-  -f "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64/flutter-embedder-test2-0.far
-$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
-  -f $(find "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64 -name parent-view2.far)
-$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
-  -f $(find "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64 -name child-view2.far)
-```
-
-## Run the test (using the package server at `fuchsia.com`)
-
-```shell
-$ fx test flutter-embedder-test2
-```
-
-## Make a change and re-run the test
-
-If, for example, you only make a change to the Dart code in `parent-view2`, you
-can rebuild only the parent-view2 package target, republish it, and then re-run
-the test, with:
-
-```shell
-$ ninja -C out/fuchsia_debug_x64 \
-    flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2:package
-$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
-  -f $(find "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64 -name parent-view2.far)
-$ fx test flutter-embedder-test2
-```
-
-From here, you can modify the Flutter test, rebuild flutter, and usually rerun
-the test without rebooting, by repeating the commands above.
-
-The embedder tests must be run on a product without a graphical base shell,
-such as `core` because it starts and stops Scenic.
-
-## (Alternative) Serving flutter packages from a custom package server
-
-If you want to use a custom package server, you will need to edit these sources:
-
-    * `//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.cc`
-    * `//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/parent_view2.dart`
-
-Search for the component URLs with `fuchsia.com`, and change it to `engine`,
-which is the domain currently registered with the custom package server in
-`//tools/fuchsia/devshell/serve.sh`.
-
-WARNING: Be careful not to check in that change because CI requires using the
-`fuchsia.com` domain/package server.
-
-The default fuchsia package server (launched via `fx serve`) is normally
-required, unless all of your test's package dependencies are included in the
-fuchsia system image. You can force additional packages into the system image
-with `fx set ... --with-base <package>` (instead of using `--with`). For
-example, in the `fx set` command above, using, `--with-base scenic`, and so on.
-Note, however, that the default `core.x64` configuration bundles the test
-runner as if it was included via
-`--with //garnet/bin/run_test_component`, so to include the test runner in the
-system image requires adding that package as well, via `--with-base`, instead.
-
-In order to serve fuchsia package dependencies (like `scenic`, `root_presenter`,
-and `hardware-display-controller-provider`), without forcing them into the
-system image, you will need to run the fuchsia default package server, via `fx
-serve`.
-
-The `flutter/engine` packages (tests and flutter runners, for dart-based tests)
-are served from a separate package server. The `flutter/engine` repo's
-`serve.sh` script launches this secondary package server, and configures
-package URL rewrite rules to redirect fuchsia's requests for flutter- and
-dart-runner packages from `fuchsia.com` to flutter's package server instead.
-
-**IMPORTANT:** _The flutter package server must be launched **after** the
-default package server, because both `fx serve` and flutter's `serve.sh` set
-package URL rewrite rules, and only the last one wins._
-
-Launch each package server in a separate window or shell:
-
-```shell
-$ cd "${FUCHSIA_DIR}"
-$ fx serve
-```
-
-From the flutter engine `src` directory, run the following script to launch the
-`engine` package server, to serve the flutter runner and test components.
-
-```shell
-$ flutter/tools/fuchsia/devshell/serve.sh --out out/fuchsia_debug_x64 --only-serve-runners
-```
-
-## Run the test, using `engine` as the package server domain
-
-```shell
-$ fx test flutter-embedder-test2
-```
-
-You can recompile and run the test without needing to re-publish the `.far`.
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/BUILD.gn b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/BUILD.gn
deleted file mode 100644
index 93e8363..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/BUILD.gn
+++ /dev/null
@@ -1,38 +0,0 @@
-# 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.
-
-import("//build/fuchsia/sdk.gni")
-import("//flutter/tools/fuchsia/dart/dart_library.gni")
-import("//flutter/tools/fuchsia/flutter/flutter_component.gni")
-import("//flutter/tools/fuchsia/gn-sdk/package.gni")
-
-dart_library("child-view2_dart_library") {
-  package_name = "child-view2"
-
-  source_dir = "."
-  sources = [ "child_view2.dart" ]
-
-  deps = []
-}
-
-flutter_component("child-view2_flutter_component") {
-  main_package = "child-view2"
-  component_name = "child-view2"
-  main_dart = "child_view2.dart"
-  manifest = rebase_path("meta/child-view2.cmx")
-  deps = [ ":child-view2_dart_library" ]
-}
-
-# TODO(richkadel): The target name is set differently compared to fuchsia.git's flutter_app().
-# Unlike in fuchsia.git's version of fuchsia_component, the Fuchsia GN SDK
-# version passes the component name to fuchsia_component via it's target_name only.
-# GN SDK's fuchsia_component doesn't have a `component_name` argument! So I'm forced to set
-# the component name via "target_name". This is a problem in fuchsia_package, which uses
-# the target_name to name the fuchsia_pm_tool target, creating duplicate target IDs!
-# So I have to change the fuchsia_package name to something that is NOT the component name,
-# and then set the package_name (which fuchsia_package does support).
-fuchsia_package("package") {
-  package_name = "child-view2"
-  deps = [ ":child-view2_flutter_component" ]
-}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/meta/child-view2.cmx b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/meta/child-view2.cmx
deleted file mode 100644
index 2157ca2..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/meta/child-view2.cmx
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "program": {
-        "data": "data/child-view2"
-    },
-    "sandbox": {
-        "services": [
-            "fuchsia.fonts.Provider",
-            "fuchsia.sys.Environment",
-            "fuchsia.ui.input.ImeService",
-            "fuchsia.ui.scenic.Scenic"
-        ]
-    }
-}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.cc b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.cc
deleted file mode 100644
index 63a5cd1..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.cc
+++ /dev/null
@@ -1,218 +0,0 @@
-// 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.
-
-#include "flutter-embedder-test2.h"
-
-namespace flutter_embedder_test2 {
-
-// TODO(richkadel): To run the test serving the runner and test packages from
-// the flutter/engine package server (via
-// `//flutter/tools/fuchsia/devshell/serve.sh`), change `fuchsia.com` to
-// `engine`.
-constexpr char kParentViewUrl[] =
-    "fuchsia-pkg://fuchsia.com/parent-view2#meta/parent-view2.cmx";
-
-constexpr scenic::Color kParentBackgroundColor = {0x00, 0x00, 0xFF,
-                                                  0xFF};                // Blue
-constexpr scenic::Color kParentTappedColor = {0x00, 0x00, 0x00, 0xFF};  // Black
-constexpr scenic::Color kChildBackgroundColor = {0xFF, 0x00, 0xFF,
-                                                 0xFF};                // Pink
-constexpr scenic::Color kChildTappedColor = {0xFF, 0xFF, 0x00, 0xFF};  // Yellow
-
-// TODO(fxb/94000): The new flutter renderer draws overlays as a single, large
-// layer.  Some parts of this layer are fully transparent, so we want the
-// compositor to treat the layer as transparent and blend it with the contents
-// below.
-//
-// The gfx Scenic API only provides one way to mark this layer as transparent
-// which is to set an opacity < 1.0 for the entire layer.  In practice, we use
-// 0.9961 (254 / 255) as an opacity value to force transparency.  Unfortunately
-// this causes the overlay to blend very slightly and it looks wrong.
-//
-// Flatland allows marking a layer as transparent while still using a 1.0
-// opacity value when blending, so migrating flutter to Flatland will fix this
-// issue.  For now we just hard-code the broken, blended values.
-constexpr scenic::Color kOverlayBackgroundColor1 = {
-    0x00, 0xFF, 0x0E, 0xFF};  // Green, blended with blue (FEMU local)
-constexpr scenic::Color kOverlayBackgroundColor2 = {
-    0x0E, 0xFF, 0x0E, 0xFF};  // Green, blended with pink (FEMU local)
-constexpr scenic::Color kOverlayBackgroundColor3 = {
-    0x00, 0xFF, 0x0D, 0xFF};  // Green, blended with blue (AEMU infra)
-constexpr scenic::Color kOverlayBackgroundColor4 = {
-    0x0D, 0xFF, 0x0D, 0xFF};  // Green, blended with pink (AEMU infra)
-constexpr scenic::Color kOverlayBackgroundColor5 = {
-    0x00, 0xFE, 0x0D, 0xFF};  // Green, blended with blue (NUC)
-constexpr scenic::Color kOverlayBackgroundColor6 = {
-    0x0D, 0xFF, 0x00, 0xFF};  // Green, blended with pink (NUC)
-
-static size_t OverlayPixelCount(std::map<scenic::Color, size_t>& histogram) {
-  return histogram[kOverlayBackgroundColor1] +
-         histogram[kOverlayBackgroundColor2] +
-         histogram[kOverlayBackgroundColor3] +
-         histogram[kOverlayBackgroundColor4] +
-         histogram[kOverlayBackgroundColor5] +
-         histogram[kOverlayBackgroundColor6];
-}
-
-/// Defines a list of services that are injected into the test environment.
-/// Unlike the injected-services in CMX which are injected per test package,
-/// these are injected per test and result in a more hermetic test environment.
-const std::vector<std::pair<const char*, const char*>> GetInjectedServices() {
-  std::vector<std::pair<const char*, const char*>> injected_services = {{
-      {"fuchsia.accessibility.semantics.SemanticsManager",
-       "fuchsia-pkg://fuchsia.com/a11y-manager#meta/a11y-manager.cmx"},
-      {"fuchsia.fonts.Provider",
-       "fuchsia-pkg://fuchsia.com/fonts#meta/fonts.cmx"},
-      {"fuchsia.hardware.display.Provider",
-       "fuchsia-pkg://fuchsia.com/"
-       "fake-hardware-display-controller-provider#meta/hdcp.cmx"},
-      {"fuchsia.intl.PropertyProvider",
-       "fuchsia-pkg://fuchsia.com/intl_property_manager#meta/"
-       "intl_property_manager.cmx"},
-      {"fuchsia.netstack.Netstack",
-       "fuchsia-pkg://fuchsia.com/network-legacy-deprecated#meta/netstack.cmx"},
-      {"fuchsia.posix.socket.Provider",
-       "fuchsia-pkg://fuchsia.com/network-legacy-deprecated#meta/netstack.cmx"},
-      {"fuchsia.tracing.provider.Registry",
-       "fuchsia-pkg://fuchsia.com/trace_manager#meta/trace_manager.cmx"},
-      {"fuchsia.ui.input.ImeService",
-       "fuchsia-pkg://fuchsia.com/text_manager#meta/text_manager.cmx"},
-      {"fuchsia.ui.input.ImeVisibilityService",
-       "fuchsia-pkg://fuchsia.com/text_manager#meta/text_manager.cmx"},
-      {"fuchsia.ui.scenic.Scenic",
-       "fuchsia-pkg://fuchsia.com/scenic#meta/scenic.cmx"},
-      {"fuchsia.ui.pointerinjector.Registry",
-       "fuchsia-pkg://fuchsia.com/scenic#meta/scenic.cmx"},  // For
-                                                             // root_presenter
-      // TODO(fxbug.dev/82655): Remove this after migrating to RealmBuilder.
-      {"fuchsia.ui.lifecycle.LifecycleController",
-       "fuchsia-pkg://fuchsia.com/scenic#meta/scenic.cmx"},
-      {"fuchsia.ui.policy.Presenter",
-       "fuchsia-pkg://fuchsia.com/root_presenter#meta/root_presenter.cmx"},
-      {"fuchsia.ui.input.InputDeviceRegistry",
-       "fuchsia-pkg://fuchsia.com/root_presenter#meta/root_presenter.cmx"},
-  }};
-  return injected_services;
-}
-
-TEST_F(FlutterScenicEmbedderTests, Embedding) {
-  RunAppWithArgs(kParentViewUrl);
-
-  // Take screenshot until we see the child-view2's embedded color.
-  ASSERT_TRUE(TakeScreenshotUntil(
-      kChildBackgroundColor, [](scenic::Screenshot screenshot,
-                                std::map<scenic::Color, size_t> histogram) {
-        // Expect parent and child background colors, with parent color > child
-        // color.
-        EXPECT_GT(histogram[kParentBackgroundColor], 0u);
-        EXPECT_GT(histogram[kChildBackgroundColor], 0u);
-        EXPECT_GT(histogram[kParentBackgroundColor],
-                  histogram[kChildBackgroundColor]);
-
-        // Expect all corners to be the parent-view2 background color
-        EXPECT_EQ(kParentBackgroundColor, screenshot.ColorAtPixelXY(10, 10));
-        EXPECT_EQ(kParentBackgroundColor,
-                  screenshot.ColorAtPixelXY(screenshot.width() - 10, 0));
-        EXPECT_EQ(kParentBackgroundColor,
-                  screenshot.ColorAtPixelXY(0, screenshot.height() - 10));
-        EXPECT_EQ(kParentBackgroundColor,
-                  screenshot.ColorAtPixelXY(screenshot.width() - 10,
-                                            screenshot.height() - 10));
-      }));
-}
-
-TEST_F(FlutterScenicEmbedderTests, HittestEmbedding) {
-  RunAppWithArgs(kParentViewUrl);
-
-  // Take screenshot until we see the child-view2's embedded color.
-  ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
-
-  // Tap the center of child view2.
-  InjectInput();
-
-  // Take screenshot until we see the child-view2's tapped color.
-  ASSERT_TRUE(TakeScreenshotUntil(
-      kChildTappedColor, [](scenic::Screenshot screenshot,
-                            std::map<scenic::Color, size_t> histogram) {
-        // Expect parent and child background colors, with parent color > child
-        // color.
-        EXPECT_GT(histogram[kParentBackgroundColor], 0u);
-        EXPECT_EQ(histogram[kChildBackgroundColor], 0u);
-        EXPECT_GT(histogram[kChildTappedColor], 0u);
-        EXPECT_GT(histogram[kParentBackgroundColor],
-                  histogram[kChildTappedColor]);
-      }));
-}
-
-TEST_F(FlutterScenicEmbedderTests, HittestDisabledEmbedding) {
-  RunAppWithArgs(kParentViewUrl, {"--no-hitTestable"});
-
-  // Take screenshots until we see the child-view2's embedded color.
-  ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
-
-  // Tap the center of child view2. Since it's not hit-testable, the tap should
-  // go to the parent.
-  InjectInput();
-
-  // The parent-view2 should change color.
-  ASSERT_TRUE(TakeScreenshotUntil(
-      kParentTappedColor, [](scenic::Screenshot screenshot,
-                             std::map<scenic::Color, size_t> histogram) {
-        // Expect parent and child background colors, with parent color > child
-        // color.
-        EXPECT_EQ(histogram[kParentBackgroundColor], 0u);
-        EXPECT_GT(histogram[kParentTappedColor], 0u);
-        EXPECT_GT(histogram[kChildBackgroundColor], 0u);
-        EXPECT_EQ(histogram[kChildTappedColor], 0u);
-        EXPECT_GT(histogram[kParentTappedColor],
-                  histogram[kChildBackgroundColor]);
-      }));
-}
-
-TEST_F(FlutterScenicEmbedderTests, EmbeddingWithOverlay) {
-  RunAppWithArgs(kParentViewUrl, {"--showOverlay"});
-
-  // Take screenshot until we see the child-view2's embedded color.
-  ASSERT_TRUE(TakeScreenshotUntil(
-      kChildBackgroundColor, [](scenic::Screenshot screenshot,
-                                std::map<scenic::Color, size_t> histogram) {
-        // Expect parent, overlay and child background colors.
-        // With parent color > child color and overlay color > child color.
-        const size_t overlay_pixel_count = OverlayPixelCount(histogram);
-        EXPECT_GT(histogram[kParentBackgroundColor], 0u);
-        EXPECT_GT(overlay_pixel_count, 0u);
-        EXPECT_GT(histogram[kChildBackgroundColor], 0u);
-        EXPECT_GT(histogram[kParentBackgroundColor],
-                  histogram[kChildBackgroundColor]);
-        EXPECT_GT(overlay_pixel_count, histogram[kChildBackgroundColor]);
-      }));
-}
-
-TEST_F(FlutterScenicEmbedderTests, HittestEmbeddingWithOverlay) {
-  RunAppWithArgs(kParentViewUrl, {"--showOverlay"});
-
-  // Take screenshot until we see the child-view2's embedded color.
-  ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
-
-  // Tap the center of child view2.
-  InjectInput();
-
-  // Take screenshot until we see the child-view2's tapped color.
-  ASSERT_TRUE(TakeScreenshotUntil(
-      kChildTappedColor, [](scenic::Screenshot screenshot,
-                            std::map<scenic::Color, size_t> histogram) {
-        // Expect parent, overlay and child background colors.
-        // With parent color > child color and overlay color > child color.
-        const size_t overlay_pixel_count = OverlayPixelCount(histogram);
-        EXPECT_GT(histogram[kParentBackgroundColor], 0u);
-        EXPECT_GT(overlay_pixel_count, 0u);
-        EXPECT_EQ(histogram[kChildBackgroundColor], 0u);
-        EXPECT_GT(histogram[kChildTappedColor], 0u);
-        EXPECT_GT(histogram[kParentBackgroundColor],
-                  histogram[kChildTappedColor]);
-        EXPECT_GT(overlay_pixel_count, histogram[kChildTappedColor]);
-      }));
-}
-
-}  // namespace flutter_embedder_test2
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.h b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.h
deleted file mode 100644
index 1a8cbf5..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/flutter-embedder-test2.h
+++ /dev/null
@@ -1,234 +0,0 @@
-// 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 SRC_UI_TESTS_INTEGRATION_FLUTTER_TESTS_EMBEDDER_flutter_embedder_test2_H_
-#define SRC_UI_TESTS_INTEGRATION_FLUTTER_TESTS_EMBEDDER_flutter_embedder_test2_H_
-
-#include <fuchsia/ui/lifecycle/cpp/fidl.h>
-#include <fuchsia/ui/policy/cpp/fidl.h>
-#include <fuchsia/ui/scenic/cpp/fidl.h>
-#include <fuchsia/ui/views/cpp/fidl.h>
-#include <gtest/gtest.h>
-#include <lib/async/cpp/task.h>
-#include <lib/fidl/cpp/binding_set.h>
-#include <lib/sys/cpp/component_context.h>
-#include <lib/sys/cpp/testing/test_with_environment.h>
-#include <lib/ui/scenic/cpp/view_token_pair.h>
-#include <lib/zx/clock.h>
-#include <zircon/status.h>
-#include <zircon/time.h>
-#include "flutter/fml/logging.h"
-
-#include <vector>
-
-#include "src/lib/ui/base_view/embedded_view_utils.h"
-#include "src/ui/testing/views/color.h"
-#include "src/ui/testing/views/embedder_view.h"
-
-namespace flutter_embedder_test2 {
-
-/// Defines a list of services that are injected into the test environment.
-/// Unlike the injected-services in CMX which are injected per test package,
-/// these are injected per test and result in a more hermetic test environment.
-const std::vector<std::pair<const char*, const char*>> GetInjectedServices();
-
-// Timeout when waiting on Scenic API calls like |GetDisplayInfo|.
-constexpr zx::duration kCallTimeout = zx::sec(5);
-// Timeout for Scenic's |TakeScreenshot| FIDL call.
-constexpr zx::duration kScreenshotTimeout = zx::sec(10);
-// Timeout to fail the test if it goes beyond this duration.
-constexpr zx::duration kTestTimeout = zx::min(1);
-
-class FlutterScenicEmbedderTests : public sys::testing::TestWithEnvironment,
-                                   public ::testing::Test {
- public:
-  // |testing::Test|
-  void SetUp() override {
-    Test::SetUp();
-
-    // Create test-specific launchable services.
-    auto services = TestWithEnvironment::CreateServices();
-    for (const auto& service_info : GetInjectedServices()) {
-      zx_status_t status = services->AddServiceWithLaunchInfo(
-          {.url = service_info.second}, service_info.first);
-      FML_CHECK(status == ZX_OK)
-          << "Failed to add service " << service_info.first;
-    }
-
-    environment_ = CreateNewEnclosingEnvironment(
-        "flutter-embedder-test2s", std::move(services),
-        {.inherit_parent_services = true});
-    WaitForEnclosingEnvToStart(environment());
-
-    FML_VLOG(fml::LOG_INFO) << "Created test environment.";
-
-    // Connects to scenic lifecycle controller in order to shutdown scenic at
-    // the end of the test. This ensures the correct ordering of shutdown under
-    // CFv1: first scenic, then the fake display controller.
-    //
-    // TODO(fxbug.dev/82655): Remove this after migrating to RealmBuilder.
-    environment_->ConnectToService<fuchsia::ui::lifecycle::LifecycleController>(
-        scenic_lifecycle_controller_.NewRequest());
-
-    environment_->ConnectToService(scenic_.NewRequest());
-    scenic_.set_error_handler([](zx_status_t status) {
-      FAIL() << "Lost connection to Scenic: " << zx_status_get_string(status);
-    });
-
-    // Post a "just in case" quit task, if the test hangs.
-    async::PostDelayedTask(
-        dispatcher(),
-        [] {
-          FML_LOG(FATAL)
-              << "\n\n>> Test did not complete in time, terminating.  <<\n\n";
-        },
-        kTestTimeout);
-  }
-
-  // |testing::Test|
-  void TearDown() override {
-    // Avoid spurious errors since we are about to kill scenic.
-    //
-    // TODO(fxbug.dev/82655): Remove this after migrating to RealmBuilder.
-    scenic_.set_error_handler(nullptr);
-
-    zx_status_t terminate_status = scenic_lifecycle_controller_->Terminate();
-    FML_CHECK(terminate_status == ZX_OK)
-        << "Failed to terminate Scenic with status: "
-        << zx_status_get_string(terminate_status);
-  }
-
-  sys::testing::EnclosingEnvironment* environment() {
-    return environment_.get();
-  }
-
-  fuchsia::ui::views::ViewToken CreatePresentationViewToken() {
-    auto [view_token, view_holder_token] = scenic::ViewTokenPair::New();
-
-    auto presenter =
-        environment()->ConnectToService<fuchsia::ui::policy::Presenter>();
-    presenter.set_error_handler([](zx_status_t status) {
-      FAIL() << "presenter: " << zx_status_get_string(status);
-    });
-    presenter->PresentView(std::move(view_holder_token), nullptr);
-
-    return std::move(view_token);
-  }
-
-  void RunAppWithArgs(const std::string& component_url,
-                      const std::vector<std::string>& component_args = {}) {
-    scenic::EmbeddedViewInfo flutter_runner =
-        scenic::LaunchComponentAndCreateView(environment()->launcher_ptr(),
-                                             component_url, component_args);
-    flutter_runner.controller.events().OnTerminated = [](auto...) { FAIL(); };
-
-    // Present the view.
-    embedder_view_.emplace(scenic::ViewContext{
-        .session_and_listener_request =
-            scenic::CreateScenicSessionPtrAndListenerRequest(scenic_.get()),
-        .view_token = CreatePresentationViewToken(),
-    });
-
-    // Embed the view.
-    bool is_rendering = false;
-    embedder_view_->EmbedView(
-        std::move(flutter_runner),
-        [&is_rendering](fuchsia::ui::gfx::ViewState view_state) {
-          is_rendering = view_state.is_rendering;
-        });
-    RunLoopUntil([&is_rendering] { return is_rendering; });
-    FML_LOG(INFO) << "Launched component: " << component_url;
-  }
-
-  scenic::Screenshot TakeScreenshot() {
-    FML_LOG(INFO) << "Taking screenshot... ";
-    fuchsia::ui::scenic::ScreenshotData screenshot_out;
-    scenic_->TakeScreenshot(
-        [this, &screenshot_out](fuchsia::ui::scenic::ScreenshotData screenshot,
-                                bool status) {
-          EXPECT_TRUE(status) << "Failed to take screenshot";
-          screenshot_out = std::move(screenshot);
-          QuitLoop();
-        });
-    EXPECT_FALSE(RunLoopWithTimeout(kScreenshotTimeout))
-        << "Timed out waiting for screenshot.";
-    FML_LOG(INFO) << "Screenshot captured.";
-
-    return scenic::Screenshot(screenshot_out);
-  }
-
-  bool TakeScreenshotUntil(
-      scenic::Color color,
-      fit::function<void(scenic::Screenshot, std::map<scenic::Color, size_t>)>
-          callback = nullptr,
-      zx::duration timeout = kTestTimeout) {
-    return RunLoopWithTimeoutOrUntil(
-        [this, &callback, &color] {
-          auto screenshot = TakeScreenshot();
-          auto histogram = screenshot.Histogram();
-
-          bool color_found = histogram[color] > 0;
-          if (color_found && callback != nullptr) {
-            callback(std::move(screenshot), std::move(histogram));
-          }
-          return color_found;
-        },
-        timeout);
-  }
-
-  // Inject directly into Root Presenter, using fuchsia.ui.input FIDLs.
-  void InjectInput() {
-    using fuchsia::ui::input::InputReport;
-    // Device parameters
-    auto parameters = fuchsia::ui::input::TouchscreenDescriptor::New();
-    *parameters = {.x = {.range = {.min = -1000, .max = 1000}},
-                   .y = {.range = {.min = -1000, .max = 1000}},
-                   .max_finger_id = 10};
-
-    FML_LOG(INFO) << "Injecting input... ";
-    // Register it against Root Presenter.
-    fuchsia::ui::input::DeviceDescriptor device{.touchscreen =
-                                                    std::move(parameters)};
-    auto registry =
-        environment()
-            ->ConnectToService<fuchsia::ui::input::InputDeviceRegistry>();
-    fuchsia::ui::input::InputDevicePtr connection;
-    registry->RegisterDevice(std::move(device), connection.NewRequest());
-
-    {
-      // Inject one input report, then a conclusion (empty) report.
-      auto touch = fuchsia::ui::input::TouchscreenReport::New();
-      *touch = {
-          .touches = {{.finger_id = 1, .x = 0, .y = 0}}};  // center of display
-      InputReport report{
-          .event_time = static_cast<uint64_t>(zx::clock::get_monotonic().get()),
-          .touchscreen = std::move(touch)};
-      connection->DispatchReport(std::move(report));
-    }
-
-    {
-      auto touch = fuchsia::ui::input::TouchscreenReport::New();
-      InputReport report{
-          .event_time = static_cast<uint64_t>(zx::clock::get_monotonic().get()),
-          .touchscreen = std::move(touch)};
-      connection->DispatchReport(std::move(report));
-    }
-    FML_LOG(INFO) << "Input dispatched.";
-  }
-
- private:
-  const std::unique_ptr<sys::ComponentContext> component_context_;
-  std::unique_ptr<sys::testing::EnclosingEnvironment> environment_;
-
-  fuchsia::ui::lifecycle::LifecycleControllerSyncPtr
-      scenic_lifecycle_controller_;
-  fuchsia::ui::scenic::ScenicPtr scenic_;
-
-  // Wrapped in optional since the view is not created until the middle of SetUp
-  std::optional<scenic::EmbedderView> embedder_view_;
-};
-
-}  // namespace flutter_embedder_test2
-
-#endif  // SRC_UI_TESTS_INTEGRATION_FLUTTER_TESTS_EMBEDDER_flutter_embedder_test2_H_
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/meta/flutter-embedder-test2.cmx b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/meta/flutter-embedder-test2.cmx
deleted file mode 100644
index 0e21e6d..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/meta/flutter-embedder-test2.cmx
+++ /dev/null
@@ -1,25 +0,0 @@
-{
-    "facets": {
-        "fuchsia.test": {
-            "system-services": [
-                "fuchsia.scheduler.ProfileProvider",
-                "fuchsia.sysmem.Allocator",
-                "fuchsia.vulkan.loader.Loader"
-            ]
-        }
-    },
-    "program": {
-        "binary": "bin/app"
-    },
-    "sandbox": {
-        "services": [
-            "fuchsia.logger.LogSink",
-            "fuchsia.sys.Environment",
-            "fuchsia.sys.Launcher",
-            "fuchsia.sys.Loader",
-            "fuchsia.sysmem.Allocator",
-            "fuchsia.tracing.provider.Registry",
-            "fuchsia.vulkan.loader.Loader"
-        ]
-    }
-}
\ No newline at end of file
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/BUILD.gn b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/BUILD.gn
deleted file mode 100644
index 0b2ec39..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/BUILD.gn
+++ /dev/null
@@ -1,46 +0,0 @@
-# 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.
-
-import("//build/fuchsia/sdk.gni")
-import("//flutter/tools/fuchsia/dart/dart_library.gni")
-import("//flutter/tools/fuchsia/flutter/flutter_component.gni")
-import("//flutter/tools/fuchsia/gn-sdk/package.gni")
-
-dart_library("parent-view2_dart_library") {
-  package_name = "parent-view2"
-
-  source_dir = "."
-  sources = [ "parent_view2.dart" ]
-
-  deps = [
-    "//flutter/shell/platform/fuchsia/dart:args",
-    "//flutter/shell/platform/fuchsia/dart:vector_math",
-    "//flutter/tools/fuchsia/dart:fuchsia_services",
-    "//flutter/tools/fuchsia/dart:zircon",
-    "//flutter/tools/fuchsia/fidl:fuchsia.sys",
-    "//flutter/tools/fuchsia/fidl:fuchsia.ui.app",
-    "//flutter/tools/fuchsia/fidl:fuchsia.ui.views",
-  ]
-}
-
-flutter_component("parent-view2_flutter_component") {
-  main_package = "parent-view2"
-  component_name = "parent-view2"
-  main_dart = "parent_view2.dart"
-  manifest = rebase_path("meta/parent-view2.cmx")
-  deps = [ ":parent-view2_dart_library" ]
-}
-
-# TODO(richkadel): The target name is set differently compared to fuchsia.git's flutter_app().
-# Unlike in fuchsia.git's version of fuchsia_component, the Fuchsia GN SDK
-# version passes the component name to fuchsia_component via it's target_name only.
-# GN SDK's fuchsia_component doesn't have a `component_name` argument! So I'm forced to set
-# the component name via "target_name". This is a problem in fuchsia_package, which uses
-# the target_name to name the fuchsia_pm_tool target, creating duplicate target IDs!
-# So I have to change the fuchsia_package name to something that is NOT the component name,
-# and then set the package_name (which fuchsia_package does support).
-fuchsia_package("package") {
-  package_name = "parent-view2"
-  deps = [ ":parent-view2_flutter_component" ]
-}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/meta/parent-view2.cmx b/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/meta/parent-view2.cmx
deleted file mode 100644
index b839053..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/meta/parent-view2.cmx
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-    "program": {
-        "data": "data/parent-view2"
-    },
-    "sandbox": {
-        "services": [
-            "fuchsia.fonts.Provider",
-            "fuchsia.sys.Environment",
-            "fuchsia.sys.Launcher",
-            "fuchsia.ui.input.ImeService",
-            "fuchsia.ui.scenic.Scenic"
-        ]
-    }
-}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/BUILD.gn b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/BUILD.gn
deleted file mode 100644
index 36d862c..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/BUILD.gn
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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.
-
-import("//build/fuchsia/sdk.gni")
-
-source_set("base_view") {
-  sources = [
-    "base_view.cc",
-    "base_view.h",
-    "embedded_view_utils.cc",
-    "embedded_view_utils.h",
-    "math.h",
-  ]
-
-  include_dirs = [ "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing" ]
-
-  public_deps = [
-    "$fuchsia_sdk_root/fidl:fuchsia.sys",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.app",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.gfx",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.input",
-    "$fuchsia_sdk_root/fidl:fuchsia.ui.views",
-    "$fuchsia_sdk_root/pkg:scenic_cpp",
-    "$fuchsia_sdk_root/pkg:sys_cpp",
-    "//flutter/fml",
-  ]
-
-  deps = [ "$fuchsia_sdk_root/pkg:trace" ]
-}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/base_view.cc b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/base_view.cc
deleted file mode 100644
index e4756f0..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/base_view.cc
+++ /dev/null
@@ -1,240 +0,0 @@
-// 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.
-
-#include "src/lib/ui/base_view/base_view.h"
-
-#include <lib/trace/event.h>
-#include <lib/ui/scenic/cpp/commands.h>
-#include <lib/ui/scenic/cpp/view_token_pair.h>
-#include <zircon/status.h>
-#include "flutter/fml/logging.h"
-
-namespace scenic {
-
-BaseView::BaseView(ViewContext context, const std::string& debug_name)
-    : component_context_(context.component_context),
-      listener_binding_(this,
-                        std::move(context.session_and_listener_request.second)),
-      session_(std::move(context.session_and_listener_request.first)),
-      root_node_(&session_),
-      ime_client_(this),
-      enable_ime_(context.enable_ime) {
-  if (!context.view_ref_pair) {
-    context.view_ref_pair = scenic::ViewRefPair::New();
-  }
-  view_.emplace(&session_, std::move(context.view_token),
-                std::move(context.view_ref_pair->control_ref),
-                std::move(context.view_ref_pair->view_ref), debug_name);
-  FML_DCHECK(view_);
-
-  session_.SetDebugName(debug_name);
-
-  // Listen for metrics events on our top node.
-  root_node_.SetEventMask(fuchsia::ui::gfx::kMetricsEventMask);
-  view_->AddChild(root_node_);
-
-  if (enable_ime_) {
-    ime_manager_ =
-        component_context_->svc()->Connect<fuchsia::ui::input::ImeService>();
-
-    ime_.set_error_handler([](zx_status_t status) {
-      FML_LOG(ERROR) << "Interface error on: Input Method Editor "
-                     << zx_status_get_string(status);
-    });
-    ime_manager_.set_error_handler([](zx_status_t status) {
-      FML_LOG(ERROR) << "Interface error on: Text Sync Service "
-                     << zx_status_get_string(status);
-    });
-  }
-
-  // We must immediately invalidate the scene, otherwise we wouldn't ever hook
-  // the View up to the ViewHolder.  An alternative would be to require
-  // subclasses to call an Init() method to set up the initial connection.
-  InvalidateScene();
-}
-
-void BaseView::SetReleaseHandler(fit::function<void(zx_status_t)> callback) {
-  listener_binding_.set_error_handler(std::move(callback));
-}
-
-void BaseView::InvalidateScene(PresentCallback present_callback) {
-  TRACE_DURATION("view", "BaseView::InvalidateScene");
-  if (present_callback) {
-    callbacks_for_next_present_.push_back(std::move(present_callback));
-  }
-  if (invalidate_pending_)
-    return;
-
-  invalidate_pending_ = true;
-
-  // Present the scene ASAP. Pass in the last presentation time; otherwise, if
-  // presentation_time argument is less than the previous time passed to
-  // PresentScene, the Session will be closed.
-  // (We cannot use the current time because the last requested presentation
-  // time, |last_presentation_time_|, could still be in the future. This is
-  // because Session.Present() returns after it _begins_ preparing the given
-  // frame, not after it is presented.)
-  if (!present_pending_)
-    PresentScene(last_presentation_time_);
-}
-
-void BaseView::PresentScene() {
-  PresentScene(last_presentation_time_);
-}
-
-void BaseView::OnScenicEvent(std::vector<fuchsia::ui::scenic::Event> events) {
-  TRACE_DURATION("view", "BaseView::OnScenicEvent");
-  for (auto& event : events) {
-    switch (event.Which()) {
-      case ::fuchsia::ui::scenic::Event::Tag::kGfx:
-        switch (event.gfx().Which()) {
-          case ::fuchsia::ui::gfx::Event::Tag::kViewPropertiesChanged: {
-            auto& evt = event.gfx().view_properties_changed();
-            FML_DCHECK(view_->id() == evt.view_id);
-            auto old_props = view_properties_;
-            view_properties_ = evt.properties;
-
-            ::fuchsia::ui::gfx::BoundingBox layout_box =
-                ViewPropertiesLayoutBox(view_properties_);
-
-            logical_size_ = scenic::Max(layout_box.max - layout_box.min, 0.f);
-            physical_size_.x = logical_size_.x * metrics_.scale_x;
-            physical_size_.y = logical_size_.y * metrics_.scale_y;
-            physical_size_.z = logical_size_.z * metrics_.scale_z;
-
-            OnPropertiesChanged(std::move(old_props));
-            InvalidateScene();
-            break;
-          }
-          case fuchsia::ui::gfx::Event::Tag::kMetrics: {
-            auto& evt = event.gfx().metrics();
-            if (evt.node_id == root_node_.id()) {
-              auto old_metrics = metrics_;
-              metrics_ = std::move(evt.metrics);
-              physical_size_.x = logical_size_.x * metrics_.scale_x;
-              physical_size_.y = logical_size_.y * metrics_.scale_y;
-              physical_size_.z = logical_size_.z * metrics_.scale_z;
-              OnMetricsChanged(std::move(old_metrics));
-              InvalidateScene();
-            }
-            break;
-          }
-          default: {
-            OnScenicEvent(std::move(event));
-          }
-        }
-        break;
-      case ::fuchsia::ui::scenic::Event::Tag::kInput: {
-        if (event.input().Which() ==
-                fuchsia::ui::input::InputEvent::Tag::kFocus &&
-            enable_ime_) {
-          OnHandleFocusEvent(event.input().focus());
-        }
-        OnInputEvent(std::move(event.input()));
-        break;
-      }
-      case ::fuchsia::ui::scenic::Event::Tag::kUnhandled: {
-        OnUnhandledCommand(std::move(event.unhandled()));
-        break;
-      }
-      default: {
-        OnScenicEvent(std::move(event));
-      }
-    }
-  }
-}
-
-void BaseView::PresentScene(zx_time_t presentation_time) {
-  TRACE_DURATION("view", "BaseView::PresentScene");
-  // TODO(fxbug.dev/24406): Remove this when BaseView::PresentScene() is
-  // deprecated, see fxbug.dev/24573.
-  if (present_pending_)
-    return;
-
-  present_pending_ = true;
-
-  // Keep track of the most recent presentation time we've passed to
-  // Session.Present(), for use in InvalidateScene().
-  last_presentation_time_ = presentation_time;
-
-  TRACE_FLOW_BEGIN("gfx", "Session::Present", session_present_count_);
-  ++session_present_count_;
-
-  session()->Present(
-      presentation_time,
-      [this, present_callbacks = std::move(callbacks_for_next_present_)](
-          fuchsia::images::PresentationInfo info) mutable {
-        TRACE_DURATION("view", "BaseView::PresentationCallback");
-        TRACE_FLOW_END("gfx", "present_callback", info.presentation_time);
-
-        FML_DCHECK(present_pending_);
-
-        zx_time_t next_presentation_time =
-            info.presentation_time + info.presentation_interval;
-
-        bool present_needed = false;
-        if (invalidate_pending_) {
-          invalidate_pending_ = false;
-          OnSceneInvalidated(std::move(info));
-          present_needed = true;
-        }
-
-        for (auto& callback : present_callbacks) {
-          callback(info);
-        }
-
-        present_pending_ = false;
-        if (present_needed)
-          PresentScene(next_presentation_time);
-      });
-  callbacks_for_next_present_.clear();
-}
-
-// |fuchsia::ui::input::InputMethodEditorClient|
-void BaseView::DidUpdateState(
-    fuchsia::ui::input::TextInputState state,
-    std::unique_ptr<fuchsia::ui::input::InputEvent> input_event) {
-  if (input_event) {
-    const fuchsia::ui::input::InputEvent& input = *input_event;
-    fuchsia::ui::input::InputEvent input_event_copy;
-    fidl::Clone(input, &input_event_copy);
-    OnInputEvent(std::move(input_event_copy));
-  }
-}
-
-// |fuchsia::ui::input::InputMethodEditorClient|
-void BaseView::OnAction(fuchsia::ui::input::InputMethodAction action) {}
-
-bool BaseView::OnHandleFocusEvent(const fuchsia::ui::input::FocusEvent& focus) {
-  if (focus.focused) {
-    ActivateIme();
-    return true;
-  } else if (!focus.focused) {
-    DeactivateIme();
-    return true;
-  }
-  return false;
-}
-
-void BaseView::ActivateIme() {
-  ime_manager_->GetInputMethodEditor(
-      fuchsia::ui::input::KeyboardType::TEXT,       // keyboard type
-      fuchsia::ui::input::InputMethodAction::DONE,  // input method action
-      fuchsia::ui::input::TextInputState{},         // initial state
-      ime_client_.NewBinding(),                     // client
-      ime_.NewRequest()                             // editor
-  );
-}
-
-void BaseView::DeactivateIme() {
-  if (ime_) {
-    ime_manager_->HideKeyboard();
-    ime_ = nullptr;
-  }
-  if (ime_client_.is_bound()) {
-    ime_client_.Unbind();
-  }
-}
-
-}  // namespace scenic
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/base_view.h b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/base_view.h
deleted file mode 100644
index 6ad0257..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/base_view.h
+++ /dev/null
@@ -1,210 +0,0 @@
-// 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 SRC_LIB_UI_BASE_VIEW_BASE_VIEW_H_
-#define SRC_LIB_UI_BASE_VIEW_BASE_VIEW_H_
-
-#include <fuchsia/ui/gfx/cpp/fidl.h>
-#include <fuchsia/ui/input/cpp/fidl.h>
-#include <fuchsia/ui/scenic/cpp/fidl.h>
-#include <lib/sys/cpp/component_context.h>
-#include <lib/ui/scenic/cpp/resources.h>
-#include <lib/ui/scenic/cpp/session.h>
-#include <lib/ui/scenic/cpp/view_ref_pair.h>
-
-#include "src/lib/ui/base_view/embedded_view_utils.h"
-#include "src/lib/ui/base_view/math.h"
-
-namespace scenic {
-
-// Parameters for creating a BaseView.
-struct ViewContext {
-  scenic::SessionPtrAndListenerRequest session_and_listener_request;
-  fuchsia::ui::views::ViewToken view_token;
-  std::optional<ViewRefPair> view_ref_pair;
-  sys::ComponentContext* component_context;
-  bool enable_ime = false;
-};
-
-// Abstract base implementation of a view for simple applications.
-// Subclasses must handle layout and provide content for the scene by
-// overriding the virtual methods defined in this class.
-//
-// It is not necessary to use this class to implement all Views.
-// This class is merely intended to make the simple apps easier to write.
-class BaseView : private fuchsia::ui::scenic::SessionListener,
-                 private fuchsia::ui::input::InputMethodEditorClient {
- public:
-  using PresentCallback =
-      fit::function<void(const fuchsia::images::PresentationInfo& info)>;
-
-  // Subclasses are typically created by ViewProviderService::CreateView(),
-  // which provides the necessary args to pass down to this base class.
-  BaseView(ViewContext context, const std::string& debug_name);
-
-  BaseView(const BaseView&) = delete;
-
-  // |root_node| is the node directly under our View; i.e. it's the top-most
-  // node within the tree under our View. Use it to attach any resources for
-  // your UI.
-  scenic::EntityNode& root_node() { return root_node_; }
-  Session* session() { return &session_; }
-  sys::ComponentContext* component_context() { return component_context_; }
-
-  fuchsia::ui::gfx::ViewProperties view_properties() const {
-    return view_properties_;
-  }
-
-  // Returns true if the view has a non-empty size in logical pixels.
-  bool has_logical_size() const {
-    auto& sz = logical_size();
-    return sz.x > 0.f && sz.y > 0.f && sz.z > 0.f;
-  }
-
-  // Gets the size of the view in logical pixels.
-  // This value is zero until the view receives a layout from its parent.
-  const fuchsia::ui::gfx::vec3& logical_size() const { return logical_size_; }
-
-  // Returns true if the view has a non-empty size in physical pixels.
-  bool has_physical_size() const {
-    auto& sz = physical_size();
-    return sz.x > 0.f && sz.y > 0.f && sz.z > 0.f;
-  }
-
-  // Gets the size of the view in physical pixels.
-  // This value is zero until the view receives a layout from its parent
-  // and metrics from its session.
-  const fuchsia::ui::gfx::vec3& physical_size() const { return physical_size_; }
-
-  // Returns true if the view has received metrics from its session.
-  bool has_metrics() const {
-    return metrics_.scale_x > 0.f && metrics_.scale_y > 0.f &&
-           metrics_.scale_z > 0.f;
-  }
-
-  // Gets the view's metrics.
-  // This value is zero until the view receives metrics from its session.
-  const fuchsia::ui::gfx::Metrics& metrics() const { return metrics_; }
-
-  // Sets a callback which is invoked when the view's owner releases the
-  // view causing the view manager to unregister it.
-  //
-  // This should be used to implement cleanup policies to release resources
-  // associated with the view (including the object itself).
-  void SetReleaseHandler(fit::function<void(zx_status_t)> callback);
-
-  // Invalidates the scene, causing |OnSceneInvalidated()| to be invoked
-  // during the next frame. When the Present() callback corresponding to this
-  // invalidate is invoked, the optional |present_callback| will also be
-  // invoked.
-  void InvalidateScene(PresentCallback present_callback = nullptr);
-
-  // Called when it's time for the view to update its scene contents due to
-  // invalidation.  The new contents are presented once this function returns.
-  //
-  // The default implementation does nothing.
-  virtual void OnSceneInvalidated(
-      fuchsia::images::PresentationInfo presentation_info) {}
-
-  // Called when the view's properties have changed.
-  //
-  // The subclass should compare the old and new properties and make note of
-  // whether these property changes will affect the layout or content of
-  // the view then update accordingly.
-  //
-  // The default implementation does nothing.
-  virtual void OnPropertiesChanged(
-      fuchsia::ui::gfx::ViewProperties old_properties) {}
-
-  // Called when the view's metrics have changed.
-  //
-  // The subclass should compare the old and new metrics and make note of
-  // whether this change will affect the layout or content of the view then
-  // update accordingly.
-  //
-  // The default implementation does nothing.
-  virtual void OnMetricsChanged(fuchsia::ui::gfx::Metrics old_metrics){};
-
-  // Called to handle an input event.
-  //
-  // The default implementation does nothing.
-  virtual void OnInputEvent(fuchsia::ui::input::InputEvent event) {}
-
-  // Called when a command sent by the client was not handled by Scenic.
-  //
-  // The default implementation does nothing.
-  virtual void OnUnhandledCommand(fuchsia::ui::scenic::Command unhandled) {}
-
-  // Called when an event that is not handled directly by BaseView is received.
-  // For example, BaseView handles fuchsia::ui::gfx::ViewPropertiesChangedEvent,
-  // and notifies the subclass via OnPropertiesChanged(); not all events are
-  // handled in this way.
-  //
-  // The default implementation does nothing.
-  virtual void OnScenicEvent(fuchsia::ui::scenic::Event) {}
-
- protected:
-  // An alternative way to update the scene. Provide a faster way to cause a
-  // present in comparison to InvalidateScene(). Caller should update the
-  // scene contents before calling this method.
-  void PresentScene();
-
- private:
-  // |scenic::SessionListener|
-  //
-  // Iterates over the received events and either handles them in a sensible way
-  // (e.g. fuchsia::ui::gfx::ViewPropertiesChangedEvent is handled by invoking
-  // the virtual method OnPropertiesChanged()), or delegates handling to the
-  // subclass via the single-event version of OnEvent() above.
-  //
-  // Subclasses should not override this.
-  void OnScenicEvent(std::vector<fuchsia::ui::scenic::Event> events) override;
-
-  // |fuchsia::ui::input::InputMethodEditorClient|
-  void DidUpdateState(
-      fuchsia::ui::input::TextInputState state,
-      std::unique_ptr<fuchsia::ui::input::InputEvent> event) override;
-
-  // |fuchsia::ui::input::InputMethodEditorClient|
-  void OnAction(fuchsia::ui::input::InputMethodAction action) override;
-
-  void PresentScene(zx_time_t presentation_time);
-
-  // Handles focus event when IME is enabled. This event is used to activate
-  // or deactivate the IME client.
-  bool OnHandleFocusEvent(const fuchsia::ui::input::FocusEvent& focus);
-
-  // Gets a new input method editor from the IME manager.
-  void ActivateIme();
-
-  // Detaches the input method editor connection, ending the edit session and
-  // closing the onscreen keyboard.
-  void DeactivateIme();
-
-  sys::ComponentContext* const component_context_;
-  fidl::Binding<fuchsia::ui::scenic::SessionListener> listener_binding_;
-  Session session_;
-  std::optional<scenic::View> view_;
-  scenic::EntityNode root_node_;
-
-  fidl::Binding<fuchsia::ui::input::InputMethodEditorClient> ime_client_;
-  fuchsia::ui::input::InputMethodEditorPtr ime_;
-  fuchsia::ui::input::ImeServicePtr ime_manager_;
-
-  fuchsia::ui::gfx::vec3 logical_size_;
-  fuchsia::ui::gfx::vec3 physical_size_;
-  fuchsia::ui::gfx::ViewProperties view_properties_;
-  fuchsia::ui::gfx::Metrics metrics_;
-
-  zx_time_t last_presentation_time_ = 0;
-  size_t session_present_count_ = 0;
-  bool invalidate_pending_ = false;
-  std::vector<PresentCallback> callbacks_for_next_present_;
-  bool present_pending_ = false;
-  bool enable_ime_ = false;
-};
-
-}  // namespace scenic
-
-#endif  // SRC_LIB_UI_BASE_VIEW_BASE_VIEW_H_
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/embedded_view_utils.cc b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/embedded_view_utils.cc
deleted file mode 100644
index 6235b8d..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/embedded_view_utils.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// 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.
-
-#include "src/lib/ui/base_view/embedded_view_utils.h"
-
-#include <lib/ui/scenic/cpp/view_ref_pair.h>
-#include <lib/ui/scenic/cpp/view_token_pair.h>
-#include "flutter/fml/logging.h"
-
-namespace scenic {
-
-EmbeddedViewInfo LaunchComponentAndCreateView(
-    const fuchsia::sys::LauncherPtr& launcher,
-    const std::string& component_url,
-    const std::vector<std::string>& component_args) {
-  FML_DCHECK(launcher);
-
-  EmbeddedViewInfo info;
-
-  // Configure the information to launch the component with.
-  fuchsia::sys::LaunchInfo launch_info;
-  info.app_services =
-      sys::ServiceDirectory::CreateWithRequest(&launch_info.directory_request);
-  launch_info.url = component_url;
-  launch_info.arguments = fidl::VectorPtr(
-      std::vector<std::string>(component_args.begin(), component_args.end()));
-
-  launcher->CreateComponent(std::move(launch_info),
-                            info.controller.NewRequest());
-
-  info.view_provider =
-      info.app_services->Connect<fuchsia::ui::app::ViewProvider>();
-
-  auto [view_token, view_holder_token] = scenic::ViewTokenPair::New();
-  info.view_holder_token = std::move(view_holder_token);
-
-  auto [view_ref_control, view_ref] = scenic::ViewRefPair::New();
-  fidl::Clone(view_ref, &info.view_ref);
-
-  info.view_provider->CreateViewWithViewRef(std::move(view_token.value),
-                                            std::move(view_ref_control),
-                                            std::move(view_ref));
-
-  return info;
-}
-
-}  // namespace scenic
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/embedded_view_utils.h b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/embedded_view_utils.h
deleted file mode 100644
index ff087d4..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/embedded_view_utils.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// 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 SRC_LIB_UI_BASE_VIEW_EMBEDDED_VIEW_UTILS_H_
-#define SRC_LIB_UI_BASE_VIEW_EMBEDDED_VIEW_UTILS_H_
-
-#include <fuchsia/ui/app/cpp/fidl.h>
-#include <fuchsia/ui/gfx/cpp/fidl.h>
-#include <fuchsia/ui/input/cpp/fidl.h>
-#include <fuchsia/ui/scenic/cpp/fidl.h>
-#include <fuchsia/ui/views/cpp/fidl.h>
-#include <lib/sys/cpp/service_directory.h>
-#include <lib/ui/scenic/cpp/resources.h>
-#include <lib/ui/scenic/cpp/session.h>
-
-namespace scenic {
-
-// Serves as the return value for LaunchAppAndCreateView(), below.
-struct EmbeddedViewInfo {
-  // Controls the launched app.  The app will be destroyed if this connection
-  // is closed.
-  fuchsia::sys::ComponentControllerPtr controller;
-
-  // Services provided by the launched app.  Must not be destroyed
-  // immediately, otherwise the |view_provider| connection may not be
-  // established.
-  std::shared_ptr<sys::ServiceDirectory> app_services;
-
-  // ViewProvider service obtained from the app via |app_services|.  Must not
-  // be destroyed immediately, otherwise the call to CreateView() might not be
-  // processed.
-  fuchsia::ui::app::ViewProviderPtr view_provider;
-
-  // A token that can be used to create a ViewHolder; the corresponding token
-  // was provided to |view_provider| via ViewProvider.CreateView().  The
-  // launched app is expected to create a View, which will be connected to the
-  // ViewHolder created with this token.
-  fuchsia::ui::views::ViewHolderToken view_holder_token;
-
-  // The ViewRef of the embedded View.
-  fuchsia::ui::views::ViewRef view_ref;
-};
-
-// Launch a component and connect to its ViewProvider service, passing it the
-// necessary information to attach itself as a child view2.  Populates the
-// returned EmbeddedViewInfo, which the caller can use to embed the child.
-// For example, an interface to a ViewProvider is obtained, a pair of
-// zx::eventpairs is created, CreateView is called, etc.  This encapsulates
-// the boilerplate the client would otherwise write themselves.
-EmbeddedViewInfo LaunchComponentAndCreateView(
-    const fuchsia::sys::LauncherPtr& launcher,
-    const std::string& component_url,
-    const std::vector<std::string>& component_args = {});
-
-}  // namespace scenic
-
-#endif  // SRC_LIB_UI_BASE_VIEW_EMBEDDED_VIEW_UTILS_H_
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/math.h b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/math.h
deleted file mode 100644
index 9cf99ce..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view/math.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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 SRC_LIB_UI_BASE_VIEW_MATH_H_
-#define SRC_LIB_UI_BASE_VIEW_MATH_H_
-
-#include <fuchsia/ui/gfx/cpp/fidl.h>
-
-namespace scenic {
-
-// Return a vec3 consisting of the component-wise sum of the two arguments.
-inline fuchsia::ui::gfx::vec3 operator+(const fuchsia::ui::gfx::vec3& a,
-                                        const fuchsia::ui::gfx::vec3& b) {
-  return {.x = a.x + b.x, .y = a.y + b.y, .z = a.z + b.z};
-}
-
-// Return a vec3 consisting of the component-wise difference of the two args.
-inline fuchsia::ui::gfx::vec3 operator-(const fuchsia::ui::gfx::vec3& a,
-                                        const fuchsia::ui::gfx::vec3& b) {
-  return {.x = a.x - b.x, .y = a.y - b.y, .z = a.z - b.z};
-}
-
-// Return true if |point| is contained by |box|, including when it is on the
-// box boundary, and false otherwise.
-inline bool ContainsPoint(const fuchsia::ui::gfx::BoundingBox& box,
-                          const fuchsia::ui::gfx::vec3& point) {
-  return point.x >= box.min.x && point.y >= box.min.y && point.z >= box.min.z &&
-         point.x <= box.max.x && point.y <= box.max.y && point.z <= box.max.z;
-}
-
-// Similar to fuchsia::ui::gfx::ViewProperties: adds the inset to box.min, and
-// subtracts it from box.max.
-inline fuchsia::ui::gfx::BoundingBox InsetBy(
-    const fuchsia::ui::gfx::BoundingBox& box,
-    const fuchsia::ui::gfx::vec3& inset) {
-  return {.min = box.min + inset, .max = box.max - inset};
-}
-
-// Similar to fuchsia::ui::gfx::ViewProperties: adds the inset to box.min, and
-// subtracts it from box.max.
-inline fuchsia::ui::gfx::BoundingBox InsetBy(
-    const fuchsia::ui::gfx::BoundingBox& box,
-    const fuchsia::ui::gfx::vec3& inset_from_min,
-    const fuchsia::ui::gfx::vec3& inset_from_max) {
-  return {.min = box.min + inset_from_min, .max = box.max - inset_from_max};
-}
-
-// Inset the view properties' outer box by its insets.
-inline fuchsia::ui::gfx::BoundingBox ViewPropertiesLayoutBox(
-    const fuchsia::ui::gfx::ViewProperties& view_properties) {
-  return InsetBy(view_properties.bounding_box, view_properties.inset_from_min,
-                 view_properties.inset_from_max);
-}
-
-// Return a vec3 consisting of the maximum x/y/z from the two arguments.
-inline fuchsia::ui::gfx::vec3 Max(const fuchsia::ui::gfx::vec3& a,
-                                  const fuchsia::ui::gfx::vec3& b) {
-  return {.x = std::max(a.x, b.x),
-          .y = std::max(a.y, b.y),
-          .z = std::max(a.z, b.z)};
-}
-
-// Return a vec3 consisting of the maximum of the x/y/z components of |v|,
-// compared with |min_val|.
-inline fuchsia::ui::gfx::vec3 Max(const fuchsia::ui::gfx::vec3& v,
-                                  float min_val) {
-  return {.x = std::max(v.x, min_val),
-          .y = std::max(v.y, min_val),
-          .z = std::max(v.z, min_val)};
-}
-
-// Return a vec3 consisting of the minimum x/y/z from the two arguments.
-inline fuchsia::ui::gfx::vec3 Min(const fuchsia::ui::gfx::vec3& a,
-                                  const fuchsia::ui::gfx::vec3& b) {
-  return {.x = std::min(a.x, b.x),
-          .y = std::min(a.y, b.y),
-          .z = std::min(a.z, b.z)};
-}
-
-// Return a vec3 consisting of the minimum of the x/y/z components of |v|,
-// compared with |max_val|.
-inline fuchsia::ui::gfx::vec3 Min(const fuchsia::ui::gfx::vec3& v,
-                                  float max_val) {
-  return {.x = std::min(v.x, max_val),
-          .y = std::min(v.y, max_val),
-          .z = std::min(v.z, max_val)};
-}
-
-}  // namespace scenic
-
-#endif  // SRC_LIB_UI_BASE_VIEW_MATH_H_
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/BUILD.gn b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/BUILD.gn
deleted file mode 100644
index f97e927..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/BUILD.gn
+++ /dev/null
@@ -1,24 +0,0 @@
-# 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.
-
-import("//build/fuchsia/sdk.gni")
-
-source_set("views") {
-  testonly = true
-
-  sources = [
-    "color.cc",
-    "color.h",
-    "embedder_view.cc",
-    "embedder_view.h",
-  ]
-
-  include_dirs = [ "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing" ]
-
-  public_deps = [
-    "$fuchsia_sdk_root/pkg:scenic_cpp",
-    "//flutter/fml",
-    "//flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/lib/ui/base_view",
-  ]
-}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/embedder_view.cc b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/embedder_view.cc
deleted file mode 100644
index 0d11282..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/embedder_view.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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.
-
-#include <zircon/status.h>
-
-#include "flutter/fml/logging.h"
-#include "src/ui/testing/views/embedder_view.h"
-
-namespace scenic {
-
-EmbedderView::EmbedderView(ViewContext context, const std::string& debug_name)
-    : binding_(this, std::move(context.session_and_listener_request.second)),
-      session_(std::move(context.session_and_listener_request.first)),
-      view_(&session_, std::move(context.view_token), debug_name),
-      top_node_(&session_) {
-  binding_.set_error_handler([](zx_status_t status) {
-    FML_LOG(FATAL) << "Session listener binding: "
-                   << zx_status_get_string(status);
-  });
-  view_.AddChild(top_node_);
-  // Call |Session::Present| in order to flush events having to do with
-  // creation of |view_| and |top_node_|.
-  session_.Present(0, [](auto) {});
-}
-
-// Sets the EmbeddedViewInfo and attaches the embedded View to the scene. Any
-// callbacks for the embedded View's ViewState are delivered to the supplied
-// callback.
-void EmbedderView::EmbedView(EmbeddedViewInfo info,
-                             std::function<void(fuchsia::ui::gfx::ViewState)>
-                                 view_state_changed_callback) {
-  // Only one EmbeddedView is currently supported.
-  FML_CHECK(!embedded_view_);
-  embedded_view_ = std::make_unique<EmbeddedView>(
-      std::move(info), &session_, std::move(view_state_changed_callback));
-
-  // Attach the embedded view to the scene.
-  top_node_.Attach(embedded_view_->view_holder);
-
-  // Call |Session::Present| to apply the embedded view to the scene graph.
-  session_.Present(0, [](auto) {});
-}
-
-void EmbedderView::OnScenicEvent(
-    std::vector<fuchsia::ui::scenic::Event> events) {
-  for (const auto& event : events) {
-    if (event.Which() == fuchsia::ui::scenic::Event::Tag::kGfx &&
-        event.gfx().Which() ==
-            fuchsia::ui::gfx::Event::Tag::kViewPropertiesChanged) {
-      const auto& evt = event.gfx().view_properties_changed();
-      // Naively apply the parent's ViewProperties to any EmbeddedViews.
-      if (embedded_view_) {
-        embedded_view_->view_holder.SetViewProperties(
-            std::move(evt.properties));
-        session_.Present(0, [](auto) {});
-      }
-    } else if (event.Which() == fuchsia::ui::scenic::Event::Tag::kGfx &&
-               event.gfx().Which() ==
-                   fuchsia::ui::gfx::Event::Tag::kViewStateChanged) {
-      const auto& evt = event.gfx().view_state_changed();
-      if (embedded_view_ &&
-          evt.view_holder_id == embedded_view_->view_holder.id()) {
-        // Clients of |EmbedderView| *must* set a view state changed
-        // callback.  Failure to do so is a usage error.
-        FML_CHECK(embedded_view_->view_state_changed_callback);
-        embedded_view_->view_state_changed_callback(evt.state);
-      }
-    }
-  }
-}
-
-void EmbedderView::OnScenicError(std::string error) {
-  FML_LOG(FATAL) << "OnScenicError: " << error;
-}
-
-EmbedderView::EmbeddedView::EmbeddedView(
-    EmbeddedViewInfo info,
-    Session* session,
-    std::function<void(fuchsia::ui::gfx::ViewState)> view_state_callback,
-    const std::string& debug_name)
-    : embedded_info(std::move(info)),
-      view_holder(session,
-                  std::move(embedded_info.view_holder_token),
-                  debug_name + " ViewHolder"),
-      view_state_changed_callback(std::move(view_state_callback)) {}
-
-}  // namespace scenic
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/embedder_view.h b/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/embedder_view.h
deleted file mode 100644
index 4514d0f..0000000
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/embedder_view.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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 SRC_UI_TESTING_VIEWS_EMBEDDER_VIEW_H_
-#define SRC_UI_TESTING_VIEWS_EMBEDDER_VIEW_H_
-
-#include <fuchsia/ui/scenic/cpp/fidl.h>
-#include <lib/ui/scenic/cpp/resources.h>
-#include <lib/ui/scenic/cpp/session.h>
-
-#include "src/lib/ui/base_view/base_view.h"
-
-namespace scenic {
-
-// This is a simplified |BaseView| that exposes view state events.
-//
-// See also lib/ui/base_view.
-class EmbedderView : public fuchsia::ui::scenic::SessionListener {
- public:
-  EmbedderView(ViewContext context,
-               const std::string& debug_name = "EmbedderView");
-
-  // Sets the EmbeddedViewInfo and attaches the embedded View to the scene. Any
-  // callbacks for the embedded View's ViewState are delivered to the supplied
-  // callback.
-  void EmbedView(EmbeddedViewInfo info,
-                 std::function<void(fuchsia::ui::gfx::ViewState)>
-                     view_state_changed_callback);
-
- private:
-  // |fuchsia::ui::scenic::SessionListener|
-  void OnScenicEvent(std::vector<fuchsia::ui::scenic::Event> events) override;
-  // |fuchsia::ui::scenic::SessionListener|
-  void OnScenicError(std::string error) override;
-
-  struct EmbeddedView {
-    EmbeddedView(
-        EmbeddedViewInfo info,
-        Session* session,
-        std::function<void(fuchsia::ui::gfx::ViewState)> view_state_callback,
-        const std::string& debug_name = "EmbedderView");
-
-    EmbeddedViewInfo embedded_info;
-    ViewHolder view_holder;
-    std::function<void(fuchsia::ui::gfx::ViewState)>
-        view_state_changed_callback;
-  };
-
-  fidl::Binding<fuchsia::ui::scenic::SessionListener> binding_;
-  Session session_;
-  View view_;
-  EntityNode top_node_;
-  std::optional<fuchsia::ui::gfx::ViewProperties> embedded_view_properties_;
-  std::unique_ptr<EmbeddedView> embedded_view_;
-};
-
-}  // namespace scenic
-#endif  // SRC_UI_TESTING_VIEWS_EMBEDDER_VIEW_H_
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/BUILD.gn b/shell/platform/fuchsia/flutter/tests/integration/BUILD.gn
similarity index 72%
rename from shell/platform/fuchsia/flutter/integration_flutter_tests/BUILD.gn
rename to shell/platform/fuchsia/flutter/tests/integration/BUILD.gn
index 6e5e43e..c25f18a 100644
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/BUILD.gn
+++ b/shell/platform/fuchsia/flutter/tests/integration/BUILD.gn
@@ -2,7 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-group("integration_flutter_tests") {
+assert(is_fuchsia)
+
+import("//build/fuchsia/sdk.gni")
+
+group("integration") {
   testonly = true
   deps = [ "embedder:tests" ]
 }
diff --git a/shell/platform/fuchsia/flutter/tests/integration/README.md b/shell/platform/fuchsia/flutter/tests/integration/README.md
new file mode 100644
index 0000000..2e86aa7
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/README.md
@@ -0,0 +1,84 @@
+# `flutter integration tests`
+
+## Configure and build fuchsia
+
+```shell
+$ cd "$FUCHSIA_DIR"
+$ fx set terminal.x64
+$ fx build
+```
+
+## Build the test
+
+You can specify the test's package target to build only the test package, with
+its dependencies. This will also build the required runner.
+
+```shell
+$ cd "$ENGINE_DIR/src"
+$ ./flutter/tools/gn --fuchsia <flags> \
+      # for example: --goma --fuchsia-cpu=x64 --runtime-mode=debug
+$ ninja -C out/fuchsia_debug_x64 \
+    flutter/shell/platform/fuchsia/flutter/tests/integration
+```
+
+
+## Start an emulator
+
+```shell
+ffx emu start --net tap
+```
+
+NOTE: Do _not_ run the default package server. The instructions below describe
+how to launch a flutter-specific package server.
+
+## Publish the test packages to the Fuchsia package server
+
+The tests currently specify the Fuchsia package server's standard domain,
+`fuchsia.com`, as the server to use to resolve (locate and load) the test
+packages. So, before running the test, the most recently built `.far` files
+need to be published to the Fuchsia package repo:
+
+```shell
+$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
+  -f "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64/oot_flutter_jit_runner-0.far
+$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
+  -f "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64/flutter-embedder-test-0.far
+$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
+  -f $(find "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64 -name parent-view.far)
+$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
+  -f $(find "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64 -name child-view.far)
+```
+
+## Run the test
+
+```shell
+$ ffx test run fuchsia-pkg:://fuchsia.com/flutter-embedder-test#meta/flutter-embedder-test.cm
+```
+
+If, for example, you only make a change to the Dart code in `parent-view`, you
+can rebuild only the parent-view package target, and republish it.
+
+```shell
+$ ninja -C out/fuchsia_debug_x64 \
+    flutter/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view:package
+$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
+  -f $(find "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64 -name parent-view.far)
+```
+
+Then re-run the test as above.
+
+The tests use a flutter runner with "oot_" prefixed to its package name, to
+avoid conflicting with any flutter_runner package in the base fuchsia image.
+After making a change to the flutter_runner you can re-deploy it with:
+
+```shell
+$ ninja -C out/fuchsia_debug_x64 \
+    flutter/shell/platform/fuchsia/flutter:oot_flutter_jit_runner
+$ fx pm publish -a -repo "$(cat $FUCHSIA_DIR/.fx-build-dir)/amber-files/" \
+  -f $(find "$FLUTTER_ENGINE_DIR"/src/out/fuchsia_*64 -name oot_flutter_jit_runner.far)
+```
+
+Then re-run the test as above.
+
+From here, you can modify the Flutter test, rebuild flutter, and usually rerun
+the test without rebooting, by repeating the commands above.
diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/BUILD.gn b/shell/platform/fuchsia/flutter/tests/integration/embedder/BUILD.gn
new file mode 100644
index 0000000..ce295f3
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/BUILD.gn
@@ -0,0 +1,65 @@
+# 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.
+
+assert(is_fuchsia)
+
+import("//build/fuchsia/sdk.gni")
+import("//flutter/tools/fuchsia/fuchsia_archive.gni")
+
+group("tests") {
+  testonly = true
+  deps = [ ":flutter-embedder-test" ]
+}
+
+executable("flutter-embedder-test-bin") {
+  testonly = true
+
+  output_name = "flutter-embedder-test"
+
+  sources = [
+    "color.cc",
+    "color.h",
+    "flutter-embedder-test.cc",
+  ]
+
+  # This is needed for //third_party/googletest for linking zircon symbols.
+  libs = [ "$fuchsia_sdk_path/arch/$target_cpu/sysroot/lib/libzircon.so" ]
+
+  deps = [
+    "$fuchsia_sdk_root/fidl:fuchsia.logger",
+    "$fuchsia_sdk_root/fidl:fuchsia.tracing.provider",
+    "$fuchsia_sdk_root/fidl:fuchsia.ui.app",
+    "$fuchsia_sdk_root/fidl:fuchsia.ui.composition",
+    "$fuchsia_sdk_root/fidl:fuchsia.ui.observation.geometry",
+    "$fuchsia_sdk_root/fidl:fuchsia.ui.scenic",
+    "$fuchsia_sdk_root/fidl:fuchsia.ui.test.input",
+    "$fuchsia_sdk_root/fidl:fuchsia.ui.test.scene",
+    "$fuchsia_sdk_root/pkg:async",
+    "$fuchsia_sdk_root/pkg:async-loop-testing",
+    "$fuchsia_sdk_root/pkg:fidl_cpp",
+    "$fuchsia_sdk_root/pkg:scenic_cpp",
+    "$fuchsia_sdk_root/pkg:sys_component_cpp_testing",
+    "$fuchsia_sdk_root/pkg:zx",
+    "//flutter/fml",
+    "//third_party/googletest:gtest",
+    "//third_party/googletest:gtest_main",
+  ]
+}
+
+fuchsia_test_archive("flutter-embedder-test") {
+  deps = [
+    ":flutter-embedder-test-bin",
+    "child-view:package",
+    "parent-view:package",
+
+    # "OOT" copies of the runners used by tests, to avoid conflicting with the
+    # runners in the base fuchsia image.
+    # TODO(fxbug.dev/106575): Fix this with subpackages.
+    "//flutter/shell/platform/fuchsia/flutter:oot_flutter_jit_runner",
+  ]
+
+  binary = "$target_name"
+
+  cml_file = rebase_path("meta/$target_name.cml")
+}
diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/BUILD.gn b/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/BUILD.gn
new file mode 100644
index 0000000..dedf77c
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/BUILD.gn
@@ -0,0 +1,26 @@
+# 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.
+
+import("//build/fuchsia/sdk.gni")
+import("//flutter/tools/fuchsia/dart/dart_library.gni")
+import("//flutter/tools/fuchsia/flutter/flutter_component.gni")
+import("//flutter/tools/fuchsia/gn-sdk/package.gni")
+
+dart_library("lib") {
+  package_name = "child-view"
+  sources = [ "child_view.dart" ]
+}
+
+flutter_component("component") {
+  main_package = "child-view"
+  component_name = "child-view"
+  main_dart = "child_view.dart"
+  manifest = rebase_path("meta/child-view.cml")
+  deps = [ ":lib" ]
+}
+
+fuchsia_package("package") {
+  package_name = "child-view"
+  deps = [ ":component" ]
+}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/child_view2.dart b/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/lib/child_view.dart
similarity index 84%
rename from shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/child_view2.dart
rename to shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/lib/child_view.dart
index a361955..5b71294 100644
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/child_view2.dart
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/lib/child_view.dart
@@ -4,10 +4,10 @@
 
 import 'dart:ui';
 
-TestApp app;
-
 void main(List<String> args) {
-  app = TestApp();
+  print('child-view: starting');
+
+  TestApp app = TestApp();
   app.run();
 }
 
@@ -19,11 +19,15 @@
 
   void run() {
     window.onPointerDataPacket = (PointerDataPacket packet) {
-      app.pointerDataPacket(packet);
+      this.pointerDataPacket(packet);
+    };
+    window.onMetricsChanged = () {
+      window.scheduleFrame();
     };
     window.onBeginFrame = (Duration duration) {
-      app.beginFrame(duration);
+      this.beginFrame(duration);
     };
+
     window.scheduleFrame();
   }
 
@@ -46,7 +50,7 @@
 
   void pointerDataPacket(PointerDataPacket packet) {
     for (final data in packet.data) {
-      if (data.change == PointerChange.up) {
+      if (data.change == PointerChange.down) {
         this._backgroundColor = _yellow;
       }
     }
diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/meta/child-view.cml b/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/meta/child-view.cml
new file mode 100644
index 0000000..9e33d6a
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/meta/child-view.cml
@@ -0,0 +1,21 @@
+{
+    include: [ "syslog/client.shard.cml" ],
+    program: {
+        data: "data/child-view",
+
+        // Always use the jit runner for now.
+        // TODO(fxbug.dev/106577): Implement manifest merging build rules for V2 components.
+        runner: "flutter_jit_runner",
+    },
+    capabilities: [
+        {
+            protocol: [ "fuchsia.ui.app.ViewProvider" ],
+        },
+    ],
+    expose: [
+        {
+            protocol: [ "fuchsia.ui.app.ViewProvider" ],
+            from: "self",
+        },
+    ],
+}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/pubspec.yaml b/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/pubspec.yaml
similarity index 100%
rename from shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/pubspec.yaml
rename to shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/pubspec.yaml
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/color.cc b/shell/platform/fuchsia/flutter/tests/integration/embedder/color.cc
similarity index 97%
rename from shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/color.cc
rename to shell/platform/fuchsia/flutter/tests/integration/embedder/color.cc
index d723734..24fd675 100644
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/color.cc
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/color.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "color.h"
+
 #include <zircon/status.h>
 
 #include "flutter/fml/logging.h"
-#include "src/ui/testing/views/color.h"
 
 namespace scenic {
 
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/color.h b/shell/platform/fuchsia/flutter/tests/integration/embedder/color.h
similarity index 100%
rename from shell/platform/fuchsia/flutter/integration_flutter_tests/fuchsia_testing/src/ui/testing/views/color.h
rename to shell/platform/fuchsia/flutter/tests/integration/embedder/color.h
diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/flutter-embedder-test.cc b/shell/platform/fuchsia/flutter/tests/integration/embedder/flutter-embedder-test.cc
new file mode 100644
index 0000000..73f36e8
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/flutter-embedder-test.cc
@@ -0,0 +1,602 @@
+// 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.
+
+#include <fuchsia/logger/cpp/fidl.h>
+#include <fuchsia/tracing/provider/cpp/fidl.h>
+#include <fuchsia/ui/app/cpp/fidl.h>
+#include <fuchsia/ui/composition/cpp/fidl.h>
+#include <fuchsia/ui/observation/geometry/cpp/fidl.h>
+#include <fuchsia/ui/scenic/cpp/fidl.h>
+#include <fuchsia/ui/test/input/cpp/fidl.h>
+#include <fuchsia/ui/test/scene/cpp/fidl.h>
+#include <lib/async-loop/testing/cpp/real_loop.h>
+#include <lib/async/cpp/task.h>
+#include <lib/fidl/cpp/binding_set.h>
+#include <lib/sys/component/cpp/testing/realm_builder.h>
+#include <lib/sys/component/cpp/testing/realm_builder_types.h>
+#include <lib/ui/scenic/cpp/view_ref_pair.h>
+#include <lib/zx/clock.h>
+#include <zircon/status.h>
+#include <zircon/time.h>
+
+#include <optional>
+#include <vector>
+
+#include "flutter/fml/logging.h"
+#include "gtest/gtest.h"
+
+#include "color.h"
+
+namespace flutter_embedder_test {
+namespace {
+
+// Types imported for the realm_builder library.
+using component_testing::ChildOptions;
+using component_testing::ChildRef;
+using component_testing::DirectoryContents;
+using component_testing::ParentRef;
+using component_testing::Protocol;
+using component_testing::RealmRoot;
+using component_testing::Route;
+using component_testing::StartupMode;
+
+// The FIDL bindings for this service are not exposed in the Fuchsia SDK, so we
+// must encode the name manually here.
+constexpr auto kVulkanLoaderServiceName = "fuchsia.vulkan.loader.Loader";
+
+constexpr auto kFlutterJitRunnerUrl =
+    "fuchsia-pkg://fuchsia.com/oot_flutter_jit_runner#meta/"
+    "flutter_jit_runner.cm";
+constexpr auto kFlutterJitProductRunnerUrl =
+    "fuchsia-pkg://fuchsia.com/oot_flutter_jit_product_runner#meta/"
+    "flutter_jit_product_runner.cm";
+constexpr auto kFlutterAotRunnerUrl =
+    "fuchsia-pkg://fuchsia.com/oot_flutter_aot_runner#meta/"
+    "flutter_aot_runner.cm";
+constexpr auto kFlutterAotProductRunnerUrl =
+    "fuchsia-pkg://fuchsia.com/oot_flutter_aot_product_runner#meta/"
+    "flutter_aot_product_runner.cm";
+constexpr char kChildViewUrl[] =
+    "fuchsia-pkg://fuchsia.com/child-view#meta/child-view.cm";
+constexpr char kParentViewUrl[] =
+    "fuchsia-pkg://fuchsia.com/parent-view#meta/parent-view.cm";
+static constexpr auto kTestUIStackUrl =
+    "fuchsia-pkg://fuchsia.com/test-ui-stack#meta/test-ui-stack.cm";
+
+constexpr auto kFlutterRunnerEnvironment = "flutter_runner_env";
+constexpr auto kFlutterJitRunner = "flutter_jit_runner";
+constexpr auto kFlutterJitRunnerRef = ChildRef{kFlutterJitRunner};
+constexpr auto kFlutterJitProductRunner = "flutter_jit_product_runner";
+constexpr auto kFlutterJitProductRunnerRef = ChildRef{kFlutterJitProductRunner};
+constexpr auto kFlutterAotRunner = "flutter_aot_runner";
+constexpr auto kFlutterAotRunnerRef = ChildRef{kFlutterAotRunner};
+constexpr auto kFlutterAotProductRunner = "flutter_aot_product_runner";
+constexpr auto kFlutterAotProductRunnerRef = ChildRef{kFlutterAotProductRunner};
+constexpr auto kChildView = "child_view";
+constexpr auto kChildViewRef = ChildRef{kChildView};
+constexpr auto kParentView = "parent_view";
+constexpr auto kParentViewRef = ChildRef{kParentView};
+constexpr auto kTestUIStack = "ui";
+constexpr auto kTestUIStackRef = ChildRef{kTestUIStack};
+
+constexpr scenic::Color kParentBackgroundColor = {0x00, 0x00, 0xFF,
+                                                  0xFF};                // Blue
+constexpr scenic::Color kParentTappedColor = {0x00, 0x00, 0x00, 0xFF};  // Black
+constexpr scenic::Color kChildBackgroundColor = {0xFF, 0x00, 0xFF,
+                                                 0xFF};                // Pink
+constexpr scenic::Color kChildTappedColor = {0xFF, 0xFF, 0x00, 0xFF};  // Yellow
+
+// TODO(fxb/64201): Remove forced opacity colors when Flatland is enabled.
+constexpr scenic::Color kOverlayBackgroundColor1 = {
+    0x00, 0xFF, 0x0E, 0xFF};  // Green, blended with blue (FEMU local)
+constexpr scenic::Color kOverlayBackgroundColor2 = {
+    0x0E, 0xFF, 0x0E, 0xFF};  // Green, blended with pink (FEMU local)
+constexpr scenic::Color kOverlayBackgroundColor3 = {
+    0x00, 0xFF, 0x0D, 0xFF};  // Green, blended with blue (AEMU infra)
+constexpr scenic::Color kOverlayBackgroundColor4 = {
+    0x0D, 0xFF, 0x0D, 0xFF};  // Green, blended with pink (AEMU infra)
+constexpr scenic::Color kOverlayBackgroundColor5 = {
+    0x00, 0xFE, 0x0D, 0xFF};  // Green, blended with blue (NUC)
+constexpr scenic::Color kOverlayBackgroundColor6 = {
+    0x0D, 0xFF, 0x00, 0xFF};  // Green, blended with pink (NUC)
+
+static size_t OverlayPixelCount(std::map<scenic::Color, size_t>& histogram) {
+  return histogram[kOverlayBackgroundColor1] +
+         histogram[kOverlayBackgroundColor2] +
+         histogram[kOverlayBackgroundColor3] +
+         histogram[kOverlayBackgroundColor4] +
+         histogram[kOverlayBackgroundColor5] +
+         histogram[kOverlayBackgroundColor6];
+}
+
+// Timeout for Scenic's |TakeScreenshot| FIDL call.
+constexpr zx::duration kScreenshotTimeout = zx::sec(10);
+// Timeout to fail the test if it goes beyond this duration.
+constexpr zx::duration kTestTimeout = zx::min(1);
+
+bool CheckViewExistsInSnapshot(
+    const fuchsia::ui::observation::geometry::ViewTreeSnapshot& snapshot,
+    zx_koid_t view_ref_koid) {
+  if (!snapshot.has_views()) {
+    return false;
+  }
+
+  auto snapshot_count =
+      std::count_if(snapshot.views().begin(), snapshot.views().end(),
+                    [view_ref_koid](const auto& view) {
+                      return view.view_ref_koid() == view_ref_koid;
+                    });
+
+  return snapshot_count > 0;
+}
+
+bool CheckViewExistsInUpdates(
+    const std::vector<fuchsia::ui::observation::geometry::ViewTreeSnapshot>&
+        updates,
+    zx_koid_t view_ref_koid) {
+  auto update_count = std::count_if(
+      updates.begin(), updates.end(), [view_ref_koid](auto& snapshot) {
+        return CheckViewExistsInSnapshot(snapshot, view_ref_koid);
+      });
+
+  return update_count > 0;
+}
+
+}  // namespace
+
+class FlutterEmbedderTest : public ::loop_fixture::RealLoop,
+                            public ::testing::Test {
+ public:
+  FlutterEmbedderTest()
+      : realm_builder_(component_testing::RealmBuilder::Create()) {
+    FML_VLOG(-1) << "Setting up base realm";
+    SetUpRealmBase();
+
+    // Post a "just in case" quit task, if the test hangs.
+    async::PostDelayedTask(
+        dispatcher(),
+        [] {
+          FML_LOG(FATAL)
+              << "\n\n>> Test did not complete in time, terminating.  <<\n\n";
+        },
+        kTestTimeout);
+  }
+
+  bool HasViewConnected(
+      const fuchsia::ui::observation::geometry::ViewTreeWatcherPtr&
+          view_tree_watcher,
+      std::optional<fuchsia::ui::observation::geometry::WatchResponse>&
+          watch_response,
+      zx_koid_t view_ref_koid);
+
+  void LaunchParentViewInRealm(
+      const std::vector<std::string>& component_args = {});
+
+  scenic::Screenshot TakeScreenshot();
+
+  bool TakeScreenshotUntil(
+      scenic::Color color,
+      fit::function<void(std::map<scenic::Color, size_t>)> callback = nullptr,
+      zx::duration timeout = kTestTimeout);
+
+  // Simulates a tap at location (x, y).
+  void InjectTap(int32_t x, int32_t y);
+
+  // Injects an input event, and posts a task to retry after
+  // `kTapRetryInterval`.
+  //
+  // We post the retry task because the first input event we send to Flutter may
+  // be lost. The reason the first event may be lost is that there is a race
+  // condition as the scene owner starts up.
+  //
+  // More specifically: in order for our app
+  // to receive the injected input, two things must be true before we inject
+  // touch input:
+  // * The Scenic root view must have been installed, and
+  // * The Input Pipeline must have received a viewport to inject touch into.
+  //
+  // The problem we have is that the `is_rendering` signal that we monitor only
+  // guarantees us the view is ready. If the viewport is not ready in Input
+  // Pipeline at that time, it will drop the touch event.
+  //
+  // TODO(fxbug.dev/96986): Improve synchronization and remove retry logic.
+  void TryInject(int32_t x, int32_t y);
+
+ private:
+  fuchsia::ui::scenic::Scenic* scenic() { return scenic_.get(); }
+
+  void SetUpRealmBase();
+
+  // Registers a fake touch screen device with an injection coordinate space
+  // spanning [-1000, 1000] on both axes.
+  void RegisterTouchScreen();
+
+  fuchsia::ui::scenic::ScenicPtr scenic_;
+  fuchsia::ui::test::input::RegistryPtr input_registry_;
+  fuchsia::ui::test::input::TouchScreenPtr fake_touchscreen_;
+  fuchsia::ui::test::scene::ControllerPtr scene_provider_;
+  fuchsia::ui::observation::geometry::ViewTreeWatcherPtr view_tree_watcher_;
+
+  // Wrapped in optional since the view is not created until the middle of SetUp
+  component_testing::RealmBuilder realm_builder_;
+  std::unique_ptr<component_testing::RealmRoot> realm_;
+
+  // The typical latency on devices we've tested is ~60 msec. The retry interval
+  // is chosen to be a) Long enough that it's unlikely that we send a new tap
+  // while a previous tap is still being
+  //    processed. That is, it should be far more likely that a new tap is sent
+  //    because the first tap was lost, than because the system is just running
+  //    slowly.
+  // b) Short enough that we don't slow down tryjobs.
+  //
+  // The first property is important to avoid skewing the latency metrics that
+  // we collect. For an explanation of why a tap might be lost, see the
+  // documentation for TryInject().
+  static constexpr auto kTapRetryInterval = zx::sec(1);
+};
+
+void FlutterEmbedderTest::SetUpRealmBase() {
+  FML_LOG(INFO) << "Setting up realm base.";
+
+  // First, add the flutter runner(s) as children.
+  realm_builder_.AddChild(kFlutterJitRunner, kFlutterJitRunnerUrl);
+  realm_builder_.AddChild(kFlutterJitProductRunner,
+                          kFlutterJitProductRunnerUrl);
+  realm_builder_.AddChild(kFlutterAotRunner, kFlutterAotRunnerUrl);
+  realm_builder_.AddChild(kFlutterAotProductRunner,
+                          kFlutterAotProductRunnerUrl);
+
+  // Then, add an environment providing them.
+  fuchsia::component::decl::Environment flutter_runner_environment;
+  flutter_runner_environment.set_name(kFlutterRunnerEnvironment);
+  flutter_runner_environment.set_extends(
+      fuchsia::component::decl::EnvironmentExtends::REALM);
+  flutter_runner_environment.set_runners({});
+  auto environment_runners = flutter_runner_environment.mutable_runners();
+  fuchsia::component::decl::RunnerRegistration flutter_jit_runner_reg;
+  flutter_jit_runner_reg.set_source(fuchsia::component::decl::Ref::WithChild(
+      fuchsia::component::decl::ChildRef{.name = kFlutterJitRunner}));
+  flutter_jit_runner_reg.set_source_name(kFlutterJitRunner);
+  flutter_jit_runner_reg.set_target_name(kFlutterJitRunner);
+  environment_runners->push_back(std::move(flutter_jit_runner_reg));
+  fuchsia::component::decl::RunnerRegistration flutter_jit_product_runner_reg;
+  flutter_jit_product_runner_reg.set_source(
+      fuchsia::component::decl::Ref::WithChild(
+          fuchsia::component::decl::ChildRef{.name =
+                                                 kFlutterJitProductRunner}));
+  flutter_jit_product_runner_reg.set_source_name(kFlutterJitProductRunner);
+  flutter_jit_product_runner_reg.set_target_name(kFlutterJitProductRunner);
+  environment_runners->push_back(std::move(flutter_jit_product_runner_reg));
+  fuchsia::component::decl::RunnerRegistration flutter_aot_runner_reg;
+  flutter_aot_runner_reg.set_source(fuchsia::component::decl::Ref::WithChild(
+      fuchsia::component::decl::ChildRef{.name = kFlutterAotRunner}));
+  flutter_aot_runner_reg.set_source_name(kFlutterAotRunner);
+  flutter_aot_runner_reg.set_target_name(kFlutterAotRunner);
+  environment_runners->push_back(std::move(flutter_aot_runner_reg));
+  fuchsia::component::decl::RunnerRegistration flutter_aot_product_runner_reg;
+  flutter_aot_product_runner_reg.set_source(
+      fuchsia::component::decl::Ref::WithChild(
+          fuchsia::component::decl::ChildRef{.name =
+                                                 kFlutterAotProductRunner}));
+  flutter_aot_product_runner_reg.set_source_name(kFlutterAotProductRunner);
+  flutter_aot_product_runner_reg.set_target_name(kFlutterAotProductRunner);
+  environment_runners->push_back(std::move(flutter_aot_product_runner_reg));
+  auto realm_decl = realm_builder_.GetRealmDecl();
+  if (!realm_decl.has_environments()) {
+    realm_decl.set_environments({});
+  }
+  auto realm_environments = realm_decl.mutable_environments();
+  realm_environments->push_back(std::move(flutter_runner_environment));
+  realm_builder_.ReplaceRealmDecl(std::move(realm_decl));
+
+  // Add test UI stack component.
+  realm_builder_.AddChild(kTestUIStack, kTestUIStackUrl);
+
+  // Add embedded parent and child components.
+  realm_builder_.AddChild(kChildView, kChildViewUrl,
+                          ChildOptions{
+                              .environment = kFlutterRunnerEnvironment,
+                          });
+  realm_builder_.AddChild(kParentView, kParentViewUrl,
+                          ChildOptions{
+                              .environment = kFlutterRunnerEnvironment,
+                          });
+
+  // Route base system services to flutter runners.
+  realm_builder_.AddRoute(
+      Route{.capabilities =
+                {
+                    Protocol{fuchsia::logger::LogSink::Name_},
+                    Protocol{fuchsia::sysmem::Allocator::Name_},
+                    Protocol{fuchsia::tracing::provider::Registry::Name_},
+                    Protocol{kVulkanLoaderServiceName},
+                },
+            .source = ParentRef{},
+            .targets = {kFlutterJitRunnerRef, kFlutterJitProductRunnerRef,
+                        kFlutterAotRunnerRef, kFlutterAotProductRunnerRef}});
+
+  // Route base system services to the test UI stack.
+  realm_builder_.AddRoute(Route{
+      .capabilities = {Protocol{fuchsia::logger::LogSink::Name_},
+                       Protocol{fuchsia::sysmem::Allocator::Name_},
+                       Protocol{fuchsia::tracing::provider::Registry::Name_},
+                       Protocol{kVulkanLoaderServiceName}},
+      .source = ParentRef{},
+      .targets = {kTestUIStackRef}});
+
+  // Route UI capabilities from test UI stack to flutter runners.
+  realm_builder_.AddRoute(Route{
+      .capabilities = {Protocol{fuchsia::ui::composition::Flatland::Name_},
+                       Protocol{fuchsia::ui::scenic::Scenic::Name_}},
+      .source = kTestUIStackRef,
+      .targets = {kFlutterJitRunnerRef, kFlutterJitProductRunnerRef,
+                  kFlutterAotRunnerRef, kFlutterAotProductRunnerRef}});
+
+  // Route test capabilities from test UI stack to test driver.
+  realm_builder_.AddRoute(Route{
+      .capabilities = {Protocol{fuchsia::ui::test::input::Registry::Name_},
+                       Protocol{fuchsia::ui::test::scene::Controller::Name_},
+                       Protocol{fuchsia::ui::scenic::Scenic::Name_}},
+      .source = kTestUIStackRef,
+      .targets = {ParentRef{}}});
+
+  // Route ViewProvider from child to parent, and parent to test.
+  realm_builder_.AddRoute(
+      Route{.capabilities = {Protocol{fuchsia::ui::app::ViewProvider::Name_}},
+            .source = kParentViewRef,
+            .targets = {ParentRef()}});
+  realm_builder_.AddRoute(
+      Route{.capabilities = {Protocol{fuchsia::ui::app::ViewProvider::Name_}},
+            .source = kChildViewRef,
+            .targets = {kParentViewRef}});
+}
+
+// Checks whether the view with |view_ref_koid| has connected to the view tree.
+// The response of a f.u.o.g.Provider.Watch call is stored in |watch_response|
+// if it contains |view_ref_koid|.
+bool FlutterEmbedderTest::HasViewConnected(
+    const fuchsia::ui::observation::geometry::ViewTreeWatcherPtr&
+        view_tree_watcher,
+    std::optional<fuchsia::ui::observation::geometry::WatchResponse>&
+        watch_response,
+    zx_koid_t view_ref_koid) {
+  std::optional<fuchsia::ui::observation::geometry::WatchResponse> watch_result;
+  view_tree_watcher->Watch(
+      [&watch_result](auto response) { watch_result = std::move(response); });
+  FML_LOG(INFO) << "Waiting for view tree watch result";
+  RunLoopUntil([&watch_result] { return watch_result.has_value(); });
+  FML_LOG(INFO) << "Received for view tree watch result";
+  if (CheckViewExistsInUpdates(watch_result->updates(), view_ref_koid)) {
+    watch_response = std::move(watch_result);
+  };
+  return watch_response.has_value();
+}
+
+void FlutterEmbedderTest::LaunchParentViewInRealm(
+    const std::vector<std::string>& component_args) {
+  FML_LOG(INFO) << "Launching parent-view";
+
+  if (!component_args.empty()) {
+    // Construct a args.csv file containing the specified comma-separated
+    // component args.
+    std::string csv;
+    for (const auto& arg : component_args) {
+      csv += arg + ',';
+    }
+    // Remove last comma.
+    csv.pop_back();
+
+    auto config_directory_contents = DirectoryContents();
+    config_directory_contents.AddFile("args.csv", csv);
+    realm_builder_.RouteReadOnlyDirectory("config-data", {kParentViewRef},
+                                          std::move(config_directory_contents));
+  }
+  realm_ = std::make_unique<RealmRoot>(realm_builder_.Build());
+
+  // Register fake touch screen device.
+  RegisterTouchScreen();
+
+  // Instruct Test UI Stack to present parent-view's View.
+  std::optional<zx_koid_t> view_ref_koid;
+  scene_provider_ = realm_->Connect<fuchsia::ui::test::scene::Controller>();
+  scene_provider_.set_error_handler(
+      [](auto) { FML_LOG(ERROR) << "Error from test scene provider"; });
+  fuchsia::ui::test::scene::ControllerAttachClientViewRequest request;
+  request.set_view_provider(realm_->Connect<fuchsia::ui::app::ViewProvider>());
+  scene_provider_->RegisterViewTreeWatcher(view_tree_watcher_.NewRequest(),
+                                           []() {});
+  scene_provider_->AttachClientView(
+      std::move(request), [&view_ref_koid](auto client_view_ref_koid) {
+        view_ref_koid = client_view_ref_koid;
+      });
+
+  FML_LOG(INFO) << "Waiting for client view ref koid";
+  RunLoopUntil([&view_ref_koid] { return view_ref_koid.has_value(); });
+
+  // Wait for the client view to get attached to the view tree.
+  std::optional<fuchsia::ui::observation::geometry::WatchResponse>
+      watch_response;
+  FML_LOG(INFO) << "Waiting for client view to render; koid is "
+                << (view_ref_koid.has_value() ? view_ref_koid.value() : 0);
+  RunLoopUntil([this, &watch_response, &view_ref_koid] {
+    return HasViewConnected(view_tree_watcher_, watch_response, *view_ref_koid);
+  });
+  FML_LOG(INFO) << "Client view has rendered";
+
+  scenic_ = realm_->Connect<fuchsia::ui::scenic::Scenic>();
+  FML_LOG(INFO) << "Launched parent-view";
+}
+
+scenic::Screenshot FlutterEmbedderTest::TakeScreenshot() {
+  FML_LOG(INFO) << "Taking screenshot... ";
+  fuchsia::ui::scenic::ScreenshotData screenshot_out;
+  scenic_->TakeScreenshot(
+      [this, &screenshot_out](fuchsia::ui::scenic::ScreenshotData screenshot,
+                              bool status) {
+        EXPECT_TRUE(status) << "Failed to take screenshot";
+        screenshot_out = std::move(screenshot);
+        QuitLoop();
+      });
+  EXPECT_FALSE(RunLoopWithTimeout(kScreenshotTimeout))
+      << "Timed out waiting for screenshot.";
+  FML_LOG(INFO) << "Screenshot captured.";
+
+  return scenic::Screenshot(screenshot_out);
+}
+
+bool FlutterEmbedderTest::TakeScreenshotUntil(
+    scenic::Color color,
+    fit::function<void(std::map<scenic::Color, size_t>)> callback,
+    zx::duration timeout) {
+  return RunLoopWithTimeoutOrUntil(
+      [this, &callback, &color] {
+        auto screenshot = TakeScreenshot();
+        auto histogram = screenshot.Histogram();
+
+        bool color_found = histogram[color] > 0;
+        if (color_found && callback != nullptr) {
+          callback(std::move(histogram));
+        }
+        return color_found;
+      },
+      timeout);
+}
+
+void FlutterEmbedderTest::RegisterTouchScreen() {
+  FML_LOG(INFO) << "Registering fake touch screen";
+  input_registry_ = realm_->Connect<fuchsia::ui::test::input::Registry>();
+  input_registry_.set_error_handler(
+      [](auto) { FML_LOG(ERROR) << "Error from input helper"; });
+  bool touchscreen_registered = false;
+  fuchsia::ui::test::input::RegistryRegisterTouchScreenRequest request;
+  request.set_device(fake_touchscreen_.NewRequest());
+  input_registry_->RegisterTouchScreen(
+      std::move(request),
+      [&touchscreen_registered]() { touchscreen_registered = true; });
+  RunLoopUntil([&touchscreen_registered] { return touchscreen_registered; });
+  FML_LOG(INFO) << "Touchscreen registered";
+}
+
+void FlutterEmbedderTest::InjectTap(int32_t x, int32_t y) {
+  fuchsia::ui::test::input::TouchScreenSimulateTapRequest tap_request;
+  tap_request.mutable_tap_location()->x = x;
+  tap_request.mutable_tap_location()->y = y;
+  fake_touchscreen_->SimulateTap(std::move(tap_request), [x, y]() {
+    FML_LOG(INFO) << "Tap injected at (" << x << ", " << y << ")";
+  });
+}
+
+void FlutterEmbedderTest::TryInject(int32_t x, int32_t y) {
+  InjectTap(x, y);
+  async::PostDelayedTask(
+      dispatcher(), [this, x, y] { TryInject(x, y); }, kTapRetryInterval);
+}
+
+TEST_F(FlutterEmbedderTest, Embedding) {
+  LaunchParentViewInRealm();
+
+  // Take screenshot until we see the child-view's embedded color.
+  ASSERT_TRUE(TakeScreenshotUntil(
+      kChildBackgroundColor, [](std::map<scenic::Color, size_t> histogram) {
+        // Expect parent and child background colors, with parent color > child
+        // color.
+        EXPECT_GT(histogram[kParentBackgroundColor], 0u);
+        EXPECT_GT(histogram[kChildBackgroundColor], 0u);
+        EXPECT_GT(histogram[kParentBackgroundColor],
+                  histogram[kChildBackgroundColor]);
+      }));
+}
+
+TEST_F(FlutterEmbedderTest, HittestEmbedding) {
+  LaunchParentViewInRealm();
+
+  // Take screenshot until we see the child-view's embedded color.
+  ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
+
+  // Simulate a tap at the center of the child view.
+  TryInject(/* x = */ 0, /* y = */ 0);
+
+  // Take screenshot until we see the child-view's tapped color.
+  ASSERT_TRUE(TakeScreenshotUntil(
+      kChildTappedColor, [](std::map<scenic::Color, size_t> histogram) {
+        // Expect parent and child background colors, with parent color > child
+        // color.
+        EXPECT_GT(histogram[kParentBackgroundColor], 0u);
+        EXPECT_EQ(histogram[kChildBackgroundColor], 0u);
+        EXPECT_GT(histogram[kChildTappedColor], 0u);
+        EXPECT_GT(histogram[kParentBackgroundColor],
+                  histogram[kChildTappedColor]);
+      }));
+}
+
+TEST_F(FlutterEmbedderTest, HittestDisabledEmbedding) {
+  LaunchParentViewInRealm({"--no-hitTestable"});
+
+  // Take screenshots until we see the child-view's embedded color.
+  ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
+
+  // Simulate a tap at the center of the child view.
+  TryInject(/* x = */ 0, /* y = */ 0);
+
+  // The parent-view should change color.
+  ASSERT_TRUE(TakeScreenshotUntil(
+      kParentTappedColor, [](std::map<scenic::Color, size_t> histogram) {
+        // Expect parent and child background colors, with parent color > child
+        // color.
+        EXPECT_EQ(histogram[kParentBackgroundColor], 0u);
+        EXPECT_GT(histogram[kParentTappedColor], 0u);
+        EXPECT_GT(histogram[kChildBackgroundColor], 0u);
+        EXPECT_EQ(histogram[kChildTappedColor], 0u);
+        EXPECT_GT(histogram[kParentTappedColor],
+                  histogram[kChildBackgroundColor]);
+      }));
+}
+
+TEST_F(FlutterEmbedderTest, EmbeddingWithOverlay) {
+  LaunchParentViewInRealm({"--showOverlay"});
+
+  // Take screenshot until we see the child-view's embedded color.
+  ASSERT_TRUE(TakeScreenshotUntil(
+      kChildBackgroundColor, [](std::map<scenic::Color, size_t> histogram) {
+        // Expect parent, overlay and child background colors.
+        // With parent color > child color and overlay color > child color.
+        const size_t overlay_pixel_count = OverlayPixelCount(histogram);
+        EXPECT_GT(histogram[kParentBackgroundColor], 0u);
+        EXPECT_GT(overlay_pixel_count, 0u);
+        EXPECT_GT(histogram[kChildBackgroundColor], 0u);
+        EXPECT_GT(histogram[kParentBackgroundColor],
+                  histogram[kChildBackgroundColor]);
+        EXPECT_GT(overlay_pixel_count, histogram[kChildBackgroundColor]);
+      }));
+}
+
+TEST_F(FlutterEmbedderTest, HittestEmbeddingWithOverlay) {
+  LaunchParentViewInRealm({"--showOverlay"});
+
+  // Take screenshot until we see the child-view's embedded color.
+  ASSERT_TRUE(TakeScreenshotUntil(kChildBackgroundColor));
+
+  // The bottom-left corner of the overlay is at the center of the screen,
+  // which is at (0, 0) in the injection coordinate space. Inject a pointer
+  // event just outside the overlay's bounds, and ensure that it goes to the
+  // embedded view.
+  TryInject(/* x = */ -1, /* y = */ 1);
+
+  // Take screenshot until we see the child-view's tapped color.
+  ASSERT_TRUE(TakeScreenshotUntil(
+      kChildTappedColor, [](std::map<scenic::Color, size_t> histogram) {
+        // Expect parent, overlay and child background colors.
+        // With parent color > child color and overlay color > child color.
+        const size_t overlay_pixel_count = OverlayPixelCount(histogram);
+        EXPECT_GT(histogram[kParentBackgroundColor], 0u);
+        EXPECT_GT(overlay_pixel_count, 0u);
+        EXPECT_EQ(histogram[kChildBackgroundColor], 0u);
+        EXPECT_GT(histogram[kChildTappedColor], 0u);
+        EXPECT_GT(histogram[kParentBackgroundColor],
+                  histogram[kChildTappedColor]);
+        EXPECT_GT(overlay_pixel_count, histogram[kChildTappedColor]);
+      }));
+}
+
+}  // namespace flutter_embedder_test
diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/meta/flutter-embedder-test.cml b/shell/platform/fuchsia/flutter/tests/integration/embedder/meta/flutter-embedder-test.cml
new file mode 100644
index 0000000..b053b0a
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/meta/flutter-embedder-test.cml
@@ -0,0 +1,27 @@
+{
+    include: [
+        "gtest_runner.shard.cml",
+        "sys/component/realm_builder_absolute.shard.cml",
+
+        // This test needs both the vulkan facet and the hermetic-tier-2 facet,
+        // so we are forced to make it a system test.
+        "sys/testing/system-test.shard.cml",
+    ],
+    program: {
+        binary: "bin/app",
+    },
+    offer: [
+        {
+            // Offer capabilities needed by components in this test realm.
+            // Keep it minimal, describe only what's actually needed.
+            protocol: [
+                "fuchsia.logger.LogSink",
+                "fuchsia.sysmem.Allocator",
+                "fuchsia.tracing.provider.Registry",
+                "fuchsia.vulkan.loader.Loader",
+            ],
+            from: "parent",
+            to: "#realm_builder",
+        },
+    ],
+}
diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/meta/gtest_runner.shard.cml b/shell/platform/fuchsia/flutter/tests/integration/embedder/meta/gtest_runner.shard.cml
new file mode 100644
index 0000000..4593cf2
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/meta/gtest_runner.shard.cml
@@ -0,0 +1,14 @@
+{
+    program: {
+        runner: "gtest_runner",
+    },
+    capabilities: [
+        { protocol: "fuchsia.test.Suite" },
+    ],
+    expose: [
+        {
+            protocol: "fuchsia.test.Suite",
+            from: "self",
+        },
+    ],
+}
diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/BUILD.gn b/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/BUILD.gn
new file mode 100644
index 0000000..ceaf829
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/BUILD.gn
@@ -0,0 +1,36 @@
+# 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.
+
+import("//build/fuchsia/sdk.gni")
+import("//flutter/tools/fuchsia/dart/dart_library.gni")
+import("//flutter/tools/fuchsia/flutter/flutter_component.gni")
+import("//flutter/tools/fuchsia/gn-sdk/package.gni")
+
+dart_library("lib") {
+  package_name = "parent-view"
+  sources = [ "parent_view.dart" ]
+
+  deps = [
+    "//flutter/shell/platform/fuchsia/dart:args",
+    "//flutter/shell/platform/fuchsia/dart:vector_math",
+    "//flutter/tools/fuchsia/dart:fuchsia_services",
+    "//flutter/tools/fuchsia/dart:zircon",
+    "//flutter/tools/fuchsia/fidl:fuchsia.sys",
+    "//flutter/tools/fuchsia/fidl:fuchsia.ui.app",
+    "//flutter/tools/fuchsia/fidl:fuchsia.ui.views",
+  ]
+}
+
+flutter_component("component") {
+  main_package = "parent-view"
+  component_name = "parent-view"
+  main_dart = "parent_view.dart"
+  manifest = rebase_path("meta/parent-view.cml")
+  deps = [ ":lib" ]
+}
+
+fuchsia_package("package") {
+  package_name = "parent-view"
+  deps = [ ":component" ]
+}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/parent_view2.dart b/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/lib/parent_view.dart
similarity index 71%
rename from shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/parent_view2.dart
rename to shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/lib/parent_view.dart
index 6dcddd2..5fd5216 100644
--- a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/parent_view2.dart
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/lib/parent_view.dart
@@ -4,42 +4,49 @@
 
 import 'dart:convert';
 import 'dart:typed_data';
+import 'dart:io';
 import 'dart:ui';
-import 'package:vector_math/vector_math_64.dart' as vector_math_64;
+
 import 'package:args/args.dart';
-import 'package:fidl_fuchsia_sys/fidl_async.dart';
 import 'package:fidl_fuchsia_ui_app/fidl_async.dart';
 import 'package:fidl_fuchsia_ui_views/fidl_async.dart';
 import 'package:fuchsia_services/services.dart';
+import 'package:vector_math/vector_math_64.dart' as vector_math_64;
 import 'package:zircon/zircon.dart';
 
-// TODO(richkadel): To run the test serving the runner and test packages from
-// the flutter/engine package server (via
-// `//flutter/tools/fuchsia/devshell/serve.sh`), change `fuchsia.com` to
-// `engine`.
-const _kChildAppUrl =
-    'fuchsia-pkg://fuchsia.com/child-view2#meta/child-view2.cmx';
-
-TestApp app;
+final _argsCsvFilePath = '/config/data/args.csv';
 
 void main(List<String> args) {
+  print('parent-view: starting');
+
+  args = args + _GetArgsFromConfigFile();
   final parser = ArgParser()
     ..addFlag('showOverlay', defaultsTo: false)
     ..addFlag('hitTestable', defaultsTo: true)
-    ..addFlag('focusable', defaultsTo: true);
+    ..addFlag('focusable', defaultsTo: true)
+    ..addFlag('useFlatland', defaultsTo: false);
   final arguments = parser.parse(args);
   for (final option in arguments.options) {
-    print('parent-view2: $option: ${arguments[option]}');
+    print('parent-view: $option: ${arguments[option]}');
   }
 
-  final childViewToken = _launchApp(_kChildAppUrl);
-
-  app = TestApp(
-    ChildView(childViewToken),
-    showOverlay: arguments['showOverlay'],
-    hitTestable: arguments['hitTestable'],
-    focusable: arguments['focusable'],
-  );
+  TestApp app;
+  final useFlatland = arguments['useFlatland'];
+  if (useFlatland) {
+    app = TestApp(
+      ChildView(_launchFlatlandChildView()),
+      showOverlay: arguments['showOverlay'],
+      hitTestable: arguments['hitTestable'],
+      focusable: arguments['focusable'],
+    );
+  } else {
+    app = TestApp(
+      ChildView.gfx(_launchGfxChildView()),
+      showOverlay: arguments['showOverlay'],
+      hitTestable: arguments['hitTestable'],
+      focusable: arguments['focusable'],
+    );
+  }
 
   app.run();
 }
@@ -64,19 +71,24 @@
 
   void run() {
     childView.create(hitTestable, focusable, (ByteData reply) {
-        // The child-view2 should be attached to Scenic now.
-        // Ready to build the scene.
+        // Set up window allbacks.
         window.onPointerDataPacket = (PointerDataPacket packet) {
           for (final data in packet.data) {
-            if (data.change == PointerChange.up) {
+            if (data.change == PointerChange.down) {
               this._backgroundColor = _black;
             }
           }
           window.scheduleFrame();
         };
-        window.onBeginFrame = (Duration duration) {
-          app.beginFrame(duration);
+        window.onMetricsChanged = () {
+          window.scheduleFrame();
         };
+        window.onBeginFrame = (Duration duration) {
+          this.beginFrame(duration);
+        };
+
+        // The child view should be attached to Scenic now.
+        // Ready to build the scene.
         window.scheduleFrame();
       });
   }
@@ -149,45 +161,16 @@
   }
 }
 
-ViewHolderToken _launchApp(String componentUrl) {
-  final incoming = Incoming();
-  final componentController = ComponentControllerProxy();
-
-  final launcher = LauncherProxy();
-  Incoming.fromSvcPath()
-    ..connectToService(launcher)
-    ..close();
-  launcher.createComponent(
-    LaunchInfo(
-      url: componentUrl,
-      directoryRequest: incoming.request().passChannel(),
-    ),
-    componentController.ctrl.request(),
-  );
-  launcher.ctrl.close();
-
-  ViewProviderProxy viewProvider = ViewProviderProxy();
-  incoming
-    ..connectToService(viewProvider)
-    ..close();
-
-  final viewTokens = EventPairPair();
-  assert(viewTokens.status == ZX.OK);
-  final viewHolderToken = ViewHolderToken(value: viewTokens.first);
-  final viewToken = ViewToken(value: viewTokens.second);
-
-  viewProvider.createView(viewToken.value, null, null);
-  viewProvider.ctrl.close();
-
-  return viewHolderToken;
-}
-
 class ChildView {
-
-  final ViewHolderToken viewToken;
+  final ViewHolderToken viewHolderToken;
+  final ViewportCreationToken viewportCreationToken;
   final int viewId;
 
-  ChildView(this.viewToken) : viewId = viewToken.value.handle.handle {
+  ChildView(this.viewportCreationToken) : viewHolderToken = null, viewId = viewportCreationToken.value.handle.handle {
+    assert(viewId != null);
+  }
+
+  ChildView.gfx(this.viewHolderToken) : viewportCreationToken = null, viewId = viewHolderToken.value.handle.handle {
     assert(viewId != null);
   }
 
@@ -227,3 +210,49 @@
       callback);
   }
 }
+
+ViewportCreationToken _launchFlatlandChildView() {
+  ViewProviderProxy viewProvider = ViewProviderProxy();
+  Incoming.fromSvcPath()
+    ..connectToService(viewProvider)
+    ..close();
+
+  final viewTokens = ChannelPair();
+  assert(viewTokens.status == ZX.OK);
+  final viewportCreationToken = ViewportCreationToken(value: viewTokens.first);
+  final viewCreationToken = ViewCreationToken(value: viewTokens.second);
+
+  final createViewArgs = CreateView2Args(viewCreationToken: viewCreationToken);
+  viewProvider.createView2(createViewArgs);
+  viewProvider.ctrl.close();
+
+  return viewportCreationToken;
+}
+
+ViewHolderToken _launchGfxChildView() {
+  ViewProviderProxy viewProvider = ViewProviderProxy();
+  Incoming.fromSvcPath()
+    ..connectToService(viewProvider)
+    ..close();
+
+  final viewTokens = EventPairPair();
+  assert(viewTokens.status == ZX.OK);
+  final viewHolderToken = ViewHolderToken(value: viewTokens.first);
+  final viewToken = ViewToken(value: viewTokens.second);
+
+  viewProvider.createView(viewToken.value, null, null);
+  viewProvider.ctrl.close();
+
+  return viewHolderToken;
+}
+
+List<String> _GetArgsFromConfigFile() {
+  List<String> args;
+  final f = File(_argsCsvFilePath);
+  if (!f.existsSync()) {
+    return List.empty();
+  }
+  final fileContentCsv = f.readAsStringSync();
+  args = fileContentCsv.split('\n');
+  return args;
+}
diff --git a/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/meta/parent-view.cml b/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/meta/parent-view.cml
new file mode 100644
index 0000000..aea9b8b
--- /dev/null
+++ b/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/meta/parent-view.cml
@@ -0,0 +1,33 @@
+{
+    include: [ "syslog/client.shard.cml" ],
+    program: {
+        data: "data/parent-view",
+
+        // Always use the jit runner for now.
+        // TODO(fxbug.dev/106577): Implement manifest merging build rules for V2 components.
+        runner: "flutter_jit_runner",
+    },
+    capabilities: [
+        {
+            protocol: [ "fuchsia.ui.app.ViewProvider" ],
+        },
+    ],
+    use: [
+        {
+            protocol: [
+                "fuchsia.ui.app.ViewProvider",
+            ],
+        },
+        {
+            directory: "config-data",
+            rights: [ "r*" ],
+            path: "/config/data",
+        },
+    ],
+    expose: [
+        {
+            protocol: [ "fuchsia.ui.app.ViewProvider" ],
+            from: "self",
+        },
+    ],
+}
diff --git a/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/pubspec.yaml b/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/pubspec.yaml
similarity index 100%
rename from shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/pubspec.yaml
rename to shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/pubspec.yaml
diff --git a/testing/fuchsia/test_suites.yaml b/testing/fuchsia/test_suites.yaml
index 8dcbc8a..86630bd 100644
--- a/testing/fuchsia/test_suites.yaml
+++ b/testing/fuchsia/test_suites.yaml
@@ -1,15 +1,13 @@
 # This configuration file specifies several test suites with their package and
 # test command for femu_test.py.
 
-# Legacy Component Framework v1 components.
-- test_command: run-test-component fuchsia-pkg://fuchsia.com/flutter-embedder-test2#meta/flutter-embedder-test2.cmx
-  packages:
-    - flutter-embedder-test2-0.far
-    - gen/flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/child-view2/child-view2/child-view2.far
-    - gen/flutter/shell/platform/fuchsia/flutter/integration_flutter_tests/embedder/parent-view2/parent-view2/parent-view2.far
-    - flutter_jit_runner-0.far
-
 # v2 components.
+- test_command: run-test-suite fuchsia-pkg://fuchsia.com/flutter-embedder-test#meta/flutter-embedder-test.cm
+  packages:
+    - flutter-embedder-test-0.far
+    - oot_flutter_jit_runner-0.far
+    - gen/flutter/shell/platform/fuchsia/flutter/tests/integration/embedder/child-view/child-view/child-view.far
+    - gen/flutter/shell/platform/fuchsia/flutter/tests/integration/embedder/parent-view/parent-view/parent-view.far
 - test_command: run-test-suite fuchsia-pkg://fuchsia.com/dart_runner_tests#meta/dart_runner_tests.cm
   package: dart_runner_tests-0.far
 - test_command: run-test-suite fuchsia-pkg://fuchsia.com/flutter_runner_tests#meta/flutter_runner_tests.cm
diff --git a/tools/fuchsia/fuchsia_archive.gni b/tools/fuchsia/fuchsia_archive.gni
index c0cc730..a30d392 100644
--- a/tools/fuchsia/fuchsia_archive.gni
+++ b/tools/fuchsia/fuchsia_archive.gni
@@ -36,6 +36,8 @@
       "--output",
       rebase_path(invoker.output, root_build_dir),
       "--includepath",
+      rebase_path("$fuchsia_sdk/pkg/", root_build_dir),
+      "--includepath",
       get_path_info(invoker.manifest, "dir"),
       "--includepath",
       rebase_path("//"),
@@ -258,42 +260,66 @@
 # cmx_file (optional):
 #   A path to the .cmx file for the test archive.
 #   If not defined, a generated .cml file for the test archive will be used instead.
+# cml_file (optional):
+#   The path to the V2 component manifest (.cml file) for the test archive's component.
+#   Should include the file extension.
+#   If not defined, a generated .cml file for the test archive will be used instead.
 # libraries (optional):
 #   Paths to .so libraries that should be dynamically linked to the binary.
 # resources (optional):
 #   Files that should be placed into the `data/` directory of the archive.
 template("fuchsia_test_archive") {
   assert(defined(invoker.deps), "package must define deps")
-
-  # Interpolate test_suite.cml template with the test suite's name.
-  test_suite = target_name
-  interpolate_cml_target = "${test_suite}_interpolate_cml"
-  generated_cml_file = "$root_out_dir/$test_suite.cml"
-  action(interpolate_cml_target) {
-    testonly = true
-    script = "//flutter/tools/fuchsia/interpolate_test_suite.py"
-    sources = [ "//flutter/testing/fuchsia/meta/test_suite.cml" ]
-    args = [
-      "--input",
-      rebase_path("//flutter/testing/fuchsia/meta/test_suite.cml"),
-      "--test-suite",
-      test_suite,
-      "--output",
-      rebase_path(generated_cml_file),
-    ]
-    outputs = [ generated_cml_file ]
+  _deps = []
+  if (defined(invoker.deps)) {
+    _deps += invoker.deps
   }
 
-  far_base_dir = "$root_out_dir/${target_name}_far"
+  if (defined(invoker.cml_file)) {
+    _far_base_dir = "$root_out_dir/${target_name}_far"
+    _cml_file_name = get_path_info(invoker.cml_file, "name")
+    _compile_cml_target = "${target_name}_${_cml_file_name}_compile_cml"
 
-  # Compile the resulting interpolated test suite's cml.
-  compile_test_suite_cml_target = "${test_suite}_test_suite_compile_cml"
-  _compile_cml(compile_test_suite_cml_target) {
-    testonly = true
-    deps = [ ":$interpolate_cml_target" ]
+    _compile_cml(_compile_cml_target) {
+      forward_variables_from(invoker, [ "testonly" ])
 
-    manifest = generated_cml_file
-    output = "$far_base_dir/meta/${test_suite}.cm"
+      manifest = invoker.cml_file
+      output = "$_far_base_dir/meta/${_cml_file_name}.cm"
+    }
+    _deps += [ ":$_compile_cml_target" ]
+  } else {
+    # Interpolate test_suite.cml template with the test suite's name.
+    test_suite = target_name
+    interpolate_cml_target = "${test_suite}_interpolate_cml"
+    generated_cml_file = "$root_out_dir/$test_suite.cml"
+    action(interpolate_cml_target) {
+      testonly = true
+      script = "//flutter/tools/fuchsia/interpolate_test_suite.py"
+      sources = [ "//flutter/testing/fuchsia/meta/test_suite.cml" ]
+      args = [
+        "--input",
+        rebase_path("//flutter/testing/fuchsia/meta/test_suite.cml"),
+        "--test-suite",
+        test_suite,
+        "--output",
+        rebase_path(generated_cml_file),
+      ]
+      outputs = [ generated_cml_file ]
+    }
+
+    far_base_dir = "$root_out_dir/${target_name}_far"
+
+    # Compile the resulting interpolated test suite's cml.
+    compile_test_suite_cml_target = "${test_suite}_test_suite_compile_cml"
+    _compile_cml(compile_test_suite_cml_target) {
+      testonly = true
+      deps = [ ":$interpolate_cml_target" ]
+
+      manifest = generated_cml_file
+      output = "$far_base_dir/meta/${test_suite}.cm"
+    }
+
+    _deps += [ ":$compile_test_suite_cml_target" ]
   }
 
   _fuchsia_archive(target_name) {
@@ -309,15 +335,6 @@
       libraries += invoker.libraries
     }
 
-    # TODO(fxbug.dev/79873): Only cfv2 components should be allowed after
-    # FakeScenic is available.
-    if (defined(invoker.cmx_file)) {
-      cmx_file = invoker.cmx_file
-
-      # Don't include cml files.
-      deps = invoker.deps
-    } else {
-      deps = invoker.deps + [ ":$compile_test_suite_cml_target" ]
-    }
+    deps = _deps
   }
 }