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

Commit d18a901b authored by Kohsuke Yatoh's avatar Kohsuke Yatoh
Browse files

Clear updated font files in safe mode.

Bug: 176939176
Bug: 181536798
Bug: 187190639
Test: atest FrameworksServicesTests:UpdatableFontDirTest
Test: atest UpdatableSystemFontTest
Test: manually triggered safe mode and confirmed updated fonts are
      removed.
Change-Id: I946a7df383a27bbfda2931a916ca28d8ee14feb6
parent a759abbe
Loading
Loading
Loading
Loading
+29 −17
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ public final class FontManagerService extends IFontManager.Stub {
    private static final String TAG = "FontManagerService";

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

    @Override
    public FontConfig getFontConfig() {
@@ -126,9 +127,9 @@ public final class FontManagerService extends IFontManager.Stub {
    public static final class Lifecycle extends SystemService {
        private final FontManagerService mService;

        public Lifecycle(@NonNull Context context) {
        public Lifecycle(@NonNull Context context, boolean safeMode) {
            super(context);
            mService = new FontManagerService(context);
            mService = new FontManagerService(context, safeMode);
        }

        @Override
@@ -237,18 +238,24 @@ public final class FontManagerService extends IFontManager.Stub {
    @Nullable
    private SharedMemory mSerializedFontMap = null;

    private FontManagerService(Context context) {
    private FontManagerService(Context context, boolean safeMode) {
        if (safeMode) {
            Slog.i(TAG, "Entering safe mode. Deleting all font updates.");
            UpdatableFontDir.deleteAllFiles(new File(FONT_FILES_DIR), new File(CONFIG_XML_FILE));
        }
        mContext = context;
        mUpdatableFontDir = createUpdatableFontDir();
        mUpdatableFontDir = createUpdatableFontDir(safeMode);
        initialize();
    }

    @Nullable
    private static UpdatableFontDir createUpdatableFontDir() {
    private static UpdatableFontDir createUpdatableFontDir(boolean safeMode) {
        // Never read updatable font files in safe mode.
        if (safeMode) return null;
        // If apk verity is supported, fs-verity should be available.
        if (!VerityUtils.isFsVeritySupported()) return null;
        return new UpdatableFontDir(new File(FONT_FILES_DIR),
                new OtfFontFileParser(), new FsverityUtilImpl());
        return new UpdatableFontDir(new File(FONT_FILES_DIR), new OtfFontFileParser(),
                new FsverityUtilImpl(), new File(CONFIG_XML_FILE));
    }

    private void initialize() {
@@ -299,18 +306,23 @@ public final class FontManagerService extends IFontManager.Stub {
        }
    }

    /* package */ void clearUpdates() throws SystemFontException {
        if (mUpdatableFontDir == null) {
            throw new SystemFontException(
                    FontManager.RESULT_ERROR_FONT_UPDATER_DISABLED,
                    "The font updater is disabled.");
        }
        synchronized (mUpdatableFontDirLock) {
            mUpdatableFontDir.clearUpdates();
            updateSerializedFontMap();
        }
    /**
     * Clears all updates and restarts FontManagerService.
     *
     * <p>CAUTION: this method is not safe. Existing processes may crash due to missing font files.
     * This method is only for {@link FontManagerShellCommand}.
     */
    /* package */ void clearUpdates() {
        UpdatableFontDir.deleteAllFiles(new File(FONT_FILES_DIR), new File(CONFIG_XML_FILE));
        initialize();
    }

    /**
     * Restarts FontManagerService, removing not-the-latest font files.
     *
     * <p>CAUTION: this method is not safe. Existing processes may crash due to missing font files.
     * This method is only for {@link FontManagerShellCommand}.
     */
    /* package */ void restart() {
        initialize();
    }
+1 −1
Original line number Diff line number Diff line
@@ -448,7 +448,7 @@ public class FontManagerShellCommand extends ShellCommand {
        }
    }

    private int clear(ShellCommand shell) throws SystemFontException {
    private int clear(ShellCommand shell) {
        mService.clearUpdates();
        shell.getOutPrintWriter().println("Success");
        return 0;
+18 −15
Original line number Diff line number Diff line
@@ -59,8 +59,6 @@ final class UpdatableFontDir {
    private static final String TAG = "UpdatableFontDir";
    private static final String RANDOM_DIR_PREFIX = "~~";

    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;
@@ -137,8 +135,9 @@ final class UpdatableFontDir {
     */
    private final ArrayMap<String, FontFileInfo> mFontFileInfoMap = new ArrayMap<>();

    UpdatableFontDir(File filesDir, FontFileParser parser, FsverityUtil fsverityUtil) {
        this(filesDir, parser, fsverityUtil, new File(CONFIG_XML_FILE),
    UpdatableFontDir(File filesDir, FontFileParser parser, FsverityUtil fsverityUtil,
            File configFile) {
        this(filesDir, parser, fsverityUtil, configFile,
                System::currentTimeMillis,
                (map) -> SystemFonts.getSystemFontConfig(map, 0, 0)
        );
@@ -213,17 +212,6 @@ final class UpdatableFontDir {
        }
    }

    /* package */ void clearUpdates() throws SystemFontException {
        mFontFileInfoMap.clear();
        FileUtils.deleteContents(mFilesDir);

        mLastModifiedMillis = mCurrentTimeSupplier.get();
        PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
        config.lastModifiedMillis = mLastModifiedMillis;
        writePersistentConfig(config);
        mConfigVersion++;
    }

    /**
     * Applies multiple {@link FontUpdateRequest}s in transaction.
     * If one of the request fails, the fonts and config are rolled back to the previous state
@@ -604,4 +592,19 @@ final class UpdatableFontDir {
        }
        return familyMap;
    }

    /* package */ static void deleteAllFiles(File filesDir, File configFile) {
        // As this method is called in safe mode, try to delete all files even though an exception
        // is thrown.
        try {
            new AtomicFile(configFile).delete();
        } catch (Throwable t) {
            Slog.w(TAG, "Failed to delete " + configFile);
        }
        try {
            FileUtils.deleteContents(filesDir);
        } catch (Throwable t) {
            Slog.w(TAG, "Failed to delete " + filesDir);
        }
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -1804,7 +1804,7 @@ public final class SystemServer implements Dumpable {
            t.traceEnd();

            t.traceBegin("StartFontManagerService");
            mSystemServiceManager.startService(FontManagerService.Lifecycle.class);
            mSystemServiceManager.startService(new FontManagerService.Lifecycle(context, safeMode));
            t.traceEnd();

            t.traceBegin("StartTextServicesManager");
+18 −0
Original line number Diff line number Diff line
@@ -949,6 +949,24 @@ public final class UpdatableFontDirTest {
        assertThat(updated).isNotEqualTo(firstFontFamily);
    }

    @Test
    public void deleteAllFiles() throws Exception {
        FakeFontFileParser parser = new FakeFontFileParser();
        FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
        UpdatableFontDir dirForPreparation = new UpdatableFontDir(
                mUpdatableFontFilesDir, parser, fakeFsverityUtil,
                mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
        dirForPreparation.loadFontFileMap();
        dirForPreparation.update(Collections.singletonList(
                newFontUpdateRequest("foo.ttf,1,foo", GOOD_SIGNATURE)));
        assertThat(mConfigFile.exists()).isTrue();
        assertThat(mUpdatableFontFilesDir.list()).hasLength(1);

        UpdatableFontDir.deleteAllFiles(mUpdatableFontFilesDir, mConfigFile);
        assertThat(mConfigFile.exists()).isFalse();
        assertThat(mUpdatableFontFilesDir.list()).hasLength(0);
    }

    private FontUpdateRequest newFontUpdateRequest(String content, String signature)
            throws Exception {
        File file = File.createTempFile("font", "ttf", mCacheDir);