diff options
author | Kohsuke Yatoh <kyatoh@google.com> | 2021-03-02 13:38:07 -0800 |
---|---|---|
committer | Kohsuke Yatoh <kyatoh@google.com> | 2021-05-09 09:42:13 -0700 |
commit | d18a901b23660695d2f76b495ea0aa8c214dfb3c (patch) | |
tree | 6f70ecec0def2b0759ffe58d2521f86e382622a2 | |
parent | a759abbe4b0d1336a43a33042702c07fed2df33c (diff) |
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
5 files changed, 67 insertions, 34 deletions
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 7c013e0bf330..1bfb6a9d52cf 100644 --- a/services/core/java/com/android/server/graphics/fonts/FontManagerService.java +++ b/services/core/java/com/android/server/graphics/fonts/FontManagerService.java @@ -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(); } diff --git a/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java index e4928ce65a2d..3fecef703613 100644 --- a/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java +++ b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java @@ -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; 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 d5326055a754..4fa08ebcfb5d 100644 --- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java +++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java @@ -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); + } + } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 8dc501119af1..fd76e4aa5e51 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -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"); 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 7b4803724180..6b7e1dd27e84 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 @@ -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); |