From 8a6095052b4c0efef6465a0b459c695ebf9e2931 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 29 Jul 2024 12:20:23 -0700 Subject: [PATCH 1/3] [iOS] leak a single overlay layer. --- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 7 ++++++- .../ios/framework/Source/FlutterPlatformViewsTest.mm | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 74ac5ab1208a4..98f9130c59ab1 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -158,7 +158,12 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, for (size_t i = available_layer_index_; i < layers_.size(); i++) { results.push_back(layers_[i]); } - layers_.erase(layers_.begin() + available_layer_index_, layers_.end()); + // Leave at least one overlay layer, to work around cases where scrolling + // platform views under an app bar continually adds and removes an + // overlay layer. This logic could be removed if https://github.com/flutter/flutter/issues/150646 + // is fixed. + size_t erase_offset = std::max(available_layer_index_, 1u); + layers_.erase(layers_.begin() + erase_offset, layers_.end()); return results; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index a14dcf8007844..32d1ed30a01cf 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -3335,10 +3335,10 @@ - (void)testLayerPool { pool.RecycleLayers(); XCTAssertEqual(pool.size(), 2u); - // Free the unused layers. + // Free the unused layers. One should remain. auto unused_layers = pool.RemoveUnusedLayers(); XCTAssertEqual(unused_layers.size(), 2u); - XCTAssertEqual(pool.size(), 0u); + XCTAssertEqual(pool.size(), 1u); } @end From 17519cc0ff99a1ffa0d26477a9a97bd89ef0d847 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 29 Jul 2024 12:40:42 -0700 Subject: [PATCH 2/3] ++ --- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 98f9130c59ab1..3030cf3094436 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -162,7 +162,8 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, // platform views under an app bar continually adds and removes an // overlay layer. This logic could be removed if https://github.com/flutter/flutter/issues/150646 // is fixed. - size_t erase_offset = std::max(available_layer_index_, 1u); + static constexpr size_t kLeakLayerCount = 1; + size_t erase_offset = std::max(available_layer_index_, kLeakLayerCount); layers_.erase(layers_.begin() + erase_offset, layers_.end()); return results; } From 7a469a7b4e31ba5f8e6f5591ab6ce61a864429d2 Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Mon, 29 Jul 2024 13:44:14 -0700 Subject: [PATCH 3/3] Update FlutterPlatformViews.mm --- .../darwin/ios/framework/Source/FlutterPlatformViews.mm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 3030cf3094436..e08e7fbb995b4 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -164,7 +164,9 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect, // is fixed. static constexpr size_t kLeakLayerCount = 1; size_t erase_offset = std::max(available_layer_index_, kLeakLayerCount); - layers_.erase(layers_.begin() + erase_offset, layers_.end()); + if (erase_offset < layers_.size()) { + layers_.erase(layers_.begin() + erase_offset, layers_.end()); + } return results; }