Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9040d23f authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Use correct extension based on file contents.

Bug: 180364535
Test: atest com.android.server.graphics.fonts
Test: atest ApkVerityTest
Test: atest UpdatableSystemFontTest
Test: atest FontManagerTest
Change-Id: Ia0e0822105868e47e7356a120ce20d8bf5d1e106
parent 1c2df9c5
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -183,6 +183,23 @@ public class FontFileUtil {
        return nIsPostScriptType1Font(buffer, index);
    }

    /**
     * Analyze the file content and returns 1 if the font file is an OpenType collection file, 0 if
     * the font file is a OpenType font file, -1 otherwise.
     */
    public static int isCollectionFont(@NonNull ByteBuffer buffer) {
        ByteBuffer copied = buffer.slice();
        copied.order(ByteOrder.BIG_ENDIAN);
        int magicNumber = copied.getInt(0);
        if (magicNumber == TTC_TAG) {
            return 1;
        } else if (magicNumber == SFNT_VERSION_1 || magicNumber == SFNT_VERSION_OTTO) {
            return 0;
        } else {
            return -1;
        }
    }

    @FastNative
    private static native long nGetFontRevision(@NonNull ByteBuffer buffer,
            @IntRange(from = 0) int index);
+17 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.os.SharedMemory;
import android.os.ShellCallback;
import android.system.ErrnoException;
import android.text.FontConfig;
import android.text.TextUtils;
import android.util.AndroidException;
import android.util.IndentingPrintWriter;
import android.util.Slog;
@@ -148,10 +149,24 @@ public final class FontManagerService extends IFontManager.Stub {

    /* package */ static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
        @Override
        public String getPostScriptName(File file) throws IOException {
        public String getCanonicalFileName(File file) throws IOException {
            ByteBuffer buffer = mmap(file);
            try {
                return FontFileUtil.getPostScriptName(buffer, 0);
                String psName = FontFileUtil.getPostScriptName(buffer, 0);
                int isType1Font = FontFileUtil.isPostScriptType1Font(buffer, 0);
                int isCollection = FontFileUtil.isCollectionFont(buffer);

                if (TextUtils.isEmpty(psName) || isType1Font == -1 || isCollection == -1) {
                    return null;
                }

                String extension;
                if (isCollection == 1) {
                    extension = isType1Font == 1 ? ".otc" : ".ttc";
                } else {
                    extension = isType1Font == 1 ? ".otf" : ".ttf";
                }
                return psName + extension;
            } finally {
                NioUtils.freeDirectBuffer(buffer);
            }
+38 −18
Original line number Diff line number Diff line
@@ -56,14 +56,12 @@ final class UpdatableFontDir {

    private static final String TAG = "UpdatableFontDir";
    private static final String RANDOM_DIR_PREFIX = "~~";
    // TODO: Support .otf
    private static final String ALLOWED_EXTENSION = ".ttf";

    private static final String CONFIG_XML_FILE = "/data/fonts/config/config.xml";

    /** Interface to mock font file access in tests. */
    interface FontFileParser {
        String getPostScriptName(File file) throws IOException;
        String getCanonicalFileName(File file) throws IOException;

        long getRevision(File file) throws IOException;
    }
@@ -321,20 +319,20 @@ final class UpdatableFontDir {
                        FontManager.RESULT_ERROR_VERIFICATION_FAILURE,
                        "Failed to setup fs-verity.", e);
            }
            String postScriptName;
            String canonicalFileName;
            try {
                postScriptName = mParser.getPostScriptName(tempNewFontFile);
                canonicalFileName = mParser.getCanonicalFileName(tempNewFontFile);
            } catch (IOException e) {
                throw new SystemFontException(
                        FontManager.RESULT_ERROR_INVALID_FONT_FILE,
                        "Failed to read PostScript name from font file", e);
            }
            if (postScriptName == null) {
            if (canonicalFileName == null) {
                throw new SystemFontException(
                        FontManager.RESULT_ERROR_INVALID_FONT_NAME,
                        "Failed to read PostScript name from font file");
            }
            File newFontFile = new File(newDir, postScriptName + ALLOWED_EXTENSION);
            File newFontFile = new File(newDir, canonicalFileName);
            if (!mFsverityUtil.rename(tempNewFontFile, newFontFile)) {
                throw new SystemFontException(
                        FontManager.RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE,
@@ -380,20 +378,38 @@ final class UpdatableFontDir {
        return dir;
    }

    private FontFileInfo lookupFontFileInfo(File file) {
        String name = file.getName();

        if (!name.endsWith(".ttf") && !name.endsWith(".otf") && !name.endsWith(".ttc")
                && !name.endsWith(".otc")) {
            return null;
        }
        String key = name.substring(0, name.length() - 4);
        return mFontFileInfoMap.get(key);
    }

    private void putFontFileInfo(FontFileInfo info) {
        String name = info.getFile().getName();
        // The file name in FontFileInfo is already validated. Thus, just strip last 4 chars.
        String key = name.substring(0, name.length() - 4);
        mFontFileInfoMap.put(key, info);
    }

    /**
     * Add the given {@link FontFileInfo} to {@link #mFontFileInfoMap} if its font revision is
     * higher than the currently used font file (either in {@link #mFontFileInfoMap} or {@link
     * #mPreinstalledFontDirs}).
     */
    private boolean addFileToMapIfNewer(FontFileInfo fontFileInfo, boolean deleteOldFile) {
        String name = fontFileInfo.getFile().getName();
        FontFileInfo existingInfo = mFontFileInfoMap.get(name);
        FontFileInfo existingInfo = lookupFontFileInfo(fontFileInfo.getFile());
        final boolean shouldAddToMap;
        if (existingInfo == null) {
            // We got a new updatable font. We need to check if it's newer than preinstalled fonts.
            // Note that getPreinstalledFontRevision() returns -1 if there is no preinstalled font
            // with 'name'.
            shouldAddToMap = getPreinstalledFontRevision(name) < fontFileInfo.getRevision();
            long preInstalledRev = getPreinstalledFontRevision(fontFileInfo.getFile().getName());
            shouldAddToMap = preInstalledRev < fontFileInfo.getRevision();
        } else {
            shouldAddToMap = existingInfo.getRevision() < fontFileInfo.getRevision();
        }
@@ -401,7 +417,7 @@ final class UpdatableFontDir {
            if (deleteOldFile && existingInfo != null) {
                FileUtils.deleteContentsAndDir(existingInfo.getRandomizedFontDir());
            }
            mFontFileInfoMap.put(name, fontFileInfo);
            putFontFileInfo(fontFileInfo);
        } else {
            if (deleteOldFile) {
                FileUtils.deleteContentsAndDir(fontFileInfo.getRandomizedFontDir());
@@ -464,15 +480,18 @@ final class UpdatableFontDir {
     */
    private boolean validateFontFileName(File file) {
        String fileName = file.getName();
        String postScriptName = getPostScriptName(file);
        return (postScriptName + ALLOWED_EXTENSION).equals(fileName);
        String canonicalFileName = getCanonicalFileName(file);
        if (canonicalFileName == null) {
            return false;
        }
        return canonicalFileName.equals(fileName);
    }

    /** Returns the PostScript name of the given font file, or null. */
    @Nullable
    private String getPostScriptName(File file) {
    private String getCanonicalFileName(File file) {
        try {
            return mParser.getPostScriptName(file);
            return mParser.getCanonicalFileName(file);
        } catch (IOException e) {
            Slog.e(TAG, "Failed to read font file", e);
            return null;
@@ -514,7 +533,7 @@ final class UpdatableFontDir {
        List<FontConfig.Font> fontList = fontFamily.getFontList();
        for (int i = 0; i < fontList.size(); i++) {
            FontConfig.Font font = fontList.get(i);
            FontFileInfo info = mFontFileInfoMap.get(font.getFile().getName());
            FontFileInfo info = lookupFontFileInfo(font.getFile());
            if (info == null) {
                return null;
            }
@@ -537,8 +556,9 @@ final class UpdatableFontDir {

    Map<String, File> getFontFileMap() {
        Map<String, File> map = new ArrayMap<>();
        for (Map.Entry<String, FontFileInfo> entry : mFontFileInfoMap.entrySet()) {
            map.put(entry.getKey(), entry.getValue().getFile());
        for (int i = 0; i < mFontFileInfoMap.size(); ++i) {
            File file = mFontFileInfoMap.valueAt(i).getFile();
            map.put(file.getName(), file);
        }
        return map;
    }
+53 −46
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ public final class UpdatableFontDirTest {
     */
    private static class FakeFontFileParser implements UpdatableFontDir.FontFileParser {
        @Override
        public String getPostScriptName(File file) throws IOException {
        public String getCanonicalFileName(File file) throws IOException {
            String content = FileUtils.readTextFile(file, 100, "");
            return content.split(",")[0];
        }
@@ -160,10 +160,10 @@ public final class UpdatableFontDirTest {
        assertThat(dirForPreparation.getSystemFontConfig().getLastModifiedTimeMillis())
                .isEqualTo(expectedModifiedDate);
        dirForPreparation.update(Arrays.asList(
                newFontUpdateRequest("foo,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,2", GOOD_SIGNATURE),
                newFontUpdateRequest("foo,3", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,4", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,2", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,3", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,4", GOOD_SIGNATURE),
                newAddFontFamilyRequest("<family name='foobar'>"
                        + "  <font>foo.ttf</font>"
                        + "  <font>bar.ttf</font>"
@@ -214,10 +214,10 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dirForPreparation.loadFontFileMap();
        dirForPreparation.update(Arrays.asList(
                newFontUpdateRequest("foo,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,2", GOOD_SIGNATURE),
                newFontUpdateRequest("foo,3", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,4", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,2", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,3", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,4", GOOD_SIGNATURE),
                newAddFontFamilyRequest("<family name='foobar'>"
                        + "  <font>foo.ttf</font>"
                        + "  <font>bar.ttf</font>"
@@ -246,10 +246,10 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dirForPreparation.loadFontFileMap();
        dirForPreparation.update(Arrays.asList(
                newFontUpdateRequest("foo,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,2", GOOD_SIGNATURE),
                newFontUpdateRequest("foo,3", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,4", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,2", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,3", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,4", GOOD_SIGNATURE),
                newAddFontFamilyRequest("<family name='foobar'>"
                        + "  <font>foo.ttf</font>"
                        + "  <font>bar.ttf</font>"
@@ -279,10 +279,10 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dirForPreparation.loadFontFileMap();
        dirForPreparation.update(Arrays.asList(
                newFontUpdateRequest("foo,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,2", GOOD_SIGNATURE),
                newFontUpdateRequest("foo,3", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,4", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,2", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,3", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,4", GOOD_SIGNATURE),
                newAddFontFamilyRequest("<family name='foobar'>"
                        + "  <font>foo.ttf</font>"
                        + "  <font>bar.ttf</font>"
@@ -332,14 +332,14 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dirForPreparation.loadFontFileMap();
        dirForPreparation.update(Arrays.asList(
                newFontUpdateRequest("foo,1", GOOD_SIGNATURE),
                newFontUpdateRequest("foo.ttf,1", GOOD_SIGNATURE),
                newAddFontFamilyRequest("<family name='foobar'>"
                        + "  <font>foo.ttf</font>"
                        + "</family>")));
        try {
            dirForPreparation.update(Arrays.asList(
                    newFontUpdateRequest("foo,2", GOOD_SIGNATURE),
                    newFontUpdateRequest("bar,2", "Invalid signature"),
                    newFontUpdateRequest("foo.ttf,2", GOOD_SIGNATURE),
                    newFontUpdateRequest("bar.ttf,2", "Invalid signature"),
                    newAddFontFamilyRequest("<family name='foobar'>"
                            + "  <font>foo.ttf</font>"
                            + "  <font>bar.ttf</font>"
@@ -372,7 +372,7 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dir.loadFontFileMap();

        dir.update(Collections.singletonList(newFontUpdateRequest("test,1", GOOD_SIGNATURE)));
        dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1", GOOD_SIGNATURE)));
        assertThat(dir.getFontFileMap()).containsKey("test.ttf");
        assertThat(parser.getRevision(dir.getFontFileMap().get("test.ttf"))).isEqualTo(1);
        File fontFile = dir.getFontFileMap().get("test.ttf");
@@ -390,9 +390,9 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dir.loadFontFileMap();

        dir.update(Collections.singletonList(newFontUpdateRequest("test,1", GOOD_SIGNATURE)));
        dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1", GOOD_SIGNATURE)));
        Map<String, File> mapBeforeUpgrade = dir.getFontFileMap();
        dir.update(Collections.singletonList(newFontUpdateRequest("test,2", GOOD_SIGNATURE)));
        dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,2", GOOD_SIGNATURE)));
        assertThat(dir.getFontFileMap()).containsKey("test.ttf");
        assertThat(parser.getRevision(dir.getFontFileMap().get("test.ttf"))).isEqualTo(2);
        assertThat(mapBeforeUpgrade).containsKey("test.ttf");
@@ -409,9 +409,10 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dir.loadFontFileMap();

        dir.update(Collections.singletonList(newFontUpdateRequest("test,2", GOOD_SIGNATURE)));
        dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,2", GOOD_SIGNATURE)));
        try {
            dir.update(Collections.singletonList(newFontUpdateRequest("test,1", GOOD_SIGNATURE)));
            dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1",
                    GOOD_SIGNATURE)));
            fail("Expect SystemFontException");
        } catch (FontManagerService.SystemFontException e) {
            assertThat(e.getErrorCode()).isEqualTo(FontManager.RESULT_ERROR_DOWNGRADING);
@@ -430,8 +431,8 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dir.loadFontFileMap();

        dir.update(Collections.singletonList(newFontUpdateRequest("foo,1", GOOD_SIGNATURE)));
        dir.update(Collections.singletonList(newFontUpdateRequest("bar,2", GOOD_SIGNATURE)));
        dir.update(Collections.singletonList(newFontUpdateRequest("foo.ttf,1", GOOD_SIGNATURE)));
        dir.update(Collections.singletonList(newFontUpdateRequest("bar.ttf,2", GOOD_SIGNATURE)));
        assertThat(dir.getFontFileMap()).containsKey("foo.ttf");
        assertThat(parser.getRevision(dir.getFontFileMap().get("foo.ttf"))).isEqualTo(1);
        assertThat(dir.getFontFileMap()).containsKey("bar.ttf");
@@ -448,8 +449,8 @@ public final class UpdatableFontDirTest {
        dir.loadFontFileMap();

        dir.update(Arrays.asList(
                newFontUpdateRequest("foo,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar,2", GOOD_SIGNATURE)));
                newFontUpdateRequest("foo.ttf,1", GOOD_SIGNATURE),
                newFontUpdateRequest("bar.ttf,2", GOOD_SIGNATURE)));
        assertThat(dir.getFontFileMap()).containsKey("foo.ttf");
        assertThat(parser.getRevision(dir.getFontFileMap().get("foo.ttf"))).isEqualTo(1);
        assertThat(dir.getFontFileMap()).containsKey("bar.ttf");
@@ -467,7 +468,8 @@ public final class UpdatableFontDirTest {

        try {
            dir.update(
                    Collections.singletonList(newFontUpdateRequest("test,1", "Invalid signature")));
                    Collections.singletonList(newFontUpdateRequest("test.ttf,1",
                            "Invalid signature")));
            fail("Expect SystemFontException");
        } catch (FontManagerService.SystemFontException e) {
            assertThat(e.getErrorCode())
@@ -480,14 +482,15 @@ public final class UpdatableFontDirTest {
    public void installFontFile_olderThanPreinstalledFont() throws Exception {
        FakeFontFileParser parser = new FakeFontFileParser();
        FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
        FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"), "test,1");
        FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"), "test.ttf,1");
        UpdatableFontDir dir = new UpdatableFontDir(
                mUpdatableFontFilesDir, mPreinstalledFontDirs, parser, fakeFsverityUtil,
                mConfigFile);
        dir.loadFontFileMap();

        try {
            dir.update(Collections.singletonList(newFontUpdateRequest("test,1", GOOD_SIGNATURE)));
            dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1",
                    GOOD_SIGNATURE)));
            fail("Expect SystemFontException");
        } catch (FontManagerService.SystemFontException e) {
            assertThat(e.getErrorCode()).isEqualTo(FontManager.RESULT_ERROR_DOWNGRADING);
@@ -500,7 +503,7 @@ public final class UpdatableFontDirTest {
        long expectedModifiedDate = 1234567890;
        FakeFontFileParser parser = new FakeFontFileParser();
        FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
        FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"), "test,1");
        FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"), "test.ttf,1");

        File readonlyDir = new File(mCacheDir, "readonly");
        assertThat(readonlyDir.mkdir()).isTrue();
@@ -519,7 +522,8 @@ public final class UpdatableFontDirTest {

            try {
                dir.update(
                        Collections.singletonList(newFontUpdateRequest("test,2", GOOD_SIGNATURE)));
                        Collections.singletonList(newFontUpdateRequest("test.ttf,2",
                                GOOD_SIGNATURE)));
            } catch (FontManagerService.SystemFontException e) {
                assertThat(e.getErrorCode())
                        .isEqualTo(FontManager.RESULT_ERROR_FAILED_UPDATE_CONFIG);
@@ -539,7 +543,7 @@ public final class UpdatableFontDirTest {
                mUpdatableFontFilesDir, mPreinstalledFontDirs,
                new UpdatableFontDir.FontFileParser() {
                    @Override
                    public String getPostScriptName(File file) throws IOException {
                    public String getCanonicalFileName(File file) throws IOException {
                        return null;
                    }

@@ -551,7 +555,8 @@ public final class UpdatableFontDirTest {
        dir.loadFontFileMap();

        try {
            dir.update(Collections.singletonList(newFontUpdateRequest("foo,1", GOOD_SIGNATURE)));
            dir.update(Collections.singletonList(newFontUpdateRequest("foo.ttf,1",
                    GOOD_SIGNATURE)));
            fail("Expect SystemFontException");
        } catch (FontManagerService.SystemFontException e) {
            assertThat(e.getErrorCode())
@@ -567,7 +572,7 @@ public final class UpdatableFontDirTest {
                mUpdatableFontFilesDir, mPreinstalledFontDirs,
                new UpdatableFontDir.FontFileParser() {
                    @Override
                    public String getPostScriptName(File file) throws IOException {
                    public String getCanonicalFileName(File file) throws IOException {
                        throw new IOException();
                    }

@@ -579,7 +584,8 @@ public final class UpdatableFontDirTest {
        dir.loadFontFileMap();

        try {
            dir.update(Collections.singletonList(newFontUpdateRequest("foo,1", GOOD_SIGNATURE)));
            dir.update(Collections.singletonList(newFontUpdateRequest("foo.ttf,1",
                    GOOD_SIGNATURE)));
            fail("Expect SystemFontException");
        } catch (FontManagerService.SystemFontException e) {
            assertThat(e.getErrorCode())
@@ -615,7 +621,8 @@ public final class UpdatableFontDirTest {
        dir.loadFontFileMap();

        try {
            dir.update(Collections.singletonList(newFontUpdateRequest("foo,1", GOOD_SIGNATURE)));
            dir.update(Collections.singletonList(newFontUpdateRequest("foo.ttf,1",
                    GOOD_SIGNATURE)));
            fail("Expect SystemFontException");
        } catch (FontManagerService.SystemFontException e) {
            assertThat(e.getErrorCode())
@@ -633,11 +640,11 @@ public final class UpdatableFontDirTest {
                mConfigFile);
        dir.loadFontFileMap();

        dir.update(Collections.singletonList(newFontUpdateRequest("foo,1", GOOD_SIGNATURE)));
        dir.update(Collections.singletonList(newFontUpdateRequest("foo.ttf,1", GOOD_SIGNATURE)));
        try {
            dir.update(Arrays.asList(
                    newFontUpdateRequest("foo,2", GOOD_SIGNATURE),
                    newFontUpdateRequest("bar,2", "Invalid signature")));
                    newFontUpdateRequest("foo.ttf,2", GOOD_SIGNATURE),
                    newFontUpdateRequest("bar.ttf,2", "Invalid signature")));
            fail("Batch update with invalid signature should fail");
        } catch (FontManagerService.SystemFontException e) {
            // Expected
@@ -657,7 +664,7 @@ public final class UpdatableFontDirTest {
        dir.loadFontFileMap();

        dir.update(Arrays.asList(
                newFontUpdateRequest("test,1", GOOD_SIGNATURE),
                newFontUpdateRequest("test.ttf,1", GOOD_SIGNATURE),
                newAddFontFamilyRequest("<family name='test'>"
                        + "  <font>test.ttf</font>"
                        + "</family>")));
@@ -680,7 +687,7 @@ public final class UpdatableFontDirTest {

        try {
            dir.update(Arrays.asList(
                    newFontUpdateRequest("test,1", GOOD_SIGNATURE),
                    newFontUpdateRequest("test.ttf,1", GOOD_SIGNATURE),
                    newAddFontFamilyRequest("<family lang='en'>"
                            + "  <font>test.ttf</font>"
                            + "</family>")));
@@ -722,7 +729,7 @@ public final class UpdatableFontDirTest {
        assertNamedFamilyExists(dir.getSystemFontConfig(), "monospace");

        dir.update(Arrays.asList(
                newFontUpdateRequest("test,1", GOOD_SIGNATURE),
                newFontUpdateRequest("test.ttf,1", GOOD_SIGNATURE),
                // Updating an existing font family.
                newAddFontFamilyRequest("<family name='monospace'>"
                        + "  <font>test.ttf</font>"
@@ -755,7 +762,7 @@ public final class UpdatableFontDirTest {
        assertThat(firstFontFamily.getName()).isNotEmpty();

        dir.update(Arrays.asList(
                newFontUpdateRequest("test,1", GOOD_SIGNATURE),
                newFontUpdateRequest("test.ttf,1", GOOD_SIGNATURE),
                newAddFontFamilyRequest("<family name='" + firstFontFamily.getName() + "'>"
                        + "  <font>test.ttf</font>"
                        + "</family>")));