Setup default font manager after engine created, to improve startup performance (#18225)
diff --git a/lib/ui/text/font_collection.cc b/lib/ui/text/font_collection.cc
index 8d10708..c59dac7 100644
--- a/lib/ui/text/font_collection.cc
+++ b/lib/ui/text/font_collection.cc
@@ -47,8 +47,6 @@
FontCollection::FontCollection()
: collection_(std::make_shared<txt::FontCollection>()) {
- collection_->SetupDefaultFontManager();
-
dynamic_font_manager_ = sk_make_sp<txt::DynamicFontManager>();
collection_->SetDynamicFontManager(dynamic_font_manager_);
}
@@ -68,6 +66,10 @@
return collection_;
}
+void FontCollection::SetupDefaultFontManager() {
+ collection_->SetupDefaultFontManager();
+}
+
void FontCollection::RegisterFonts(
std::shared_ptr<AssetManager> asset_manager) {
std::unique_ptr<fml::Mapping> manifest_mapping =
diff --git a/lib/ui/text/font_collection.h b/lib/ui/text/font_collection.h
index 4e19e2a..48e0e1e 100644
--- a/lib/ui/text/font_collection.h
+++ b/lib/ui/text/font_collection.h
@@ -29,6 +29,8 @@
std::shared_ptr<txt::FontCollection> GetFontCollection() const;
+ void SetupDefaultFontManager();
+
void RegisterFonts(std::shared_ptr<AssetManager> asset_manager);
void RegisterTestFonts();
diff --git a/shell/common/engine.cc b/shell/common/engine.cc
index 4703411..9f03c92 100644
--- a/shell/common/engine.cc
+++ b/shell/common/engine.cc
@@ -90,6 +90,11 @@
return weak_factory_.GetWeakPtr();
}
+void Engine::SetupDefaultFontManager() {
+ TRACE_EVENT0("flutter", "Engine::SetupDefaultFontManager");
+ font_collection_.SetupDefaultFontManager();
+}
+
bool Engine::UpdateAssetManager(
std::shared_ptr<AssetManager> new_asset_manager) {
if (asset_manager_ == new_asset_manager) {
diff --git a/shell/common/engine.h b/shell/common/engine.h
index 0f5f071..5f970b3 100644
--- a/shell/common/engine.h
+++ b/shell/common/engine.h
@@ -364,6 +364,11 @@
[[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
/// `Engine::Run` and `Engine::Restart` as the asset manager is
diff --git a/shell/common/shell.cc b/shell/common/shell.cc
index fd5a581..99236e0 100644
--- a/shell/common/shell.cc
+++ b/shell/common/shell.cc
@@ -542,6 +542,14 @@
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 cb2d516..1493bf4 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 @@
});
}
+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 @@
"lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
.fnPtr = reinterpret_cast<void*>(&Init),
},
+ {
+ .name = "nativePrefetchDefaultFontManager",
+ .signature = "()V",
+ .fnPtr = reinterpret_cast<void*>(&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 6f55fce..b0d5ad9 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 @@
@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 bd50695..c57d8c8 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 @@
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();
}