diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm index 7b8d2a43c7..8d2269c141 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViewsTest.mm @@ -4624,9 +4624,9 @@ fml::RefPtr GetDefaultTaskRunner() { FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar"]; [engine run]; XCTAssertTrue(engine.platformView != nullptr); - auto ios_context = engine.platformView->GetIosContext(); + std::shared_ptr ios_context = engine.platformView->GetIosContext(); - auto pool = flutter::OverlayLayerPool{}; + flutter::OverlayLayerPool pool; // Add layers to the pool. pool.CreateLayer(ios_context, MTLPixelFormatBGRA8Unorm, 1); @@ -4644,6 +4644,26 @@ fml::RefPtr GetDefaultTaskRunner() { XCTAssertEqual(pool.size(), 1u); } +- (void)testLayerUpdateViewStateWithNilFlutterViewShouldNotCrash { + // Create an IOSContext. + FlutterEngine* engine = [[FlutterEngine alloc] initWithName:@"foobar"]; + [engine run]; + XCTAssertTrue(engine.platformView != nullptr); + std::shared_ptr ios_context = engine.platformView->GetIosContext(); + + flutter::OverlayLayerPool pool; + + // Add layers to the pool. + pool.CreateLayer(ios_context, MTLPixelFormatBGRA8Unorm, 1); + XCTAssertEqual(pool.size(), 1u); + + std::shared_ptr layer = pool.GetNextLayer(); + + layer->UpdateViewState(nil, SkRect::MakeXYWH(1, 2, 3, 4), 0, 0); + // Should not update the view state (e.g. overlay_view_wrapper's frame) when FlutterView is nil. + XCTAssertTrue(CGRectEqualToRect(layer->overlay_view_wrapper.frame, CGRectZero)); +} + - (void)testFlutterPlatformViewControllerSubmitFramePreservingFrameDamage { flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate; diff --git a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.mm b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.mm index 89b61ca357..8cd0e4f1f6 100644 --- a/engine/src/flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.mm +++ b/engine/src/flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.mm @@ -23,6 +23,11 @@ void OverlayLayer::UpdateViewState(UIView* flutter_view, SkRect rect, int64_t view_id, int64_t overlay_id) { + // There can be a race where UpdateViewState() is called when flutter_view is nil when app is + // backgrounded. + if (!flutter_view) { + return; + } auto screenScale = ((FlutterView*)flutter_view).screen.scale; // Set the size of the overlay view wrapper. // This wrapper view masks the overlay view.