1 /*
2  * Copyright (C) 2017 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 androidx.core.provider;
18 
19 import static androidx.annotation.RestrictTo.Scope.LIBRARY;
20 import static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX;
21 
22 import android.content.Context;
23 import android.content.pm.PackageManager;
24 import android.content.pm.ProviderInfo;
25 import android.content.res.Resources;
26 import android.graphics.Typeface;
27 import android.net.Uri;
28 import android.os.CancellationSignal;
29 import android.os.Handler;
30 import android.os.ParcelFileDescriptor;
31 import android.provider.BaseColumns;
32 
33 import androidx.annotation.IntDef;
34 import androidx.annotation.IntRange;
35 import androidx.annotation.RestrictTo;
36 import androidx.annotation.VisibleForTesting;
37 import androidx.core.content.res.ResourcesCompat;
38 import androidx.core.graphics.TypefaceCompat;
39 import androidx.core.graphics.TypefaceCompatUtil;
40 import androidx.core.util.Preconditions;
41 
42 import org.jspecify.annotations.NonNull;
43 import org.jspecify.annotations.Nullable;
44 
45 import java.lang.annotation.Retention;
46 import java.lang.annotation.RetentionPolicy;
47 import java.nio.ByteBuffer;
48 import java.util.Collections;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.concurrent.Executor;
52 
53 /**
54  * Utility class to deal with Font ContentProviders.
55  */
56 public class FontsContractCompat {
FontsContractCompat()57     private FontsContractCompat() { }
58 
59     @RestrictTo(RestrictTo.Scope.LIBRARY)
60     @Retention(RetentionPolicy.SOURCE)
61     @IntDef({
62             Typeface.NORMAL,
63             Typeface.BOLD,
64             Typeface.ITALIC,
65             Typeface.BOLD_ITALIC
66     })
67     public @interface TypefaceStyle {}
68 
69     /**
70      * Build a Typeface from an array of {@link FontInfo}
71      *
72      * Results that are marked as not ready will be skipped.
73      *
74      * @param context A {@link Context} that will be used to fetch the font contents.
75      * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
76      *                           the operation is canceled, then {@link
77      *                           android.os.OperationCanceledException} will be thrown.
78      * @param fonts An array of {@link FontInfo} to be used to create a Typeface.
79      * @return A Typeface object. Returns null if typeface creation fails.
80      */
buildTypeface( @onNull Context context, @Nullable CancellationSignal cancellationSignal, FontInfo @NonNull [] fonts )81     public static @Nullable Typeface buildTypeface(
82             @NonNull Context context,
83             @Nullable CancellationSignal cancellationSignal,
84             FontInfo @NonNull [] fonts
85     ) {
86         return TypefaceCompat.createFromFontInfo(context, cancellationSignal, fonts,
87                 Typeface.NORMAL);
88     }
89 
90     /**
91      * Fetch fonts given a font request.
92      *
93      * @param context A {@link Context} to be used for fetching fonts.
94      * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If
95      *                           the operation is canceled, then {@link
96      *                           android.os.OperationCanceledException} will be thrown when the
97      *                           query is executed.
98      * @param request A {@link FontRequest} object that identifies the provider and query for the
99      *                request.
100      *
101      * @return {@link FontFamilyResult}
102      *
103      * @throws PackageManager.NameNotFoundException If requested package or authority was not found
104      *      in the system.
105      */
fetchFonts( @onNull Context context, @Nullable CancellationSignal cancellationSignal, @NonNull FontRequest request )106     public static @NonNull FontFamilyResult fetchFonts(
107             @NonNull Context context,
108             @Nullable CancellationSignal cancellationSignal,
109             @NonNull FontRequest request
110     ) throws PackageManager.NameNotFoundException {
111         return FontProvider.getFontFamilyResult(context, List.of(request), cancellationSignal);
112     }
113 
114     /**
115      * Create a typeface object given a font request. The font will be asynchronously fetched,
116      * therefore the result is delivered to the given callback. See {@link FontRequest}.
117      * Only one of the methods in callback will be invoked, depending on whether the request
118      * succeeds or fails. These calls will happen on the main thread.
119      *
120      * @deprecated due to the non-standard pattern of taking a handler for a non-UI thread - leading
121      * to both easily passing an incorrect handler and requiring all callers spin up an extra
122      * thread.
123      *
124      * @see this#requestFont(Context, FontRequest, int, Executor, Executor, FontRequestCallback)
125      *
126      * @param context A context to be used for fetching from font provider.
127      * @param request A {@link FontRequest} object that identifies the provider and query for the
128      *                request. May not be null.
129      * @param callback A callback that will be triggered when results are obtained. May not be null.
130      * @param handler A handler for running font fetch tasks on.
131      */
132     // Deprecating this to direct developers to use Executor based loading/callback, but no
133     // intention to remove this from binary since it's a very old method.
134     @Deprecated // deprecated in 1.14.0-alpha02
requestFont( final @NonNull Context context, final @NonNull FontRequest request, final @NonNull FontRequestCallback callback, final @NonNull Handler handler )135     public static void requestFont(
136             final @NonNull Context context,
137             final @NonNull FontRequest request,
138             final @NonNull FontRequestCallback callback,
139             final @NonNull Handler handler
140     ) {
141         CallbackWrapper callbackWrapper = new CallbackWrapper(callback);
142         Executor executor = RequestExecutor.createHandlerExecutor(handler);
143         FontRequestWorker.requestFontAsync(context.getApplicationContext(),
144                 List.of(request), Typeface.NORMAL, executor, callbackWrapper);
145     }
146 
147     /**
148      * Request a font async as specified with {@link FontRequest}
149      *
150      * Loading may take several seconds, and the {@code loadingExecutor} passed should be available
151      * to run blocking requests for several seconds. Results will be returned via
152      * {@code callbackExecutor}.
153      *
154      * @param context A context to be used for fetching from font provider
155      * @param request A {@link FontRequest} object that identifies the provider and query for the
156      *                request.
157      * @param style Typeface Style such as {@link Typeface#NORMAL}, {@link Typeface#BOLD}
158      *              {@link Typeface#ITALIC}, {@link Typeface#BOLD_ITALIC}.
159      * @param loadingExecutor executor to load font on. Loading may take several _seconds_. If
160      *                       {@code null}, a default executor shared with other null-requests will
161      *                        be used.
162      * @param callbackExecutor Used to dispatch callback
163      * @param callback A callback that will be triggered when results are obtained.
164      */
requestFont( @onNull Context context, @NonNull FontRequest request, @TypefaceStyle int style, @Nullable Executor loadingExecutor, @NonNull Executor callbackExecutor, @NonNull FontRequestCallback callback )165     public static void requestFont(
166             @NonNull Context context,
167             @NonNull FontRequest request,
168             @TypefaceStyle int style,
169             @Nullable Executor loadingExecutor,
170             @NonNull Executor callbackExecutor,
171             @NonNull FontRequestCallback callback
172     ) {
173         CallbackWrapper callbacKWrapper = new CallbackWrapper(callback, callbackExecutor);
174         Context applicationContext = context.getApplicationContext();
175         FontRequestWorker.requestFontAsync(applicationContext, List.of(request),
176                 style, loadingExecutor, callbacKWrapper);
177     }
178 
179     /**
180      * Request a font async as specified with {@link FontRequest}
181      *
182      * Loading may take several seconds, and the {@code loadingExecutor} passed should be available
183      * to run blocking requests for several seconds. Results will be returned via
184      * {@code callbackExecutor}.
185      *
186      * @param context A context to be used for fetching from font provider
187      * @param requests An array of {@link FontRequest} objects that identify the provider and query
188      *                 for the request, followed by any fallbacks.
189      *                 Fallbacks are used in the order specified.
190      *                 Note that the performance implications of font fallback scale with the number
191      *                 of fonts involved, so the length of this parameter should be kept to a
192      *                 minimum; we recommend no more than 2 (that is, the primary font and a single
193      *                 downloadable custom fallback).
194      * @param style Typeface Style such as {@link Typeface#NORMAL}, {@link Typeface#BOLD}
195      *              {@link Typeface#ITALIC}, {@link Typeface#BOLD_ITALIC}.
196      * @param loadingExecutor executor to load font on. Loading may take several _seconds_. If
197      *                       {@code null}, a default executor shared with other null-requests will
198      *                        be used.
199      * @param callbackExecutor Used to dispatch callback
200      * @param callback A callback that will be triggered when results are obtained.
201      */
requestFontWithFallbackChain( @onNull Context context, @NonNull List<FontRequest> requests, @TypefaceStyle int style, @Nullable Executor loadingExecutor, @NonNull Executor callbackExecutor, @NonNull FontRequestCallback callback )202     public static void requestFontWithFallbackChain(
203             @NonNull Context context,
204             @NonNull List<FontRequest> requests,
205             @TypefaceStyle int style,
206             @Nullable Executor loadingExecutor,
207             @NonNull Executor callbackExecutor,
208             @NonNull FontRequestCallback callback
209     ) {
210         CallbackWrapper callbacKWrapper = new CallbackWrapper(callback, callbackExecutor);
211         Context applicationContext = context.getApplicationContext();
212         FontRequestWorker.requestFontAsync(applicationContext, requests,
213                 style, loadingExecutor, callbacKWrapper);
214     }
215 
216     /**
217      * Loads a Typeface. Based on the parameters isBlockingFetch, and timeoutInMillis, the fetch
218      * is either sync or async.
219      * - If timeoutInMillis is infinite, and isBlockingFetch is true -> sync
220      * - If timeoutInMillis is NOT infinite, and isBlockingFetch is true -> sync with timeout
221      * - else -> async without timeout.
222      *
223      * Used by TypefaceCompat and tests.
224      *
225      * @param context Context
226      * @param requests List of FontRequests that define the font to be loaded, followed by any
227      *                 custom fallbacks, in order
228      * @param style Typeface Style such as {@link Typeface#NORMAL}, {@link Typeface#BOLD}
229      *              {@link Typeface#ITALIC}, {@link Typeface#BOLD_ITALIC}.
230      * @param isBlockingFetch when true the call will be synchronous.
231      * @param timeout timeout in milliseconds for the request. It is not used for async
232      *                request.
233      * @param handler the handler to call the callback on.
234      * @param callback the callback to be called.
235      *
236      * @return the resulting Typeface if the requested font is in the cache or the request is a
237      * sync request.
238      *
239      */
240     @RestrictTo(LIBRARY)
requestFont( final @NonNull Context context, final @NonNull List<FontRequest> requests, @TypefaceStyle final int style, boolean isBlockingFetch, @IntRange(from = 0) int timeout, final @NonNull Handler handler, final @NonNull FontRequestCallback callback )241     public static @Nullable Typeface requestFont(
242             final @NonNull Context context,
243             final @NonNull List<FontRequest> requests,
244             @TypefaceStyle final int style,
245             boolean isBlockingFetch,
246             @IntRange(from = 0) int timeout,
247             final @NonNull Handler handler,
248             final @NonNull FontRequestCallback callback
249     ) {
250         CallbackWrapper callbackWrapper = new CallbackWrapper(
251                 callback, RequestExecutor.createHandlerExecutor(handler));
252 
253         if (isBlockingFetch) {
254             if (requests.size() > 1) {
255                 throw new IllegalArgumentException(
256                         "Fallbacks with blocking fetches are not supported for performance "
257                                 + "reasons");
258             }
259             return FontRequestWorker.requestFontSync(context, requests.get(0), callbackWrapper,
260                     style, timeout);
261         } else {
262             return FontRequestWorker.requestFontAsync(context, requests, style, null /*executor*/,
263                     callbackWrapper);
264         }
265     }
266 
267     /**
268      * Loads a Typeface. Based on the parameters isBlockingFetch, and timeoutInMillis, the fetch
269      * is either sync or async.
270      * - If timeoutInMillis is infinite, and isBlockingFetch is true -> sync
271      * - If timeoutInMillis is NOT infinite, and isBlockingFetch is true -> sync with timeout
272      * - else -> async without timeout.
273      *
274      * Used by TypefaceCompat and tests.
275      *
276      * @param context Context
277      * @param request FontRequest that define the font to be loaded and any fallbacks
278      * @param style Typeface Style such as {@link Typeface#NORMAL}, {@link Typeface#BOLD}
279      *              {@link Typeface#ITALIC}, {@link Typeface#BOLD_ITALIC}.
280      * @param isBlockingFetch when true the call will be synchronous.
281      * @param timeout timeout in milliseconds for the request. It is not used for async
282      *                request.
283      * @param handler the handler to call the callback on.
284      * @param callback the callback to be called.
285      *
286      * @return the resulting Typeface if the requested font is in the cache or the request is a
287      * sync request.
288      *
289      */
290     @RestrictTo(LIBRARY_GROUP_PREFIX)
requestFont( final @NonNull Context context, final @NonNull FontRequest request, @TypefaceStyle final int style, boolean isBlockingFetch, @IntRange(from = 0) int timeout, final @NonNull Handler handler, final @NonNull FontRequestCallback callback )291     public static @Nullable Typeface requestFont(
292             final @NonNull Context context,
293             final @NonNull FontRequest request,
294             @TypefaceStyle final int style,
295             boolean isBlockingFetch,
296             @IntRange(from = 0) int timeout,
297             final @NonNull Handler handler,
298             final @NonNull FontRequestCallback callback
299     ) {
300         return requestFont(context, List.of(request), style, isBlockingFetch, timeout, handler,
301                 callback);
302     }
303 
304     @RestrictTo(LIBRARY)
305     @VisibleForTesting
resetTypefaceCache()306     public static void resetTypefaceCache() {
307         FontRequestWorker.resetTypefaceCache();
308     }
309 
310     /**
311      * Defines the constants used in a response from a Font Provider. The cursor returned from the
312      * query should have the ID column populated with the content uri ID for the resulting font.
313      * This should point to a real file or shared memory, as the client will mmap the given file
314      * descriptor. Pipes, sockets and other non-mmap-able file descriptors will fail to load in the
315      * client application.
316      */
317     public static final class Columns implements BaseColumns {
318         /**
319          * Constant used to request data from a font provider. The cursor returned from the query
320          * may populate this column with a long for the font file ID. The client will request a file
321          * descriptor to "file/FILE_ID" with this ID immediately under the top-level content URI. If
322          * not present, the client will request a file descriptor to the top-level URI with the
323          * given base font ID. Note that several results may return the same file ID, e.g. for TTC
324          * files with different indices.
325          */
326         public static final String FILE_ID = "file_id";
327         /**
328          * Constant used to request data from a font provider. The cursor returned from the query
329          * should have this column populated with an int for the ttc index for the resulting font.
330          */
331         public static final String TTC_INDEX = android.provider.FontsContract.Columns.TTC_INDEX;
332         /**
333          * Constant used to request data from a font provider. The cursor returned from the query
334          * may populate this column with the font variation settings String information for the
335          * font.
336          */
337         public static final String VARIATION_SETTINGS =
338                 android.provider.FontsContract.Columns.VARIATION_SETTINGS;
339         /**
340          * Constant used to request data from a font provider. The cursor returned from the query
341          * should have this column populated with the int weight for the resulting font. This value
342          * should be between 100 and 900. The most common values are 400 for regular weight and 700
343          * for bold weight.
344          */
345         public static final String WEIGHT = android.provider.FontsContract.Columns.WEIGHT;
346         /**
347          * Constant used to request data from a font provider. The cursor returned from the query
348          * should have this column populated with the int italic for the resulting font. This should
349          * be 0 for regular style and 1 for italic.
350          */
351         public static final String ITALIC = android.provider.FontsContract.Columns.ITALIC;
352         /**
353          * Constant used to request data from a font provider. The cursor returned from the query
354          * should have this column populated to indicate the result status of the
355          * query. This will be checked before any other data in the cursor. Possible values are
356          * {@link #RESULT_CODE_OK}, {@link #RESULT_CODE_FONT_NOT_FOUND},
357          * {@link #RESULT_CODE_MALFORMED_QUERY} and {@link #RESULT_CODE_FONT_UNAVAILABLE}. If not
358          * present, {@link #RESULT_CODE_OK} will be assumed.
359          */
360         public static final String RESULT_CODE = android.provider.FontsContract.Columns.RESULT_CODE;
361 
362         /**
363          * Constant used to represent a result was retrieved successfully. The given fonts will be
364          * attempted to retrieve immediately via
365          * {@link android.content.ContentProvider#openFile(Uri, String)}. See {@link #RESULT_CODE}.
366          */
367         public static final int RESULT_CODE_OK =
368                 android.provider.FontsContract.Columns.RESULT_CODE_OK;
369         /**
370          * Constant used to represent a result was not found. See {@link #RESULT_CODE}.
371          */
372         public static final int RESULT_CODE_FONT_NOT_FOUND =
373                 android.provider.FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND;
374         /**
375          * Constant used to represent a result was found, but cannot be provided at this moment. Use
376          * this to indicate, for example, that a font needs to be fetched from the network. See
377          * {@link #RESULT_CODE}.
378          */
379         public static final int RESULT_CODE_FONT_UNAVAILABLE =
380                 android.provider.FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE;
381         /**
382          * Constant used to represent that the query was not in a supported format by the provider.
383          * See {@link #RESULT_CODE}.
384          */
385         public static final int RESULT_CODE_MALFORMED_QUERY =
386                 android.provider.FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY;
387     }
388 
389     /**
390      * Object represent a font entry in the family returned from {@link #fetchFonts}.
391      */
392     public static class FontInfo {
393         private final Uri mUri;
394         private final int mTtcIndex;
395         private final int mWeight;
396         private final boolean mItalic;
397         private final int mResultCode;
398 
399         /**
400          * Creates a Font with all the information needed about a provided font.
401          * @param uri A URI associated to the font file.
402          * @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0.
403          * @param weight An integer that indicates the font weight.
404          * @param italic A boolean that indicates the font is italic style or not.
405          * @param resultCode A boolean that indicates the font contents is ready.
406          *
407          * @deprecated Not being used by any cross library, and should not be used, internal
408          * implementation detail.
409          *
410          */
411         // TODO after removing from public API make package private.
412         @Deprecated
413         @RestrictTo(LIBRARY_GROUP_PREFIX)
FontInfo( @onNull Uri uri, @IntRange(from = 0) int ttcIndex, @IntRange(from = 1, to = 1000) int weight, boolean italic, int resultCode )414         public FontInfo(
415                 @NonNull Uri uri,
416                 @IntRange(from = 0) int ttcIndex,
417                 @IntRange(from = 1, to = 1000) int weight,
418                 boolean italic,
419                 int resultCode
420         ) {
421             mUri = Preconditions.checkNotNull(uri);
422             mTtcIndex = ttcIndex;
423             mWeight = weight;
424             mItalic = italic;
425             mResultCode = resultCode;
426         }
427 
428         @SuppressWarnings("deprecation")
create( @onNull Uri uri, @IntRange(from = 0) int ttcIndex, @IntRange(from = 1, to = 1000) int weight, boolean italic, int resultCode )429         static FontInfo create(
430                 @NonNull Uri uri,
431                 @IntRange(from = 0) int ttcIndex,
432                 @IntRange(from = 1, to = 1000) int weight,
433                 boolean italic,
434                 int resultCode
435         ) {
436             return new FontInfo(uri, ttcIndex, weight, italic, resultCode);
437         }
438 
439         /**
440          * Returns a URI associated to this record.
441          */
getUri()442         public @NonNull Uri getUri() {
443             return mUri;
444         }
445 
446         /**
447          * Returns the index to be used to access this font when accessing a TTC file.
448          */
getTtcIndex()449         public @IntRange(from = 0) int getTtcIndex() {
450             return mTtcIndex;
451         }
452 
453         /**
454          * Returns the weight value for this font.
455          */
getWeight()456         public @IntRange(from = 1, to = 1000) int getWeight() {
457             return mWeight;
458         }
459 
460         /**
461          * Returns whether this font is italic.
462          */
isItalic()463         public boolean isItalic() {
464             return mItalic;
465         }
466 
467         /**
468          * Returns result code.
469          *
470          * {@link FontsContractCompat.Columns#RESULT_CODE}
471          */
getResultCode()472         public int getResultCode() {
473             return mResultCode;
474         }
475     }
476 
477     /**
478      * Object returned from {@link #fetchFonts}.
479      */
480     public static class FontFamilyResult {
481         /**
482          * Constant represents that the font was successfully retrieved. Note that when this value
483          * is set and {@link #getFonts} returns an empty array, it means there were no fonts
484          * matching the given query.
485          */
486         public static final int STATUS_OK = 0;
487 
488         /**
489          * Constant represents that the given certificate was not matched with the provider's
490          * signature. {@link #getFonts} returns null if this status was set.
491          */
492         public static final int STATUS_WRONG_CERTIFICATES = 1;
493 
494         /**
495          * Constant represents that the provider returns unexpected data. {@link #getFonts} returns
496          * null if this status was set. For example, this value is set when the font provider
497          * gives invalid format of variation settings.
498          */
499         public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2;
500 
501         @RestrictTo(LIBRARY)
502         @IntDef({STATUS_OK, STATUS_WRONG_CERTIFICATES, STATUS_UNEXPECTED_DATA_PROVIDED})
503         @Retention(RetentionPolicy.SOURCE)
504         @interface FontResultStatus {}
505 
506         private final @FontResultStatus int mStatusCode;
507         private final List<FontInfo[]> mFonts;
508 
509         /**
510          * @deprecated Not being used by any cross library, and should not be used, internal
511          * implementation detail.
512          */
513         // TODO after removing from public API make package private.
514         @Deprecated
515         @RestrictTo(LIBRARY_GROUP_PREFIX)
FontFamilyResult(@ontResultStatus int statusCode, FontInfo @Nullable [] fonts)516         public FontFamilyResult(@FontResultStatus int statusCode, FontInfo @Nullable [] fonts) {
517             mStatusCode = statusCode;
518             mFonts = Collections.singletonList(fonts);
519         }
520 
FontFamilyResult(@ontResultStatus int statusCode, @NonNull List<FontInfo[]> fonts)521         FontFamilyResult(@FontResultStatus int statusCode, @NonNull List<FontInfo[]> fonts) {
522             mStatusCode = statusCode;
523             mFonts = fonts;
524         }
525 
getStatusCode()526         public @FontResultStatus int getStatusCode() {
527             return mStatusCode;
528         }
529 
530         /**
531          * For a single request, returns an array of the fonts making up the family.
532          * <p>
533          * For a request with fallbacks, use {@link #getFontsWithFallbacks()},
534          * as this will only return the information for the first requested family.
535          */
getFonts()536         public FontInfo[] getFonts() {
537             return mFonts.get(0);
538         }
539 
hasFallback()540         boolean hasFallback() {
541             return mFonts.size() > 1;
542         }
543 
544         /**
545          * Returns a list of arrays of fonts for each font family requested, in order.
546          */
getFontsWithFallbacks()547         public @NonNull List<FontInfo[]> getFontsWithFallbacks() {
548             return mFonts;
549         }
550 
551         @SuppressWarnings("deprecation")
create( @ontResultStatus int statusCode, FontInfo @Nullable [] fonts)552         static FontFamilyResult create(
553                 @FontResultStatus int statusCode,
554                 FontInfo @Nullable [] fonts) {
555             return new FontFamilyResult(statusCode, fonts);
556         }
557 
create( @ontResultStatus int statusCode, @Nullable List<FontInfo[]> fonts)558         static FontFamilyResult create(
559                 @FontResultStatus int statusCode,
560                 @Nullable List<FontInfo[]> fonts) {
561             return new FontFamilyResult(statusCode, fonts);
562         }
563     }
564 
565     /**
566      * Interface used to receive asynchronously fetched typefaces.
567      */
568     public static class FontRequestCallback {
569         /**
570          * @deprecated Not being used by any cross library, and should not be used, internal
571          * implementation detail.
572          */
573         @Deprecated
574         @RestrictTo(LIBRARY_GROUP_PREFIX)
575         public static final int RESULT_OK = Columns.RESULT_CODE_OK;
576 
577         static final int RESULT_SUCCESS = Columns.RESULT_CODE_OK;
578 
579         /**
580          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
581          * provider was not found on the device.
582          */
583         public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1;
584 
585         /**
586          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
587          * provider must be authenticated and the given certificates do not match its signature.
588          */
589         public static final int FAIL_REASON_WRONG_CERTIFICATES = -2;
590 
591         /**
592          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
593          * returned by the provider was not loaded properly.
594          */
595         public static final int FAIL_REASON_FONT_LOAD_ERROR = -3;
596 
597         /**
598          * Constant that signals that the font was not loaded due to security issues. This usually
599          * means the font was attempted to load on a restricted context.
600          */
601         public static final int FAIL_REASON_SECURITY_VIOLATION = -4;
602 
603         /**
604          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
605          * provider did not return any results for the given query.
606          */
607         public static final int FAIL_REASON_FONT_NOT_FOUND = Columns.RESULT_CODE_FONT_NOT_FOUND;
608 
609         /**
610          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
611          * provider found the queried font, but it is currently unavailable.
612          */
613         public static final int FAIL_REASON_FONT_UNAVAILABLE = Columns.RESULT_CODE_FONT_UNAVAILABLE;
614 
615         /**
616          * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
617          * query was not supported by the provider.
618          */
619         public static final int FAIL_REASON_MALFORMED_QUERY = Columns.RESULT_CODE_MALFORMED_QUERY;
620 
621         @SuppressWarnings("deprecation")
622         @RestrictTo(LIBRARY_GROUP_PREFIX)
623         @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR,
624                 FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE,
625                 FAIL_REASON_MALFORMED_QUERY, FAIL_REASON_WRONG_CERTIFICATES,
626                 FAIL_REASON_SECURITY_VIOLATION, RESULT_OK })
627         @Retention(RetentionPolicy.SOURCE)
628         public @interface FontRequestFailReason {}
629 
FontRequestCallback()630         public FontRequestCallback() {}
631 
632         /**
633          * Called then a Typeface request done via {@link #requestFont(Context, FontRequest,
634          * FontRequestCallback, Handler)} is complete. Note that this method will not be called if
635          * {@link #onTypefaceRequestFailed(int)} is called instead.
636          * @param typeface  The Typeface object retrieved.
637          */
onTypefaceRetrieved(Typeface typeface)638         public void onTypefaceRetrieved(Typeface typeface) {}
639 
640         /**
641          * Called when a Typeface request done via {@link #requestFont(Context, FontRequest,
642          * FontRequestCallback, Handler)} fails.
643          * @param reason May be one of {@link #FAIL_REASON_PROVIDER_NOT_FOUND},
644          *               {@link #FAIL_REASON_FONT_NOT_FOUND},
645          *               {@link #FAIL_REASON_FONT_LOAD_ERROR},
646          *               {@link #FAIL_REASON_FONT_UNAVAILABLE},
647          *               {@link #FAIL_REASON_MALFORMED_QUERY} or
648          *               {@link #FAIL_REASON_WRONG_CERTIFICATES}, or a provider defined positive
649          *               code number.
650          */
onTypefaceRequestFailed(@ontRequestFailReason int reason)651         public void onTypefaceRequestFailed(@FontRequestFailReason int reason) {}
652     }
653 
654     /**
655      * Constant used to identify the List of {@link ParcelFileDescriptor} item in the Bundle
656      * returned to the ResultReceiver in getFont.
657      *
658      * @deprecated Not being used by any cross library, and should not be used, internal
659      * implementation detail.
660      *
661      */
662     @Deprecated // unused
663     @RestrictTo(LIBRARY_GROUP_PREFIX)
664     public static final String PARCEL_FONT_RESULTS = "font_results";
665 
666     // Error codes internal to the system, which can not come from a provider. To keep the number
667     // space open for new provider codes, these should all be negative numbers.
668     /**
669      * @deprecated Not being used by any cross library, and should not be used, internal
670      * implementation detail.
671      */
672     @Deprecated // unused
673     @RestrictTo(LIBRARY_GROUP_PREFIX)
674     static final int RESULT_CODE_PROVIDER_NOT_FOUND = -1;
675 
676     /**
677      * @deprecated Not being used by any cross library, and should not be used, internal
678      * implementation detail.
679      */
680     @Deprecated // unused
681     @RestrictTo(LIBRARY_GROUP_PREFIX)
682     static final int RESULT_CODE_WRONG_CERTIFICATES = -2;
683     // Note -3 is used by FontRequestCallback to indicate the font failed to load.
684 
685     /**
686      * @deprecated Not being used by any cross library, and should not be used, internal
687      * implementation detail.
688      */
689     @Deprecated // unused
690     @RestrictTo(LIBRARY_GROUP_PREFIX)
getFontSync( final Context context, final FontRequest request, final ResourcesCompat.@Nullable FontCallback fontCallback, final @Nullable Handler handler, boolean isBlockingFetch, int timeout, @TypefaceStyle final int style )691     public static Typeface getFontSync(
692             final Context context,
693             final FontRequest request,
694             final ResourcesCompat.@Nullable FontCallback fontCallback,
695             final @Nullable Handler handler,
696             boolean isBlockingFetch,
697             int timeout,
698             @TypefaceStyle final int style
699     ) {
700         FontRequestCallback newCallback = new TypefaceCompat.ResourcesCallbackAdapter(fontCallback);
701         Handler newHandler = ResourcesCompat.FontCallback.getHandler(handler);
702         return requestFont(context, List.of(request), style, isBlockingFetch, timeout,
703                 newHandler, newCallback
704         );
705     }
706 
707     /**
708      * @deprecated Not being used by any cross library, and should not be used, internal
709      * implementation detail.
710      */
711     @Deprecated // unused
712     @RestrictTo(LIBRARY_GROUP_PREFIX)
resetCache()713     public static void resetCache() {
714         FontRequestWorker.resetTypefaceCache();
715     }
716 
717     /**
718      * A helper function to create a mapping from {@link Uri} to {@link ByteBuffer}.
719      *
720      * Skip if the file contents is not ready to be read.
721      *
722      * @param context A {@link Context} to be used for resolving content URI in
723      *                {@link FontInfo}.
724      * @param fonts An array of {@link FontInfo}.
725      * @return A map from {@link Uri} to {@link ByteBuffer}.
726      *
727      * @deprecated Not being used by any cross library, and should not be used, internal
728      * implementation detail.
729      *
730      */
731     @Deprecated // unused
732     @RestrictTo(LIBRARY_GROUP_PREFIX)
prepareFontData( Context context, FontInfo[] fonts, CancellationSignal cancellationSignal )733     public static Map<Uri, ByteBuffer> prepareFontData(
734             Context context,
735             FontInfo[] fonts,
736             CancellationSignal cancellationSignal
737     ) {
738         return TypefaceCompatUtil.readFontInfoIntoByteBuffer(context, fonts, cancellationSignal);
739     }
740 
741     /**
742      * @deprecated Not being used by any cross library, and should not be used, internal
743      * implementation detail.
744      */
745     @Deprecated // unused
746     @VisibleForTesting
747     @RestrictTo(LIBRARY_GROUP_PREFIX)
getProvider( @onNull PackageManager packageManager, @NonNull FontRequest request, @Nullable Resources resources )748     public static @Nullable ProviderInfo getProvider(
749             @NonNull PackageManager packageManager,
750             @NonNull FontRequest request,
751             @Nullable Resources resources
752     ) throws PackageManager.NameNotFoundException {
753         return FontProvider.getProvider(packageManager, request, resources);
754     }
755 }
756