• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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