diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java index 7c013e0bf330c..609bd8b0fcfdb 100644 --- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java +++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.Typeface; +import android.graphics.fonts.Font; import android.graphics.fonts.FontFamily; import android.graphics.fonts.FontFileUtil; import android.graphics.fonts.FontManager; @@ -194,6 +195,13 @@ public final class FontManagerService extends IFontManager.Stub { } } + @Override + public void tryToCreateTypeface(File file) throws IOException { + Font font = new Font.Builder(file).build(); + FontFamily family = new FontFamily.Builder(font).build(); + new Typeface.CustomFallbackBuilder(family).build(); + } + private static ByteBuffer mmap(File file) throws IOException { try (FileInputStream in = new FileInputStream(file)) { FileChannel fileChannel = in.getChannel(); diff --git a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java index d5326055a7540..e74dac5b1d754 100644 --- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java +++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java @@ -68,6 +68,8 @@ final class UpdatableFontDir { String buildFontFileName(File file) throws IOException; long getRevision(File file) throws IOException; + + void tryToCreateTypeface(File file) throws IOException; } /** Interface to mock fs-verity in tests. */ @@ -372,6 +374,16 @@ final class UpdatableFontDir { "Failed to change mode to 711", e); } FontFileInfo fontFileInfo = validateFontFile(newFontFile); + + // Try to create Typeface and treat as failure something goes wrong. + try { + mParser.tryToCreateTypeface(fontFileInfo.getFile()); + } catch (IOException e) { + throw new SystemFontException( + FontManager.RESULT_ERROR_INVALID_FONT_FILE, + "Failed to create Typeface from file", e); + } + FontConfig fontConfig = getSystemFontConfig(); if (!addFileToMapIfSameOrNewer(fontFileInfo, fontConfig, false)) { throw new SystemFontException( diff --git a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java index 7b4803724180c..5caff3d01825f 100644 --- a/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java +++ b/services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java @@ -90,6 +90,10 @@ public final class UpdatableFontDirTest { String content = FileUtils.readTextFile(file, 100, ""); return Long.parseLong(content.split(",")[1]); } + + @Override + public void tryToCreateTypeface(File file) throws IOException { + } } // FakeFsverityUtil will successfully set up fake fs-verity if the signature is GOOD_SIGNATURE. @@ -717,6 +721,10 @@ public final class UpdatableFontDirTest { public long getRevision(File file) throws IOException { return 0; } + + @Override + public void tryToCreateTypeface(File file) throws IOException { + } }, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier); dir.loadFontFileMap(); @@ -751,6 +759,50 @@ public final class UpdatableFontDirTest { public long getRevision(File file) throws IOException { return 0; } + + @Override + public void tryToCreateTypeface(File file) throws IOException { + } + }, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier); + dir.loadFontFileMap(); + + try { + dir.update(Collections.singletonList(newFontUpdateRequest("foo.ttf,1,foo", + GOOD_SIGNATURE))); + fail("Expect SystemFontException"); + } catch (FontManagerService.SystemFontException e) { + assertThat(e.getErrorCode()) + .isEqualTo(FontManager.RESULT_ERROR_INVALID_FONT_FILE); + } + assertThat(dir.getPostScriptMap()).isEmpty(); + } + + @Test + public void installFontFile_failedToCreateTypeface() throws Exception { + FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil(); + FakeFontFileParser parser = new FakeFontFileParser(); + UpdatableFontDir dir = new UpdatableFontDir( + mUpdatableFontFilesDir, + new UpdatableFontDir.FontFileParser() { + @Override + public String getPostScriptName(File file) throws IOException { + return parser.getPostScriptName(file); + } + + @Override + public String buildFontFileName(File file) throws IOException { + return parser.buildFontFileName(file); + } + + @Override + public long getRevision(File file) throws IOException { + return parser.getRevision(file); + } + + @Override + public void tryToCreateTypeface(File file) throws IOException { + throw new IOException(); + } }, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier); dir.loadFontFileMap();