Android Typeface.createFromFile(File) native crashes in production

Issue

Looking for suggestions for fixing this production crash.

Crashlytics and Play report that our app is crashing in a call to Typeface.createFromFile(File). I’m surprised to see a native callstack for this since we have the calling function wrapped in a try/catch:

suspend fun fetchAndSaveFontFamily(familyEnum: GlyphType, fontFile: File): FontFamily? =
    withContext(ioDispatcher) {
        val response = api.getFontFamily(familyEnum.value, FONT_API_VERSION)
        if (response.contentType() == FONT_TYPE.toMediaType()) {
            fontFile.outputStream().use { outputStream ->
                response.byteStream().use { inputStream ->
                    inputStream.copyTo(outputStream)
                }
            }
            FontFamily(Typeface.createFromFile(fontFile))
        } else {
            null
        }
    }

The top of the backtrace from Play is reported like this:

backtrace:
  #00  pc 0x0000000000539758  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (java.nio.DirectByteBuffer.getInt+152)
  #01  pc 0x00000000006fff30  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.graphics.fonts.FontFileUtil.analyzeStyle+464)
  #02  pc 0x00000000006fedc0  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.graphics.fonts.Font$Builder.build+128)
  #03  pc 0x00000000006f4de0  /data/misc/apexdata/com.android.art/dalvik-cache/arm64/boot.oat (android.graphics.Typeface$Builder.build+96)
  #04  pc 0x00000000005ba6b0  /apex/com.android.art/lib64/libart.so (nterp_helper+4016)
  #05  pc 0x0000000000469416  /system/framework/framework.jar (android.graphics.Typeface.createFromFile+10)
  #06  pc 0x00000000005b9734  /apex/com.android.art/lib64/libart.so (nterp_helper+52)
  #07  pc 0x0000000001131bb4  /data/app/~~hWuuZV7aOJ841iaRatSNZg==/onxmaps.offroad-gE35ozrMYNfogkMEA4aWsw==/oat/arm64/base.vdex (com.onxmaps.onxmaps.search.searchby.impl.glyph.SearchGlyphRepositoryImpl$fetchAndSaveFontFamily$2.invokeSuspend+184)

And I’ve correlated these with some Crashlytics reports since they occur in libft2.so

0
libft2.so
(Missing BuildId fd922ff846fe5ab8a3f4f4334985b34a)
1
libft2.so
(Missing BuildId fd922ff846fe5ab8a3f4f4334985b34a)
2
libft2.so
(Missing BuildId fd922ff846fe5ab8a3f4f4334985b34a)
3
libft2.so
(Missing BuildId fd922ff846fe5ab8a3f4f4334985b34a)
4
libft2.so
(Missing BuildId fd922ff846fe5ab8a3f4f4334985b34a)
5
libft2.so
(Missing BuildId fd922ff846fe5ab8a3f4f4334985b34a)
6
libhwui.so
(Missing BuildId db02c8d3ce41198e823c57fcb95d880e)
7
libhwui.so
(Missing BuildId db02c8d3ce41198e823c57fcb95d880e)

I haven’t established any data validity guarantees from the api font response, but I was expecting that the try/catch wrapper around this function would provide an adequate fallback.

Solution

fetchAndSaveFontFamily() is being called in a loop. I made some changes to prevent reentrant calls to FontFamily(Typeface.createFromFile(fontFile)) by applying a Mutex section. This seems to fix the issue.

Answered By – jchristof

Answer Checked By – Cary Denson (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *