diff --git a/src/android/app/src/main/jni/config.cpp b/src/android/app/src/main/jni/config.cpp
index 7851330577..7a83fea42e 100644
--- a/src/android/app/src/main/jni/config.cpp
+++ b/src/android/app/src/main/jni/config.cpp
@@ -217,6 +217,7 @@ void Config::ReadValues() {
     ReadSetting("Renderer", Settings::values.accelerate_astc);
     ReadSetting("Renderer", Settings::values.use_fast_gpu_time);
     ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache);
+    ReadSetting("Renderer", Settings::values.async_presentation);
 
     // Use GPU accuracy normal by default on Android
     Settings::values.gpu_accuracy = static_cast<Settings::GPUAccuracy>(config->GetInteger(
@@ -230,10 +231,6 @@ void Config::ReadValues() {
     Settings::values.renderer_force_max_clock =
         config->GetBoolean("Renderer", "force_max_clock", true);
 
-    // Enable asynchronous presentation by default on Android
-    Settings::values.async_presentation =
-        config->GetBoolean("Renderer", "async_presentation", true);
-
     // Audio
     ReadSetting("Audio", Settings::values.sink_id);
     ReadSetting("Audio", Settings::values.audio_output_device_id);
diff --git a/src/android/app/src/main/jni/emu_window/emu_window.cpp b/src/android/app/src/main/jni/emu_window/emu_window.cpp
index 2fdb688236..926bb30e85 100644
--- a/src/android/app/src/main/jni/emu_window/emu_window.cpp
+++ b/src/android/app/src/main/jni/emu_window/emu_window.cpp
@@ -8,7 +8,7 @@
 #include "jni/emu_window/emu_window.h"
 
 void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
-    m_render_window = surface;
+    window_info.render_surface = reinterpret_cast<void*>(surface);
 }
 
 void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
@@ -37,7 +37,7 @@ void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timesta
                                              float gyro_y, float gyro_z, float accel_x,
                                              float accel_y, float accel_z) {
     m_input_subsystem->GetVirtualGamepad()->SetMotionState(
-            player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z);
+        player_index, delta_timestamp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z);
 }
 
 void EmuWindow_Android::OnReadNfcTag(std::span<u8> data) {
@@ -65,9 +65,8 @@ EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsyste
     // Ensures that we emulate with the correct aspect ratio.
     UpdateCurrentFramebufferLayout(m_window_width, m_window_height);
 
-    m_host_window = surface;
     window_info.type = Core::Frontend::WindowSystemType::Android;
-    window_info.render_surface = reinterpret_cast<void*>(m_host_window);
+    window_info.render_surface = reinterpret_cast<void*>(surface);
 
     m_input_subsystem->Initialize();
 }
diff --git a/src/android/app/src/main/jni/emu_window/emu_window.h b/src/android/app/src/main/jni/emu_window/emu_window.h
index 2a0a720772..36d46eb510 100644
--- a/src/android/app/src/main/jni/emu_window/emu_window.h
+++ b/src/android/app/src/main/jni/emu_window/emu_window.h
@@ -54,9 +54,6 @@ public:
 private:
     InputCommon::InputSubsystem* m_input_subsystem{};
 
-    ANativeWindow* m_render_window{};
-    ANativeWindow* m_host_window{};
-
     float m_window_width{};
     float m_window_height{};
 
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 30dc69f130..77128c6e29 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -93,7 +93,8 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_,
       state_tracker(), scheduler(device, state_tracker),
       swapchain(*surface, device, scheduler, render_window.GetFramebufferLayout().width,
                 render_window.GetFramebufferLayout().height, false),
-      present_manager(render_window, device, memory_allocator, scheduler, swapchain),
+      present_manager(instance, render_window, device, memory_allocator, scheduler, swapchain,
+                      surface),
       blit_screen(cpu_memory, render_window, device, memory_allocator, swapchain, present_manager,
                   scheduler, screen_info),
       rasterizer(render_window, gpu, cpu_memory, screen_info, device, memory_allocator,
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp
index c495830136..77832720df 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp
@@ -4,10 +4,12 @@
 #include "common/microprofile.h"
 #include "common/settings.h"
 #include "common/thread.h"
+#include "core/frontend/emu_window.h"
 #include "video_core/renderer_vulkan/vk_present_manager.h"
 #include "video_core/renderer_vulkan/vk_scheduler.h"
 #include "video_core/renderer_vulkan/vk_swapchain.h"
 #include "video_core/vulkan_common/vulkan_device.h"
+#include "video_core/vulkan_common/vulkan_surface.h"
 
 namespace Vulkan {
 
@@ -92,14 +94,17 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice& physical_device, VkFormat form
 
 } // Anonymous namespace
 
-PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const Device& device_,
+PresentManager::PresentManager(const vk::Instance& instance_,
+                               Core::Frontend::EmuWindow& render_window_, const Device& device_,
                                MemoryAllocator& memory_allocator_, Scheduler& scheduler_,
-                               Swapchain& swapchain_)
-    : render_window{render_window_}, device{device_},
+                               Swapchain& swapchain_, vk::SurfaceKHR& surface_)
+    : instance{instance_}, render_window{render_window_}, device{device_},
       memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_},
-      blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())},
+      surface{surface_}, blit_supported{CanBlitToSwapchain(device.GetPhysical(),
+                                                           swapchain.GetImageViewFormat())},
       use_present_thread{Settings::values.async_presentation.GetValue()},
-      image_count{swapchain.GetImageCount()} {
+      image_count{swapchain.GetImageCount()}, last_render_surface{
+                                                  render_window_.GetWindowInfo().render_surface} {
 
     auto& dld = device.GetLogical();
     cmdpool = dld.CreateCommandPool({
@@ -290,10 +295,19 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
     MICROPROFILE_SCOPE(Vulkan_CopyToSwapchain);
 
     const auto recreate_swapchain = [&] {
-        swapchain.Create(frame->width, frame->height, frame->is_srgb);
+        swapchain.Create(*surface, frame->width, frame->height, frame->is_srgb);
         image_count = swapchain.GetImageCount();
     };
 
+#ifdef ANDROID
+    // If the frontend recreated the surface, recreate the renderer surface and swapchain.
+    if (last_render_surface != render_window.GetWindowInfo().render_surface) {
+        last_render_surface = render_window.GetWindowInfo().render_surface;
+        surface = CreateSurface(instance, render_window.GetWindowInfo());
+        recreate_swapchain();
+    }
+#endif
+
     // If the size or colorspace of the incoming frames has changed, recreate the swapchain
     // to account for that.
     const bool srgb_changed = swapchain.NeedsRecreation(frame->is_srgb);
@@ -454,4 +468,4 @@ void PresentManager::CopyToSwapchain(Frame* frame) {
     swapchain.Present(render_semaphore);
 }
 
-} // namespace Vulkan
+} // namespace Vulkan
\ No newline at end of file
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h
index 420a775e2a..3cbfce4edc 100644
--- a/src/video_core/renderer_vulkan/vk_present_manager.h
+++ b/src/video_core/renderer_vulkan/vk_present_manager.h
@@ -37,8 +37,9 @@ struct Frame {
 
 class PresentManager {
 public:
-    PresentManager(Core::Frontend::EmuWindow& render_window, const Device& device,
-                   MemoryAllocator& memory_allocator, Scheduler& scheduler, Swapchain& swapchain);
+    PresentManager(const vk::Instance& instance, Core::Frontend::EmuWindow& render_window,
+                   const Device& device, MemoryAllocator& memory_allocator, Scheduler& scheduler,
+                   Swapchain& swapchain, vk::SurfaceKHR& surface);
     ~PresentManager();
 
     /// Returns the last used presentation frame
@@ -60,11 +61,13 @@ private:
     void CopyToSwapchain(Frame* frame);
 
 private:
+    const vk::Instance& instance;
     Core::Frontend::EmuWindow& render_window;
     const Device& device;
     MemoryAllocator& memory_allocator;
     Scheduler& scheduler;
     Swapchain& swapchain;
+    vk::SurfaceKHR& surface;
     vk::CommandPool cmdpool;
     std::vector<Frame> frames;
     std::queue<Frame*> present_queue;
@@ -77,7 +80,8 @@ private:
     std::jthread present_thread;
     bool blit_supported;
     bool use_present_thread;
-    std::size_t image_count;
+    std::size_t image_count{};
+    void* last_render_surface{};
 };
 
 } // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp
index e43a993f91..afcf34fba4 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.cpp
+++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp
@@ -107,16 +107,17 @@ VkCompositeAlphaFlagBitsKHR ChooseAlphaFlags(const VkSurfaceCapabilitiesKHR& cap
 Swapchain::Swapchain(VkSurfaceKHR surface_, const Device& device_, Scheduler& scheduler_,
                      u32 width_, u32 height_, bool srgb)
     : surface{surface_}, device{device_}, scheduler{scheduler_} {
-    Create(width_, height_, srgb);
+    Create(surface_, width_, height_, srgb);
 }
 
 Swapchain::~Swapchain() = default;
 
-void Swapchain::Create(u32 width_, u32 height_, bool srgb) {
+void Swapchain::Create(VkSurfaceKHR surface_, u32 width_, u32 height_, bool srgb) {
     is_outdated = false;
     is_suboptimal = false;
     width = width_;
     height = height_;
+    surface = surface_;
 
     const auto physical_device = device.GetPhysical();
     const auto capabilities{physical_device.GetSurfaceCapabilitiesKHR(surface)};
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.h b/src/video_core/renderer_vulkan/vk_swapchain.h
index bf1ea7254c..b8a1465a6f 100644
--- a/src/video_core/renderer_vulkan/vk_swapchain.h
+++ b/src/video_core/renderer_vulkan/vk_swapchain.h
@@ -24,7 +24,7 @@ public:
     ~Swapchain();
 
     /// Creates (or recreates) the swapchain with a given size.
-    void Create(u32 width, u32 height, bool srgb);
+    void Create(VkSurfaceKHR surface, u32 width, u32 height, bool srgb);
 
     /// Acquires the next image in the swapchain, waits as needed.
     bool AcquireNextImage();
@@ -118,7 +118,7 @@ private:
 
     bool NeedsPresentModeUpdate() const;
 
-    const VkSurfaceKHR surface;
+    VkSurfaceKHR surface;
     const Device& device;
     Scheduler& scheduler;