diff --git a/core/java/android/graphics/fonts/FontManager.java b/core/java/android/graphics/fonts/FontManager.java index fa2ccbc189ad2..24480e954a645 100644 --- a/core/java/android/graphics/fonts/FontManager.java +++ b/core/java/android/graphics/fonts/FontManager.java @@ -180,6 +180,23 @@ public class FontManager { */ public static final int RESULT_ERROR_SIGNATURE_TOO_LARGE = -10005; + /** + * Indicates a failure of opening XML file. + * + * This error code is only used with the shell command interaction. + * + * @hide + */ + public static final int RESULT_ERROR_FAILED_TO_OPEN_XML_FILE = -10006; + + /** + * Indicates a failure due to invalid XML file. + * + * This error code is only used with the shell command interaction. + * + * @hide + */ + public static final int RESULT_ERROR_INVALID_XML = -10007; private FontManager(@NonNull IFontManager iFontManager) { mIFontManager = iFontManager; 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 8508aa7869266..e4928ce65a2dc 100644 --- a/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java +++ b/services/core/java/com/android/server/graphics/fonts/FontManagerShellCommand.java @@ -34,16 +34,23 @@ import android.os.ShellCommand; import android.text.FontConfig; import android.util.IndentingPrintWriter; import android.util.Slog; +import android.util.TypedXmlPullParser; +import android.util.Xml; import com.android.internal.util.DumpUtils; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.PrintWriter; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -93,6 +100,9 @@ public class FontManagerShellCommand extends ShellCommand { w.println("update [font file path] [signature file path]"); w.println(" Update installed font files with new font file."); w.println(); + w.println("update-family [family definition XML path]"); + w.println(" Update font families with the new definitions."); + w.println(); w.println("clear"); w.println(" Remove all installed font files and reset to the initial state."); w.println(); @@ -371,6 +381,73 @@ public class FontManagerShellCommand extends ShellCommand { return 0; } + private int updateFamily(ShellCommand shell) throws SystemFontException { + String xmlPath = shell.getNextArg(); + if (xmlPath == null) { + throw new SystemFontException( + FontManager.RESULT_ERROR_INVALID_SHELL_ARGUMENT, + "XML file path argument is required."); + } + + List requests; + try (ParcelFileDescriptor xmlFd = shell.openFileForSystem(xmlPath, "r")) { + requests = parseFontFamilyUpdateXml(new FileInputStream(xmlFd.getFileDescriptor())); + } catch (IOException e) { + throw new SystemFontException( + FontManager.RESULT_ERROR_FAILED_TO_OPEN_XML_FILE, + "Failed to open XML file.", e); + } + mService.update(-1, requests); + shell.getOutPrintWriter().println("Success"); + return 0; + } + + /** + * Parses XML representing {@link android.graphics.fonts.FontFamilyUpdateRequest}. + * + *

The format is like: + *

{@code
+     *   
+     *       
+     *           
+     *       
+     *   
+     * }
+ */ + private static List parseFontFamilyUpdateXml(InputStream inputStream) + throws SystemFontException { + try { + TypedXmlPullParser parser = Xml.resolvePullParser(inputStream); + List requests = new ArrayList<>(); + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { + if (type != XmlPullParser.START_TAG) { + continue; + } + final int depth = parser.getDepth(); + final String tag = parser.getName(); + if (depth == 1) { + if (!"fontFamilyUpdateRequest".equals(tag)) { + throw new SystemFontException(FontManager.RESULT_ERROR_INVALID_XML, + "Expected but got: " + tag); + } + } else if (depth == 2) { + // TODO: Support including FontFileUpdateRequest + if ("family".equals(tag)) { + requests.add(new FontUpdateRequest( + FontUpdateRequest.Family.readFromXml(parser))); + } else { + throw new SystemFontException(FontManager.RESULT_ERROR_INVALID_XML, + "Expected but got: " + tag); + } + } + } + return requests; + } catch (IOException | XmlPullParserException e) { + throw new SystemFontException(0, "Failed to parse xml", e); + } + } + private int clear(ShellCommand shell) throws SystemFontException { mService.clearUpdates(); shell.getOutPrintWriter().println("Success"); @@ -409,6 +486,8 @@ public class FontManagerShellCommand extends ShellCommand { return dump(shell); case "update": return update(shell); + case "update-family": + return updateFamily(shell); case "clear": return clear(shell); case "restart": 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 06a9832f1b544..d5326055a7540 100644 --- a/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java +++ b/services/core/java/com/android/server/graphics/fonts/UpdatableFontDir.java @@ -24,6 +24,7 @@ import android.graphics.fonts.FontManager; import android.graphics.fonts.FontUpdateRequest; import android.graphics.fonts.SystemFonts; import android.os.FileUtils; +import android.os.LocaleList; import android.system.ErrnoException; import android.system.Os; import android.text.FontConfig; @@ -524,7 +525,7 @@ final class UpdatableFontDir { font.getFontStyle(), font.getIndex(), font.getFontVariationSettings(), null)); } return new FontConfig.FontFamily(resolvedFonts, fontFamily.getName(), - null, FontConfig.FontFamily.VARIANT_DEFAULT); + LocaleList.getEmptyLocaleList(), FontConfig.FontFamily.VARIANT_DEFAULT); } Map getPostScriptMap() {