Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 0dc86cd

Browse files
authored
Only attempt surface creation in viewDidLayoutSubviews if the application is active. (#19592)
UIKit does not guarantee that the application is in the active state when it lays out it subviews. However, in `viewDidLayoutSubviews`, Flutter attempts to create the render surface and wait for the first frame. These operations require GPU access which is forbidden when in the background on iOS. This layout while in the background only seems to happen under very specific circumstances as described in the reproducible test case. Notably, this behavior cannot be reproduced when the application is just launched with the "Background Fetch" XCode run scheme. The other instance of invocations to create the rendering surface have been audited and I can confirm that those are already in the correct lifecycle callbacks. This was the only instance where the surface creation was in a non-lifecycle callback. Fixes flutter/flutter#55969 (This issue has a clear reproducible test case and was used as the basis for verification.) Fixes flutter/flutter#57676 (This is significantly harder to reproduce but the issue looks to be the same. I tried this patch on multiple devices overnight and could not reproduce this.) This underlying cause here was identified by the enhanced GPU error reporting introduced in iOS 14. I am not able to submit those patches because the Beta builders are not available on infra. I will submit those when available so that issues like this have more actionable error messages in the future.
1 parent a15bc1b commit 0dc86cd

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

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

+7-1
Original file line numberDiff line numberDiff line change
@@ -848,9 +848,15 @@ - (void)viewDidLayoutSubviews {
848848
[self updateViewportPadding];
849849
[self updateViewportMetrics];
850850

851+
// There is no guarantee that UIKit will layout subviews when the application is active. Creating
852+
// the surface when inactive will cause GPU accesses from the background. Only wait for the first
853+
// frame to render when the application is actually active.
854+
bool applicationIsActive =
855+
[UIApplication sharedApplication].applicationState == UIApplicationStateActive;
856+
851857
// This must run after updateViewportMetrics so that the surface creation tasks are queued after
852858
// the viewport metrics update tasks.
853-
if (firstViewBoundsUpdate) {
859+
if (firstViewBoundsUpdate && applicationIsActive) {
854860
[self surfaceUpdated:YES];
855861

856862
flutter::Shell& shell = [_engine.get() shell];

0 commit comments

Comments
 (0)