[Impeller] tear down swapchain when backgrounding. (#165259)

When we return to the foreground the swapchain is reconstructed anyway.
Eagerly tearing the old one down releases memory faster. Highlighted by
a regression in a customer: money benchmark.
diff --git a/engine/src/flutter/ci/licenses_golden/excluded_files b/engine/src/flutter/ci/licenses_golden/excluded_files
index d632d10..4227a1f 100644
--- a/engine/src/flutter/ci/licenses_golden/excluded_files
+++ b/engine/src/flutter/ci/licenses_golden/excluded_files
@@ -206,6 +206,7 @@
 ../../../flutter/impeller/renderer/backend/vulkan/render_pass_cache_unittests.cc
 ../../../flutter/impeller/renderer/backend/vulkan/render_pass_vk_unittests.cc
 ../../../flutter/impeller/renderer/backend/vulkan/resource_manager_vk_unittests.cc
+../../../flutter/impeller/renderer/backend/vulkan/surface_context_vk_unittests.cc
 ../../../flutter/impeller/renderer/backend/vulkan/swapchain/README.md
 ../../../flutter/impeller/renderer/backend/vulkan/swapchain/khr/README.md
 ../../../flutter/impeller/renderer/backend/vulkan/test
diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn b/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn
index cc800da..2f31d4f 100644
--- a/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn
+++ b/engine/src/flutter/impeller/renderer/backend/vulkan/BUILD.gn
@@ -22,6 +22,7 @@
     "render_pass_cache_unittests.cc",
     "render_pass_vk_unittests.cc",
     "resource_manager_vk_unittests.cc",
+    "surface_context_vk_unittests.cc",
     "test/gpu_tracer_unittests.cc",
     "test/mock_vulkan.cc",
     "test/mock_vulkan.h",
diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk.cc
index a96e5fa..33cbc58 100644
--- a/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk.cc
+++ b/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk.cc
@@ -72,6 +72,13 @@
   return SetSwapchain(SwapchainVK::Create(parent_, std::move(surface), size));
 }
 
+void SurfaceContextVK::TeardownSwapchain() {
+  // When background the application, tear down the swapchain to release memory
+  // from the images. When returning to the foreground, SetWindowSurface will be
+  // called which will re-create the swapchain.
+  swapchain_.reset();
+}
+
 bool SurfaceContextVK::SetSwapchain(std::shared_ptr<SwapchainVK> swapchain) {
   if (!swapchain || !swapchain->IsValid()) {
     VALIDATION_LOG << "Invalid swapchain.";
diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk.h
index c629e65..9f0b088 100644
--- a/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk.h
+++ b/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk.h
@@ -96,6 +96,9 @@
   ///        recreated on the next frame.
   void UpdateSurfaceSize(const ISize& size) const;
 
+  /// @brief Can be called when the surface is destroyed to reduce memory usage.
+  void TeardownSwapchain();
+
   // |Context|
   void InitializeCommonlyUsedShadersIfNeeded() const override;
 
diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk_unittests.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk_unittests.cc
new file mode 100644
index 0000000..5cb2c7e
--- /dev/null
+++ b/engine/src/flutter/impeller/renderer/backend/vulkan/surface_context_vk_unittests.cc
@@ -0,0 +1,47 @@
+// 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 <sys/types.h>
+#include <memory>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "impeller/renderer/backend/vulkan/surface_context_vk.h"
+#include "impeller/renderer/backend/vulkan/test/mock_vulkan.h"
+#include "impeller/renderer/surface.h"
+
+namespace impeller {
+namespace testing {
+
+namespace {
+vk::UniqueSurfaceKHR CreateSurface(const ContextVK& context) {
+#if FML_OS_DARWIN
+  impeller::vk::MetalSurfaceCreateInfoEXT createInfo = {};
+  auto [result, surface] =
+      context.GetInstance().createMetalSurfaceEXTUnique(createInfo);
+  FML_DCHECK(result == vk::Result::eSuccess);
+  return std::move(surface);
+#else
+  return {};
+#endif  // FML_OS_DARWIN
+}
+}  // namespace
+
+TEST(SurfaceContextVK, TearsDownSwapchain) {
+  SetSwapchainImageSize({100, 100});
+  std::shared_ptr<ContextVK> context = MockVulkanContextBuilder().Build();
+
+  vk::UniqueSurfaceKHR surface = CreateSurface(*context);
+  SurfaceContextVK surface_context(context);
+
+  EXPECT_TRUE(surface_context.SetWindowSurface(std::move(surface), {100, 100}));
+  EXPECT_NE(surface_context.AcquireNextSurface(), nullptr);
+
+  surface_context.TeardownSwapchain();
+
+  EXPECT_EQ(surface_context.AcquireNextSurface(), nullptr);
+}
+
+}  // namespace testing
+}  // namespace impeller
diff --git a/engine/src/flutter/shell/platform/android/android_surface_vk_impeller.cc b/engine/src/flutter/shell/platform/android/android_surface_vk_impeller.cc
index 2ecea59..008724c 100644
--- a/engine/src/flutter/shell/platform/android/android_surface_vk_impeller.cc
+++ b/engine/src/flutter/shell/platform/android/android_surface_vk_impeller.cc
@@ -37,7 +37,7 @@
 }
 
 void AndroidSurfaceVKImpeller::TeardownOnScreenContext() {
-  // Nothing to do.
+  surface_context_vk_->TeardownSwapchain();
 }
 
 std::unique_ptr<Surface> AndroidSurfaceVKImpeller::CreateGPUSurface(