Merge "Clear updated font files in safe mode." into sc-dev am: 7c4e5a69b0

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13743173

Change-Id: I2cc29e58d6b9ab08e40dbd84fe63b70b04a7315d
This commit is contained in:
TreeHugger Robot
2021-05-14 21:17:15 +00:00
committed by Automerger Merge Worker
5 changed files with 67 additions and 34 deletions

View File

@@ -62,6 +62,7 @@ public final class FontManagerService extends IFontManager.Stub {
private static final String TAG = "FontManagerService"; private static final String TAG = "FontManagerService";
private static final String FONT_FILES_DIR = "/data/fonts/files"; 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) @RequiresPermission(Manifest.permission.UPDATE_FONTS)
@Override @Override
@@ -130,9 +131,9 @@ public final class FontManagerService extends IFontManager.Stub {
public static final class Lifecycle extends SystemService { public static final class Lifecycle extends SystemService {
private final FontManagerService mService; private final FontManagerService mService;
public Lifecycle(@NonNull Context context) { public Lifecycle(@NonNull Context context, boolean safeMode) {
super(context); super(context);
mService = new FontManagerService(context); mService = new FontManagerService(context, safeMode);
} }
@Override @Override
@@ -187,18 +188,24 @@ public final class FontManagerService extends IFontManager.Stub {
@Nullable @Nullable
private SharedMemory mSerializedFontMap = null; 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; mContext = context;
mUpdatableFontDir = createUpdatableFontDir(); mUpdatableFontDir = createUpdatableFontDir(safeMode);
initialize(); initialize();
} }
@Nullable @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 apk verity is supported, fs-verity should be available.
if (!VerityUtils.isFsVeritySupported()) return null; if (!VerityUtils.isFsVeritySupported()) return null;
return new UpdatableFontDir(new File(FONT_FILES_DIR), return new UpdatableFontDir(new File(FONT_FILES_DIR), new OtfFontFileParser(),
new OtfFontFileParser(), new FsverityUtilImpl()); new FsverityUtilImpl(), new File(CONFIG_XML_FILE));
} }
private void initialize() { private void initialize() {
@@ -243,18 +250,23 @@ public final class FontManagerService extends IFontManager.Stub {
} }
} }
/* package */ void clearUpdates() throws SystemFontException { /**
if (mUpdatableFontDir == null) { * Clears all updates and restarts FontManagerService.
throw new SystemFontException( *
FontManager.RESULT_ERROR_FONT_UPDATER_DISABLED, * <p>CAUTION: this method is not safe. Existing processes may crash due to missing font files.
"The font updater is disabled."); * This method is only for {@link FontManagerShellCommand}.
} */
synchronized (mUpdatableFontDirLock) { /* package */ void clearUpdates() {
mUpdatableFontDir.clearUpdates(); UpdatableFontDir.deleteAllFiles(new File(FONT_FILES_DIR), new File(CONFIG_XML_FILE));
updateSerializedFontMap(); 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() { /* package */ void restart() {
initialize(); initialize();
} }

View File

@@ -448,7 +448,7 @@ public class FontManagerShellCommand extends ShellCommand {
} }
} }
private int clear(ShellCommand shell) throws SystemFontException { private int clear(ShellCommand shell) {
mService.clearUpdates(); mService.clearUpdates();
shell.getOutPrintWriter().println("Success"); shell.getOutPrintWriter().println("Success");
return 0; return 0;

View File

@@ -59,8 +59,6 @@ final class UpdatableFontDir {
private static final String TAG = "UpdatableFontDir"; private static final String TAG = "UpdatableFontDir";
private static final String RANDOM_DIR_PREFIX = "~~"; 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 to mock font file access in tests. */
interface FontFileParser { interface FontFileParser {
String getPostScriptName(File file) throws IOException; String getPostScriptName(File file) throws IOException;
@@ -139,8 +137,9 @@ final class UpdatableFontDir {
*/ */
private final ArrayMap<String, FontFileInfo> mFontFileInfoMap = new ArrayMap<>(); private final ArrayMap<String, FontFileInfo> mFontFileInfoMap = new ArrayMap<>();
UpdatableFontDir(File filesDir, FontFileParser parser, FsverityUtil fsverityUtil) { UpdatableFontDir(File filesDir, FontFileParser parser, FsverityUtil fsverityUtil,
this(filesDir, parser, fsverityUtil, new File(CONFIG_XML_FILE), File configFile) {
this(filesDir, parser, fsverityUtil, configFile,
System::currentTimeMillis, System::currentTimeMillis,
(map) -> SystemFonts.getSystemFontConfig(map, 0, 0) (map) -> SystemFonts.getSystemFontConfig(map, 0, 0)
); );
@@ -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. * Applies multiple {@link FontUpdateRequest}s in transaction.
* If one of the request fails, the fonts and config are rolled back to the previous state * If one of the request fails, the fonts and config are rolled back to the previous state
@@ -616,4 +604,19 @@ final class UpdatableFontDir {
} }
return familyMap; 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);
}
}
} }

View File

@@ -1793,7 +1793,7 @@ public final class SystemServer implements Dumpable {
t.traceEnd(); t.traceEnd();
t.traceBegin("StartFontManagerService"); t.traceBegin("StartFontManagerService");
mSystemServiceManager.startService(FontManagerService.Lifecycle.class); mSystemServiceManager.startService(new FontManagerService.Lifecycle(context, safeMode));
t.traceEnd(); t.traceEnd();
t.traceBegin("StartTextServicesManager"); t.traceBegin("StartTextServicesManager");

View File

@@ -947,6 +947,24 @@ public final class UpdatableFontDirTest {
assertThat(updated).isNotEqualTo(firstFontFamily); 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) private FontUpdateRequest newFontUpdateRequest(String content, String signature)
throws Exception { throws Exception {
File file = File.createTempFile("font", "ttf", mCacheDir); File file = File.createTempFile("font", "ttf", mCacheDir);