/* * 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 android.graphics.fonts; import android.Manifest; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; import android.os.RemoteException; import android.text.FontConfig; import com.android.internal.graphics.fonts.IFontManager; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; import java.util.Objects; /** * This class gives you control of system installed font files. * *
* This class gives you the information of system font configuration and ability of changing them. * * @hide */ @SystemApi @TestApi @SystemService(Context.FONT_SERVICE) public class FontManager { private static final String TAG = "FontManager"; private final @NonNull IFontManager mIFontManager; /** @hide */ @IntDef(prefix = "RESULT_", value = { RESULT_SUCCESS, RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE, RESULT_ERROR_VERIFICATION_FAILURE, RESULT_ERROR_VERSION_MISMATCH, RESULT_ERROR_INVALID_FONT_FILE, RESULT_ERROR_INVALID_FONT_NAME, RESULT_ERROR_DOWNGRADING, RESULT_ERROR_FAILED_UPDATE_CONFIG, RESULT_ERROR_FONT_UPDATER_DISABLED, RESULT_ERROR_FONT_NOT_FOUND }) @Retention(RetentionPolicy.SOURCE) public @interface ResultCode {} /** * Indicates that the request has been processed successfully. */ public static final int RESULT_SUCCESS = 0; /** * Indicates that a failure occurred while writing the font file to disk. * * This is an internal error that the system cannot place the font file for being used by * application. */ public static final int RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE = -1; /** * Indicates that a failure occurred during the verification of the font file. * * The system failed to verify given font file contents and signature with system installed * certificate. */ public static final int RESULT_ERROR_VERIFICATION_FAILURE = -2; /** * Indicates that a failure occurred as a result of invalid font format or content. * * Android only accepts OpenType compliant font files. */ public static final int RESULT_ERROR_INVALID_FONT_FILE = -3; /** * Indicates a failure due to missing PostScript name in font's name table. * * Indicates that a failure occurred since PostScript name in the name table(ID=6) was missing. * The font is expected to have a PostScript name. */ public static final int RESULT_ERROR_INVALID_FONT_NAME = -4; /** * Indicates that a failure occurred due to downgrading the font version. * * The font must have equal or newer revision in its head table. */ public static final int RESULT_ERROR_DOWNGRADING = -5; /** * Indicates that a failure occurred while updating system font configuration. * * This is an internal error that the system couldn't update the {@link FontConfig}. */ public static final int RESULT_ERROR_FAILED_UPDATE_CONFIG = -6; /** * Indicates a failure due to disabled font updater. * * This is typically returned due to missing Linux kernel feature. * The font updater only works with the Linux kernel that has fs-verity feature. The fs-verity * is required after the device shipped with Android 11. Thus the updated device may not have * fs-verity feature and font updater is disabled. */ public static final int RESULT_ERROR_FONT_UPDATER_DISABLED = -7; /** * Indicates that a failure occurred because provided {@code baseVersion} did not match. * * The {@code baseVersion} provided does not match to the current {@link FontConfig} version. * Please get the latest configuration and update {@code baseVersion} accordingly. */ public static final int RESULT_ERROR_VERSION_MISMATCH = -8; /** * Indicates a failure occurred because a font with the specified PostScript name could not be * found. */ public static final int RESULT_ERROR_FONT_NOT_FOUND = -9; /** * Indicates a failure of opening font file. * * This error code is only used with the shell command interaction. * * @hide */ public static final int RESULT_ERROR_FAILED_TO_OPEN_FONT_FILE = -10001; /** * Indicates a failure of opening signature file. * * This error code is only used with the shell command interaction. * * @hide */ public static final int RESULT_ERROR_FAILED_TO_OPEN_SIGNATURE_FILE = -10002; /** * Indicates a failure of invalid shell command arguments. * * This error code is only used with the shell command interaction. * * @hide */ public static final int RESULT_ERROR_INVALID_SHELL_ARGUMENT = -10003; /** * Indicates a failure of reading signature file. * * This error code is only used with the shell command interaction. * * @hide */ public static final int RESULT_ERROR_INVALID_SIGNATURE_FILE = -10004; /** * Indicates a failure due to exceeding allowed signature file size (8kb). * * This error code is only used with the shell command interaction. * * @hide */ 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; /** * Indicates a failure due to invalid debug certificate file. * * This error code is only used with the shell command interaction. * * @hide */ public static final int RESULT_ERROR_INVALID_DEBUG_CERTIFICATE = -10008; private FontManager(@NonNull IFontManager iFontManager) { mIFontManager = iFontManager; } /** * Returns the system font configuration. * * This information is expected to be used by system font updater. If you are looking for APIs * about drawing text and/or high-level system font information, use * {@link android.graphics.Typeface} or {@link SystemFonts} instead. * * @return The current font configuration. null if failed to fetch information from the system * service. */ @RequiresPermission(Manifest.permission.UPDATE_FONTS) public @NonNull FontConfig getFontConfig() { try { return mIFontManager.getFontConfig(); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** * Update or add system font families. * *
This method will update existing font families or add new font families. The updated * font family definitions will be used when creating {@link android.graphics.Typeface} objects * with using {@link android.graphics.Typeface#create(String, int)} specifying the family name, * or through XML resources. * * To protect devices, system font updater relies on a Linux Kernel feature called fs-verity. * If the device does not support fs-verity, {@link #RESULT_ERROR_FONT_UPDATER_DISABLED} will be * returned. * *
Android only accepts OpenType compliant font files. If other font files are provided, * {@link #RESULT_ERROR_INVALID_FONT_FILE} will be returned. * *
The font file to be updated is identified by PostScript name stored in the name table. If * the font file doesn't have PostScript name entry, {@link #RESULT_ERROR_INVALID_FONT_NAME} * will be returned. * *
The entire font file is verified with the given signature using system installed * certificates. If the system cannot verify the font file contents, * {@link #RESULT_ERROR_VERIFICATION_FAILURE} will be returned. * *
The font file must have a newer revision number in the head table. In other words, it is * not allowed to downgrade a font file. If an older font file is provided, * {@link #RESULT_ERROR_DOWNGRADING} will be returned. * *
The caller must specify the base config version for keeping the font configuration
* consistent. If the font configuration is updated for some reason between the time you get
* a configuration with {@link #getFontConfig()} and the time when you call this method,
* {@link #RESULT_ERROR_VERSION_MISMATCH} will be returned. Get the latest font configuration by
* calling {@link #getFontConfig()} and call this method again with the latest config version.
*
* @param request A {@link FontFamilyUpdateRequest} to execute.
* @param baseVersion A base config version to be updated. You can get the latest config version
* by {@link FontConfig#getConfigVersion()} via {@link #getFontConfig()}. If
* the system has a newer config version, the update will fail with
* {@link #RESULT_ERROR_VERSION_MISMATCH}.
* @return A result code.
* @see FontConfig#getConfigVersion()
* @see #getFontConfig()
* @see #RESULT_SUCCESS
* @see #RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE
* @see #RESULT_ERROR_VERIFICATION_FAILURE
* @see #RESULT_ERROR_VERSION_MISMATCH
* @see #RESULT_ERROR_INVALID_FONT_FILE
* @see #RESULT_ERROR_INVALID_FONT_NAME
* @see #RESULT_ERROR_DOWNGRADING
* @see #RESULT_ERROR_FAILED_UPDATE_CONFIG
* @see #RESULT_ERROR_FONT_UPDATER_DISABLED
* @see #RESULT_ERROR_FONT_NOT_FOUND
*/
@RequiresPermission(Manifest.permission.UPDATE_FONTS) public @ResultCode int updateFontFamily(
@NonNull FontFamilyUpdateRequest request, @IntRange(from = 0) int baseVersion) {
List