Sitelet https://github.com/flutter/flutter/pull/191841
Skip to content

Replace Shell::WaitForFirstFrame with an asynchronous API that matches the Shell threading model - #191841

Merged
auto-submit[bot] merged 2 commits into
flutter:masterfrom
jason-simmons:shell_wait_first_frame_async
Sep 1, 2026
Merged

auto-submit[bot] merged 2 commits into
flutter:masterfrom
jason-simmons:shell_wait_first_frame_async

Conversation

@jason-simmons

Copy link
Copy Markdown
Member

The Shell::WaitForFirstFrame API would block until the engine renders the first frame. This could potentially cause issues if the shell is destroyed while a thread is waiting within a call to WaitForFirstFrame.

This PR replaces WaitForFirstFrame with an AddFirstFrameCallback API that invokes a callback when the first frame has been rendered. If the shell is destroyed before the first frame, then the callback will never be executed.

See #190132

@github-actions github-actions Bot added platform-ios iOS applications specifically engine flutter/engine related. See also e: labels. team-ios Owned by iOS platform team labels Aug 26, 2026

@cbracken cbracken left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks really good.

Part of this is really similar to the hacked up local version I had. I had added a FlutterFirstFramewaiter class that tried to handle the cancellation relatively similarly to how it happens now (and cycling through them to cancel them all in destroyContext), but poking at this a bit more I think there might be a nicer solution that removes the need for all that and gets rid of the blocking (see my comment at the bottom).

// Clear any tasks waiting on first frame prior to destroying _shell.
if (_shell) {
_shell->CancelWaitForFirstFrame();
}

@cbracken cbracken Aug 31, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking back to the issue this was added for, what happens if we have someone waiting? It we destroy the engine while we're waiting, I'm assuming we'll block for up to 3 seconds on the main thread?

I think we can probably delete _firstFrameWaiters and the wait below altogether, then the waiter would just stick around in the background until timeout.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed _firstFrameWaiters and replaced its usage with the implementation in #191841 (comment)

callback:(void (^_Nonnull)(BOOL didTimeout))callback {
auto first_frame_event = std::make_shared<fml::AutoResetWaitableEvent>();

self.shell.AddFirstFrameCallback([weak_event = std::weak_ptr(first_frame_event)] {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.shell has an FML_DCHECK in it so I think if we call this before FlutterEngine run or during shutdown, the assertion would fail (or null dereference in non-unopt builds), so we should check shell.

- (flutter::Shell&)shell {
FML_DCHECK(_shell);
return *_shell;
}

Not sure what the right value to set didTimeOut is in that case... YES seems more like what I'd expect since NO suggests the first frame rendered and someone might act on that.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done (using #191841 (comment))

@cbracken cbracken Aug 31, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: With the change in destroyContext, nothing is cancelling these guys anymore so we should update the comment.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this

Comment thread engine/src/flutter/shell/common/shell.h Outdated

@cbracken cbracken Aug 31, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be deleted now.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this

@@ -529,14 +525,8 @@ class Shell final : public PlatformView::Delegate,
// waiting_for_first_frame_mutex_ in WaitForFirstFrame.
std::atomic<bool> waiting_for_first_frame_ = true;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/WaitForFirstFrame/AddFirstFrameCallback/

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


std::mutex waiting_for_first_frame_mutex_;
std::condition_variable waiting_for_first_frame_condition_;
std::vector<std::function<void()>> waiting_for_first_frame_callbacks_;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to leave the "guarded by waiting_for_first_frame_mutex_" comment to make it easier for future us to put two and two together.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

std::vector<std::function<void()>> callbacks;
{
std::scoped_lock lock(waiting_for_first_frame_mutex);
std::swap(waiting_for_first_frame_callbacks, callbacks);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonder if it would be useful to leave a comment here about the relationship between waiting_for_first_frame and waiting_for_first_frame_callbacks and specifically the ordering guarantees these need.

The fact that the atomic bool is outside the lock but the callbacks vector is inside it got me stopping and thinking for longer than I'd like to admit; specifically what could happen in between. I wonder if we should just move the bool inside the lock to avoid anyone having to think about it.

I'm pretty convinced it's fine as-is, if someone registers in the gap they'll see it's false and invoke immediately.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah - I considered changing waiting_for_first_frame_ to a simple bool that is guarded by waiting_for_first_frame_mutex_. But given that
Shell::OnAnimatorDraw is called on every frame, I decided to keep the existing atomic bool waiting_for_first_frame_ to minimize the per-frame cost.

Added a comment and moved the waiting_for_first_frame.store(false) write into the OnAnimatorDraw block that holds the waiting_for_first_frame_mutex_. That should make this clearer.

This works because waiting_for_first_frame_ is set to true when the shell launches, but after the first frame it is set to false and remains false until the shell is suspended and resumed.
Users of waiting_for_first_frame_callbacks_ will also access
waiting_for_first_frame_ while holding the waiting_for_first_frame_mutex_. But OnAnimatorDraw can check whether waiting_for_first_frame_ has become false
without acquiring the mutex.

Comment thread engine/src/flutter/shell/common/shell.h Outdated
/// GPU or UI thread, 'kDeadlineExceeded' if there is a timeout.
///
fml::Status WaitForFirstFrame(fml::TimeDelta timeout);
void AddFirstFrameCallback(std::function<void()> callback);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably state that any callbacks pending on teardown will never be invoked. Maybe worth mentioning that the callback may run on the raster thread so needs to be cheap.

consistency nit: The next frame callback uses fml::closure, which IIRC is just std::function<void()>. Doesn't bother me one way or another but noticed, since in my hacked-up attempt at this I went the other way. Up to you.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment.

I considered using fml::closure, but the recent trend in the engine seems to be towards replacing usage of FML APIs with standard library or Abseil APIs.

// Ensure CancelWaitForFirstFrame() correctly causes all tasks blocked on
// WaitForFirstFrame() to return kAborted.
//
// See: b/521830222

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is the only test coverage we had for this bug, we should probably replace it with something roughly equivalent that verifies safe shutdown. Something where we register a callback, destroy the shell, and asserting the closure never ran.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this test.

didTimeout = status.code() == fml::StatusCode::kDeadlineExceeded;
didTimeout = first_frame_event->WaitWithTimeout(waitTime);
dispatch_group_leave(firstFrameWaiters);
});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we could push this even further into async territory. What if when we register, we immediately kick off a timeout handler to fire on the main thread AND we register the completion handler (which will get called on the raster thread but post the callback back to the main thread) these guys then race each other and the winner grabs the completion handler to a local, nils it out to the other can't fire it, then invokes it.

The nice thing with this is we avoid the whole _firstFrameWaiters dispatch group and therefore avoid blocking the main thread for the timeout in destroyContext.

- (void)waitForFirstFrame:(NSTimeInterval)timeout
                 callback:(void (^_Nonnull)(BOOL didTimeout))callback {
  // Set up a completion handler that will nil itself out when it fires.
  __block void (^completion)(BOOL) = [callback copy];
  void (^complete)(BOOL) = ^(BOOL didTimeout) {
    if (completion) {
      void (^cb)(BOOL) = completion;
      completion = nil;
      cb(didTimeout);
    }
  };

  if (!_shell) {
    // No shell. Bail out since there'll never be a first frame.
    dispatch_async(dispatch_get_main_queue(), ^{
      complete(YES);
    });
    return;
  }

  // Register the first-frame callback and fire the timeout completion handler.
  // Both are scheduled on the main thread to guarantee ordering.
  // The winner nils out the completion handler so the loser is a no-op.
  _shell->AddFirstFrameCallback([complete] {
    dispatch_async(dispatch_get_main_queue(), ^{
      complete(NO);
    });
  });

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeout * NSEC_PER_SEC)),
                 dispatch_get_main_queue(), ^{
                   complete(YES);
                 });
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - that looks much cleaner! Replaced the timeout mechanism in FlutterEngine.waitForFirstFrame with this implementation.

@jason-simmons
jason-simmons marked this pull request as ready for review August 31, 2026 21:23
@jason-simmons
jason-simmons requested a review from a team as a code owner August 31, 2026 21:23
@jason-simmons jason-simmons added the CICD Run CI/CD label Aug 31, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request replaces the blocking WaitForFirstFrame mechanism in the Shell class with an asynchronous callback-based approach via AddFirstFrameCallback, updating associated unit tests and the iOS platform integration. Feedback on these changes identifies a potential deadlock or 30-second hang during engine destruction if the Shell is destroyed before the first frame is rendered, because the registered callback would be destroyed without signaling the waiting background thread.

Comment on lines 1570 to +1576
}
};

fml::TimeDelta waitTime = fml::TimeDelta::FromMilliseconds(timeout * 1000);
fml::Status status = strongSelf.shell.WaitForFirstFrame(waitTime);
didTimeout = status.code() == fml::StatusCode::kDeadlineExceeded;
dispatch_group_leave(firstFrameWaiters);
});
if (!_shell) {
// No shell. Bail out since there'll never be a first frame.
dispatch_async(dispatch_get_main_queue(), ^{
complete(YES);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If the Shell is destroyed before the first frame is rendered, the callback registered with AddFirstFrameCallback will be destroyed without being executed. Because nothing signals first_frame_event, the background thread waiting in first_frame_event->WaitWithTimeout(waitTime) (line 1593) will block for the entire timeout duration (which can be up to 30 seconds).

During engine destruction, destroyContext is called on the main thread and blocks waiting for all background waiters to finish:

dispatch_group_wait(_firstFrameWaiters, DISPATCH_TIME_FOREVER);

This will cause the main thread to freeze/deadlock for up to 30 seconds during app shutdown or engine destruction, leading to severe UI hangs or ANRs.

To prevent this, we can capture a std::shared_ptr with a custom deleter in the callback. If the callback is destroyed without being executed, the custom deleter will run and signal the event, immediately unblocking the background thread.

  auto first_frame_event = std::make_shared<fml::AutoResetWaitableEvent>();
  auto signal_on_destroy = std::shared_ptr<void>(nullptr, [first_frame_event](void*) {
    first_frame_event->Signal();
  });

  self.shell.AddFirstFrameCallback([weak_event = std::weak_ptr(first_frame_event), signal_on_destroy] {
    if (auto event = weak_event.lock()) {
      event->Signal();
    }
  });

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is referring to an obsolete version of the PR. _firstFrameWaiters and first_frame_event have been removed.

…s the Shell threading model

The Shell::WaitForFirstFrame API would block until the engine renders the first
frame.  This could potentially cause issues if the shell is destroyed while a
thread is waiting within a call to WaitForFirstFrame.

This PR replaces WaitForFirstFrame with an AddFirstFrameCallback API that
invokes a callback when the first frame has been rendered.  If the shell is
destroyed before the first frame, then the callback will never be executed.

See flutter#190132
@jason-simmons
jason-simmons force-pushed the shell_wait_first_frame_async branch from 261da90 to 967cb15 Compare September 1, 2026 01:26

@cbracken cbracken left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM stamp from a Japanese personal seal

I patched this in locally and created an app with a configurable RenderBinding.deferFirstFrame so I could test delivery before the timeout (~2900ms), after it (5000ms), and right at the boundary (2950 ~ 2990 ms). I stuck a .well-known/apple-app-site-association on a personal domain for testing this.

Everything looks good. I also tested the existing version and one thing I noticed is this performs a little better right at the boundary; I actually had to push the first frame delay by a few milliseconds to get it to timeout with the new code.

This is a really nice improvement. Thanks so much for landing this.

@jason-simmons jason-simmons added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 1, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Sep 1, 2026
Merged via the queue into flutter:master with commit 6603e14 Sep 1, 2026
23 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 1, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Sep 4, 2026
flutter/flutter@0cbd1a4...70797e1

2026-09-02 bkonyi@google.com [analysis] Upgrade package:analyzer to 14.3.0 and enable custom plugin compilation (flutter/flutter#191590)
2026-09-02 engine-flutter-autoroll@skia.org Roll Dart SDK from d8d7869d8031 to 9a8fbde80f6c (1 revision) (flutter/flutter#192179)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from dec311244db4 to ae22da2e8308 (1 revision) (flutter/flutter#192177)
2026-09-02 bkonyi@google.com [tool] Migrate DoctorCommand to modular dependency injection (flutter/flutter#190758)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 482b7e285244 to dec311244db4 (3 revisions) (flutter/flutter#192161)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 28447e9fb8d5 to 482b7e285244 (3 revisions) (flutter/flutter#192157)
2026-09-02 34465683+rkishan516@users.noreply.github.com feat: Add placeholder to DecorationImage (flutter/flutter#191528)
2026-09-02 papmodern14@gmail.com [Android] Do not schedule engine frames on a detached FlutterJNI (flutter/flutter#191204)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 3a242fb7cdb3 to 28447e9fb8d5 (1 revision) (flutter/flutter#192145)
2026-09-02 engine-flutter-autoroll@skia.org Roll Dart SDK from 9164def35347 to d8d7869d8031 (2 revisions) (flutter/flutter#192144)
2026-09-02 74458687+anazr9@users.noreply.github.com Add FadeInImageTransition.fadeInOver to fade the image in over the placeholder (flutter/flutter#186246)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 63d13ec4df6d to 3a242fb7cdb3 (9 revisions) (flutter/flutter#192138)
2026-09-02 bkonyi@google.com [flutter_tools] Add --no-plugins flag and disable plugins for benchmark (flutter/flutter#192129)
2026-09-02 bkonyi@google.com [tool] Migrate ChannelCommand to modular dependency injection (flutter/flutter#190751)
2026-09-01 46920873+gabrimatic@users.noreply.github.com Add mouseCursor to RawScrollbar (flutter/flutter#185750)
2026-09-01 ksanaullah383.khan@gmail.com Fix self-comparison and assert typos in TestSemantics (flutter/flutter#191938)
2026-09-01 robert.ancell@canonical.com [Linux] Wait for frames to be rendered before using them in another context (flutter/flutter#192094)
2026-09-01 jacksongardner@google.com [wimp] Turn on multithreading for wimp. (flutter/flutter#191747)
2026-09-01 engine-flutter-autoroll@skia.org Roll Skia from 3911a1fe7f7a to 63d13ec4df6d (6 revisions) (flutter/flutter#192125)
2026-09-01 jason-simmons@users.noreply.github.com Remove the redundant flutter/shell/platform/android:robolectric_tests build target (flutter/flutter#192117)
2026-09-01 AfzalivE@users.noreply.github.com [iOS] Preserve semantics parents after reparenting (flutter/flutter#189686)
2026-09-01 bkonyi@google.com [flutter_tools] Report preview reload timing analytics in LspPreviewDetector (flutter/flutter#192120)
2026-09-01 bkonyi@google.com [flutter_tools] Implement Templates slice and flutter create integration (flutter/flutter#191748)
2026-09-01 louisehsu@google.com Uiscene migrate add2app hosts (flutter/flutter#191847)
2026-09-01 engine-flutter-autoroll@skia.org Roll Packages from d642322 to 7a7912f (8 revisions) (flutter/flutter#192119)
2026-09-01 zhongliu88889@gmail.com [web] Anchor flt-semantics-host at 0,0 to fix WebKit semantics offset (flutter/flutter#190486)
2026-09-01 jason-simmons@users.noreply.github.com Replace Shell::WaitForFirstFrame with an asynchronous API that matches the Shell threading model (flutter/flutter#191841)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
…r#12727)

flutter/flutter@0cbd1a4...70797e1

2026-09-02 bkonyi@google.com [analysis] Upgrade package:analyzer to 14.3.0 and enable custom plugin compilation (flutter/flutter#191590)
2026-09-02 engine-flutter-autoroll@skia.org Roll Dart SDK from d8d7869d8031 to 9a8fbde80f6c (1 revision) (flutter/flutter#192179)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from dec311244db4 to ae22da2e8308 (1 revision) (flutter/flutter#192177)
2026-09-02 bkonyi@google.com [tool] Migrate DoctorCommand to modular dependency injection (flutter/flutter#190758)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 482b7e285244 to dec311244db4 (3 revisions) (flutter/flutter#192161)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 28447e9fb8d5 to 482b7e285244 (3 revisions) (flutter/flutter#192157)
2026-09-02 34465683+rkishan516@users.noreply.github.com feat: Add placeholder to DecorationImage (flutter/flutter#191528)
2026-09-02 papmodern14@gmail.com [Android] Do not schedule engine frames on a detached FlutterJNI (flutter/flutter#191204)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 3a242fb7cdb3 to 28447e9fb8d5 (1 revision) (flutter/flutter#192145)
2026-09-02 engine-flutter-autoroll@skia.org Roll Dart SDK from 9164def35347 to d8d7869d8031 (2 revisions) (flutter/flutter#192144)
2026-09-02 74458687+anazr9@users.noreply.github.com Add FadeInImageTransition.fadeInOver to fade the image in over the placeholder (flutter/flutter#186246)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 63d13ec4df6d to 3a242fb7cdb3 (9 revisions) (flutter/flutter#192138)
2026-09-02 bkonyi@google.com [flutter_tools] Add --no-plugins flag and disable plugins for benchmark (flutter/flutter#192129)
2026-09-02 bkonyi@google.com [tool] Migrate ChannelCommand to modular dependency injection (flutter/flutter#190751)
2026-09-01 46920873+gabrimatic@users.noreply.github.com Add mouseCursor to RawScrollbar (flutter/flutter#185750)
2026-09-01 ksanaullah383.khan@gmail.com Fix self-comparison and assert typos in TestSemantics (flutter/flutter#191938)
2026-09-01 robert.ancell@canonical.com [Linux] Wait for frames to be rendered before using them in another context (flutter/flutter#192094)
2026-09-01 jacksongardner@google.com [wimp] Turn on multithreading for wimp. (flutter/flutter#191747)
2026-09-01 engine-flutter-autoroll@skia.org Roll Skia from 3911a1fe7f7a to 63d13ec4df6d (6 revisions) (flutter/flutter#192125)
2026-09-01 jason-simmons@users.noreply.github.com Remove the redundant flutter/shell/platform/android:robolectric_tests build target (flutter/flutter#192117)
2026-09-01 AfzalivE@users.noreply.github.com [iOS] Preserve semantics parents after reparenting (flutter/flutter#189686)
2026-09-01 bkonyi@google.com [flutter_tools] Report preview reload timing analytics in LspPreviewDetector (flutter/flutter#192120)
2026-09-01 bkonyi@google.com [flutter_tools] Implement Templates slice and flutter create integration (flutter/flutter#191748)
2026-09-01 louisehsu@google.com Uiscene migrate add2app hosts (flutter/flutter#191847)
2026-09-01 engine-flutter-autoroll@skia.org Roll Packages from d642322 to 7a7912f (8 revisions) (flutter/flutter#192119)
2026-09-01 zhongliu88889@gmail.com [web] Anchor flt-semantics-host at 0,0 to fix WebKit semantics offset (flutter/flutter#190486)
2026-09-01 jason-simmons@users.noreply.github.com Replace Shell::WaitForFirstFrame with an asynchronous API that matches the Shell threading model (flutter/flutter#191841)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/packages that referenced this pull request Sep 9, 2026
…r#12727)

flutter/flutter@0cbd1a4...70797e1

2026-09-02 bkonyi@google.com [analysis] Upgrade package:analyzer to 14.3.0 and enable custom plugin compilation (flutter/flutter#191590)
2026-09-02 engine-flutter-autoroll@skia.org Roll Dart SDK from d8d7869d8031 to 9a8fbde80f6c (1 revision) (flutter/flutter#192179)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from dec311244db4 to ae22da2e8308 (1 revision) (flutter/flutter#192177)
2026-09-02 bkonyi@google.com [tool] Migrate DoctorCommand to modular dependency injection (flutter/flutter#190758)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 482b7e285244 to dec311244db4 (3 revisions) (flutter/flutter#192161)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 28447e9fb8d5 to 482b7e285244 (3 revisions) (flutter/flutter#192157)
2026-09-02 34465683+rkishan516@users.noreply.github.com feat: Add placeholder to DecorationImage (flutter/flutter#191528)
2026-09-02 papmodern14@gmail.com [Android] Do not schedule engine frames on a detached FlutterJNI (flutter/flutter#191204)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 3a242fb7cdb3 to 28447e9fb8d5 (1 revision) (flutter/flutter#192145)
2026-09-02 engine-flutter-autoroll@skia.org Roll Dart SDK from 9164def35347 to d8d7869d8031 (2 revisions) (flutter/flutter#192144)
2026-09-02 74458687+anazr9@users.noreply.github.com Add FadeInImageTransition.fadeInOver to fade the image in over the placeholder (flutter/flutter#186246)
2026-09-02 engine-flutter-autoroll@skia.org Roll Skia from 63d13ec4df6d to 3a242fb7cdb3 (9 revisions) (flutter/flutter#192138)
2026-09-02 bkonyi@google.com [flutter_tools] Add --no-plugins flag and disable plugins for benchmark (flutter/flutter#192129)
2026-09-02 bkonyi@google.com [tool] Migrate ChannelCommand to modular dependency injection (flutter/flutter#190751)
2026-09-01 46920873+gabrimatic@users.noreply.github.com Add mouseCursor to RawScrollbar (flutter/flutter#185750)
2026-09-01 ksanaullah383.khan@gmail.com Fix self-comparison and assert typos in TestSemantics (flutter/flutter#191938)
2026-09-01 robert.ancell@canonical.com [Linux] Wait for frames to be rendered before using them in another context (flutter/flutter#192094)
2026-09-01 jacksongardner@google.com [wimp] Turn on multithreading for wimp. (flutter/flutter#191747)
2026-09-01 engine-flutter-autoroll@skia.org Roll Skia from 3911a1fe7f7a to 63d13ec4df6d (6 revisions) (flutter/flutter#192125)
2026-09-01 jason-simmons@users.noreply.github.com Remove the redundant flutter/shell/platform/android:robolectric_tests build target (flutter/flutter#192117)
2026-09-01 AfzalivE@users.noreply.github.com [iOS] Preserve semantics parents after reparenting (flutter/flutter#189686)
2026-09-01 bkonyi@google.com [flutter_tools] Report preview reload timing analytics in LspPreviewDetector (flutter/flutter#192120)
2026-09-01 bkonyi@google.com [flutter_tools] Implement Templates slice and flutter create integration (flutter/flutter#191748)
2026-09-01 louisehsu@google.com Uiscene migrate add2app hosts (flutter/flutter#191847)
2026-09-01 engine-flutter-autoroll@skia.org Roll Packages from d642322 to 7a7912f (8 revisions) (flutter/flutter#192119)
2026-09-01 zhongliu88889@gmail.com [web] Anchor flt-semantics-host at 0,0 to fix WebKit semantics offset (flutter/flutter#190486)
2026-09-01 jason-simmons@users.noreply.github.com Replace Shell::WaitForFirstFrame with an asynchronous API that matches the Shell threading model (flutter/flutter#191841)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
pull Bot pushed a commit to phamminhphuc/flutter that referenced this pull request Sep 29, 2026
In flutter#191841, we replaced `Shell::WaitForFirstFrame` with
`Shell::AddFirstFrameCallback` but didn't update the test names to match
the new API.

In particular, `WaitForFirstFrameTimeout` no longer tested that any
caller-visible timeout fired, since the new API manages the timeout
internally. The test now just verifies the first frame callback doesn't
fire when no frame has rendered.

Just naming changes, no semantic changes.

Issue: b/521830222


## Pre-launch Checklist

- [X] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [X] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [X] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [X] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [X] I signed the [CLA].
- [X] I listed at least one issue that this PR fixes in the description
above.
- [X] I updated/added relevant in-code documentation (doc comments with
`///`).
- [X] If this PR introduces a new feature or capability, I created and
linked a website documentation issue or PR in [flutter/website] (or
verified none is needed).
- [X] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [X] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [X] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[flutter/website]: https://github.com/flutter/website
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-ios iOS applications specifically team-ios Owned by iOS platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants