[Android] HC++ external view embedder and JNI plumbing. (#162493)

Part of HC++ work. still not wired up end to end, but only requires a
few more swapchain changes and a runtime flag...
diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter
index ae9dd84..6269a3c 100644
--- a/engine/src/flutter/ci/licenses_golden/licenses_flutter
+++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter
@@ -41611,6 +41611,8 @@
 ORIGIN: ../../../flutter/shell/platform/android/context/android_context.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder.h + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.cc + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.h + ../../../flutter/LICENSE
 ORIGIN: ../../../flutter/shell/platform/android/flutter_main.cc + ../../../flutter/LICENSE
@@ -44563,6 +44565,8 @@
 FILE: ../../../flutter/shell/platform/android/context/android_context.h
 FILE: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc
 FILE: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder.h
+FILE: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc
+FILE: ../../../flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h
 FILE: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.cc
 FILE: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.h
 FILE: ../../../flutter/shell/platform/android/flutter_main.cc
diff --git a/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc b/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc
index 114861a..0685018 100644
--- a/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc
+++ b/engine/src/flutter/shell/gpu/gpu_surface_vulkan_impeller.cc
@@ -115,11 +115,12 @@
       }
 
       SkIRect sk_cull_rect = SkIRect::MakeWH(cull_rect.width, cull_rect.height);
-      return impeller::RenderToTarget(aiks_context->GetContentContext(),  //
-                                      render_target,                      //
-                                      display_list,                       //
-                                      sk_cull_rect,                       //
-                                      /*reset_host_buffer=*/true          //
+      return impeller::RenderToTarget(
+          aiks_context->GetContentContext(),                                //
+          render_target,                                                    //
+          display_list,                                                     //
+          sk_cull_rect,                                                     //
+          /*reset_host_buffer=*/surface_frame.submit_info().frame_boundary  //
       );
     };
 
diff --git a/engine/src/flutter/shell/platform/android/android_shell_holder_unittests.cc b/engine/src/flutter/shell/platform/android/android_shell_holder_unittests.cc
index 88fb462..d5bf555 100644
--- a/engine/src/flutter/shell/platform/android/android_shell_holder_unittests.cc
+++ b/engine/src/flutter/shell/platform/android/android_shell_holder_unittests.cc
@@ -91,6 +91,25 @@
               (),
               (override));
   MOCK_METHOD(void, FlutterViewDestroyOverlaySurfaces, (), (override));
+  MOCK_METHOD(ASurfaceTransaction*, createTransaction, (), (override));
+  MOCK_METHOD(void, swapTransaction, (), (override));
+  MOCK_METHOD(void, applyTransaction, (), (override));
+  MOCK_METHOD(void, destroyOverlaySurface2, (), (override));
+  MOCK_METHOD(std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>,
+              createOverlaySurface2,
+              (),
+              (override));
+  MOCK_METHOD(void,
+              onDisplayPlatformView2,
+              (int32_t view_id,
+               int32_t x,
+               int32_t y,
+               int32_t width,
+               int32_t height,
+               int32_t viewWidth,
+               int32_t viewHeight,
+               MutatorsStack mutators_stack),
+              (override));
   MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
               FlutterViewComputePlatformResolvedLocale,
               (std::vector<std::string> supported_locales_data),
diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/BUILD.gn b/engine/src/flutter/shell/platform/android/external_view_embedder/BUILD.gn
index 44ae110..0c85a4d 100644
--- a/engine/src/flutter/shell/platform/android/external_view_embedder/BUILD.gn
+++ b/engine/src/flutter/shell/platform/android/external_view_embedder/BUILD.gn
@@ -9,6 +9,8 @@
   sources = [
     "external_view_embedder.cc",
     "external_view_embedder.h",
+    "external_view_embedder_2.cc",
+    "external_view_embedder_2.h",
     "surface_pool.cc",
     "surface_pool.h",
   ]
diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc
index a957df9..77962bc 100644
--- a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc
+++ b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.cc
@@ -19,7 +19,8 @@
       android_context_(android_context),
       jni_facade_(std::move(jni_facade)),
       surface_factory_(std::move(surface_factory)),
-      surface_pool_(std::make_unique<SurfacePool>()),
+      surface_pool_(
+          std::make_unique<SurfacePool>(/*use_new_surface_methods=*/false)),
       task_runners_(task_runners) {}
 
 // |ExternalViewEmbedder|
diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.h b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.h
index ab00870..616eb36 100644
--- a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.h
+++ b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder.h
@@ -74,8 +74,10 @@
                 const fml::RefPtr<fml::RasterThreadMerger>&
                     raster_thread_merger) override;
 
+  // |ExternalViewEmbedder|
   bool SupportsDynamicThreadMerging() override;
 
+  // |ExternalViewEmbedder|
   void Teardown() override;
 
   // Gets the rect based on the device pixel ratio of a platform view displayed
diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc
new file mode 100644
index 0000000..cf87cd4
--- /dev/null
+++ b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc
@@ -0,0 +1,254 @@
+// 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/shell/platform/android/external_view_embedder/external_view_embedder_2.h"
+#include "flow/view_slicer.h"
+#include "flutter/common/constants.h"
+#include "flutter/fml/synchronization/waitable_event.h"
+#include "flutter/fml/trace_event.h"
+#include "fml/make_copyable.h"
+
+namespace flutter {
+
+AndroidExternalViewEmbedder2::AndroidExternalViewEmbedder2(
+    const AndroidContext& android_context,
+    std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
+    std::shared_ptr<AndroidSurfaceFactory> surface_factory,
+    const TaskRunners& task_runners)
+    : ExternalViewEmbedder(),
+      android_context_(android_context),
+      jni_facade_(std::move(jni_facade)),
+      surface_factory_(std::move(surface_factory)),
+      surface_pool_(
+          std::make_unique<SurfacePool>(/*use_new_surface_methods=*/true)),
+      task_runners_(task_runners) {}
+
+// |ExternalViewEmbedder|
+void AndroidExternalViewEmbedder2::PrerollCompositeEmbeddedView(
+    int64_t view_id,
+    std::unique_ptr<EmbeddedViewParams> params) {
+  TRACE_EVENT0("flutter",
+               "AndroidExternalViewEmbedder2::PrerollCompositeEmbeddedView");
+
+  SkRect view_bounds = SkRect::Make(frame_size_);
+  std::unique_ptr<EmbedderViewSlice> view;
+  view = std::make_unique<DisplayListEmbedderViewSlice>(view_bounds);
+  slices_.insert_or_assign(view_id, std::move(view));
+
+  composition_order_.push_back(view_id);
+  // Update params only if they changed.
+  if (view_params_.count(view_id) == 1 &&
+      view_params_.at(view_id) == *params.get()) {
+    return;
+  }
+  view_params_.insert_or_assign(view_id, EmbeddedViewParams(*params.get()));
+}
+
+// |ExternalViewEmbedder|
+DlCanvas* AndroidExternalViewEmbedder2::CompositeEmbeddedView(int64_t view_id) {
+  if (slices_.count(view_id) == 1) {
+    return slices_.at(view_id)->canvas();
+  }
+  return nullptr;
+}
+
+SkRect AndroidExternalViewEmbedder2::GetViewRect(
+    int64_t view_id,
+    const std::unordered_map<int64_t, EmbeddedViewParams>& view_params) {
+  const EmbeddedViewParams& params = view_params.at(view_id);
+  // https://github.com/flutter/flutter/issues/59821
+  return SkRect::MakeXYWH(params.finalBoundingRect().x(),      //
+                          params.finalBoundingRect().y(),      //
+                          params.finalBoundingRect().width(),  //
+                          params.finalBoundingRect().height()  //
+  );
+}
+
+// |ExternalViewEmbedder|
+void AndroidExternalViewEmbedder2::SubmitFlutterView(
+    int64_t flutter_view_id,
+    GrDirectContext* context,
+    const std::shared_ptr<impeller::AiksContext>& aiks_context,
+    std::unique_ptr<SurfaceFrame> frame) {
+  TRACE_EVENT0("flutter", "AndroidExternalViewEmbedder2::SubmitFlutterView");
+
+  if (!FrameHasPlatformLayers()) {
+    frame->Submit();
+    jni_facade_->applyTransaction();
+    return;
+  }
+
+  std::unordered_map<int64_t, SkRect> view_rects;
+  for (auto platform_id : composition_order_) {
+    view_rects[platform_id] = GetViewRect(platform_id, view_params_);
+  }
+
+  std::unordered_map<int64_t, SkRect> overlay_layers =
+      SliceViews(frame->Canvas(),     //
+                 composition_order_,  //
+                 slices_,             //
+                 view_rects           //
+      );
+
+  // Create Overlay frame.
+  surface_pool_->TrimLayers();
+  std::unique_ptr<SurfaceFrame> overlay_frame;
+  if (surface_pool_->HasLayers()) {
+    for (int64_t view_id : composition_order_) {
+      std::unordered_map<int64_t, SkRect>::const_iterator overlay =
+          overlay_layers.find(view_id);
+
+      if (overlay == overlay_layers.end()) {
+        continue;
+      }
+      if (overlay_frame == nullptr) {
+        std::shared_ptr<OverlayLayer> layer = surface_pool_->GetLayer(
+            context, android_context_, jni_facade_, surface_factory_);
+        overlay_frame = layer->surface->AcquireFrame(frame_size_);
+      }
+
+      DlCanvas* overlay_canvas = overlay_frame->Canvas();
+      int restore_count = overlay_canvas->GetSaveCount();
+      overlay_canvas->Save();
+      overlay_canvas->ClipRect(overlay->second);
+      overlay_canvas->Clear(DlColor::kTransparent());
+      slices_[view_id]->render_into(overlay_canvas);
+      overlay_canvas->RestoreToCount(restore_count);
+    }
+  }
+  if (overlay_frame != nullptr) {
+    overlay_frame->set_submit_info({.frame_boundary = false});
+    overlay_frame->Submit();
+  }
+  frame->Submit();
+
+  task_runners_.GetPlatformTaskRunner()->PostTask(fml::MakeCopyable(
+      [&, composition_order = composition_order_, view_params = view_params_,
+       jni_facade = jni_facade_, device_pixel_ratio = device_pixel_ratio_,
+       slices = std::move(slices_)]() -> void {
+        jni_facade->swapTransaction();
+        for (int64_t view_id : composition_order) {
+          SkRect view_rect = GetViewRect(view_id, view_params);
+          const EmbeddedViewParams& params = view_params.at(view_id);
+          // Display the platform view. If it's already displayed, then it's
+          // just positioned and sized.
+          jni_facade->FlutterViewOnDisplayPlatformView(
+              view_id,             //
+              view_rect.x(),       //
+              view_rect.y(),       //
+              view_rect.width(),   //
+              view_rect.height(),  //
+              params.sizePoints().width() * device_pixel_ratio,
+              params.sizePoints().height() * device_pixel_ratio,
+              params.mutatorsStack()  //
+          );
+        }
+        if (!surface_pool_->HasLayers()) {
+          surface_pool_->GetLayer(context, android_context_, jni_facade_,
+                                  surface_factory_);
+        }
+        jni_facade->FlutterViewEndFrame();
+      }));
+}
+
+// |ExternalViewEmbedder|
+std::unique_ptr<SurfaceFrame>
+AndroidExternalViewEmbedder2::CreateSurfaceIfNeeded(GrDirectContext* context,
+                                                    int64_t view_id,
+                                                    EmbedderViewSlice* slice,
+                                                    const SkRect& rect) {
+  std::shared_ptr<OverlayLayer> layer = surface_pool_->GetLayer(
+      context, android_context_, jni_facade_, surface_factory_);
+
+  std::unique_ptr<SurfaceFrame> frame =
+      layer->surface->AcquireFrame(frame_size_);
+
+  DlCanvas* overlay_canvas = frame->Canvas();
+  overlay_canvas->Clear(DlColor::kTransparent());
+  // Offset the picture since its absolute position on the scene is determined
+  // by the position of the overlay view.
+  slice->render_into(overlay_canvas);
+  return frame;
+}
+
+// |ExternalViewEmbedder|
+PostPrerollResult AndroidExternalViewEmbedder2::PostPrerollAction(
+    const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {
+  return PostPrerollResult::kSuccess;
+}
+
+bool AndroidExternalViewEmbedder2::FrameHasPlatformLayers() {
+  return !composition_order_.empty();
+}
+
+// |ExternalViewEmbedder|
+DlCanvas* AndroidExternalViewEmbedder2::GetRootCanvas() {
+  // On Android, the root surface is created from the on-screen render target.
+  return nullptr;
+}
+
+void AndroidExternalViewEmbedder2::Reset() {
+  previous_frame_view_count_ = composition_order_.size();
+
+  composition_order_.clear();
+  slices_.clear();
+}
+
+// |ExternalViewEmbedder|
+void AndroidExternalViewEmbedder2::BeginFrame(
+    GrDirectContext* context,
+    const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
+
+// |ExternalViewEmbedder|
+void AndroidExternalViewEmbedder2::PrepareFlutterView(
+    SkISize frame_size,
+    double device_pixel_ratio) {
+  Reset();
+
+  // The surface size changed. Therefore, destroy existing surfaces as
+  // the existing surfaces in the pool can't be recycled.
+  if (frame_size_ != frame_size) {
+    DestroySurfaces();
+  }
+  surface_pool_->SetFrameSize(frame_size);
+
+  frame_size_ = frame_size;
+  device_pixel_ratio_ = device_pixel_ratio;
+}
+
+// |ExternalViewEmbedder|
+void AndroidExternalViewEmbedder2::CancelFrame() {
+  Reset();
+}
+
+// |ExternalViewEmbedder|
+void AndroidExternalViewEmbedder2::EndFrame(
+    bool should_resubmit_frame,
+    const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger) {}
+
+// |ExternalViewEmbedder|
+bool AndroidExternalViewEmbedder2::SupportsDynamicThreadMerging() {
+  return false;
+}
+
+// |ExternalViewEmbedder|
+void AndroidExternalViewEmbedder2::Teardown() {
+  DestroySurfaces();
+}
+
+// |ExternalViewEmbedder|
+void AndroidExternalViewEmbedder2::DestroySurfaces() {
+  if (!surface_pool_->HasLayers()) {
+    return;
+  }
+  fml::AutoResetWaitableEvent latch;
+  fml::TaskRunner::RunNowOrPostTask(task_runners_.GetPlatformTaskRunner(),
+                                    [&]() {
+                                      surface_pool_->DestroyLayers(jni_facade_);
+                                      latch.Signal();
+                                    });
+  latch.Wait();
+}
+
+}  // namespace flutter
diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h
new file mode 100644
index 0000000..2d8e91e
--- /dev/null
+++ b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h
@@ -0,0 +1,159 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_EXTERNAL_VIEW_EMBEDDER_EXTERNAL_VIEW_EMBEDDER_2_H_
+#define FLUTTER_SHELL_PLATFORM_ANDROID_EXTERNAL_VIEW_EMBEDDER_EXTERNAL_VIEW_EMBEDDER_2_H_
+
+#include <unordered_map>
+
+#include "flutter/common/task_runners.h"
+#include "flutter/flow/embedded_views.h"
+#include "flutter/shell/platform/android/context/android_context.h"
+#include "flutter/shell/platform/android/external_view_embedder/surface_pool.h"
+#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
+#include "flutter/shell/platform/android/surface/android_surface.h"
+
+namespace flutter {
+
+//------------------------------------------------------------------------------
+/// Allows to embed Android views into a Flutter application.
+///
+/// This class calls Java methods via |PlatformViewAndroidJNI| to manage the
+/// lifecycle of the Android view corresponding to |flutter::PlatformViewLayer|.
+///
+/// It also orchestrates overlay surfaces. These are Android views
+/// that render above (by Z order) the Android view corresponding to
+/// |flutter::PlatformViewLayer|.
+///
+/// This implementation of the external view embedder is designed only to use
+/// HC++ mode. Mixing old HC modes is not supported, but either of the texture
+/// composition based platform views can be used with either mode.
+class AndroidExternalViewEmbedder2 final : public ExternalViewEmbedder {
+ public:
+  AndroidExternalViewEmbedder2(
+      const AndroidContext& android_context,
+      std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
+      std::shared_ptr<AndroidSurfaceFactory> surface_factory,
+      const TaskRunners& task_runners);
+
+  // |ExternalViewEmbedder|
+  void PrerollCompositeEmbeddedView(
+      int64_t view_id,
+      std::unique_ptr<flutter::EmbeddedViewParams> params) override;
+
+  // |ExternalViewEmbedder|
+  DlCanvas* CompositeEmbeddedView(int64_t view_id) override;
+
+  // |ExternalViewEmbedder|
+  void SubmitFlutterView(
+      int64_t flutter_view_id,
+      GrDirectContext* context,
+      const std::shared_ptr<impeller::AiksContext>& aiks_context,
+      std::unique_ptr<SurfaceFrame> frame) override;
+
+  // |ExternalViewEmbedder|
+  PostPrerollResult PostPrerollAction(
+      const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger)
+      override;
+
+  // |ExternalViewEmbedder|
+  DlCanvas* GetRootCanvas() override;
+
+  // |ExternalViewEmbedder|
+  void BeginFrame(GrDirectContext* context,
+                  const fml::RefPtr<fml::RasterThreadMerger>&
+                      raster_thread_merger) override;
+
+  // |ExternalViewEmbedder|
+  void PrepareFlutterView(SkISize frame_size,
+                          double device_pixel_ratio) override;
+
+  // |ExternalViewEmbedder|
+  void CancelFrame() override;
+
+  // |ExternalViewEmbedder|
+  void EndFrame(bool should_resubmit_frame,
+                const fml::RefPtr<fml::RasterThreadMerger>&
+                    raster_thread_merger) override;
+
+  // |ExternalViewEmbedder|
+  bool SupportsDynamicThreadMerging() override;
+
+  // |ExternalViewEmbedder|
+  void Teardown() override;
+
+  // Gets the rect based on the device pixel ratio of a platform view displayed
+  // on the screen.
+  static SkRect GetViewRect(
+      int64_t view_id,
+      const std::unordered_map<int64_t, EmbeddedViewParams>& view_params);
+
+ private:
+  // The number of frames the rasterizer task runner will continue
+  // to run on the platform thread after no platform view is rendered.
+  //
+  // Note: this is an arbitrary number that attempts to account for cases
+  // where the platform view might be momentarily off the screen.
+  static const int kDefaultMergedLeaseDuration = 10;
+
+  // Provides metadata to the Android surfaces.
+  const AndroidContext& android_context_;
+
+  // Allows to call methods in Java.
+  const std::shared_ptr<PlatformViewAndroidJNI> jni_facade_;
+
+  // Allows to create surfaces.
+  const std::shared_ptr<AndroidSurfaceFactory> surface_factory_;
+
+  // Holds surfaces. Allows to recycle surfaces or allocate new ones.
+  const std::unique_ptr<SurfacePool> surface_pool_;
+
+  // The task runners.
+  const TaskRunners task_runners_;
+
+  // The size of the root canvas.
+  SkISize frame_size_;
+
+  // The pixel ratio used to determinate the size of a platform view layer
+  // relative to the device layout system.
+  double device_pixel_ratio_;
+
+  // The order of composition. Each entry contains a unique id for the platform
+  // view.
+  std::vector<int64_t> composition_order_;
+
+  // The |EmbedderViewSlice| implementation keyed off the platform view id,
+  // which contains any subsequent operations until the next platform view or
+  // the end of the last leaf node in the layer tree.
+  std::unordered_map<int64_t, std::unique_ptr<EmbedderViewSlice>> slices_;
+
+  // The params for a platform view, which contains the size, position and
+  // mutation stack.
+  std::unordered_map<int64_t, EmbeddedViewParams> view_params_;
+
+  // The number of platform views in the previous frame.
+  int64_t previous_frame_view_count_;
+
+  // Destroys the surfaces created from the surface factory.
+  // This method schedules a task on the platform thread, and waits for
+  // the task until it completes.
+  void DestroySurfaces();
+
+  // Resets the state.
+  void Reset();
+
+  // Whether the layer tree in the current frame has platform layers.
+  bool FrameHasPlatformLayers();
+
+  // Creates a Surface when needed or recycles an existing one.
+  // Finally, draws the picture on the frame's canvas.
+  std::unique_ptr<SurfaceFrame> CreateSurfaceIfNeeded(GrDirectContext* context,
+                                                      int64_t view_id,
+                                                      EmbedderViewSlice* slice,
+                                                      const SkRect& rect);
+};
+
+}  // namespace flutter
+
+#endif  // FLUTTER_SHELL_PLATFORM_ANDROID_EXTERNAL_VIEW_EMBEDDER_EXTERNAL_VIEW_EMBEDDER_2_H_
diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool.cc b/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool.cc
index 7290a58..ed979c8 100644
--- a/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool.cc
+++ b/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool.cc
@@ -17,7 +17,8 @@
 
 OverlayLayer::~OverlayLayer() = default;
 
-SurfacePool::SurfacePool() = default;
+SurfacePool::SurfacePool(bool use_new_surface_methods)
+    : use_new_surface_methods_(use_new_surface_methods) {}
 
 SurfacePool::~SurfacePool() = default;
 
@@ -42,7 +43,9 @@
            "rendering.";
 
     std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata> java_metadata =
-        jni_facade->FlutterViewCreateOverlaySurface();
+        use_new_surface_methods_
+            ? jni_facade->createOverlaySurface2()
+            : jni_facade->FlutterViewCreateOverlaySurface();
 
     FML_CHECK(java_metadata->window);
     android_surface->SetNativeWindow(java_metadata->window, jni_facade);
@@ -96,7 +99,11 @@
   if (layers_.empty()) {
     return;
   }
-  jni_facade->FlutterViewDestroyOverlaySurfaces();
+  if (use_new_surface_methods_) {
+    jni_facade->destroyOverlaySurface2();
+  } else {
+    jni_facade->FlutterViewDestroyOverlaySurfaces();
+  }
   layers_.clear();
   available_layer_index_ = 0;
 }
@@ -115,4 +122,9 @@
   requested_frame_size_ = frame_size;
 }
 
+void SurfacePool::TrimLayers() {
+  std::lock_guard lock(mutex_);
+  layers_.erase(layers_.begin() + available_layer_index_, layers_.end());
+  available_layer_index_ = 0;
+}
 }  // namespace flutter
diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool.h b/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool.h
index 5f09d6d..45719bc 100644
--- a/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool.h
+++ b/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool.h
@@ -45,7 +45,7 @@
 
 class SurfacePool {
  public:
-  SurfacePool();
+  explicit SurfacePool(bool use_new_surface_methods);
 
   ~SurfacePool();
 
@@ -76,6 +76,8 @@
   // Returns true if the current pool has layers in use.
   bool HasLayers();
 
+  void TrimLayers();
+
  private:
   // The index of the entry in the layers_ vector that determines the beginning
   // of the unused layers. For example, consider the following vector:
@@ -102,6 +104,7 @@
 
   // Used to guard public methods.
   std::mutex mutex_;
+  bool use_new_surface_methods_ = false;
 
   void DestroyLayersLocked(
       const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);
diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool_unittests.cc b/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool_unittests.cc
index 09cf54b..98df5f0 100644
--- a/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool_unittests.cc
+++ b/engine/src/flutter/shell/platform/android/external_view_embedder/surface_pool_unittests.cc
@@ -38,7 +38,7 @@
 };
 
 TEST(SurfacePool, GetLayerAllocateOneLayer) {
-  auto pool = std::make_unique<SurfacePool>();
+  auto pool = std::make_unique<SurfacePool>(/*use_new_surface_methods=*/false);
 
   auto gr_context = GrDirectContext::MakeMock(nullptr);
   auto android_context =
@@ -69,7 +69,7 @@
 }
 
 TEST(SurfacePool, GetUnusedLayers) {
-  auto pool = std::make_unique<SurfacePool>();
+  auto pool = std::make_unique<SurfacePool>(/*use_new_surface_methods=*/false);
 
   auto gr_context = GrDirectContext::MakeMock(nullptr);
   auto android_context =
@@ -102,7 +102,7 @@
 }
 
 TEST(SurfacePool, GetLayerRecycle) {
-  auto pool = std::make_unique<SurfacePool>();
+  auto pool = std::make_unique<SurfacePool>(/*use_new_surface_methods=*/false);
 
   auto gr_context_1 = GrDirectContext::MakeMock(nullptr);
   auto jni_mock = std::make_shared<JNIMock>();
@@ -147,7 +147,7 @@
 }
 
 TEST(SurfacePool, GetLayerAllocateTwoLayers) {
-  auto pool = std::make_unique<SurfacePool>();
+  auto pool = std::make_unique<SurfacePool>(/*use_new_surface_methods=*/false);
 
   auto gr_context = GrDirectContext::MakeMock(nullptr);
   auto android_context =
@@ -185,8 +185,45 @@
   ASSERT_EQ(1, layer_2->id);
 }
 
+TEST(SurfacePool, DestroyLayersNew) {
+  auto pool = std::make_unique<SurfacePool>(/*use_new_surface_methods=*/true);
+  auto jni_mock = std::make_shared<JNIMock>();
+
+  EXPECT_CALL(*jni_mock, destroyOverlaySurface2()).Times(0);
+  pool->DestroyLayers(jni_mock);
+
+  auto gr_context = GrDirectContext::MakeMock(nullptr);
+  auto android_context =
+      std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
+
+  auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
+  EXPECT_CALL(*jni_mock, createOverlaySurface2())
+      .Times(1)
+      .WillOnce(Return(
+          ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
+              0, window))));
+
+  auto surface_factory =
+      std::make_shared<TestAndroidSurfaceFactory>([gr_context, window]() {
+        auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
+        EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()));
+        EXPECT_CALL(*android_surface_mock, SetNativeWindow(window, _));
+        EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
+        return android_surface_mock;
+      });
+  pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory);
+
+  EXPECT_CALL(*jni_mock, destroyOverlaySurface2());
+
+  ASSERT_TRUE(pool->HasLayers());
+  pool->DestroyLayers(jni_mock);
+
+  ASSERT_FALSE(pool->HasLayers());
+  ASSERT_TRUE(pool->GetUnusedLayers().empty());
+}
+
 TEST(SurfacePool, DestroyLayers) {
-  auto pool = std::make_unique<SurfacePool>();
+  auto pool = std::make_unique<SurfacePool>(/*use_new_surface_methods=*/false);
   auto jni_mock = std::make_shared<JNIMock>();
 
   EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces()).Times(0);
@@ -223,7 +260,7 @@
 }
 
 TEST(SurfacePool, DestroyLayersFrameSizeChanged) {
-  auto pool = std::make_unique<SurfacePool>();
+  auto pool = std::make_unique<SurfacePool>(/*use_new_surface_methods=*/false);
   auto jni_mock = std::make_shared<JNIMock>();
 
   auto gr_context = GrDirectContext::MakeMock(nullptr);
@@ -267,5 +304,50 @@
   ASSERT_TRUE(pool->HasLayers());
 }
 
+TEST(SurfacePool, DestroyLayersFrameSizeChangedNew) {
+  auto pool = std::make_unique<SurfacePool>(/*use_new_surface_methods=*/true);
+  auto jni_mock = std::make_shared<JNIMock>();
+
+  auto gr_context = GrDirectContext::MakeMock(nullptr);
+  auto android_context =
+      std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
+
+  auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
+
+  auto surface_factory =
+      std::make_shared<TestAndroidSurfaceFactory>([gr_context, window]() {
+        auto android_surface_mock = std::make_unique<AndroidSurfaceMock>();
+        EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()));
+        EXPECT_CALL(*android_surface_mock, SetNativeWindow(window, _));
+        EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
+        return android_surface_mock;
+      });
+  pool->SetFrameSize(SkISize::Make(10, 10));
+  EXPECT_CALL(*jni_mock, destroyOverlaySurface2()).Times(0);
+  EXPECT_CALL(*jni_mock, createOverlaySurface2())
+      .Times(1)
+      .WillOnce(Return(
+          ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
+              0, window))));
+
+  ASSERT_FALSE(pool->HasLayers());
+
+  pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory);
+
+  ASSERT_TRUE(pool->HasLayers());
+
+  pool->SetFrameSize(SkISize::Make(20, 20));
+  EXPECT_CALL(*jni_mock, destroyOverlaySurface2()).Times(1);
+  EXPECT_CALL(*jni_mock, createOverlaySurface2())
+      .Times(1)
+      .WillOnce(Return(
+          ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
+              1, window))));
+  pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory);
+
+  ASSERT_TRUE(pool->GetUnusedLayers().empty());
+  ASSERT_TRUE(pool->HasLayers());
+}
+
 }  // namespace testing
 }  // namespace flutter
diff --git a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
index fdfd13a..a4e123c 100644
--- a/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
+++ b/engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java
@@ -321,7 +321,6 @@
     asyncWaitForVsyncDelegate = delegate;
   }
 
-  // TODO(mattcarroll): add javadocs
   // Called by native.
   private static void asyncWaitForVsync(final long cookie) {
     if (asyncWaitForVsyncDelegate != null) {
@@ -596,7 +595,6 @@
     }
   }
 
-  // TODO(mattcarroll): get native to call this when rendering stops.
   @VisibleForTesting
   @UiThread
   void onRenderingStopped() {
@@ -810,8 +808,6 @@
     if (accessibilityDelegate != null) {
       accessibilityDelegate.updateSemantics(buffer, strings, stringAttributeArgs);
     }
-    // TODO(mattcarroll): log dropped messages when in debug mode
-    // (https://github.com/flutter/flutter/issues/25391)
   }
 
   /**
@@ -831,8 +827,6 @@
     if (accessibilityDelegate != null) {
       accessibilityDelegate.updateCustomAccessibilityActions(buffer, strings);
     }
-    // TODO(mattcarroll): log dropped messages when in debug mode
-    // (https://github.com/flutter/flutter/issues/25391)
   }
 
   /** Sends a semantics action to Flutter's engine, without any additional arguments. */
@@ -896,8 +890,6 @@
 
   private native void nativeSetSemanticsEnabled(long nativeShellHolderId, boolean enabled);
 
-  // TODO(mattcarroll): figure out what flags are supported and add javadoc about when/why/where to
-  // use this.
   @UiThread
   public void setAccessibilityFeatures(int flags) {
     ensureRunningOnMainThread();
@@ -1073,7 +1065,6 @@
   }
 
   // Called by native on any thread.
-  // TODO(mattcarroll): determine if message is nonull or nullable
   @SuppressWarnings("unused")
   @VisibleForTesting
   public void handlePlatformMessage(
@@ -1086,19 +1077,14 @@
     } else {
       nativeCleanupMessageData(messageData);
     }
-    // TODO(mattcarroll): log dropped messages when in debug mode
-    // (https://github.com/flutter/flutter/issues/25391)
   }
 
   // Called by native to respond to a platform message that we sent.
-  // TODO(mattcarroll): determine if reply is nonull or nullable
   @SuppressWarnings("unused")
   private void handlePlatformMessageResponse(int replyId, ByteBuffer reply) {
     if (platformMessageHandler != null) {
       platformMessageHandler.handlePlatformMessageResponse(replyId, reply);
     }
-    // TODO(mattcarroll): log dropped messages when in debug mode
-    // (https://github.com/flutter/flutter/issues/25391)
   }
 
   /**
@@ -1149,7 +1135,6 @@
       int position,
       int responseId);
 
-  // TODO(mattcarroll): differentiate between channel responses and platform responses.
   public void invokePlatformMessageEmptyResponseCallback(int responseId) {
     // Called on any thread.
     shellHolderLock.readLock().lock();
@@ -1171,7 +1156,6 @@
   private native void nativeInvokePlatformMessageEmptyResponseCallback(
       long nativeShellHolderId, int responseId);
 
-  // TODO(mattcarroll): differentiate between channel responses and platform responses.
   public void invokePlatformMessageResponseCallback(
       int responseId, @NonNull ByteBuffer message, int position) {
     // Called on any thread.
@@ -1557,7 +1541,6 @@
         viewId, x, y, width, height, viewWidth, viewHeight, mutatorsStack);
   }
 
-  // TODO(mattcarroll): determine if this is nonull or nullable
   @UiThread
   public Bitmap getBitmap() {
     ensureRunningOnMainThread();
@@ -1565,7 +1548,6 @@
     return nativeGetBitmap(nativeShellHolderId);
   }
 
-  // TODO(mattcarroll): determine if this is nonull or nullable
   private native Bitmap nativeGetBitmap(long nativeShellHolderId);
 
   /**
diff --git a/engine/src/flutter/shell/platform/android/jni/jni_mock.h b/engine/src/flutter/shell/platform/android/jni/jni_mock.h
index cf5b329..1dedcf8 100644
--- a/engine/src/flutter/shell/platform/android/jni/jni_mock.h
+++ b/engine/src/flutter/shell/platform/android/jni/jni_mock.h
@@ -114,6 +114,31 @@
 
   MOCK_METHOD(void, FlutterViewDestroyOverlaySurfaces, (), (override));
 
+  MOCK_METHOD(ASurfaceTransaction*, createTransaction, (), (override));
+
+  MOCK_METHOD(void, swapTransaction, (), (override));
+
+  MOCK_METHOD(void, applyTransaction, (), (override));
+
+  MOCK_METHOD(void, destroyOverlaySurface2, (), (override));
+
+  MOCK_METHOD(std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>,
+              createOverlaySurface2,
+              (),
+              (override));
+
+  MOCK_METHOD(void,
+              onDisplayPlatformView2,
+              (int32_t view_id,
+               int32_t x,
+               int32_t y,
+               int32_t width,
+               int32_t height,
+               int32_t viewWidth,
+               int32_t viewHeight,
+               MutatorsStack mutators_stack),
+              (override));
+
   MOCK_METHOD(std::unique_ptr<std::vector<std::string>>,
               FlutterViewComputePlatformResolvedLocale,
               (std::vector<std::string> supported_locales_data),
diff --git a/engine/src/flutter/shell/platform/android/jni/platform_view_android_jni.h b/engine/src/flutter/shell/platform/android/jni/platform_view_android_jni.h
index 356b677..68e3b42 100644
--- a/engine/src/flutter/shell/platform/android/jni/platform_view_android_jni.h
+++ b/engine/src/flutter/shell/platform/android/jni/platform_view_android_jni.h
@@ -19,6 +19,8 @@
 #include "flutter/fml/platform/android/scoped_java_ref.h"
 #endif
 
+struct ASurfaceTransaction;
+
 namespace flutter {
 
 #if FML_OS_ANDROID
@@ -214,6 +216,27 @@
   ///
   virtual void FlutterViewDestroyOverlaySurfaces() = 0;
 
+  // New Platform View Support.
+  virtual ASurfaceTransaction* createTransaction() = 0;
+
+  virtual void swapTransaction() = 0;
+
+  virtual void applyTransaction() = 0;
+
+  virtual std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>
+  createOverlaySurface2() = 0;
+
+  virtual void destroyOverlaySurface2() = 0;
+
+  virtual void onDisplayPlatformView2(int32_t view_id,
+                                      int32_t x,
+                                      int32_t y,
+                                      int32_t width,
+                                      int32_t height,
+                                      int32_t viewWidth,
+                                      int32_t viewHeight,
+                                      MutatorsStack mutators_stack) = 0;
+
   //----------------------------------------------------------------------------
   /// @brief      Computes the locale Android would select.
   ///
diff --git a/engine/src/flutter/shell/platform/android/platform_view_android.cc b/engine/src/flutter/shell/platform/android/platform_view_android.cc
index 694b3eb..db8de49 100644
--- a/engine/src/flutter/shell/platform/android/platform_view_android.cc
+++ b/engine/src/flutter/shell/platform/android/platform_view_android.cc
@@ -30,6 +30,7 @@
 #endif
 #include "flutter/shell/platform/android/context/android_context.h"
 #include "flutter/shell/platform/android/external_view_embedder/external_view_embedder.h"
+#include "flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h"
 #include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
 #include "flutter/shell/platform/android/platform_message_response_android.h"
 #include "flutter/shell/platform/android/surface/android_surface.h"
@@ -366,6 +367,10 @@
 // |PlatformView|
 std::shared_ptr<ExternalViewEmbedder>
 PlatformViewAndroid::CreateExternalViewEmbedder() {
+  if (android_use_new_platform_view_) {
+    return std::make_shared<AndroidExternalViewEmbedder2>(
+        *android_context_, jni_facade_, surface_factory_, task_runners_);
+  }
   return std::make_shared<AndroidExternalViewEmbedder>(
       *android_context_, jni_facade_, surface_factory_, task_runners_);
 }
diff --git a/engine/src/flutter/shell/platform/android/platform_view_android.h b/engine/src/flutter/shell/platform/android/platform_view_android.h
index 5310826..5d0b630 100644
--- a/engine/src/flutter/shell/platform/android/platform_view_android.h
+++ b/engine/src/flutter/shell/platform/android/platform_view_android.h
@@ -128,6 +128,7 @@
 
   std::unique_ptr<AndroidSurface> android_surface_;
   std::shared_ptr<PlatformMessageHandlerAndroid> platform_message_handler_;
+  bool android_use_new_platform_view_ = false;
 
   // |PlatformView|
   void UpdateSemantics(
diff --git a/engine/src/flutter/shell/platform/android/platform_view_android_jni_impl.cc b/engine/src/flutter/shell/platform/android/platform_view_android_jni_impl.cc
index 8977d21..18c34ae 100644
--- a/engine/src/flutter/shell/platform/android/platform_view_android_jni_impl.cc
+++ b/engine/src/flutter/shell/platform/android/platform_view_android_jni_impl.cc
@@ -33,6 +33,7 @@
 #include "flutter/shell/platform/android/image_external_texture_gl.h"
 #include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
 #include "flutter/shell/platform/android/platform_view_android.h"
+#include "impeller/toolkit/android/proc_table.h"
 
 #define ANDROID_SHELL_HOLDER \
   (reinterpret_cast<AndroidShellHolder*>(shell_holder))
@@ -132,8 +133,6 @@
 // Called By Java
 static jmethodID g_on_display_platform_view_method = nullptr;
 
-// static jmethodID g_on_composite_platform_view_method = nullptr;
-
 static jmethodID g_on_display_overlay_surface_method = nullptr;
 
 static jmethodID g_overlay_surface_id_method = nullptr;
@@ -146,6 +145,19 @@
 
 static jmethodID g_bitmap_config_value_of = nullptr;
 
+// New platform Views
+static jmethodID g_create_transaction_method = nullptr;
+
+static jmethodID g_swap_transaction_method = nullptr;
+
+static jmethodID g_apply_transaction_method = nullptr;
+
+static jmethodID g_create_overlay_surface2_method = nullptr;
+
+static jmethodID g_destroy_overlay_surface2_method = nullptr;
+
+static jmethodID g_on_display_platform_view2_method = nullptr;
+
 // Mutators
 static fml::jni::ScopedJavaGlobalRef<jclass>* g_mutators_stack_class = nullptr;
 static jmethodID g_mutators_stack_init_method = nullptr;
@@ -968,6 +980,60 @@
     return false;
   }
 
+  // new platform views
+  g_create_transaction_method =
+      env->GetMethodID(g_flutter_jni_class->obj(), "createTransaction",
+                       "()Landroid/view/SurfaceControl$Transaction;");
+
+  if (g_create_transaction_method == nullptr) {
+    FML_LOG(ERROR) << "Could not locate createTransaction method";
+    return false;
+  }
+
+  g_swap_transaction_method =
+      env->GetMethodID(g_flutter_jni_class->obj(), "swapTransactions", "()V");
+
+  if (g_swap_transaction_method == nullptr) {
+    FML_LOG(ERROR) << "Could not locate swapTransactions method";
+    return false;
+  }
+
+  g_apply_transaction_method =
+      env->GetMethodID(g_flutter_jni_class->obj(), "applyTransactions", "()V");
+
+  if (g_apply_transaction_method == nullptr) {
+    FML_LOG(ERROR) << "Could not locate applyTransactions method";
+    return false;
+  }
+
+  g_create_overlay_surface2_method =
+      env->GetMethodID(g_flutter_jni_class->obj(), "createOverlaySurface2",
+                       "()Lio/flutter/embedding/engine/FlutterOverlaySurface;");
+
+  if (g_create_overlay_surface2_method == nullptr) {
+    FML_LOG(ERROR) << "Could not locate createOverlaySurface2 method";
+    return false;
+  }
+
+  g_destroy_overlay_surface2_method = env->GetMethodID(
+      g_flutter_jni_class->obj(), "destroyOverlaySurface2", "()V");
+
+  if (g_destroy_overlay_surface2_method == nullptr) {
+    FML_LOG(ERROR) << "Could not locate destroyOverlaySurface2 method";
+    return false;
+  }
+
+  g_on_display_platform_view2_method =
+      env->GetMethodID(g_flutter_jni_class->obj(), "onDisplayPlatformView2",
+                       "(IIIIIIILio/flutter/embedding/engine/mutatorsstack/"
+                       "FlutterMutatorsStack;)V");
+
+  if (g_on_display_platform_view2_method == nullptr) {
+    FML_LOG(ERROR) << "Could not locate onDisplayPlatformView2 method";
+    return false;
+  }
+  //
+
   fml::jni::ScopedJavaLocalRef<jclass> overlay_surface_class(
       env, env->FindClass("io/flutter/embedding/engine/FlutterOverlaySurface"));
   if (overlay_surface_class.is_null()) {
@@ -1913,4 +1979,176 @@
   return true;
 }
 
+// New Platform View Support.
+
+ASurfaceTransaction* PlatformViewAndroidJNIImpl::createTransaction() {
+  JNIEnv* env = fml::jni::AttachCurrentThread();
+
+  auto java_object = java_object_.get(env);
+
+  fml::jni::ScopedJavaLocalRef<jobject> transaction(
+      env,
+      env->CallObjectMethod(java_object.obj(), g_create_transaction_method));
+
+  if (transaction.is_null()) {
+    return nullptr;
+  }
+
+  FML_CHECK(fml::jni::CheckException(env));
+  return impeller::android::GetProcTable().ASurfaceTransaction_fromJava(
+      env, transaction.obj());
+}
+
+void PlatformViewAndroidJNIImpl::swapTransaction() {
+  JNIEnv* env = fml::jni::AttachCurrentThread();
+
+  auto java_object = java_object_.get(env);
+  if (java_object.is_null()) {
+    return;
+  }
+
+  env->CallVoidMethod(java_object.obj(), g_swap_transaction_method);
+
+  FML_CHECK(fml::jni::CheckException(env));
+}
+
+void PlatformViewAndroidJNIImpl::applyTransaction() {
+  JNIEnv* env = fml::jni::AttachCurrentThread();
+
+  auto java_object = java_object_.get(env);
+  if (java_object.is_null()) {
+    return;
+  }
+
+  env->CallVoidMethod(java_object.obj(), g_apply_transaction_method);
+
+  FML_CHECK(fml::jni::CheckException(env));
+}
+
+std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>
+PlatformViewAndroidJNIImpl::createOverlaySurface2() {
+  JNIEnv* env = fml::jni::AttachCurrentThread();
+
+  auto java_object = java_object_.get(env);
+  if (java_object.is_null()) {
+    return nullptr;
+  }
+
+  fml::jni::ScopedJavaLocalRef<jobject> overlay(
+      env, env->CallObjectMethod(java_object.obj(),
+                                 g_create_overlay_surface2_method));
+  FML_CHECK(fml::jni::CheckException(env));
+
+  if (overlay.is_null()) {
+    return std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(0,
+                                                                     nullptr);
+  }
+
+  jint overlay_id =
+      env->CallIntMethod(overlay.obj(), g_overlay_surface_id_method);
+
+  jobject overlay_surface =
+      env->CallObjectMethod(overlay.obj(), g_overlay_surface_surface_method);
+
+  auto overlay_window = fml::MakeRefCounted<AndroidNativeWindow>(
+      ANativeWindow_fromSurface(env, overlay_surface));
+
+  return std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
+      overlay_id, std::move(overlay_window));
+}
+
+void PlatformViewAndroidJNIImpl::destroyOverlaySurface2() {
+  JNIEnv* env = fml::jni::AttachCurrentThread();
+
+  auto java_object = java_object_.get(env);
+  if (java_object.is_null()) {
+    return;
+  }
+
+  env->CallVoidMethod(java_object.obj(), g_destroy_overlay_surface2_method);
+
+  FML_CHECK(fml::jni::CheckException(env));
+}
+
+void PlatformViewAndroidJNIImpl::onDisplayPlatformView2(
+    int32_t view_id,
+    int32_t x,
+    int32_t y,
+    int32_t width,
+    int32_t height,
+    int32_t viewWidth,
+    int32_t viewHeight,
+    MutatorsStack mutators_stack) {
+  JNIEnv* env = fml::jni::AttachCurrentThread();
+  auto java_object = java_object_.get(env);
+  if (java_object.is_null()) {
+    return;
+  }
+
+  jobject mutatorsStack = env->NewObject(g_mutators_stack_class->obj(),
+                                         g_mutators_stack_init_method);
+
+  std::vector<std::shared_ptr<Mutator>>::const_iterator iter =
+      mutators_stack.Begin();
+  while (iter != mutators_stack.End()) {
+    switch ((*iter)->GetType()) {
+      case kTransform: {
+        const SkMatrix& matrix = (*iter)->GetMatrix();
+        SkScalar matrix_array[9];
+        matrix.get9(matrix_array);
+        fml::jni::ScopedJavaLocalRef<jfloatArray> transformMatrix(
+            env, env->NewFloatArray(9));
+
+        env->SetFloatArrayRegion(transformMatrix.obj(), 0, 9, matrix_array);
+        env->CallVoidMethod(mutatorsStack,
+                            g_mutators_stack_push_transform_method,
+                            transformMatrix.obj());
+        break;
+      }
+      case kClipRect: {
+        const SkRect& rect = (*iter)->GetRect();
+        env->CallVoidMethod(
+            mutatorsStack, g_mutators_stack_push_cliprect_method,
+            static_cast<int>(rect.left()), static_cast<int>(rect.top()),
+            static_cast<int>(rect.right()), static_cast<int>(rect.bottom()));
+        break;
+      }
+      case kClipRRect: {
+        const SkRRect& rrect = (*iter)->GetRRect();
+        const SkRect& rect = rrect.rect();
+        const SkVector& upper_left = rrect.radii(SkRRect::kUpperLeft_Corner);
+        const SkVector& upper_right = rrect.radii(SkRRect::kUpperRight_Corner);
+        const SkVector& lower_right = rrect.radii(SkRRect::kLowerRight_Corner);
+        const SkVector& lower_left = rrect.radii(SkRRect::kLowerLeft_Corner);
+        SkScalar radiis[8] = {
+            upper_left.x(),  upper_left.y(),  upper_right.x(), upper_right.y(),
+            lower_right.x(), lower_right.y(), lower_left.x(),  lower_left.y(),
+        };
+        fml::jni::ScopedJavaLocalRef<jfloatArray> radiisArray(
+            env, env->NewFloatArray(8));
+        env->SetFloatArrayRegion(radiisArray.obj(), 0, 8, radiis);
+        env->CallVoidMethod(
+            mutatorsStack, g_mutators_stack_push_cliprrect_method,
+            static_cast<int>(rect.left()), static_cast<int>(rect.top()),
+            static_cast<int>(rect.right()), static_cast<int>(rect.bottom()),
+            radiisArray.obj());
+        break;
+      }
+      // TODO(cyanglaz): Implement other mutators.
+      // https://github.com/flutter/flutter/issues/58426
+      case kClipPath:
+      case kOpacity:
+      case kBackdropFilter:
+        break;
+    }
+    ++iter;
+  }
+
+  env->CallVoidMethod(java_object.obj(), g_on_display_platform_view2_method,
+                      view_id, x, y, width, height, viewWidth, viewHeight,
+                      mutatorsStack);
+
+  FML_CHECK(fml::jni::CheckException(env));
+}
+
 }  // namespace flutter
diff --git a/engine/src/flutter/shell/platform/android/platform_view_android_jni_impl.h b/engine/src/flutter/shell/platform/android/platform_view_android_jni_impl.h
index 73cb6a4..d05ee13 100644
--- a/engine/src/flutter/shell/platform/android/platform_view_android_jni_impl.h
+++ b/engine/src/flutter/shell/platform/android/platform_view_android_jni_impl.h
@@ -103,6 +103,27 @@
   double FlutterViewGetScaledFontSize(double unscaled_font_size,
                                       int configuration_id) const override;
 
+  // New Platform View Support.
+  ASurfaceTransaction* createTransaction() override;
+
+  void swapTransaction() override;
+
+  void applyTransaction() override;
+
+  std::unique_ptr<PlatformViewAndroidJNI::OverlayMetadata>
+  createOverlaySurface2() override;
+
+  void destroyOverlaySurface2() override;
+
+  void onDisplayPlatformView2(int32_t view_id,
+                              int32_t x,
+                              int32_t y,
+                              int32_t width,
+                              int32_t height,
+                              int32_t viewWidth,
+                              int32_t viewHeight,
+                              MutatorsStack mutators_stack) override;
+
  private:
   // Reference to FlutterJNI object.
   const fml::jni::JavaObjectWeakGlobalRef java_object_;