diff --git a/lib/ui/text/font_collection.cc b/lib/ui/text/font_collection.cc index 8d1070852c391..c59dac720875d 100644 --- a/lib/ui/text/font_collection.cc +++ b/lib/ui/text/font_collection.cc @@ -47,8 +47,6 @@ void _LoadFontFromList(Dart_NativeArguments args) { FontCollection::FontCollection() : collection_(std::make_shared()) { - collection_->SetupDefaultFontManager(); - dynamic_font_manager_ = sk_make_sp(); collection_->SetDynamicFontManager(dynamic_font_manager_); } @@ -68,6 +66,10 @@ std::shared_ptr FontCollection::GetFontCollection() const { return collection_; } +void FontCollection::SetupDefaultFontManager() { + collection_->SetupDefaultFontManager(); +} + void FontCollection::RegisterFonts( std::shared_ptr asset_manager) { std::unique_ptr manifest_mapping = diff --git a/lib/ui/text/font_collection.h b/lib/ui/text/font_collection.h index 4e19e2a999776..48e0e1e49db06 100644 --- a/lib/ui/text/font_collection.h +++ b/lib/ui/text/font_collection.h @@ -29,6 +29,8 @@ class FontCollection { std::shared_ptr GetFontCollection() const; + void SetupDefaultFontManager(); + void RegisterFonts(std::shared_ptr asset_manager); void RegisterTestFonts(); diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 4703411376357..9f03c9200fd32 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -90,6 +90,11 @@ fml::WeakPtr Engine::GetWeakPtr() const { return weak_factory_.GetWeakPtr(); } +void Engine::SetupDefaultFontManager() { + TRACE_EVENT0("flutter", "Engine::SetupDefaultFontManager"); + font_collection_.SetupDefaultFontManager(); +} + bool Engine::UpdateAssetManager( std::shared_ptr new_asset_manager) { if (asset_manager_ == new_asset_manager) { diff --git a/shell/common/engine.h b/shell/common/engine.h index 0f5f0717220b1..5f970b3717701 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -363,6 +363,11 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { /// [[nodiscard]] bool Restart(RunConfiguration configuration); + //---------------------------------------------------------------------------- + /// @brief Setup default font manager according to specific platform. + /// + void SetupDefaultFontManager(); + //---------------------------------------------------------------------------- /// @brief Updates the asset manager referenced by the root isolate of a /// Flutter application. This happens implicitly in the call to diff --git a/shell/common/shell.cc b/shell/common/shell.cc index fd5a581647de8..99236e05cb50f 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -542,6 +542,14 @@ bool Shell::Setup(std::unique_ptr platform_view, weak_rasterizer_ = rasterizer_->GetWeakPtr(); weak_platform_view_ = platform_view_->GetWeakPtr(); + // Setup the time-consuming default font manager right after engine created. + fml::TaskRunner::RunNowOrPostTask(task_runners_.GetUITaskRunner(), + [engine = weak_engine_] { + if (engine) { + engine->SetupDefaultFontManager(); + } + }); + is_setup_ = true; vm_->GetServiceProtocol()->AddHandler(this, GetServiceProtocolDescription()); diff --git a/shell/platform/android/flutter_main.cc b/shell/platform/android/flutter_main.cc index cb2d51649aaeb..1493bf4f0d161 100644 --- a/shell/platform/android/flutter_main.cc +++ b/shell/platform/android/flutter_main.cc @@ -21,6 +21,7 @@ #include "flutter/shell/common/shell.h" #include "flutter/shell/common/switches.h" #include "third_party/dart/runtime/include/dart_tools_api.h" +#include "third_party/skia/include/core/SkFontMgr.h" namespace flutter { @@ -155,6 +156,11 @@ void FlutterMain::SetupObservatoryUriCallback(JNIEnv* env) { }); } +static void PrefetchDefaultFontManager(JNIEnv* env, jclass jcaller) { + // Initialize a singleton owned by Skia. + SkFontMgr::RefDefault(); +} + bool FlutterMain::Register(JNIEnv* env) { static const JNINativeMethod methods[] = { { @@ -163,6 +169,11 @@ bool FlutterMain::Register(JNIEnv* env) { "lang/String;Ljava/lang/String;Ljava/lang/String;J)V", .fnPtr = reinterpret_cast(&Init), }, + { + .name = "nativePrefetchDefaultFontManager", + .signature = "()V", + .fnPtr = reinterpret_cast(&PrefetchDefaultFontManager), + }, }; jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI"); diff --git a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java index 6f55fce248f72..b0d5ad9ba19e2 100644 --- a/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java +++ b/shell/platform/android/io/flutter/embedding/engine/FlutterJNI.java @@ -106,6 +106,13 @@ public static native void nativeInit( @NonNull String engineCachesPath, long initTimeMillis); + /** + * Prefetch the default font manager provided by SkFontMgr::RefDefault() which is a process-wide + * singleton owned by Skia. Note that, the first call to SkFontMgr::RefDefault() will take + * noticeable time, but later calls will return a reference to the preexisting font manager. + */ + public static native void nativePrefetchDefaultFontManager(); + // TODO(mattcarroll): add javadocs @UiThread public native boolean nativeGetIsSoftwareRenderingEnabled(); diff --git a/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java b/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java index bd506957289fe..c57d8c86b8374 100644 --- a/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java +++ b/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java @@ -144,6 +144,17 @@ public InitResult call() { System.loadLibrary("flutter"); + // Prefetch the default font manager as soon as possible on a background thread. + // It helps to reduce time cost of engine setup that blocks the platform thread. + Executors.newSingleThreadExecutor() + .execute( + new Runnable() { + @Override + public void run() { + FlutterJNI.nativePrefetchDefaultFontManager(); + } + }); + if (resourceExtractor != null) { resourceExtractor.waitForCompletion(); }