Merge changes I09ac3f34,Id3e36922 into sc-dev
* changes: Close FDs / mmap handles promptly. Remove unused IFontManager#updateFontFile().
This commit is contained in:
committed by
Android (Google) Code Review
commit
c27e46f595
@@ -30,7 +30,5 @@ import java.util.List;
|
|||||||
interface IFontManager {
|
interface IFontManager {
|
||||||
FontConfig getFontConfig();
|
FontConfig getFontConfig();
|
||||||
|
|
||||||
int updateFontFile(in FontUpdateRequest request, int baseVersion);
|
|
||||||
|
|
||||||
int updateFontFamily(in List<FontUpdateRequest> request, int baseVersion);
|
int updateFontFamily(in List<FontUpdateRequest> request, int baseVersion);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,8 +262,14 @@ public final class SystemFonts {
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static Map<String, FontFamily[]> buildSystemFallback(FontConfig fontConfig) {
|
public static Map<String, FontFamily[]> buildSystemFallback(FontConfig fontConfig) {
|
||||||
|
return buildSystemFallback(fontConfig, new ArrayMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@VisibleForTesting
|
||||||
|
public static Map<String, FontFamily[]> buildSystemFallback(FontConfig fontConfig,
|
||||||
|
ArrayMap<String, ByteBuffer> outBufferCache) {
|
||||||
final Map<String, FontFamily[]> fallbackMap = new ArrayMap<>();
|
final Map<String, FontFamily[]> fallbackMap = new ArrayMap<>();
|
||||||
final ArrayMap<String, ByteBuffer> bufferCache = new ArrayMap<>();
|
|
||||||
final List<FontConfig.FontFamily> xmlFamilies = fontConfig.getFontFamilies();
|
final List<FontConfig.FontFamily> xmlFamilies = fontConfig.getFontFamilies();
|
||||||
|
|
||||||
final ArrayMap<String, ArrayList<FontFamily>> fallbackListMap = new ArrayMap<>();
|
final ArrayMap<String, ArrayList<FontFamily>> fallbackListMap = new ArrayMap<>();
|
||||||
@@ -273,7 +279,7 @@ public final class SystemFonts {
|
|||||||
if (familyName == null) {
|
if (familyName == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
appendNamedFamily(xmlFamily, bufferCache, fallbackListMap);
|
appendNamedFamily(xmlFamily, outBufferCache, fallbackListMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, add fallback fonts to the each fallback map.
|
// Then, add fallback fonts to the each fallback map.
|
||||||
@@ -282,7 +288,7 @@ public final class SystemFonts {
|
|||||||
// The first family (usually the sans-serif family) is always placed immediately
|
// The first family (usually the sans-serif family) is always placed immediately
|
||||||
// after the primary family in the fallback.
|
// after the primary family in the fallback.
|
||||||
if (i == 0 || xmlFamily.getName() == null) {
|
if (i == 0 || xmlFamily.getName() == null) {
|
||||||
pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache);
|
pushFamilyToFallback(xmlFamily, fallbackListMap, outBufferCache);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,25 +20,19 @@ import android.Manifest;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.fonts.Font;
|
|
||||||
import android.graphics.fonts.FontFamily;
|
import android.graphics.fonts.FontFamily;
|
||||||
import android.graphics.fonts.FontFileUtil;
|
|
||||||
import android.graphics.fonts.FontManager;
|
import android.graphics.fonts.FontManager;
|
||||||
import android.graphics.fonts.FontUpdateRequest;
|
import android.graphics.fonts.FontUpdateRequest;
|
||||||
import android.graphics.fonts.SystemFonts;
|
import android.graphics.fonts.SystemFonts;
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.ResultReceiver;
|
import android.os.ResultReceiver;
|
||||||
import android.os.SharedMemory;
|
import android.os.SharedMemory;
|
||||||
import android.os.ShellCallback;
|
import android.os.ShellCallback;
|
||||||
import android.system.ErrnoException;
|
import android.system.ErrnoException;
|
||||||
import android.text.FontConfig;
|
import android.text.FontConfig;
|
||||||
import android.text.Layout;
|
|
||||||
import android.text.StaticLayout;
|
|
||||||
import android.text.TextPaint;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.AndroidException;
|
import android.util.AndroidException;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.IndentingPrintWriter;
|
import android.util.IndentingPrintWriter;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
@@ -52,19 +46,17 @@ import com.android.server.SystemService;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.DirectByteBuffer;
|
||||||
import java.nio.NioUtils;
|
import java.nio.NioUtils;
|
||||||
import java.nio.channels.FileChannel;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/** A service for managing system fonts. */
|
/** A service for managing system fonts. */
|
||||||
// TODO(b/173619554): Add API to update fonts.
|
|
||||||
public final class FontManagerService extends IFontManager.Stub {
|
public final class FontManagerService extends IFontManager.Stub {
|
||||||
private static final String TAG = "FontManagerService";
|
private static final String TAG = "FontManagerService";
|
||||||
|
|
||||||
@@ -77,23 +69,6 @@ public final class FontManagerService extends IFontManager.Stub {
|
|||||||
return getSystemFontConfig();
|
return getSystemFontConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int updateFontFile(@NonNull FontUpdateRequest request, int baseVersion) {
|
|
||||||
Preconditions.checkArgumentNonnegative(baseVersion);
|
|
||||||
Objects.requireNonNull(request);
|
|
||||||
Objects.requireNonNull(request.getFd());
|
|
||||||
Objects.requireNonNull(request.getSignature());
|
|
||||||
getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS,
|
|
||||||
"UPDATE_FONTS permission required.");
|
|
||||||
try {
|
|
||||||
update(baseVersion, Collections.singletonList(request));
|
|
||||||
return FontManager.RESULT_SUCCESS;
|
|
||||||
} catch (SystemFontException e) {
|
|
||||||
Slog.e(TAG, "Failed to update font file", e);
|
|
||||||
return e.getErrorCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int updateFontFamily(@NonNull List<FontUpdateRequest> requests, int baseVersion) {
|
public int updateFontFamily(@NonNull List<FontUpdateRequest> requests, int baseVersion) {
|
||||||
Preconditions.checkArgumentNonnegative(baseVersion);
|
Preconditions.checkArgumentNonnegative(baseVersion);
|
||||||
@@ -106,6 +81,17 @@ public final class FontManagerService extends IFontManager.Stub {
|
|||||||
} catch (SystemFontException e) {
|
} catch (SystemFontException e) {
|
||||||
Slog.e(TAG, "Failed to update font family", e);
|
Slog.e(TAG, "Failed to update font family", e);
|
||||||
return e.getErrorCode();
|
return e.getErrorCode();
|
||||||
|
} finally {
|
||||||
|
for (FontUpdateRequest request : requests) {
|
||||||
|
ParcelFileDescriptor fd = request.getFd();
|
||||||
|
if (fd != null) {
|
||||||
|
try {
|
||||||
|
fd.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Slog.w(TAG, "Failed to close fd", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,89 +140,6 @@ public final class FontManagerService extends IFontManager.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ static class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
|
|
||||||
@Override
|
|
||||||
public String getPostScriptName(File file) throws IOException {
|
|
||||||
ByteBuffer buffer = mmap(file);
|
|
||||||
try {
|
|
||||||
return FontFileUtil.getPostScriptName(buffer, 0);
|
|
||||||
} finally {
|
|
||||||
NioUtils.freeDirectBuffer(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String buildFontFileName(File file) throws IOException {
|
|
||||||
ByteBuffer buffer = mmap(file);
|
|
||||||
try {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getRevision(File file) throws IOException {
|
|
||||||
ByteBuffer buffer = mmap(file);
|
|
||||||
try {
|
|
||||||
return FontFileUtil.getRevision(buffer, 0);
|
|
||||||
} finally {
|
|
||||||
NioUtils.freeDirectBuffer(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tryToCreateTypeface(File file) throws Throwable {
|
|
||||||
Font font = new Font.Builder(file).build();
|
|
||||||
FontFamily family = new FontFamily.Builder(font).build();
|
|
||||||
Typeface typeface = new Typeface.CustomFallbackBuilder(family).build();
|
|
||||||
|
|
||||||
TextPaint p = new TextPaint();
|
|
||||||
p.setTextSize(24f);
|
|
||||||
p.setTypeface(typeface);
|
|
||||||
|
|
||||||
// Test string to try with the passed font.
|
|
||||||
// TODO: Good to extract from font file.
|
|
||||||
String testTextToDraw = "abcXYZ@- "
|
|
||||||
+ "\uD83E\uDED6" // Emoji E13.0
|
|
||||||
+ "\uD83C\uDDFA\uD83C\uDDF8" // Emoji Flags
|
|
||||||
+ "\uD83D\uDC8F\uD83C\uDFFB" // Emoji Skin tone Sequence
|
|
||||||
// ZWJ Sequence
|
|
||||||
+ "\uD83D\uDC68\uD83C\uDFFC\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D"
|
|
||||||
+ "\uD83D\uDC68\uD83C\uDFFF";
|
|
||||||
|
|
||||||
int width = (int) Math.ceil(Layout.getDesiredWidth(testTextToDraw, p));
|
|
||||||
StaticLayout layout = StaticLayout.Builder.obtain(
|
|
||||||
testTextToDraw, 0, testTextToDraw.length(), p, width).build();
|
|
||||||
Bitmap bmp = Bitmap.createBitmap(
|
|
||||||
layout.getWidth(), layout.getHeight(), Bitmap.Config.ALPHA_8);
|
|
||||||
Canvas canvas = new Canvas(bmp);
|
|
||||||
layout.draw(canvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ByteBuffer mmap(File file) throws IOException {
|
|
||||||
try (FileInputStream in = new FileInputStream(file)) {
|
|
||||||
FileChannel fileChannel = in.getChannel();
|
|
||||||
return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class FsverityUtilImpl implements UpdatableFontDir.FsverityUtil {
|
private static class FsverityUtilImpl implements UpdatableFontDir.FsverityUtil {
|
||||||
@Override
|
@Override
|
||||||
public boolean hasFsverity(String filePath) {
|
public boolean hasFsverity(String filePath) {
|
||||||
@@ -289,13 +192,7 @@ public final class FontManagerService extends IFontManager.Stub {
|
|||||||
private void initialize() {
|
private void initialize() {
|
||||||
synchronized (mUpdatableFontDirLock) {
|
synchronized (mUpdatableFontDirLock) {
|
||||||
if (mUpdatableFontDir == null) {
|
if (mUpdatableFontDir == null) {
|
||||||
synchronized (mSerializedFontMapLock) {
|
setSerializedFontMap(serializeSystemServerFontMap());
|
||||||
try {
|
|
||||||
mSerializedFontMap = Typeface.serializeFontMap(Typeface.getSystemFontMap());
|
|
||||||
} catch (IOException | ErrnoException e) {
|
|
||||||
mSerializedFontMap = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mUpdatableFontDir.loadFontFileMap();
|
mUpdatableFontDir.loadFontFileMap();
|
||||||
@@ -391,36 +288,57 @@ public final class FontManagerService extends IFontManager.Stub {
|
|||||||
/**
|
/**
|
||||||
* Makes new serialized font map data and updates mSerializedFontMap.
|
* Makes new serialized font map data and updates mSerializedFontMap.
|
||||||
*/
|
*/
|
||||||
public void updateSerializedFontMap() {
|
private void updateSerializedFontMap() {
|
||||||
|
SharedMemory serializedFontMap = serializeFontMap(getSystemFontConfig());
|
||||||
|
if (serializedFontMap == null) {
|
||||||
|
// Fallback to the preloaded config.
|
||||||
|
serializedFontMap = serializeSystemServerFontMap();
|
||||||
|
}
|
||||||
|
setSerializedFontMap(serializedFontMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static SharedMemory serializeFontMap(FontConfig fontConfig) {
|
||||||
|
final ArrayMap<String, ByteBuffer> bufferCache = new ArrayMap<>();
|
||||||
try {
|
try {
|
||||||
final FontConfig fontConfig = getSystemFontConfig();
|
final Map<String, FontFamily[]> fallback =
|
||||||
final Map<String, FontFamily[]> fallback = SystemFonts.buildSystemFallback(fontConfig);
|
SystemFonts.buildSystemFallback(fontConfig, bufferCache);
|
||||||
final Map<String, Typeface> typefaceMap =
|
final Map<String, Typeface> typefaceMap =
|
||||||
SystemFonts.buildSystemTypefaces(fontConfig, fallback);
|
SystemFonts.buildSystemTypefaces(fontConfig, fallback);
|
||||||
|
return Typeface.serializeFontMap(typefaceMap);
|
||||||
SharedMemory serializeFontMap = Typeface.serializeFontMap(typefaceMap);
|
|
||||||
synchronized (mSerializedFontMapLock) {
|
|
||||||
mSerializedFontMap = serializeFontMap;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} catch (IOException | ErrnoException e) {
|
} catch (IOException | ErrnoException e) {
|
||||||
Slog.w(TAG, "Failed to serialize updatable font map. "
|
Slog.w(TAG, "Failed to serialize updatable font map. "
|
||||||
+ "Retrying with system image fonts.", e);
|
+ "Retrying with system image fonts.", e);
|
||||||
}
|
return null;
|
||||||
|
} finally {
|
||||||
try {
|
// Unmap buffers promptly, as we map a lot of files and may hit mmap limit before
|
||||||
final FontConfig fontConfig = SystemFonts.getSystemPreinstalledFontConfig();
|
// GC collects ByteBuffers and unmaps them.
|
||||||
final Map<String, FontFamily[]> fallback = SystemFonts.buildSystemFallback(fontConfig);
|
for (ByteBuffer buffer : bufferCache.values()) {
|
||||||
final Map<String, Typeface> typefaceMap =
|
if (buffer instanceof DirectByteBuffer) {
|
||||||
SystemFonts.buildSystemTypefaces(fontConfig, fallback);
|
NioUtils.freeDirectBuffer(buffer);
|
||||||
|
}
|
||||||
SharedMemory serializeFontMap = Typeface.serializeFontMap(typefaceMap);
|
|
||||||
synchronized (mSerializedFontMapLock) {
|
|
||||||
mSerializedFontMap = serializeFontMap;
|
|
||||||
}
|
}
|
||||||
} catch (IOException | ErrnoException e) {
|
|
||||||
Slog.e(TAG, "Failed to serialize SystemServer system font map", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static SharedMemory serializeSystemServerFontMap() {
|
||||||
|
try {
|
||||||
|
return Typeface.serializeFontMap(Typeface.getSystemFontMap());
|
||||||
|
} catch (IOException | ErrnoException e) {
|
||||||
|
Slog.e(TAG, "Failed to serialize SystemServer system font map", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setSerializedFontMap(SharedMemory serializedFontMap) {
|
||||||
|
SharedMemory oldFontMap = null;
|
||||||
|
synchronized (mSerializedFontMapLock) {
|
||||||
|
oldFontMap = mSerializedFontMap;
|
||||||
|
mSerializedFontMap = serializedFontMap;
|
||||||
|
}
|
||||||
|
if (oldFontMap != null) {
|
||||||
|
oldFontMap.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server.graphics.fonts;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
import android.graphics.fonts.Font;
|
||||||
|
import android.graphics.fonts.FontFamily;
|
||||||
|
import android.graphics.fonts.FontFileUtil;
|
||||||
|
import android.text.Layout;
|
||||||
|
import android.text.StaticLayout;
|
||||||
|
import android.text.TextPaint;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.DirectByteBuffer;
|
||||||
|
import java.nio.NioUtils;
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
|
||||||
|
/* package */ class OtfFontFileParser implements UpdatableFontDir.FontFileParser {
|
||||||
|
@Override
|
||||||
|
public String getPostScriptName(File file) throws IOException {
|
||||||
|
ByteBuffer buffer = mmap(file);
|
||||||
|
try {
|
||||||
|
return FontFileUtil.getPostScriptName(buffer, 0);
|
||||||
|
} finally {
|
||||||
|
unmap(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String buildFontFileName(File file) throws IOException {
|
||||||
|
ByteBuffer buffer = mmap(file);
|
||||||
|
try {
|
||||||
|
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 {
|
||||||
|
unmap(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRevision(File file) throws IOException {
|
||||||
|
ByteBuffer buffer = mmap(file);
|
||||||
|
try {
|
||||||
|
return FontFileUtil.getRevision(buffer, 0);
|
||||||
|
} finally {
|
||||||
|
unmap(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tryToCreateTypeface(File file) throws Throwable {
|
||||||
|
ByteBuffer buffer = mmap(file);
|
||||||
|
try {
|
||||||
|
Font font = new Font.Builder(buffer).build();
|
||||||
|
FontFamily family = new FontFamily.Builder(font).build();
|
||||||
|
Typeface typeface = new Typeface.CustomFallbackBuilder(family).build();
|
||||||
|
|
||||||
|
TextPaint p = new TextPaint();
|
||||||
|
p.setTextSize(24f);
|
||||||
|
p.setTypeface(typeface);
|
||||||
|
|
||||||
|
// Test string to try with the passed font.
|
||||||
|
// TODO: Good to extract from font file.
|
||||||
|
String testTextToDraw = "abcXYZ@- "
|
||||||
|
+ "\uD83E\uDED6" // Emoji E13.0
|
||||||
|
+ "\uD83C\uDDFA\uD83C\uDDF8" // Emoji Flags
|
||||||
|
+ "\uD83D\uDC8F\uD83C\uDFFB" // Emoji Skin tone Sequence
|
||||||
|
// ZWJ Sequence
|
||||||
|
+ "\uD83D\uDC68\uD83C\uDFFC\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D"
|
||||||
|
+ "\uD83D\uDC68\uD83C\uDFFF";
|
||||||
|
|
||||||
|
int width = (int) Math.ceil(Layout.getDesiredWidth(testTextToDraw, p));
|
||||||
|
StaticLayout layout = StaticLayout.Builder.obtain(
|
||||||
|
testTextToDraw, 0, testTextToDraw.length(), p, width).build();
|
||||||
|
Bitmap bmp = Bitmap.createBitmap(
|
||||||
|
layout.getWidth(), layout.getHeight(), Bitmap.Config.ALPHA_8);
|
||||||
|
Canvas canvas = new Canvas(bmp);
|
||||||
|
layout.draw(canvas);
|
||||||
|
} finally {
|
||||||
|
unmap(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ByteBuffer mmap(File file) throws IOException {
|
||||||
|
try (FileInputStream in = new FileInputStream(file)) {
|
||||||
|
FileChannel fileChannel = in.getChannel();
|
||||||
|
return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void unmap(ByteBuffer buffer) {
|
||||||
|
if (buffer instanceof DirectByteBuffer) {
|
||||||
|
NioUtils.freeDirectBuffer(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -139,9 +139,11 @@ public final class UpdatableFontDirTest {
|
|||||||
private File mUpdatableFontFilesDir;
|
private File mUpdatableFontFilesDir;
|
||||||
private File mConfigFile;
|
private File mConfigFile;
|
||||||
private List<File> mPreinstalledFontDirs;
|
private List<File> mPreinstalledFontDirs;
|
||||||
private Supplier<Long> mCurrentTimeSupplier = () -> CURRENT_TIME;
|
private final Supplier<Long> mCurrentTimeSupplier = () -> CURRENT_TIME;
|
||||||
private Function<Map<String, File>, FontConfig> mConfigSupplier =
|
private final Function<Map<String, File>, FontConfig> mConfigSupplier =
|
||||||
(map) -> SystemFonts.getSystemFontConfig(map, 0, 0);
|
(map) -> SystemFonts.getSystemFontConfig(map, 0, 0);
|
||||||
|
private FakeFontFileParser mParser;
|
||||||
|
private FakeFsverityUtil mFakeFsverityUtil;
|
||||||
|
|
||||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||||
@Before
|
@Before
|
||||||
@@ -159,6 +161,8 @@ public final class UpdatableFontDirTest {
|
|||||||
dir.mkdir();
|
dir.mkdir();
|
||||||
}
|
}
|
||||||
mConfigFile = new File(mCacheDir, "config.xml");
|
mConfigFile = new File(mCacheDir, "config.xml");
|
||||||
|
mParser = new FakeFontFileParser();
|
||||||
|
mFakeFsverityUtil = new FakeFsverityUtil();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -169,13 +173,11 @@ public final class UpdatableFontDirTest {
|
|||||||
@Test
|
@Test
|
||||||
public void construct() throws Exception {
|
public void construct() throws Exception {
|
||||||
long expectedModifiedDate = CURRENT_TIME / 2;
|
long expectedModifiedDate = CURRENT_TIME / 2;
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
|
PersistentSystemFontConfig.Config config = new PersistentSystemFontConfig.Config();
|
||||||
config.lastModifiedMillis = expectedModifiedDate;
|
config.lastModifiedMillis = expectedModifiedDate;
|
||||||
writeConfig(config, mConfigFile);
|
writeConfig(config, mConfigFile);
|
||||||
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dirForPreparation.loadFontFileMap();
|
dirForPreparation.loadFontFileMap();
|
||||||
assertThat(dirForPreparation.getSystemFontConfig().getLastModifiedTimeMillis())
|
assertThat(dirForPreparation.getSystemFontConfig().getLastModifiedTimeMillis())
|
||||||
@@ -198,13 +200,13 @@ public final class UpdatableFontDirTest {
|
|||||||
.isNotEqualTo(expectedModifiedDate);
|
.isNotEqualTo(expectedModifiedDate);
|
||||||
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(3);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(3);
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(4);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(4);
|
||||||
// Outdated font dir should be deleted.
|
// Outdated font dir should be deleted.
|
||||||
assertThat(mUpdatableFontFilesDir.list()).hasLength(2);
|
assertThat(mUpdatableFontFilesDir.list()).hasLength(2);
|
||||||
assertNamedFamilyExists(dir.getSystemFontConfig(), "foobar");
|
assertNamedFamilyExists(dir.getSystemFontConfig(), "foobar");
|
||||||
@@ -219,10 +221,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void construct_empty() {
|
public void construct_empty() {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
assertThat(dir.getPostScriptMap()).isEmpty();
|
assertThat(dir.getPostScriptMap()).isEmpty();
|
||||||
@@ -231,10 +231,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void construct_missingFsverity() throws Exception {
|
public void construct_missingFsverity() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dirForPreparation.loadFontFileMap();
|
dirForPreparation.loadFontFileMap();
|
||||||
dirForPreparation.update(Arrays.asList(
|
dirForPreparation.update(Arrays.asList(
|
||||||
@@ -249,10 +247,10 @@ public final class UpdatableFontDirTest {
|
|||||||
// Four font dirs are created.
|
// Four font dirs are created.
|
||||||
assertThat(mUpdatableFontFilesDir.list()).hasLength(4);
|
assertThat(mUpdatableFontFilesDir.list()).hasLength(4);
|
||||||
|
|
||||||
fakeFsverityUtil.remove(
|
mFakeFsverityUtil.remove(
|
||||||
dirForPreparation.getPostScriptMap().get("foo").getAbsolutePath());
|
dirForPreparation.getPostScriptMap().get("foo").getAbsolutePath());
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
assertThat(dir.getPostScriptMap()).isEmpty();
|
assertThat(dir.getPostScriptMap()).isEmpty();
|
||||||
@@ -263,10 +261,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void construct_fontNameMismatch() throws Exception {
|
public void construct_fontNameMismatch() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dirForPreparation.loadFontFileMap();
|
dirForPreparation.loadFontFileMap();
|
||||||
dirForPreparation.update(Arrays.asList(
|
dirForPreparation.update(Arrays.asList(
|
||||||
@@ -285,7 +281,7 @@ public final class UpdatableFontDirTest {
|
|||||||
FileUtils.stringToFile(dirForPreparation.getPostScriptMap().get("foo"), "bar,4");
|
FileUtils.stringToFile(dirForPreparation.getPostScriptMap().get("foo"), "bar,4");
|
||||||
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
assertThat(dir.getPostScriptMap()).isEmpty();
|
assertThat(dir.getPostScriptMap()).isEmpty();
|
||||||
@@ -296,8 +292,6 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void construct_olderThanPreinstalledFont() throws Exception {
|
public void construct_olderThanPreinstalledFont() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
Function<Map<String, File>, FontConfig> configSupplier = (map) -> {
|
Function<Map<String, File>, FontConfig> configSupplier = (map) -> {
|
||||||
FontConfig.Font fooFont = new FontConfig.Font(
|
FontConfig.Font fooFont = new FontConfig.Font(
|
||||||
new File(mPreinstalledFontDirs.get(0), "foo.ttf"), null, "foo",
|
new File(mPreinstalledFontDirs.get(0), "foo.ttf"), null, "foo",
|
||||||
@@ -314,7 +308,7 @@ public final class UpdatableFontDirTest {
|
|||||||
};
|
};
|
||||||
|
|
||||||
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, configSupplier);
|
mConfigFile, mCurrentTimeSupplier, configSupplier);
|
||||||
dirForPreparation.loadFontFileMap();
|
dirForPreparation.loadFontFileMap();
|
||||||
dirForPreparation.update(Arrays.asList(
|
dirForPreparation.update(Arrays.asList(
|
||||||
@@ -334,14 +328,14 @@ public final class UpdatableFontDirTest {
|
|||||||
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(1), "bar.ttf"), "bar,1,bar");
|
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(1), "bar.ttf"), "bar,1,bar");
|
||||||
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(1), "bar.ttf"), "bar,2,bar");
|
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(1), "bar.ttf"), "bar,2,bar");
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, configSupplier);
|
mConfigFile, mCurrentTimeSupplier, configSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
// For foo.ttf, preinstalled font (revision 5) should be used.
|
// For foo.ttf, preinstalled font (revision 5) should be used.
|
||||||
assertThat(dir.getPostScriptMap()).doesNotContainKey("foo");
|
assertThat(dir.getPostScriptMap()).doesNotContainKey("foo");
|
||||||
// For bar.ttf, updated font (revision 4) should be used.
|
// For bar.ttf, updated font (revision 4) should be used.
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(4);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(4);
|
||||||
// Outdated font dir should be deleted.
|
// Outdated font dir should be deleted.
|
||||||
// We don't delete bar.ttf in this case, because it's normal that OTA updates preinstalled
|
// We don't delete bar.ttf in this case, because it's normal that OTA updates preinstalled
|
||||||
// fonts.
|
// fonts.
|
||||||
@@ -352,10 +346,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void construct_failedToLoadConfig() throws Exception {
|
public void construct_failedToLoadConfig() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
new File("/dev/null"), mCurrentTimeSupplier, mConfigSupplier);
|
new File("/dev/null"), mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
assertThat(dir.getPostScriptMap()).isEmpty();
|
assertThat(dir.getPostScriptMap()).isEmpty();
|
||||||
@@ -364,10 +356,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void construct_afterBatchFailure() throws Exception {
|
public void construct_afterBatchFailure() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
UpdatableFontDir dirForPreparation = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dirForPreparation.loadFontFileMap();
|
dirForPreparation.loadFontFileMap();
|
||||||
dirForPreparation.update(Arrays.asList(
|
dirForPreparation.update(Arrays.asList(
|
||||||
@@ -389,12 +379,12 @@ public final class UpdatableFontDirTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
// The state should be rolled back as a whole if one of the update requests fail.
|
// The state should be rolled back as a whole if one of the update requests fail.
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
|
||||||
assertThat(dir.getFontFamilyMap()).containsKey("foobar");
|
assertThat(dir.getFontFamilyMap()).containsKey("foobar");
|
||||||
FontConfig.FontFamily foobar = dir.getFontFamilyMap().get("foobar");
|
FontConfig.FontFamily foobar = dir.getFontFamilyMap().get("foobar");
|
||||||
assertThat(foobar.getFontList()).hasSize(1);
|
assertThat(foobar.getFontList()).hasSize(1);
|
||||||
@@ -404,10 +394,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void loadFontFileMap_twice() throws Exception {
|
public void loadFontFileMap_twice() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
|
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
|
||||||
@@ -420,17 +408,15 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile() throws Exception {
|
public void installFontFile() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
|
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
|
||||||
GOOD_SIGNATURE)));
|
GOOD_SIGNATURE)));
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("test");
|
assertThat(dir.getPostScriptMap()).containsKey("test");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
|
||||||
File fontFile = dir.getPostScriptMap().get("test");
|
File fontFile = dir.getPostScriptMap().get("test");
|
||||||
assertThat(Os.stat(fontFile.getAbsolutePath()).st_mode & 0777).isEqualTo(0644);
|
assertThat(Os.stat(fontFile.getAbsolutePath()).st_mode & 0777).isEqualTo(0644);
|
||||||
File fontDir = fontFile.getParentFile();
|
File fontDir = fontFile.getParentFile();
|
||||||
@@ -439,10 +425,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_upgrade() throws Exception {
|
public void installFontFile_upgrade() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -452,10 +436,10 @@ public final class UpdatableFontDirTest {
|
|||||||
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,2,test",
|
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,2,test",
|
||||||
GOOD_SIGNATURE)));
|
GOOD_SIGNATURE)));
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("test");
|
assertThat(dir.getPostScriptMap()).containsKey("test");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
|
||||||
assertThat(mapBeforeUpgrade).containsKey("test");
|
assertThat(mapBeforeUpgrade).containsKey("test");
|
||||||
assertWithMessage("Older fonts should not be deleted until next loadFontFileMap")
|
assertWithMessage("Older fonts should not be deleted until next loadFontFileMap")
|
||||||
.that(parser.getRevision(mapBeforeUpgrade.get("test"))).isEqualTo(1);
|
.that(mParser.getRevision(mapBeforeUpgrade.get("test"))).isEqualTo(1);
|
||||||
// Check that updatedFontDirs is pruned.
|
// Check that updatedFontDirs is pruned.
|
||||||
assertWithMessage("config.updatedFontDirs should only list latest active dirs")
|
assertWithMessage("config.updatedFontDirs should only list latest active dirs")
|
||||||
.that(readConfig(mConfigFile).updatedFontDirs)
|
.that(readConfig(mConfigFile).updatedFontDirs)
|
||||||
@@ -464,15 +448,13 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_systemFontHasPSNameDifferentFromFileName() throws Exception {
|
public void installFontFile_systemFontHasPSNameDifferentFromFileName() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
|
|
||||||
// Setup the environment that the system installed font file named "foo.ttf" has PostScript
|
// Setup the environment that the system installed font file named "foo.ttf" has PostScript
|
||||||
// name "bar".
|
// name "bar".
|
||||||
File file = new File(mPreinstalledFontDirs.get(0), "foo.ttf");
|
File file = new File(mPreinstalledFontDirs.get(0), "foo.ttf");
|
||||||
FileUtils.stringToFile(file, "foo.ttf,1,bar");
|
FileUtils.stringToFile(file, "foo.ttf,1,bar");
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, (map) -> {
|
mConfigFile, mCurrentTimeSupplier, (map) -> {
|
||||||
FontConfig.Font font = new FontConfig.Font(
|
FontConfig.Font font = new FontConfig.Font(
|
||||||
file, null, "bar", new FontStyle(400, FontStyle.FONT_SLANT_UPRIGHT),
|
file, null, "bar", new FontStyle(400, FontStyle.FONT_SLANT_UPRIGHT),
|
||||||
@@ -489,7 +471,7 @@ public final class UpdatableFontDirTest {
|
|||||||
GOOD_SIGNATURE)));
|
GOOD_SIGNATURE)));
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
||||||
assertThat(dir.getPostScriptMap().size()).isEqualTo(1);
|
assertThat(dir.getPostScriptMap().size()).isEqualTo(1);
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
|
||||||
File fontFile = dir.getPostScriptMap().get("bar");
|
File fontFile = dir.getPostScriptMap().get("bar");
|
||||||
assertThat(Os.stat(fontFile.getAbsolutePath()).st_mode & 0777).isEqualTo(0644);
|
assertThat(Os.stat(fontFile.getAbsolutePath()).st_mode & 0777).isEqualTo(0644);
|
||||||
File fontDir = fontFile.getParentFile();
|
File fontDir = fontFile.getParentFile();
|
||||||
@@ -498,10 +480,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_sameVersion() throws Exception {
|
public void installFontFile_sameVersion() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -510,15 +490,13 @@ public final class UpdatableFontDirTest {
|
|||||||
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
|
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
|
||||||
GOOD_SIGNATURE)));
|
GOOD_SIGNATURE)));
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("test");
|
assertThat(dir.getPostScriptMap()).containsKey("test");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_downgrade() throws Exception {
|
public void installFontFile_downgrade() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -533,7 +511,7 @@ public final class UpdatableFontDirTest {
|
|||||||
}
|
}
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("test");
|
assertThat(dir.getPostScriptMap()).containsKey("test");
|
||||||
assertWithMessage("Font should not be downgraded to an older revision")
|
assertWithMessage("Font should not be downgraded to an older revision")
|
||||||
.that(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
|
.that(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
|
||||||
// Check that updatedFontDirs is not updated.
|
// Check that updatedFontDirs is not updated.
|
||||||
assertWithMessage("config.updatedFontDirs should only list latest active dirs")
|
assertWithMessage("config.updatedFontDirs should only list latest active dirs")
|
||||||
.that(readConfig(mConfigFile).updatedFontDirs)
|
.that(readConfig(mConfigFile).updatedFontDirs)
|
||||||
@@ -542,10 +520,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_multiple() throws Exception {
|
public void installFontFile_multiple() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -554,17 +530,15 @@ public final class UpdatableFontDirTest {
|
|||||||
dir.update(Collections.singletonList(newFontUpdateRequest("bar.ttf,2,bar",
|
dir.update(Collections.singletonList(newFontUpdateRequest("bar.ttf,2,bar",
|
||||||
GOOD_SIGNATURE)));
|
GOOD_SIGNATURE)));
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_batch() throws Exception {
|
public void installFontFile_batch() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -572,17 +546,15 @@ public final class UpdatableFontDirTest {
|
|||||||
newFontUpdateRequest("foo.ttf,1,foo", GOOD_SIGNATURE),
|
newFontUpdateRequest("foo.ttf,1,foo", GOOD_SIGNATURE),
|
||||||
newFontUpdateRequest("bar.ttf,2,bar", GOOD_SIGNATURE)));
|
newFontUpdateRequest("bar.ttf,2,bar", GOOD_SIGNATURE)));
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
assertThat(dir.getPostScriptMap()).containsKey("bar");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("bar"))).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_invalidSignature() throws Exception {
|
public void installFontFile_invalidSignature() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -600,46 +572,40 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_preinstalled_upgrade() throws Exception {
|
public void installFontFile_preinstalled_upgrade() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
|
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
|
||||||
"test.ttf,1,test");
|
"test.ttf,1,test");
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,2,test",
|
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,2,test",
|
||||||
GOOD_SIGNATURE)));
|
GOOD_SIGNATURE)));
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("test");
|
assertThat(dir.getPostScriptMap()).containsKey("test");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_preinstalled_sameVersion() throws Exception {
|
public void installFontFile_preinstalled_sameVersion() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
|
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
|
||||||
"test.ttf,1,test");
|
"test.ttf,1,test");
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
|
dir.update(Collections.singletonList(newFontUpdateRequest("test.ttf,1,test",
|
||||||
GOOD_SIGNATURE)));
|
GOOD_SIGNATURE)));
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("test");
|
assertThat(dir.getPostScriptMap()).containsKey("test");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("test"))).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_preinstalled_downgrade() throws Exception {
|
public void installFontFile_preinstalled_downgrade() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
File file = new File(mPreinstalledFontDirs.get(0), "test.ttf");
|
File file = new File(mPreinstalledFontDirs.get(0), "test.ttf");
|
||||||
FileUtils.stringToFile(file, "test.ttf,2,test");
|
FileUtils.stringToFile(file, "test.ttf,2,test");
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, (map) -> {
|
mConfigFile, mCurrentTimeSupplier, (map) -> {
|
||||||
FontConfig.Font font = new FontConfig.Font(
|
FontConfig.Font font = new FontConfig.Font(
|
||||||
file, null, "test", new FontStyle(400, FontStyle.FONT_SLANT_UPRIGHT), 0, null,
|
file, null, "test", new FontStyle(400, FontStyle.FONT_SLANT_UPRIGHT), 0, null,
|
||||||
@@ -664,8 +630,6 @@ public final class UpdatableFontDirTest {
|
|||||||
@Test
|
@Test
|
||||||
public void installFontFile_failedToWriteConfigXml() throws Exception {
|
public void installFontFile_failedToWriteConfigXml() throws Exception {
|
||||||
long expectedModifiedDate = 1234567890;
|
long expectedModifiedDate = 1234567890;
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
|
FileUtils.stringToFile(new File(mPreinstalledFontDirs.get(0), "test.ttf"),
|
||||||
"test.ttf,1,test");
|
"test.ttf,1,test");
|
||||||
|
|
||||||
@@ -680,7 +644,7 @@ public final class UpdatableFontDirTest {
|
|||||||
assertThat(readonlyDir.setWritable(false, false)).isTrue();
|
assertThat(readonlyDir.setWritable(false, false)).isTrue();
|
||||||
try {
|
try {
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
readonlyFile, mCurrentTimeSupplier, mConfigSupplier);
|
readonlyFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -702,7 +666,6 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_failedToParsePostScript() throws Exception {
|
public void installFontFile_failedToParsePostScript() throws Exception {
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir,
|
mUpdatableFontFilesDir,
|
||||||
new UpdatableFontDir.FontFileParser() {
|
new UpdatableFontDir.FontFileParser() {
|
||||||
@@ -725,7 +688,7 @@ public final class UpdatableFontDirTest {
|
|||||||
@Override
|
@Override
|
||||||
public void tryToCreateTypeface(File file) throws IOException {
|
public void tryToCreateTypeface(File file) throws IOException {
|
||||||
}
|
}
|
||||||
}, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
}, mFakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -741,7 +704,6 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_failedToParsePostScriptName_invalidFont() throws Exception {
|
public void installFontFile_failedToParsePostScriptName_invalidFont() throws Exception {
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir,
|
mUpdatableFontFilesDir,
|
||||||
new UpdatableFontDir.FontFileParser() {
|
new UpdatableFontDir.FontFileParser() {
|
||||||
@@ -763,7 +725,7 @@ public final class UpdatableFontDirTest {
|
|||||||
@Override
|
@Override
|
||||||
public void tryToCreateTypeface(File file) throws IOException {
|
public void tryToCreateTypeface(File file) throws IOException {
|
||||||
}
|
}
|
||||||
}, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
}, mFakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -779,31 +741,29 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_failedToCreateTypeface() throws Exception {
|
public void installFontFile_failedToCreateTypeface() throws Exception {
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir,
|
mUpdatableFontFilesDir,
|
||||||
new UpdatableFontDir.FontFileParser() {
|
new UpdatableFontDir.FontFileParser() {
|
||||||
@Override
|
@Override
|
||||||
public String getPostScriptName(File file) throws IOException {
|
public String getPostScriptName(File file) throws IOException {
|
||||||
return parser.getPostScriptName(file);
|
return mParser.getPostScriptName(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String buildFontFileName(File file) throws IOException {
|
public String buildFontFileName(File file) throws IOException {
|
||||||
return parser.buildFontFileName(file);
|
return mParser.buildFontFileName(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getRevision(File file) throws IOException {
|
public long getRevision(File file) throws IOException {
|
||||||
return parser.getRevision(file);
|
return mParser.getRevision(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tryToCreateTypeface(File file) throws IOException {
|
public void tryToCreateTypeface(File file) throws IOException {
|
||||||
throw new IOException();
|
throw new IOException();
|
||||||
}
|
}
|
||||||
}, fakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
}, mFakeFsverityUtil, mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -820,16 +780,15 @@ public final class UpdatableFontDirTest {
|
|||||||
@Test
|
@Test
|
||||||
public void installFontFile_renameToPsNameFailure() throws Exception {
|
public void installFontFile_renameToPsNameFailure() throws Exception {
|
||||||
UpdatableFontDir.FsverityUtil fakeFsverityUtil = new UpdatableFontDir.FsverityUtil() {
|
UpdatableFontDir.FsverityUtil fakeFsverityUtil = new UpdatableFontDir.FsverityUtil() {
|
||||||
private final FakeFsverityUtil mFake = new FakeFsverityUtil();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasFsverity(String path) {
|
public boolean hasFsverity(String path) {
|
||||||
return mFake.hasFsverity(path);
|
return mFakeFsverityUtil.hasFsverity(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUpFsverity(String path, byte[] pkcs7Signature) throws IOException {
|
public void setUpFsverity(String path, byte[] pkcs7Signature) throws IOException {
|
||||||
mFake.setUpFsverity(path, pkcs7Signature);
|
mFakeFsverityUtil.setUpFsverity(path, pkcs7Signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -837,9 +796,8 @@ public final class UpdatableFontDirTest {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, fakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -856,10 +814,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void installFontFile_batchFailure() throws Exception {
|
public void installFontFile_batchFailure() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -875,15 +831,13 @@ public final class UpdatableFontDirTest {
|
|||||||
}
|
}
|
||||||
// The state should be rolled back as a whole if one of the update requests fail.
|
// The state should be rolled back as a whole if one of the update requests fail.
|
||||||
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
assertThat(dir.getPostScriptMap()).containsKey("foo");
|
||||||
assertThat(parser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
|
assertThat(mParser.getRevision(dir.getPostScriptMap().get("foo"))).isEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addFontFamily() throws Exception {
|
public void addFontFamily() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -902,10 +856,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addFontFamily_noName() throws Exception {
|
public void addFontFamily_noName() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -924,10 +876,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void addFontFamily_fontNotAvailable() throws Exception {
|
public void addFontFamily_fontNotAvailable() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
|
|
||||||
@@ -944,10 +894,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSystemFontConfig() throws Exception {
|
public void getSystemFontConfig() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
// We assume we have monospace.
|
// We assume we have monospace.
|
||||||
@@ -976,10 +924,8 @@ public final class UpdatableFontDirTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSystemFontConfig_preserveFirstFontFamily() throws Exception {
|
public void getSystemFontConfig_preserveFirstFontFamily() throws Exception {
|
||||||
FakeFontFileParser parser = new FakeFontFileParser();
|
|
||||||
FakeFsverityUtil fakeFsverityUtil = new FakeFsverityUtil();
|
|
||||||
UpdatableFontDir dir = new UpdatableFontDir(
|
UpdatableFontDir dir = new UpdatableFontDir(
|
||||||
mUpdatableFontFilesDir, parser, fakeFsverityUtil,
|
mUpdatableFontFilesDir, mParser, mFakeFsverityUtil,
|
||||||
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
mConfigFile, mCurrentTimeSupplier, mConfigSupplier);
|
||||||
dir.loadFontFileMap();
|
dir.loadFontFileMap();
|
||||||
assertThat(dir.getSystemFontConfig().getFontFamilies()).isNotEmpty();
|
assertThat(dir.getSystemFontConfig().getFontFamilies()).isNotEmpty();
|
||||||
@@ -1011,12 +957,12 @@ public final class UpdatableFontDirTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static FontUpdateRequest newAddFontFamilyRequest(String xml) throws Exception {
|
private static FontUpdateRequest newAddFontFamilyRequest(String xml) throws Exception {
|
||||||
XmlPullParser parser = Xml.newPullParser();
|
XmlPullParser mParser = Xml.newPullParser();
|
||||||
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
|
ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8));
|
||||||
parser.setInput(is, "UTF-8");
|
mParser.setInput(is, "UTF-8");
|
||||||
parser.nextTag();
|
mParser.nextTag();
|
||||||
|
|
||||||
FontConfig.FontFamily fontFamily = FontListParser.readFamily(parser, "", null, true);
|
FontConfig.FontFamily fontFamily = FontListParser.readFamily(mParser, "", null, true);
|
||||||
List<FontUpdateRequest.Font> fonts = new ArrayList<>();
|
List<FontUpdateRequest.Font> fonts = new ArrayList<>();
|
||||||
for (FontConfig.Font font : fontFamily.getFontList()) {
|
for (FontConfig.Font font : fontFamily.getFontList()) {
|
||||||
String name = font.getFile().getName();
|
String name = font.getFile().getName();
|
||||||
|
|||||||
@@ -56,6 +56,11 @@ import java.io.InputStream;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if fonts can be updated by {@link FontManager} API.
|
* Tests if fonts can be updated by {@link FontManager} API.
|
||||||
@@ -95,6 +100,12 @@ public class UpdatableSystemFontTest {
|
|||||||
EMOJI_RENDERING_TEST_APP_ID + "/.EmojiRenderingTestActivity";
|
EMOJI_RENDERING_TEST_APP_ID + "/.EmojiRenderingTestActivity";
|
||||||
private static final long ACTIVITY_TIMEOUT_MILLIS = SECONDS.toMillis(10);
|
private static final long ACTIVITY_TIMEOUT_MILLIS = SECONDS.toMillis(10);
|
||||||
|
|
||||||
|
private static final Pattern PATTERN_FONT_FILES = Pattern.compile("\\.(ttf|otf|ttc|otc)$");
|
||||||
|
private static final Pattern PATTERN_TMP_FILES = Pattern.compile("^/data/local/tmp/");
|
||||||
|
private static final Pattern PATTERN_DATA_FONT_FILES = Pattern.compile("^/data/fonts/files/");
|
||||||
|
private static final Pattern PATTERN_SYSTEM_FONT_FILES =
|
||||||
|
Pattern.compile("^/(system|product)/fonts/");
|
||||||
|
|
||||||
private String mKeyId;
|
private String mKeyId;
|
||||||
private FontManager mFontManager;
|
private FontManager mFontManager;
|
||||||
|
|
||||||
@@ -236,6 +247,32 @@ public class UpdatableSystemFontTest {
|
|||||||
assertThat(fontPathAfterReboot).isEqualTo(fontPath);
|
assertThat(fontPathAfterReboot).isEqualTo(fontPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void fdLeakTest() throws Exception {
|
||||||
|
long originalOpenFontCount =
|
||||||
|
countMatch(getOpenFiles("system_server"), PATTERN_FONT_FILES);
|
||||||
|
Pattern patternEmojiVPlus1 =
|
||||||
|
Pattern.compile(Pattern.quote(TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF));
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
assertThat(updateFontFile(
|
||||||
|
TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF, TEST_NOTO_COLOR_EMOJI_VPLUS1_TTF_FSV_SIG))
|
||||||
|
.isEqualTo(FontManager.RESULT_SUCCESS);
|
||||||
|
List<String> openFiles = getOpenFiles("system_server");
|
||||||
|
for (Pattern p : Arrays.asList(PATTERN_FONT_FILES, PATTERN_SYSTEM_FONT_FILES,
|
||||||
|
PATTERN_DATA_FONT_FILES, PATTERN_TMP_FILES)) {
|
||||||
|
Log.i(TAG, String.format("num of %s: %d", p, countMatch(openFiles, p)));
|
||||||
|
}
|
||||||
|
// system_server should not keep /data/fonts files open.
|
||||||
|
assertThat(countMatch(openFiles, PATTERN_DATA_FONT_FILES)).isEqualTo(0);
|
||||||
|
// system_server should not keep passed FD open.
|
||||||
|
assertThat(countMatch(openFiles, patternEmojiVPlus1)).isEqualTo(0);
|
||||||
|
// The number of open font FD should not increase.
|
||||||
|
assertThat(countMatch(openFiles, PATTERN_FONT_FILES))
|
||||||
|
.isAtMost(originalOpenFontCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static String insertCert(String certPath) throws Exception {
|
private static String insertCert(String certPath) throws Exception {
|
||||||
Pair<String, String> result;
|
Pair<String, String> result;
|
||||||
try (InputStream is = new FileInputStream(certPath)) {
|
try (InputStream is = new FileInputStream(certPath)) {
|
||||||
@@ -338,7 +375,37 @@ public class UpdatableSystemFontTest {
|
|||||||
return !expectCommandToSucceed(cmd).trim().isEmpty();
|
return !expectCommandToSucceed(cmd).trim().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<String> getOpenFiles(String appId) throws Exception {
|
||||||
|
String pid = pidOf(appId);
|
||||||
|
if (pid.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
String cmd = String.format("lsof -p %s", pid);
|
||||||
|
String out = expectCommandToSucceed(cmd);
|
||||||
|
List<String> paths = new ArrayList<>();
|
||||||
|
boolean first = true;
|
||||||
|
for (String line : out.split("\n")) {
|
||||||
|
// Skip the header.
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] records = line.split(" ");
|
||||||
|
if (records.length > 0) {
|
||||||
|
paths.add(records[records.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
private static String pidOf(String appId) throws Exception {
|
private static String pidOf(String appId) throws Exception {
|
||||||
return expectCommandToSucceed("pidof " + appId).trim();
|
return expectCommandToSucceed("pidof " + appId).trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static long countMatch(List<String> paths, Pattern pattern) {
|
||||||
|
// Note: asPredicate() returns true for partial matching.
|
||||||
|
return paths.stream()
|
||||||
|
.filter(pattern.asPredicate())
|
||||||
|
.count();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user