diff --git a/shell/common/platform_view_service_protocol.cc b/shell/common/platform_view_service_protocol.cc index 8e9b295e2334d..39385d5496c74 100644 --- a/shell/common/platform_view_service_protocol.cc +++ b/shell/common/platform_view_service_protocol.cc @@ -128,6 +128,9 @@ void PlatformViewServiceProtocol::RegisterHook(bool running_precompiled_code) { } Dart_RegisterRootServiceRequestCallback(kRunInViewExtensionName, &RunInView, nullptr); + // [benchmark helper] Wait for the UI Thread to idle. + Dart_RegisterRootServiceRequestCallback(kFlushUIThreadTasksExtensionName, + &FlushUIThreadTasks, nullptr); } const char* PlatformViewServiceProtocol::kRunInViewExtensionName = @@ -202,11 +205,10 @@ bool PlatformViewServiceProtocol::ListViews(const char* method, intptr_t num_params, void* user_data, const char** json_object) { - // Ask the Shell for the list of platform views. This will run a task on - // the UI thread before returning. + // Ask the Shell for the list of platform views. Shell& shell = Shell::Shared(); std::vector platform_views; - shell.WaitForPlatformViewIds(&platform_views); + shell.GetPlatformViewIds(&platform_views); std::stringstream response; @@ -314,4 +316,32 @@ void PlatformViewServiceProtocol::ScreenshotGpuTask(SkBitmap* bitmap) { canvas->flush(); } +const char* PlatformViewServiceProtocol::kFlushUIThreadTasksExtensionName = + "_flutter.flushUIThreadTasks"; + +// This API should not be invoked by production code. +// It can potentially starve the service isolate if the main isolate pauses +// at a breakpoint or is in an infinite loop. +// +// It should be invoked from the VM Service and and blocks it until UI thread +// tasks are processed. +bool PlatformViewServiceProtocol::FlushUIThreadTasks(const char* method, + const char** param_keys, + const char** param_values, + intptr_t num_params, + void* user_data, + const char** json_object) { + ftl::AutoResetWaitableEvent latch; + blink::Threads::UI()->PostTask([&latch]() { + // This task is empty because we just need to synchronize this RPC with the + // UI Thread + latch.Signal(); + }); + + latch.Wait(); + + *json_object = strdup("{\"type\":\"Success\"}"); + return true; +} + } // namespace shell diff --git a/shell/common/platform_view_service_protocol.h b/shell/common/platform_view_service_protocol.h index 13a9cbae7c8e5..d0ad2ade489d3 100644 --- a/shell/common/platform_view_service_protocol.h +++ b/shell/common/platform_view_service_protocol.h @@ -20,6 +20,8 @@ class PlatformViewServiceProtocol { private: static const char* kRunInViewExtensionName; + // It should be invoked from the VM Service and and blocks it until previous + // UI thread tasks are processed. static bool RunInView(const char* method, const char** param_keys, const char** param_values, @@ -36,6 +38,8 @@ class PlatformViewServiceProtocol { const char** json_object); static const char* kScreenshotExtensionName; + // It should be invoked from the VM Service and and blocks it until previous + // GPU thread tasks are processed. static bool Screenshot(const char* method, const char** param_keys, const char** param_values, @@ -43,6 +47,20 @@ class PlatformViewServiceProtocol { void* user_data, const char** json_object); static void ScreenshotGpuTask(SkBitmap* bitmap); + + // This API should not be invoked by production code. + // It can potentially starve the service isolate if the main isolate pauses + // at a breakpoint or is in an infinite loop. + // + // It should be invoked from the VM Service and and blocks it until previous + // GPU thread tasks are processed. + static const char* kFlushUIThreadTasksExtensionName; + static bool FlushUIThreadTasks(const char* method, + const char** param_keys, + const char** param_values, + intptr_t num_params, + void* user_data, + const char** json_object); }; } // namespace shell diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 5231480de9157..5c791d45e630d 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -262,7 +262,7 @@ void Shell::GetPlatformViews( *platform_views = platform_views_; } -void Shell::WaitForPlatformViewIds( +void Shell::GetPlatformViewIds( std::vector* platform_view_ids) { std::lock_guard lk(platform_views_mutex_); for (auto it = platform_views_.begin(); it != platform_views_.end(); it++) { diff --git a/shell/common/shell.h b/shell/common/shell.h index 6e9022239d9c0..73ffd0e487b9e 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -44,7 +44,7 @@ class Shell { // List of PlatformViews. - // These APIs must only be accessed on UI thread. + // These APIs can be called from any thread. void AddPlatformView(const std::shared_ptr& platform_view); void PurgePlatformViews(); void GetPlatformViews( @@ -58,7 +58,7 @@ class Shell { // These APIs can be called from any thread. // Return the list of platform view ids at the time of this call. - void WaitForPlatformViewIds(std::vector* platform_view_ids); + void GetPlatformViewIds(std::vector* platform_view_ids); // Attempt to run a script inside a flutter view indicated by |view_id|. // Will set |view_existed| to true if the view was found and false otherwise.