未验证 提交 0dc86cda 编写于 作者: C Chinmay Garde 提交者: GitHub

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 https://github.com/flutter/flutter/issues/55969
(This issue has a clear reproducible test case and was used as the basis for
verification.)
Fixes https://github.com/flutter/flutter/issues/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.
上级 a15bc1be
......@@ -848,9 +848,15 @@ static flutter::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch)
[self updateViewportPadding];
[self updateViewportMetrics];
// There is no guarantee that UIKit will layout subviews when the application is active. Creating
// the surface when inactive will cause GPU accesses from the background. Only wait for the first
// frame to render when the application is actually active.
bool applicationIsActive =
[UIApplication sharedApplication].applicationState == UIApplicationStateActive;
// This must run after updateViewportMetrics so that the surface creation tasks are queued after
// the viewport metrics update tasks.
if (firstViewBoundsUpdate) {
if (firstViewBoundsUpdate && applicationIsActive) {
[self surfaceUpdated:YES];
flutter::Shell& shell = [_engine.get() shell];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册