Skip to content

Commit 2eaeffe

Browse files
author
Chris Yang
committed
# This is a combination of 3 commits.
# This is the 1st commit message: fix remove from slice test # This is the commit message flutter#2: remove comment # This is the commit message flutter#3: dispose view after it is removed from the compositon order
1 parent 1d25906 commit 2eaeffe

File tree

2 files changed

+117
-1
lines changed

2 files changed

+117
-1
lines changed

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,14 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
867867

868868
FML_DCHECK([[NSThread currentThread] isMainThread]);
869869

870+
std::unordered_set<int64_t> views_to_composite(composition_order_.begin(),
871+
composition_order_.end());
872+
std::unordered_set<int64_t> views_to_dispose_next_frame;
870873
for (int64_t viewId : views_to_dispose_) {
874+
if (views_to_composite.count(viewId)) {
875+
views_to_dispose_next_frame.insert(viewId);
876+
continue;
877+
}
871878
UIView* root_view = root_views_[viewId].get();
872879
[root_view removeFromSuperview];
873880
views_.erase(viewId);
@@ -876,8 +883,10 @@ static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
876883
current_composition_params_.erase(viewId);
877884
clip_count_.erase(viewId);
878885
views_to_recomposite_.erase(viewId);
886+
slices_.erase(viewId);
879887
}
880-
views_to_dispose_.clear();
888+
889+
views_to_dispose_ = views_to_dispose_next_frame;
881890
}
882891

883892
void FlutterPlatformViewsController::BeginCATransaction() {

shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,4 +2790,111 @@ - (BOOL)validateOneVisualEffectView:(UIView*)visualEffectView
27902790
return NO;
27912791
}
27922792

2793+
- (void)testDisposingViewInCompositionOrderDoNotCrash {
2794+
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
2795+
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
2796+
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
2797+
/*platform=*/thread_task_runner,
2798+
/*raster=*/thread_task_runner,
2799+
/*ui=*/thread_task_runner,
2800+
/*io=*/thread_task_runner);
2801+
auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
2802+
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
2803+
/*delegate=*/mock_delegate,
2804+
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
2805+
/*platform_views_controller=*/flutterPlatformViewsController,
2806+
/*task_runners=*/runners);
2807+
2808+
UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
2809+
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
2810+
2811+
FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
2812+
[[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease];
2813+
flutterPlatformViewsController->RegisterViewFactory(
2814+
factory, @"MockFlutterPlatformView",
2815+
FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
2816+
FlutterResult result = ^(id result) {
2817+
};
2818+
2819+
flutterPlatformViewsController->OnMethodCall(
2820+
[FlutterMethodCall
2821+
methodCallWithMethodName:@"create"
2822+
arguments:@{@"id" : @0, @"viewType" : @"MockFlutterPlatformView"}],
2823+
result);
2824+
flutterPlatformViewsController->OnMethodCall(
2825+
[FlutterMethodCall
2826+
methodCallWithMethodName:@"create"
2827+
arguments:@{@"id" : @1, @"viewType" : @"MockFlutterPlatformView"}],
2828+
result);
2829+
2830+
{
2831+
// **** First frame, view id 0, 1 in the composition_order_, disposing view 0 is called. **** //
2832+
// No view should be disposed, or removed from the composition order.
2833+
flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300));
2834+
flutter::MutatorsStack stack;
2835+
SkMatrix finalMatrix;
2836+
auto embeddedViewParams0 =
2837+
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
2838+
flutterPlatformViewsController->PrerollCompositeEmbeddedView(0, std::move(embeddedViewParams0));
2839+
flutterPlatformViewsController->CompositeEmbeddedView(0);
2840+
2841+
auto embeddedViewParams1 =
2842+
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
2843+
flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1));
2844+
flutterPlatformViewsController->CompositeEmbeddedView(1);
2845+
XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 2UL);
2846+
2847+
XCTestExpectation* expectation = [self expectationWithDescription:@"dispose call ended."];
2848+
FlutterResult disposeResult = ^(id result) {
2849+
[expectation fulfill];
2850+
};
2851+
2852+
flutterPlatformViewsController->OnMethodCall(
2853+
[FlutterMethodCall methodCallWithMethodName:@"dispose" arguments:@0], disposeResult);
2854+
[self waitForExpectationsWithTimeout:30 handler:nil];
2855+
2856+
const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000);
2857+
sk_sp<SkSurface> mock_sk_surface = SkSurface::MakeRaster(image_info);
2858+
flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
2859+
auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
2860+
std::move(mock_sk_surface), framebuffer_info,
2861+
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
2862+
/*frame_size=*/SkISize::Make(800, 600));
2863+
XCTAssertTrue(
2864+
flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface)));
2865+
2866+
// Disposing won't remove embedded views until the view is removed from the composition_order_
2867+
XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 2UL);
2868+
XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(0));
2869+
XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(1));
2870+
}
2871+
2872+
{
2873+
// **** Second frame, view id 1 in the composition_order_, no disposing view is called, **** //
2874+
// View 0 is removed from the composition order in this frame, hence also disposed.
2875+
flutterPlatformViewsController->BeginFrame(SkISize::Make(300, 300));
2876+
flutter::MutatorsStack stack;
2877+
SkMatrix finalMatrix;
2878+
auto embeddedViewParams1 =
2879+
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);
2880+
flutterPlatformViewsController->PrerollCompositeEmbeddedView(1, std::move(embeddedViewParams1));
2881+
flutterPlatformViewsController->CompositeEmbeddedView(1);
2882+
2883+
const SkImageInfo image_info = SkImageInfo::MakeN32Premul(1000, 1000);
2884+
sk_sp<SkSurface> mock_sk_surface = SkSurface::MakeRaster(image_info);
2885+
flutter::SurfaceFrame::FramebufferInfo framebuffer_info;
2886+
auto mock_surface = std::make_unique<flutter::SurfaceFrame>(
2887+
std::move(mock_sk_surface), framebuffer_info,
2888+
[](const flutter::SurfaceFrame& surface_frame, flutter::DlCanvas* canvas) { return true; },
2889+
/*frame_size=*/SkISize::Make(800, 600));
2890+
XCTAssertTrue(
2891+
flutterPlatformViewsController->SubmitFrame(nullptr, nullptr, std::move(mock_surface)));
2892+
2893+
// Disposing won't remove embedded views until the view is removed from the composition_order_
2894+
XCTAssertEqual(flutterPlatformViewsController->EmbeddedViewCount(), 1UL);
2895+
XCTAssertNil(flutterPlatformViewsController->GetPlatformViewByID(0));
2896+
XCTAssertNotNil(flutterPlatformViewsController->GetPlatformViewByID(1));
2897+
}
2898+
}
2899+
27932900
@end

0 commit comments

Comments
 (0)