| /* |
| * 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. |
| * |
| * <p> |
| * 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; |
| |
| 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. |
| * |
| * <p>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. |
| * |
| * <p>Android only accepts OpenType compliant font files. If other font files are provided, |
| * {@link #RESULT_ERROR_INVALID_FONT_FILE} will be returned. |
| * |
| * <p>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. |
| * |
| * <p>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. |
| * |
| * <p>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. |
| * |
| * <p>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<FontUpdateRequest> requests = new ArrayList<>(); |
| List<FontFileUpdateRequest> fontFileUpdateRequests = request.getFontFileUpdateRequests(); |
| for (int i = 0; i < fontFileUpdateRequests.size(); i++) { |
| FontFileUpdateRequest fontFile = fontFileUpdateRequests.get(i); |
| requests.add(new FontUpdateRequest(fontFile.getParcelFileDescriptor(), |
| fontFile.getSignature())); |
| } |
| List<FontFamilyUpdateRequest.FontFamily> fontFamilies = request.getFontFamilies(); |
| for (int i = 0; i < fontFamilies.size(); i++) { |
| FontFamilyUpdateRequest.FontFamily fontFamily = fontFamilies.get(i); |
| requests.add(new FontUpdateRequest(fontFamily.getName(), fontFamily.getFonts())); |
| } |
| try { |
| return mIFontManager.updateFontFamily(requests, baseVersion); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Factory method of the FontManager. |
| * |
| * Do not use this method directly. Use getSystemService(Context.FONT_SERVICE) instead. |
| * |
| * @return A new instance of FontManager |
| * @hide |
| */ |
| public static FontManager create(@NonNull IFontManager iFontManager) { |
| Objects.requireNonNull(iFontManager); |
| return new FontManager(iFontManager); |
| } |
| } |