Loading services/core/java/com/android/server/graphics/fonts/FontManagerService.java +29 −17 Original line number Diff line number Diff line Loading @@ -62,6 +62,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"; @RequiresPermission(Manifest.permission.UPDATE_FONTS) @Override Loading Loading @@ -130,9 +131,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 Loading Loading @@ -187,18 +188,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() { Loading Loading @@ -243,18 +250,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(); } Loading services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java +18 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -139,8 +137,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) ); Loading Loading @@ -215,17 +214,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 Loading Loading @@ -616,4 +604,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); } } } services/java/com/android/server/SystemServer.java +1 −1 Original line number Diff line number Diff line Loading @@ -1793,7 +1793,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"); Loading services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java +18 −0 Original line number Diff line number Diff line Loading @@ -947,6 +947,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); Loading Loading
services/core/java/com/android/server/graphics/fonts/FontManagerService.java +29 −17 Original line number Diff line number Diff line Loading @@ -62,6 +62,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"; @RequiresPermission(Manifest.permission.UPDATE_FONTS) @Override Loading Loading @@ -130,9 +131,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 Loading Loading @@ -187,18 +188,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() { Loading Loading @@ -243,18 +250,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(); } Loading
services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java +18 −15 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -139,8 +137,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) ); Loading Loading @@ -215,17 +214,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 Loading Loading @@ -616,4 +604,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); } } }
services/java/com/android/server/SystemServer.java +1 −1 Original line number Diff line number Diff line Loading @@ -1793,7 +1793,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"); Loading
services/tests/servicestests/src/com/android/server/graphics/fonts/UpdatableFontDirTest.java +18 −0 Original line number Diff line number Diff line Loading @@ -947,6 +947,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); Loading