1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.graphics.fonts; 18 19 import android.Manifest; 20 import android.annotation.IntDef; 21 import android.annotation.IntRange; 22 import android.annotation.NonNull; 23 import android.annotation.RequiresPermission; 24 import android.annotation.SystemApi; 25 import android.annotation.SystemService; 26 import android.annotation.TestApi; 27 import android.content.Context; 28 import android.os.RemoteException; 29 import android.text.FontConfig; 30 31 import com.android.internal.graphics.fonts.IFontManager; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 import java.util.ArrayList; 36 import java.util.List; 37 import java.util.Objects; 38 39 /** 40 * This class gives you control of system installed font files. 41 * 42 * <p> 43 * This class gives you the information of system font configuration and ability of changing them. 44 * 45 * @hide 46 */ 47 @SystemApi 48 @TestApi 49 @SystemService(Context.FONT_SERVICE) 50 public class FontManager { 51 private static final String TAG = "FontManager"; 52 private final @NonNull IFontManager mIFontManager; 53 54 /** @hide */ 55 @IntDef(prefix = "RESULT_", 56 value = { RESULT_SUCCESS, RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE, 57 RESULT_ERROR_VERIFICATION_FAILURE, RESULT_ERROR_VERSION_MISMATCH, 58 RESULT_ERROR_INVALID_FONT_FILE, RESULT_ERROR_INVALID_FONT_NAME, 59 RESULT_ERROR_DOWNGRADING, RESULT_ERROR_FAILED_UPDATE_CONFIG, 60 RESULT_ERROR_FONT_UPDATER_DISABLED, RESULT_ERROR_FONT_NOT_FOUND }) 61 @Retention(RetentionPolicy.SOURCE) 62 public @interface ResultCode {} 63 64 /** 65 * Indicates that the request has been processed successfully. 66 */ 67 public static final int RESULT_SUCCESS = 0; 68 69 /** 70 * Indicates that a failure occurred while writing the font file to disk. 71 * 72 * This is an internal error that the system cannot place the font file for being used by 73 * application. 74 */ 75 public static final int RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE = -1; 76 77 /** 78 * Indicates that a failure occurred during the verification of the font file. 79 * 80 * The system failed to verify given font file contents and signature with system installed 81 * certificate. 82 */ 83 public static final int RESULT_ERROR_VERIFICATION_FAILURE = -2; 84 85 /** 86 * Indicates that a failure occurred as a result of invalid font format or content. 87 * 88 * Android only accepts OpenType compliant font files. 89 */ 90 public static final int RESULT_ERROR_INVALID_FONT_FILE = -3; 91 92 /** 93 * Indicates a failure due to missing PostScript name in font's name table. 94 * 95 * Indicates that a failure occurred since PostScript name in the name table(ID=6) was missing. 96 * The font is expected to have a PostScript name. 97 */ 98 public static final int RESULT_ERROR_INVALID_FONT_NAME = -4; 99 100 /** 101 * Indicates that a failure occurred due to downgrading the font version. 102 * 103 * The font must have equal or newer revision in its head table. 104 */ 105 public static final int RESULT_ERROR_DOWNGRADING = -5; 106 107 /** 108 * Indicates that a failure occurred while updating system font configuration. 109 * 110 * This is an internal error that the system couldn't update the {@link FontConfig}. 111 */ 112 public static final int RESULT_ERROR_FAILED_UPDATE_CONFIG = -6; 113 114 /** 115 * Indicates a failure due to disabled font updater. 116 * 117 * This is typically returned due to missing Linux kernel feature. 118 * The font updater only works with the Linux kernel that has fs-verity feature. The fs-verity 119 * is required after the device shipped with Android 11. Thus the updated device may not have 120 * fs-verity feature and font updater is disabled. 121 */ 122 public static final int RESULT_ERROR_FONT_UPDATER_DISABLED = -7; 123 124 /** 125 * Indicates that a failure occurred because provided {@code baseVersion} did not match. 126 * 127 * The {@code baseVersion} provided does not match to the current {@link FontConfig} version. 128 * Please get the latest configuration and update {@code baseVersion} accordingly. 129 */ 130 public static final int RESULT_ERROR_VERSION_MISMATCH = -8; 131 132 /** 133 * Indicates a failure occurred because a font with the specified PostScript name could not be 134 * found. 135 */ 136 public static final int RESULT_ERROR_FONT_NOT_FOUND = -9; 137 138 /** 139 * Indicates a failure of opening font file. 140 * 141 * This error code is only used with the shell command interaction. 142 * 143 * @hide 144 */ 145 public static final int RESULT_ERROR_FAILED_TO_OPEN_FONT_FILE = -10001; 146 147 /** 148 * Indicates a failure of opening signature file. 149 * 150 * This error code is only used with the shell command interaction. 151 * 152 * @hide 153 */ 154 public static final int RESULT_ERROR_FAILED_TO_OPEN_SIGNATURE_FILE = -10002; 155 156 /** 157 * Indicates a failure of invalid shell command arguments. 158 * 159 * This error code is only used with the shell command interaction. 160 * 161 * @hide 162 */ 163 public static final int RESULT_ERROR_INVALID_SHELL_ARGUMENT = -10003; 164 165 /** 166 * Indicates a failure of reading signature file. 167 * 168 * This error code is only used with the shell command interaction. 169 * 170 * @hide 171 */ 172 public static final int RESULT_ERROR_INVALID_SIGNATURE_FILE = -10004; 173 174 /** 175 * Indicates a failure due to exceeding allowed signature file size (8kb). 176 * 177 * This error code is only used with the shell command interaction. 178 * 179 * @hide 180 */ 181 public static final int RESULT_ERROR_SIGNATURE_TOO_LARGE = -10005; 182 183 /** 184 * Indicates a failure of opening XML file. 185 * 186 * This error code is only used with the shell command interaction. 187 * 188 * @hide 189 */ 190 public static final int RESULT_ERROR_FAILED_TO_OPEN_XML_FILE = -10006; 191 192 /** 193 * Indicates a failure due to invalid XML file. 194 * 195 * This error code is only used with the shell command interaction. 196 * 197 * @hide 198 */ 199 public static final int RESULT_ERROR_INVALID_XML = -10007; 200 201 /** 202 * Indicates a failure due to invalid debug certificate file. 203 * 204 * This error code is only used with the shell command interaction. 205 * 206 * @hide 207 */ 208 public static final int RESULT_ERROR_INVALID_DEBUG_CERTIFICATE = -10008; 209 FontManager(@onNull IFontManager iFontManager)210 private FontManager(@NonNull IFontManager iFontManager) { 211 mIFontManager = iFontManager; 212 } 213 214 /** 215 * Returns the system font configuration. 216 * 217 * This information is expected to be used by system font updater. If you are looking for APIs 218 * about drawing text and/or high-level system font information, use 219 * {@link android.graphics.Typeface} or {@link SystemFonts} instead. 220 * 221 * @return The current font configuration. null if failed to fetch information from the system 222 * service. 223 */ 224 @RequiresPermission(Manifest.permission.UPDATE_FONTS) getFontConfig()225 public @NonNull FontConfig getFontConfig() { 226 try { 227 return mIFontManager.getFontConfig(); 228 } catch (RemoteException e) { 229 throw e.rethrowAsRuntimeException(); 230 } 231 } 232 233 /** 234 * Update or add system font families. 235 * 236 * <p>This method will update existing font families or add new font families. The updated 237 * font family definitions will be used when creating {@link android.graphics.Typeface} objects 238 * with using {@link android.graphics.Typeface#create(String, int)} specifying the family name, 239 * or through XML resources. 240 * 241 * To protect devices, system font updater relies on a Linux Kernel feature called fs-verity. 242 * If the device does not support fs-verity, {@link #RESULT_ERROR_FONT_UPDATER_DISABLED} will be 243 * returned. 244 * 245 * <p>Android only accepts OpenType compliant font files. If other font files are provided, 246 * {@link #RESULT_ERROR_INVALID_FONT_FILE} will be returned. 247 * 248 * <p>The font file to be updated is identified by PostScript name stored in the name table. If 249 * the font file doesn't have PostScript name entry, {@link #RESULT_ERROR_INVALID_FONT_NAME} 250 * will be returned. 251 * 252 * <p>The entire font file is verified with the given signature using system installed 253 * certificates. If the system cannot verify the font file contents, 254 * {@link #RESULT_ERROR_VERIFICATION_FAILURE} will be returned. 255 * 256 * <p>The font file must have a newer revision number in the head table. In other words, it is 257 * not allowed to downgrade a font file. If an older font file is provided, 258 * {@link #RESULT_ERROR_DOWNGRADING} will be returned. 259 * 260 * <p>The caller must specify the base config version for keeping the font configuration 261 * consistent. If the font configuration is updated for some reason between the time you get 262 * a configuration with {@link #getFontConfig()} and the time when you call this method, 263 * {@link #RESULT_ERROR_VERSION_MISMATCH} will be returned. Get the latest font configuration by 264 * calling {@link #getFontConfig()} and call this method again with the latest config version. 265 * 266 * @param request A {@link FontFamilyUpdateRequest} to execute. 267 * @param baseVersion A base config version to be updated. You can get the latest config version 268 * by {@link FontConfig#getConfigVersion()} via {@link #getFontConfig()}. If 269 * the system has a newer config version, the update will fail with 270 * {@link #RESULT_ERROR_VERSION_MISMATCH}. 271 * @return A result code. 272 * @see FontConfig#getConfigVersion() 273 * @see #getFontConfig() 274 * @see #RESULT_SUCCESS 275 * @see #RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE 276 * @see #RESULT_ERROR_VERIFICATION_FAILURE 277 * @see #RESULT_ERROR_VERSION_MISMATCH 278 * @see #RESULT_ERROR_INVALID_FONT_FILE 279 * @see #RESULT_ERROR_INVALID_FONT_NAME 280 * @see #RESULT_ERROR_DOWNGRADING 281 * @see #RESULT_ERROR_FAILED_UPDATE_CONFIG 282 * @see #RESULT_ERROR_FONT_UPDATER_DISABLED 283 * @see #RESULT_ERROR_FONT_NOT_FOUND 284 */ updateFontFamily( @onNull FontFamilyUpdateRequest request, @IntRange(from = 0) int baseVersion)285 @RequiresPermission(Manifest.permission.UPDATE_FONTS) public @ResultCode int updateFontFamily( 286 @NonNull FontFamilyUpdateRequest request, @IntRange(from = 0) int baseVersion) { 287 List<FontUpdateRequest> requests = new ArrayList<>(); 288 List<FontFileUpdateRequest> fontFileUpdateRequests = request.getFontFileUpdateRequests(); 289 for (int i = 0; i < fontFileUpdateRequests.size(); i++) { 290 FontFileUpdateRequest fontFile = fontFileUpdateRequests.get(i); 291 requests.add(new FontUpdateRequest(fontFile.getParcelFileDescriptor(), 292 fontFile.getSignature())); 293 } 294 List<FontFamilyUpdateRequest.FontFamily> fontFamilies = request.getFontFamilies(); 295 for (int i = 0; i < fontFamilies.size(); i++) { 296 FontFamilyUpdateRequest.FontFamily fontFamily = fontFamilies.get(i); 297 requests.add(new FontUpdateRequest(fontFamily.getName(), fontFamily.getFonts())); 298 } 299 try { 300 return mIFontManager.updateFontFamily(requests, baseVersion); 301 } catch (RemoteException e) { 302 throw e.rethrowFromSystemServer(); 303 } 304 } 305 306 /** 307 * Factory method of the FontManager. 308 * 309 * Do not use this method directly. Use getSystemService(Context.FONT_SERVICE) instead. 310 * 311 * @return A new instance of FontManager 312 * @hide 313 */ create(@onNull IFontManager iFontManager)314 public static FontManager create(@NonNull IFontManager iFontManager) { 315 Objects.requireNonNull(iFontManager); 316 return new FontManager(iFontManager); 317 } 318 } 319