diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp index a2964d6627a1f..10c80774fd165 100644 --- a/libs/hwui/jni/Typeface.cpp +++ b/libs/hwui/jni/Typeface.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#define ATRACE_TAG ATRACE_TAG_VIEW #include "FontUtils.h" #include "GraphicsJNI.h" #include "fonts/Font.h" @@ -25,8 +26,13 @@ #include #include #include +#include + +#include +#include using namespace android; +using android::uirenderer::TraceUtils; static inline Typeface* toTypeface(jlong ptr) { return reinterpret_cast(ptr); @@ -149,6 +155,20 @@ static void Typeface_registerGenericFamily(JNIEnv *env, jobject, jstring familyN toTypeface(ptr)->fFontCollection); } +static sk_sp makeSkDataCached(const std::string& path) { + // We don't clear cache as Typeface objects created by Typeface_readTypefaces() will be stored + // in a static field and will not be garbage collected. + static std::unordered_map> cache; + static std::mutex mutex; + ALOG_ASSERT(!path.empty()); + std::lock_guard lock{mutex}; + sk_sp& entry = cache[path]; + if (entry.get() == nullptr) { + entry = SkData::MakeFromFileName(path.c_str()); + } + return entry; +} + static std::function()> readMinikinFontSkia( minikin::BufferReader* reader) { std::string_view fontPath = reader->readString(); @@ -158,8 +178,9 @@ static std::function()> readMinikinFontSki std::tie(axesPtr, axesCount) = reader->readArray(); return [fontPath, fontIndex, axesPtr, axesCount]() -> std::shared_ptr { std::string path(fontPath.data(), fontPath.size()); - sk_sp data = SkData::MakeFromFileName(path.c_str()); - if (data == nullptr) { + ATRACE_FORMAT("Loading font %s", path.c_str()); + sk_sp data = makeSkDataCached(path); + if (data.get() == nullptr) { // This may happen if: // 1. When the process failed to open the file (e.g. invalid path or permission). // 2. When the process failed to map the file (e.g. hitting max_map_count limit).