10b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka/* 20b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Copyright (C) 2017 The Android Open Source Project 30b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 40b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Licensed under the Apache License, Version 2.0 (the "License"); 50b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * you may not use this file except in compliance with the License. 60b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * You may obtain a copy of the License at 70b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 80b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * http://www.apache.org/licenses/LICENSE-2.0 90b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 100b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Unless required by applicable law or agreed to in writing, software 110b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * distributed under the License is distributed on an "AS IS" BASIS, 120b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * See the License for the specific language governing permissions and 140b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * limitations under the License. 150b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 160b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.core.provider; 180b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP; 200b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 21b34c816d06018c63f61ed13d24d8301244800e01Clara Bayarriimport android.annotation.SuppressLint; 220b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.content.ContentResolver; 230b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.content.ContentUris; 240b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.content.Context; 250b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.content.pm.PackageInfo; 260b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.content.pm.PackageManager; 270b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.content.pm.ProviderInfo; 280b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.content.pm.Signature; 290b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.content.res.Resources; 300b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.database.Cursor; 310b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.graphics.Typeface; 320b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.net.Uri; 330b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.os.Build; 340b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.os.CancellationSignal; 350b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.os.Handler; 360b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.os.ParcelFileDescriptor; 37fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonakaimport android.os.Process; 380b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport android.provider.BaseColumns; 399dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikas 40ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.GuardedBy; 41ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.IntDef; 42ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.IntRange; 43ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.NonNull; 44ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.Nullable; 45ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RequiresApi; 46ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RestrictTo; 47ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.VisibleForTesting; 489dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikasimport androidx.collection.LruCache; 499dede51868bbbe16aadcd65e04860bea8ea50e05Aurimas Liutikasimport androidx.collection.SimpleArrayMap; 50ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.content.res.FontResourcesParserCompat; 51ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.content.res.ResourcesCompat; 52ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.graphics.TypefaceCompat; 53ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.graphics.TypefaceCompatUtil; 54ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.provider.SelfDestructiveThread.ReplyCallback; 55ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.core.util.Preconditions; 560b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 570b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport java.lang.annotation.Retention; 580b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport java.lang.annotation.RetentionPolicy; 5911e831738feba2bb6c5338358812a373bda9991aClara Bayarriimport java.nio.ByteBuffer; 600b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport java.util.ArrayList; 610b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport java.util.Arrays; 620b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport java.util.Collections; 630b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport java.util.Comparator; 6411e831738feba2bb6c5338358812a373bda9991aClara Bayarriimport java.util.HashMap; 650b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakaimport java.util.List; 6611e831738feba2bb6c5338358812a373bda9991aClara Bayarriimport java.util.Map; 67fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonakaimport java.util.concurrent.Callable; 680b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 690b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka/** 700b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Utility class to deal with Font ContentProviders. 710b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 720b03693667d95d2202dfbb24866665ff061acce1Seigo Nonakapublic class FontsContractCompat { 730b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private static final String TAG = "FontsContractCompat"; 740b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 750b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private FontsContractCompat() { } 760b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 770b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 780b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Defines the constants used in a response from a Font Provider. The cursor returned from the 790b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * query should have the ID column populated with the content uri ID for the resulting font. 800b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * This should point to a real file or shared memory, as the client will mmap the given file 810b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * descriptor. Pipes, sockets and other non-mmap-able file descriptors will fail to load in the 820b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * client application. 830b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 840b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final class Columns implements BaseColumns { 850b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 860b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 870b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * may populate this column with a long for the font file ID. The client will request a file 880b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * descriptor to "file/FILE_ID" with this ID immediately under the top-level content URI. If 890b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * not present, the client will request a file descriptor to the top-level URI with the 900b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * given base font ID. Note that several results may return the same file ID, e.g. for TTC 910b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * files with different indices. 920b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 930b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final String FILE_ID = "file_id"; 940b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 950b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 960b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * should have this column populated with an int for the ttc index for the resulting font. 970b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 980b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final String TTC_INDEX = android.provider.FontsContract.Columns.TTC_INDEX; 990b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1000b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 1010b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * may populate this column with the font variation settings String information for the 1020b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * font. 1030b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1040b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final String VARIATION_SETTINGS = 1050b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka android.provider.FontsContract.Columns.VARIATION_SETTINGS; 1060b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1070b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 1080b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * should have this column populated with the int weight for the resulting font. This value 1090b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * should be between 100 and 900. The most common values are 400 for regular weight and 700 1100b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * for bold weight. 1110b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1120b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final String WEIGHT = android.provider.FontsContract.Columns.WEIGHT; 1130b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1140b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 1150b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * should have this column populated with the int italic for the resulting font. This should 1160b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * be 0 for regular style and 1 for italic. 1170b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1180b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final String ITALIC = android.provider.FontsContract.Columns.ITALIC; 1190b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1200b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 1210b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * should have this column populated to indicate the result status of the 1220b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * query. This will be checked before any other data in the cursor. Possible values are 1230b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #RESULT_CODE_OK}, {@link #RESULT_CODE_FONT_NOT_FOUND}, 1240b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #RESULT_CODE_MALFORMED_QUERY} and {@link #RESULT_CODE_FONT_UNAVAILABLE}. If not 1250b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * present, {@link #RESULT_CODE_OK} will be assumed. 1260b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1270b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final String RESULT_CODE = android.provider.FontsContract.Columns.RESULT_CODE; 1280b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 1290b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1300b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to represent a result was retrieved successfully. The given fonts will be 1310b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * attempted to retrieve immediately via 1320b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link android.content.ContentProvider#openFile(Uri, String)}. See {@link #RESULT_CODE}. 1330b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1340b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int RESULT_CODE_OK = 1350b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka android.provider.FontsContract.Columns.RESULT_CODE_OK; 1360b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1370b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to represent a result was not found. See {@link #RESULT_CODE}. 1380b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1390b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int RESULT_CODE_FONT_NOT_FOUND = 1400b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka android.provider.FontsContract.Columns.RESULT_CODE_FONT_NOT_FOUND; 1410b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1420b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to represent a result was found, but cannot be provided at this moment. Use 1430b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * this to indicate, for example, that a font needs to be fetched from the network. See 1440b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #RESULT_CODE}. 1450b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1460b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int RESULT_CODE_FONT_UNAVAILABLE = 1470b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka android.provider.FontsContract.Columns.RESULT_CODE_FONT_UNAVAILABLE; 1480b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1490b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to represent that the query was not in a supported format by the provider. 1500b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * See {@link #RESULT_CODE}. 1510b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1520b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int RESULT_CODE_MALFORMED_QUERY = 1530b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka android.provider.FontsContract.Columns.RESULT_CODE_MALFORMED_QUERY; 1540b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 1550b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 1560b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 1570b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant used to identify the List of {@link ParcelFileDescriptor} item in the Bundle 1580b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * returned to the ResultReceiver in getFont. 1590b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @hide 1600b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 1610b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 1620b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final String PARCEL_FONT_RESULTS = "font_results"; 1630b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 1640b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // Error codes internal to the system, which can not come from a provider. To keep the number 1650b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // space open for new provider codes, these should all be negative numbers. 1660b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** @hide */ 1670b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 168758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri /* package */ static final int RESULT_CODE_PROVIDER_NOT_FOUND = -1; 1690b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** @hide */ 1700b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 171758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri /* package */ static final int RESULT_CODE_WRONG_CERTIFICATES = -2; 172758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri // Note -3 is used by FontRequestCallback to indicate the font failed to load. 1730b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 1748eeb6c6cdd4bdcb6807cd8152e1e36b4883a8fa5Jake Wharton static final LruCache<String, Typeface> sTypefaceCache = new LruCache<>(16); 175fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka 176fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka private static final int BACKGROUND_THREAD_KEEP_ALIVE_DURATION_MS = 10000; 177fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka private static final SelfDestructiveThread sBackgroundThread = 178fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka new SelfDestructiveThread("fonts", Process.THREAD_PRIORITY_BACKGROUND, 179fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka BACKGROUND_THREAD_KEEP_ALIVE_DURATION_MS); 180fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka 181758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri @NonNull 1828eeb6c6cdd4bdcb6807cd8152e1e36b4883a8fa5Jake Wharton static TypefaceResult getFontInternal(final Context context, final FontRequest request, 18308df2afeec46f363ef5f17146750bdf011412e56Seigo Nonaka int style) { 1842afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka FontFamilyResult result; 1852afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka try { 1862afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka result = fetchFonts(context, null /* CancellationSignal */, request); 1872afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } catch (PackageManager.NameNotFoundException e) { 188758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri return new TypefaceResult(null, FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND); 1892afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 1902afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka if (result.getStatusCode() == FontFamilyResult.STATUS_OK) { 191758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri final Typeface typeface = TypefaceCompat.createFromFontInfo( 192758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri context, null /* CancellationSignal */, result.getFonts(), style); 193758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri return new TypefaceResult(typeface, typeface != null 194758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri ? FontRequestCallback.RESULT_OK 195758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri : FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); 1962afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 197758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri int resultCode = result.getStatusCode() == FontFamilyResult.STATUS_WRONG_CERTIFICATES 198758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri ? FontRequestCallback.FAIL_REASON_WRONG_CERTIFICATES 199758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri : FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR; 200758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri return new TypefaceResult(null, resultCode); 2012afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 2022afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka 2038eeb6c6cdd4bdcb6807cd8152e1e36b4883a8fa5Jake Wharton static final Object sLock = new Object(); 2042afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka @GuardedBy("sLock") 2058eeb6c6cdd4bdcb6807cd8152e1e36b4883a8fa5Jake Wharton static final SimpleArrayMap<String, ArrayList<ReplyCallback<TypefaceResult>>> 2062afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka sPendingReplies = new SimpleArrayMap<>(); 2072afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka 208758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri private static final class TypefaceResult { 209758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri final Typeface mTypeface; 210758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri @FontRequestCallback.FontRequestFailReason final int mResult; 211758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri 212758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri TypefaceResult(@Nullable Typeface typeface, 213758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri @FontRequestCallback.FontRequestFailReason int result) { 214758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri mTypeface = typeface; 215758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri mResult = result; 216758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 217758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 218758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri 219758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri /** 220758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri * Used for tests, should not be used otherwise. 221758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri * @hide 222758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri **/ 223758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri @RestrictTo(LIBRARY_GROUP) 224c05db2551709fb74903cce69f3e4b9f553e607afJake Wharton public static void resetCache() { 225758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri sTypefaceCache.evictAll(); 226758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 227758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri 228fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka /** @hide */ 229fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 2302afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka public static Typeface getFontSync(final Context context, final FontRequest request, 231758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri final @Nullable ResourcesCompat.FontCallback fontCallback, 232758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri final @Nullable Handler handler, boolean isBlockingFetch, int timeout, 233c0eb63876d2618a3560bc7d0c06d80f70e3ebce6Seigo Nonaka final int style) { 23408df2afeec46f363ef5f17146750bdf011412e56Seigo Nonaka final String id = request.getIdentifier() + "-" + style; 235fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka Typeface cached = sTypefaceCache.get(id); 236fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka if (cached != null) { 237758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri if (fontCallback != null) { 238758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri fontCallback.onFontRetrieved(cached); 239758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 240fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka return cached; 241fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka } 242fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka 2432afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka if (isBlockingFetch && timeout == FontResourcesParserCompat.INFINITE_TIMEOUT_VALUE) { 2442afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka // Wait forever. No need to post to the thread. 245758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri TypefaceResult typefaceResult = getFontInternal(context, request, style); 246758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri if (fontCallback != null) { 247758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri if (typefaceResult.mResult == FontFamilyResult.STATUS_OK) { 248758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri fontCallback.callbackSuccessAsync(typefaceResult.mTypeface, handler); 249758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } else { 250758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri fontCallback.callbackFailAsync(typefaceResult.mResult, handler); 251758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 252758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 253758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri return typefaceResult.mTypeface; 2542afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 2552afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka 256758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri final Callable<TypefaceResult> fetcher = new Callable<TypefaceResult>() { 2572afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka @Override 258758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri public TypefaceResult call() throws Exception { 259758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri TypefaceResult typeface = getFontInternal(context, request, style); 260758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri if (typeface.mTypeface != null) { 261758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri sTypefaceCache.put(id, typeface.mTypeface); 2622afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 2632afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka return typeface; 2642afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 2652afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka }; 2662afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka 2672afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka if (isBlockingFetch) { 2682afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka try { 269758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri return sBackgroundThread.postAndWait(fetcher, timeout).mTypeface; 2702afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } catch (InterruptedException e) { 2712afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka return null; 2722afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 2732afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } else { 274758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri final ReplyCallback<TypefaceResult> reply = fontCallback == null ? null 275758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri : new ReplyCallback<TypefaceResult>() { 276758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri @Override 277758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri public void onReply(final TypefaceResult typeface) { 278b130e7d5297cca645f8747b7055a1f3e3c608755Clara Bayarri if (typeface == null) { 279b130e7d5297cca645f8747b7055a1f3e3c608755Clara Bayarri fontCallback.callbackFailAsync( 280b130e7d5297cca645f8747b7055a1f3e3c608755Clara Bayarri FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND, handler); 281b130e7d5297cca645f8747b7055a1f3e3c608755Clara Bayarri } else if (typeface.mResult == FontFamilyResult.STATUS_OK) { 282758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri fontCallback.callbackSuccessAsync(typeface.mTypeface, handler); 283758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } else { 284758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri fontCallback.callbackFailAsync(typeface.mResult, handler); 285758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 286758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 287758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri }; 2882afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka 2892afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka synchronized (sLock) { 2902afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka if (sPendingReplies.containsKey(id)) { 2912afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka // Already requested. Do not request the same provider again and insert the 2922afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka // reply to the queue instead. 293758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri if (reply != null) { 294758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri sPendingReplies.get(id).add(reply); 295758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 296fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka return null; 297fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka } 298758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri if (reply != null) { 299758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri ArrayList<ReplyCallback<TypefaceResult>> pendingReplies = new ArrayList<>(); 300758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri pendingReplies.add(reply); 301758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri sPendingReplies.put(id, pendingReplies); 302758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 3032afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 304758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri sBackgroundThread.postAndReply(fetcher, new ReplyCallback<TypefaceResult>() { 3052afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka @Override 306758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri public void onReply(final TypefaceResult typeface) { 307758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri final ArrayList<ReplyCallback<TypefaceResult>> replies; 3082afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka synchronized (sLock) { 3092afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka replies = sPendingReplies.get(id); 3101f11788de2c6be7af5790e4d6fbc4b8a8d7a5b26Seigo Nonaka if (replies == null) { 3111f11788de2c6be7af5790e4d6fbc4b8a8d7a5b26Seigo Nonaka return; // Nobody requested replies. Do nothing. 3121f11788de2c6be7af5790e4d6fbc4b8a8d7a5b26Seigo Nonaka } 3132afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka sPendingReplies.remove(id); 3142afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 3152afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka for (int i = 0; i < replies.size(); ++i) { 3162afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka replies.get(i).onReply(typeface); 3172afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka } 318758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri } 3192afabd060e15342c0ba622cb08f5be61a328e566Seigo Nonaka }); 320fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka return null; 321fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka } 322fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka } 323fc857452283b38dfbac9ca023a77a8cf8b8c5599Seigo Nonaka 3240b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3250b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Object represent a font entry in the family returned from {@link #fetchFonts}. 3260b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 3270b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static class FontInfo { 3280b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private final Uri mUri; 3290b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private final int mTtcIndex; 3300b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private final int mWeight; 3310b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private final boolean mItalic; 3320b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private final int mResultCode; 3330b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 3340b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3350b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Creates a Font with all the information needed about a provided font. 3360b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param uri A URI associated to the font file. 3370b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0. 3380b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param weight An integer that indicates the font weight. 3390b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param italic A boolean that indicates the font is italic style or not. 3400b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param resultCode A boolean that indicates the font contents is ready. 341758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri * 342758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri * @hide 3430b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 3440b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 3450b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public FontInfo(@NonNull Uri uri, @IntRange(from = 0) int ttcIndex, 3460b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @IntRange(from = 1, to = 1000) int weight, 3470b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka boolean italic, int resultCode) { 3480b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka mUri = Preconditions.checkNotNull(uri); 3490b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka mTtcIndex = ttcIndex; 3500b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka mWeight = weight; 3510b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka mItalic = italic; 3520b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka mResultCode = resultCode; 3530b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 3540b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 3550b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3560b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Returns a URI associated to this record. 3570b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 3580b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public @NonNull Uri getUri() { 3590b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return mUri; 3600b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 3610b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 3620b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3630b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Returns the index to be used to access this font when accessing a TTC file. 3640b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 3650b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public @IntRange(from = 0) int getTtcIndex() { 3660b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return mTtcIndex; 3670b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 3680b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 3690b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3700b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Returns the weight value for this font. 3710b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 3720b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public @IntRange(from = 1, to = 1000) int getWeight() { 3730b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return mWeight; 3740b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 3750b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 3760b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3770b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Returns whether this font is italic. 3780b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 3790b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public boolean isItalic() { 3800b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return mItalic; 3810b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 3820b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 3830b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3840b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Returns result code. 3850b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 3860b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link FontsContractCompat.Columns#RESULT_CODE} 3870b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 3880b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public int getResultCode() { 3890b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return mResultCode; 3900b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 3910b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 3920b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 3930b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3940b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Object returned from {@link #fetchFonts}. 3950b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 3960b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static class FontFamilyResult { 3970b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 3980b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant represents that the font was successfully retrieved. Note that when this value 3990b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * is set and {@link #getFonts} returns an empty array, it means there were no fonts 4000b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * matching the given query. 4010b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4020b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int STATUS_OK = 0; 4030b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4040b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4050b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant represents that the given certificate was not matched with the provider's 4060b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * signature. {@link #getFonts} returns null if this status was set. 4070b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4080b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int STATUS_WRONG_CERTIFICATES = 1; 4090b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4100b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4110b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant represents that the provider returns unexpected data. {@link #getFonts} returns 4120b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * null if this status was set. For example, this value is set when the font provider 4130b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * gives invalid format of variation settings. 4140b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4150b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; 4160b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4170b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** @hide */ 4180b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 4190b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @IntDef({STATUS_OK, STATUS_WRONG_CERTIFICATES, STATUS_UNEXPECTED_DATA_PROVIDED}) 4200b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Retention(RetentionPolicy.SOURCE) 4210b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @interface FontResultStatus {} 4220b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4230b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private final @FontResultStatus int mStatusCode; 4240b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private final FontInfo[] mFonts; 4250b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4260b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** @hide */ 4270b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 4280b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public FontFamilyResult(@FontResultStatus int statusCode, @Nullable FontInfo[] fonts) { 4290b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka mStatusCode = statusCode; 4300b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka mFonts = fonts; 4310b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 4320b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4330b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public @FontResultStatus int getStatusCode() { 4340b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return mStatusCode; 4350b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 4360b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4370b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public FontInfo[] getFonts() { 4380b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return mFonts; 4390b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 4400b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 4410b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4420b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4430b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Interface used to receive asynchronously fetched typefaces. 4440b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4450b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static class FontRequestCallback { 446758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri /** @hide */ 447758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri @RestrictTo(LIBRARY_GROUP) 448758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri public static final int RESULT_OK = Columns.RESULT_CODE_OK; 4490b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4500b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given 4510b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * provider was not found on the device. 4520b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4530b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int FAIL_REASON_PROVIDER_NOT_FOUND = RESULT_CODE_PROVIDER_NOT_FOUND; 4540b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4550b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given 4560b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * provider must be authenticated and the given certificates do not match its signature. 4570b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4580b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int FAIL_REASON_WRONG_CERTIFICATES = RESULT_CODE_WRONG_CERTIFICATES; 4590b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4600b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font 4610b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * returned by the provider was not loaded properly. 4620b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4630b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; 4640b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 465758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri * Constant that signals that the font was not loaded due to security issues. This usually 466758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri * means the font was attempted to load on a restricted context. 467758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri */ 468758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri public static final int FAIL_REASON_SECURITY_VIOLATION = -4; 469758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri /** 4700b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font 4710b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * provider did not return any results for the given query. 4720b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4730b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int FAIL_REASON_FONT_NOT_FOUND = Columns.RESULT_CODE_FONT_NOT_FOUND; 4740b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4750b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font 4760b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * provider found the queried font, but it is currently unavailable. 4770b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4780b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int FAIL_REASON_FONT_UNAVAILABLE = Columns.RESULT_CODE_FONT_UNAVAILABLE; 4790b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4800b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given 4810b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * query was not supported by the provider. 4820b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 4830b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static final int FAIL_REASON_MALFORMED_QUERY = Columns.RESULT_CODE_MALFORMED_QUERY; 4840b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4850b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** @hide */ 4860b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 4870b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR, 4880b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE, 489758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri FAIL_REASON_MALFORMED_QUERY, FAIL_REASON_WRONG_CERTIFICATES, 490758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri FAIL_REASON_SECURITY_VIOLATION, RESULT_OK }) 4910b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Retention(RetentionPolicy.SOURCE) 492758621d23659e4b0da3b2ad00a84a5624efb1be8Clara Bayarri public @interface FontRequestFailReason {} 4930b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4940b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public FontRequestCallback() {} 4950b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 4960b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 4970b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Called then a Typeface request done via {@link #requestFont(Context, FontRequest, 4980b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * FontRequestCallback, Handler)} is complete. Note that this method will not be called if 4990b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #onTypefaceRequestFailed(int)} is called instead. 5000b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param typeface The Typeface object retrieved. 5010b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 5020b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void onTypefaceRetrieved(Typeface typeface) {} 5030b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 5040b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 5050b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Called when a Typeface request done via {@link #requestFont(Context, FontRequest, 5060b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * FontRequestCallback, Handler)} fails. 5070b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param reason May be one of {@link #FAIL_REASON_PROVIDER_NOT_FOUND}, 5080b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #FAIL_REASON_FONT_NOT_FOUND}, 5090b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #FAIL_REASON_FONT_LOAD_ERROR}, 5100b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #FAIL_REASON_FONT_UNAVAILABLE}, 5110b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #FAIL_REASON_MALFORMED_QUERY} or 5120b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * {@link #FAIL_REASON_WRONG_CERTIFICATES}, or a provider defined positive 5130b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * code number. 5140b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 5150b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void onTypefaceRequestFailed(@FontRequestFailReason int reason) {} 5160b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5170b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 5180b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 5190b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Create a typeface object given a font request. The font will be asynchronously fetched, 5200b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * therefore the result is delivered to the given callback. See {@link FontRequest}. 5210b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Only one of the methods in callback will be invoked, depending on whether the request 5220b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * succeeds or fails. These calls will happen on the caller thread. 5230b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param context A context to be used for fetching from font provider. 5240b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param request A {@link FontRequest} object that identifies the provider and query for the 5250b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * request. May not be null. 5260b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param callback A callback that will be triggered when results are obtained. May not be null. 5270b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param handler A handler to be processed the font fetching. 5280b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 5290b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static void requestFont(final @NonNull Context context, 5300b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final @NonNull FontRequest request, final @NonNull FontRequestCallback callback, 5310b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final @NonNull Handler handler) { 5320b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final Handler callerThreadHandler = new Handler(); 5330b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka handler.post(new Runnable() { 5340b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 5350b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 5360b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // TODO: Cache the result. 5370b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontFamilyResult result; 5380b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka try { 5390b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka result = fetchFonts(context, null /* cancellation signal */, request); 5400b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } catch (PackageManager.NameNotFoundException e) { 5410b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 5420b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 5430b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 5440b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRequestFailed( 5450b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND); 5460b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5470b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 5480b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return; 5490b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5500b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 5510b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (result.getStatusCode() != FontFamilyResult.STATUS_OK) { 5520b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka switch (result.getStatusCode()) { 5530b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka case FontFamilyResult.STATUS_WRONG_CERTIFICATES: 5540b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 5550b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 5560b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 5570b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRequestFailed( 5580b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontRequestCallback.FAIL_REASON_WRONG_CERTIFICATES); 5590b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5600b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 5610b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return; 5620b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka case FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED: 5630b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 5640b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 5650b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 5660b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRequestFailed( 5670b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); 5680b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5690b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 5700b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return; 5710b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka default: 5720b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // fetchFont returns unexpected status type. Fallback to load error. 5730b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 5740b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 5750b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 5760b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRequestFailed( 5770b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); 5780b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5790b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 5800b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return; 5810b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5820b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5830b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 5840b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final FontInfo[] fonts = result.getFonts(); 5850b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (fonts == null || fonts.length == 0) { 5860b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 5870b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 5880b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 5890b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRequestFailed( 5900b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND); 5910b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5920b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 5930b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return; 5940b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 5950b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka for (final FontInfo font : fonts) { 5960b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (font.getResultCode() != Columns.RESULT_CODE_OK) { 5970b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // We proceed if all font entry is ready to use. Otherwise report the first 5980b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // error. 5990b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final int resultCode = font.getResultCode(); 6000b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (resultCode < 0) { 6010b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // Negative values are reserved for internal errors. Fallback to load 6020b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // error. 6030b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 6040b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 6050b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 6060b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRequestFailed( 6070b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); 6080b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6090b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 6100b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } else { 6110b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 6120b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 6130b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 6140b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRequestFailed(resultCode); 6150b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6160b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 6170b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6180b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return; 6190b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6200b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6210b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 6220b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final Typeface typeface = buildTypeface(context, null /* cancellation signal */, 6230b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka fonts); 6240b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (typeface == null) { 6250b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // Something went wrong during reading font files. This happens if the given 6260b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // font file is an unsupported font type. 6270b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 6280b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 6290b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 6300b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRequestFailed( 6310b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR); 6320b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6330b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 6340b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return; 6350b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6360b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 6370b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callerThreadHandler.post(new Runnable() { 6380b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 6390b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public void run() { 6400b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka callback.onTypefaceRetrieved(typeface); 6410b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6420b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 6430b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6440b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }); 6450b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6460b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 6470b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 6480b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Build a Typeface from an array of {@link FontInfo} 6490b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 6500b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Results that are marked as not ready will be skipped. 6510b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 6520b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param context A {@link Context} that will be used to fetch the font contents. 6530b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If 6540b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * the operation is canceled, then {@link 6550b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * android.os.OperationCanceledException} will be thrown. 6560b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param fonts An array of {@link FontInfo} to be used to create a Typeface. 6570b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @return A Typeface object. Returns null if typeface creation fails. 6580b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 6590a3498a4fe976baa759b1b5f27a7c8ebdeb07f4cJake Wharton @Nullable 6600b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static Typeface buildTypeface(@NonNull Context context, 6610b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts) { 66208df2afeec46f363ef5f17146750bdf011412e56Seigo Nonaka return TypefaceCompat.createFromFontInfo(context, cancellationSignal, fonts, 66308df2afeec46f363ef5f17146750bdf011412e56Seigo Nonaka Typeface.NORMAL); 6640b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 6650b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 6660b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** 66711e831738feba2bb6c5338358812a373bda9991aClara Bayarri * A helper function to create a mapping from {@link Uri} to {@link ByteBuffer}. 66811e831738feba2bb6c5338358812a373bda9991aClara Bayarri * 66911e831738feba2bb6c5338358812a373bda9991aClara Bayarri * Skip if the file contents is not ready to be read. 67011e831738feba2bb6c5338358812a373bda9991aClara Bayarri * 67111e831738feba2bb6c5338358812a373bda9991aClara Bayarri * @param context A {@link Context} to be used for resolving content URI in 67211e831738feba2bb6c5338358812a373bda9991aClara Bayarri * {@link FontInfo}. 67311e831738feba2bb6c5338358812a373bda9991aClara Bayarri * @param fonts An array of {@link FontInfo}. 67411e831738feba2bb6c5338358812a373bda9991aClara Bayarri * @return A map from {@link Uri} to {@link ByteBuffer}. 67511e831738feba2bb6c5338358812a373bda9991aClara Bayarri * @hide 67611e831738feba2bb6c5338358812a373bda9991aClara Bayarri */ 67711e831738feba2bb6c5338358812a373bda9991aClara Bayarri @RestrictTo(LIBRARY_GROUP) 67811e831738feba2bb6c5338358812a373bda9991aClara Bayarri @RequiresApi(19) 67911e831738feba2bb6c5338358812a373bda9991aClara Bayarri public static Map<Uri, ByteBuffer> prepareFontData(Context context, FontInfo[] fonts, 68011e831738feba2bb6c5338358812a373bda9991aClara Bayarri CancellationSignal cancellationSignal) { 68111e831738feba2bb6c5338358812a373bda9991aClara Bayarri final HashMap<Uri, ByteBuffer> out = new HashMap<>(); 68211e831738feba2bb6c5338358812a373bda9991aClara Bayarri 68311e831738feba2bb6c5338358812a373bda9991aClara Bayarri for (FontInfo font : fonts) { 68411e831738feba2bb6c5338358812a373bda9991aClara Bayarri if (font.getResultCode() != Columns.RESULT_CODE_OK) { 68511e831738feba2bb6c5338358812a373bda9991aClara Bayarri continue; 68611e831738feba2bb6c5338358812a373bda9991aClara Bayarri } 68711e831738feba2bb6c5338358812a373bda9991aClara Bayarri 68811e831738feba2bb6c5338358812a373bda9991aClara Bayarri final Uri uri = font.getUri(); 68911e831738feba2bb6c5338358812a373bda9991aClara Bayarri if (out.containsKey(uri)) { 69011e831738feba2bb6c5338358812a373bda9991aClara Bayarri continue; 69111e831738feba2bb6c5338358812a373bda9991aClara Bayarri } 69211e831738feba2bb6c5338358812a373bda9991aClara Bayarri 69311e831738feba2bb6c5338358812a373bda9991aClara Bayarri ByteBuffer buffer = TypefaceCompatUtil.mmap(context, cancellationSignal, uri); 69411e831738feba2bb6c5338358812a373bda9991aClara Bayarri out.put(uri, buffer); 69511e831738feba2bb6c5338358812a373bda9991aClara Bayarri } 69611e831738feba2bb6c5338358812a373bda9991aClara Bayarri return Collections.unmodifiableMap(out); 69711e831738feba2bb6c5338358812a373bda9991aClara Bayarri } 69811e831738feba2bb6c5338358812a373bda9991aClara Bayarri 69911e831738feba2bb6c5338358812a373bda9991aClara Bayarri /** 7000b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * Fetch fonts given a font request. 7010b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 7020b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param context A {@link Context} to be used for fetching fonts. 7030b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If 7040b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * the operation is canceled, then {@link 7050b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * android.os.OperationCanceledException} will be thrown when the 7060b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * query is executed. 7070b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @param request A {@link FontRequest} object that identifies the provider and query for the 7080b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * request. 7090b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 7100b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @return {@link FontFamilyResult} 7110b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * 7120b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * @throws PackageManager.NameNotFoundException If requested package or authority was not found 7130b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka * in the system. 7140b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka */ 7150b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @NonNull 7160b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static FontFamilyResult fetchFonts(@NonNull Context context, 7170b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Nullable CancellationSignal cancellationSignal, @NonNull FontRequest request) 7180b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka throws PackageManager.NameNotFoundException { 7190b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka ProviderInfo providerInfo = getProvider( 7200b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka context.getPackageManager(), request, context.getResources()); 7210b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (providerInfo == null) { 7220b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_WRONG_CERTIFICATES, null); 7230b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 7240b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7250b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka FontInfo[] fonts = getFontFromProvider( 7260b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka context, request, providerInfo.authority, cancellationSignal); 7270b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_OK, fonts); 7280b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7290b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 7300b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka /** @hide */ 7310b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @VisibleForTesting 7320b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @RestrictTo(LIBRARY_GROUP) 7330b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public static @Nullable ProviderInfo getProvider(@NonNull PackageManager packageManager, 7340b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @NonNull FontRequest request, @Nullable Resources resources) 7350b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka throws PackageManager.NameNotFoundException { 7360b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka String providerAuthority = request.getProviderAuthority(); 7370b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka ProviderInfo info = packageManager.resolveContentProvider(providerAuthority, 0); 7380b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (info == null) { 7390b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka throw new PackageManager.NameNotFoundException("No package found for authority: " 7400b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka + providerAuthority); 7410b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7420b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 7430b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (!info.packageName.equals(request.getProviderPackage())) { 7440b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka throw new PackageManager.NameNotFoundException("Found content provider " 7450b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka + providerAuthority 7460b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka + ", but package was not " + request.getProviderPackage()); 7470b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7480b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 7490b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka List<byte[]> signatures; 750b34c816d06018c63f61ed13d24d8301244800e01Clara Bayarri // We correctly check all signatures returned, as advised in the lint error. 751b34c816d06018c63f61ed13d24d8301244800e01Clara Bayarri @SuppressLint("PackageManagerGetSignatures") 7520b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka PackageInfo packageInfo = packageManager.getPackageInfo(info.packageName, 7530b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka PackageManager.GET_SIGNATURES); 7540b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka signatures = convertToByteArrayList(packageInfo.signatures); 7550b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Collections.sort(signatures, sByteArrayComparator); 7560b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka List<List<byte[]>> requestCertificatesList = getCertificates(request, resources); 7570b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka for (int i = 0; i < requestCertificatesList.size(); ++i) { 7580b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // Make a copy so we can sort it without modifying the incoming data. 7590b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka List<byte[]> requestSignatures = new ArrayList<>(requestCertificatesList.get(i)); 7600b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Collections.sort(requestSignatures, sByteArrayComparator); 7610b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (equalsByteArrayList(signatures, requestSignatures)) { 7620b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return info; 7630b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7640b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7650b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return null; 7660b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7670b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 7680b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private static List<List<byte[]>> getCertificates(FontRequest request, Resources resources) { 7690b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (request.getCertificates() != null) { 7700b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return request.getCertificates(); 7710b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7720b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka int resourceId = request.getCertificatesArrayResId(); 7730b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return FontResourcesParserCompat.readCerts(resources, resourceId); 7740b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7750b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 7760b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private static final Comparator<byte[]> sByteArrayComparator = new Comparator<byte[]>() { 7770b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @Override 7780b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka public int compare(byte[] l, byte[] r) { 7790b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (l.length != r.length) { 7800b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return l.length - r.length; 7810b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7820b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka for (int i = 0; i < l.length; ++i) { 7830b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (l[i] != r[i]) { 7840b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return l[i] - r[i]; 7850b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7860b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7870b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return 0; 7880b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7890b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka }; 7900b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 7910b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private static boolean equalsByteArrayList(List<byte[]> signatures, 7920b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka List<byte[]> requestSignatures) { 7930b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (signatures.size() != requestSignatures.size()) { 7940b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return false; 7950b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 7960b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka for (int i = 0; i < signatures.size(); ++i) { 7970b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (!Arrays.equals(signatures.get(i), requestSignatures.get(i))) { 7980b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return false; 7990b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8000b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8010b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return true; 8020b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8030b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 8040b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka private static List<byte[]> convertToByteArrayList(Signature[] signatures) { 8050b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka List<byte[]> shas = new ArrayList<>(); 8060b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka for (int i = 0; i < signatures.length; ++i) { 8070b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka shas.add(signatures[i].toByteArray()); 8080b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8090b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return shas; 8100b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8110b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 8120b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @VisibleForTesting 8130b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka @NonNull 8140b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka static FontInfo[] getFontFromProvider(Context context, FontRequest request, String authority, 8150b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka CancellationSignal cancellationSignal) { 8160b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka ArrayList<FontInfo> result = new ArrayList<>(); 8170b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 8180b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka .authority(authority) 8190b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka .build(); 8200b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final Uri fileBaseUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 8210b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka .authority(authority) 8220b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka .appendPath("file") 8230b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka .build(); 8240b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Cursor cursor = null; 8250b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka try { 8260b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (Build.VERSION.SDK_INT > 16) { 8270b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka cursor = context.getContentResolver().query(uri, new String[] { 8280b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Columns._ID, Columns.FILE_ID, Columns.TTC_INDEX, 8290b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Columns.VARIATION_SETTINGS, Columns.WEIGHT, Columns.ITALIC, 8300b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Columns.RESULT_CODE }, 8310b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka "query = ?", new String[] { request.getQuery() }, null, cancellationSignal); 8320b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } else { 8330b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka // No cancellation signal. 8340b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka cursor = context.getContentResolver().query(uri, new String[] { 8350b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Columns._ID, Columns.FILE_ID, Columns.TTC_INDEX, 8360b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Columns.VARIATION_SETTINGS, Columns.WEIGHT, Columns.ITALIC, 8370b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Columns.RESULT_CODE }, 8380b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka "query = ?", new String[] { request.getQuery() }, null); 8390b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8400b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (cursor != null && cursor.getCount() > 0) { 8410b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final int resultCodeColumnIndex = cursor.getColumnIndex(Columns.RESULT_CODE); 8420b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka result = new ArrayList<>(); 8430b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final int idColumnIndex = cursor.getColumnIndex(Columns._ID); 8440b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final int fileIdColumnIndex = cursor.getColumnIndex(Columns.FILE_ID); 8450b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX); 8460b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT); 8470b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC); 8480b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka while (cursor.moveToNext()) { 8490b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka int resultCode = resultCodeColumnIndex != -1 8500b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka ? cursor.getInt(resultCodeColumnIndex) : Columns.RESULT_CODE_OK; 8510b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka final int ttcIndex = ttcIndexColumnIndex != -1 8520b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka ? cursor.getInt(ttcIndexColumnIndex) : 0; 8530b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka Uri fileUri; 8540b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (fileIdColumnIndex == -1) { 8550b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka long id = cursor.getLong(idColumnIndex); 8560b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka fileUri = ContentUris.withAppendedId(uri, id); 8570b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } else { 8580b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka long id = cursor.getLong(fileIdColumnIndex); 8590b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka fileUri = ContentUris.withAppendedId(fileBaseUri, id); 8600b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8610b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka 8620b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka int weight = weightColumnIndex != -1 ? cursor.getInt(weightColumnIndex) : 400; 8630b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka boolean italic = italicColumnIndex != -1 && cursor.getInt(italicColumnIndex) 8640b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka == 1; 8650b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka result.add(new FontInfo(fileUri, ttcIndex, weight, italic, resultCode)); 8660b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8670b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8680b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } finally { 8690b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka if (cursor != null) { 8700b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka cursor.close(); 8710b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8720b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8730b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka return result.toArray(new FontInfo[0]); 8740b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka } 8750b03693667d95d2202dfbb24866665ff061acce1Seigo Nonaka} 876