FontsContract.java revision ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79
1b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri/* 2b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Copyright (C) 2017 The Android Open Source Project 3b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * 4b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Licensed under the Apache License, Version 2.0 (the "License"); 5b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * you may not use this file except in compliance with the License. 6b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * You may obtain a copy of the License at 7b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * 8b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * http://www.apache.org/licenses/LICENSE-2.0 9b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * 10b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Unless required by applicable law or agreed to in writing, software 11b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * distributed under the License is distributed on an "AS IS" BASIS, 12b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * See the License for the specific language governing permissions and 14b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * limitations under the License. 15b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 16b0812a30499376e09e2deb5995e998c629f24985Clara Bayarripackage android.provider; 17b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 1869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport static android.graphics.fonts.FontVariationAxis.InvalidFormatException; 1969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport static java.lang.annotation.RetentionPolicy.SOURCE; 2069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 2169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport android.annotation.IntDef; 2269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport android.annotation.IntRange; 2369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport android.annotation.NonNull; 2469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport android.annotation.Nullable; 25b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.ContentResolver; 26b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.ContentUris; 27b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.Context; 283c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport android.content.pm.PackageInfo; 2969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport android.content.pm.PackageManager.NameNotFoundException; 30b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.pm.PackageManager; 31b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.pm.ProviderInfo; 323c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport android.content.pm.Signature; 33b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.database.Cursor; 343c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport android.graphics.Typeface; 35b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.graphics.fonts.FontRequest; 36b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.graphics.fonts.FontResult; 3769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport android.graphics.fonts.FontVariationAxis; 38b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.net.Uri; 39b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.Bundle; 4069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport android.os.CancellationSignal; 41b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.Handler; 42b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.HandlerThread; 43b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.ParcelFileDescriptor; 44b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.Process; 45b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.ResultReceiver; 46b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.util.Log; 47b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 48b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport com.android.internal.annotations.GuardedBy; 493c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport com.android.internal.annotations.VisibleForTesting; 5069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport com.android.internal.util.Preconditions; 51b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 5269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport java.io.FileInputStream; 53b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport java.io.FileNotFoundException; 54bacf2352ab892724551431551ae973ae3b68db35Clara Bayarriimport java.io.IOException; 5569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport java.lang.annotation.Retention; 5669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport java.lang.annotation.RetentionPolicy; 5769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport java.nio.ByteBuffer; 5869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport java.nio.channels.FileChannel; 59b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport java.util.ArrayList; 60fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarriimport java.util.Arrays; 61fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarriimport java.util.Collections; 62fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarriimport java.util.Comparator; 6369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport java.util.HashMap; 643c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport java.util.List; 6569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport java.util.Map; 66b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 67b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri/** 68b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Utility class to deal with Font ContentProviders. 69b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 70b0812a30499376e09e2deb5995e998c629f24985Clara Bayarripublic class FontsContract { 71b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private static final String TAG = "FontsContract"; 72b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 73b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 74b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Defines the constants used in a response from a Font Provider. The cursor returned from the 75b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * query should have the ID column populated with the content uri ID for the resulting font. 76b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * This should point to a real file or shared memory, as the client will mmap the given file 77b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * descriptor. Pipes, sockets and other non-mmap-able file descriptors will fail to load in the 78b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * client application. 79b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 80b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final class Columns implements BaseColumns { 81b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 82b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Constant used to request data from a font provider. The cursor returned from the query 8343c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * may populate this column with a long for the font file ID. The client will request a file 8443c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * descriptor to "file/FILE_ID" with this ID immediately under the top-level content URI. If 8543c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * not present, the client will request a file descriptor to the top-level URI with the 8643c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * given base font ID. Note that several results may return the same file ID, e.g. for TTC 8743c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * files with different indices. 8843c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka */ 8943c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka public static final String FILE_ID = "file_id"; 9043c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka /** 9143c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 92b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * should have this column populated with an int for the ttc index for the resulting font. 93b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 94b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final String TTC_INDEX = "font_ttc_index"; 95b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 96b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Constant used to request data from a font provider. The cursor returned from the query 97b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * may populate this column with the font variation settings String information for the 98b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * font. 99b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 100b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final String VARIATION_SETTINGS = "font_variation_settings"; 101b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 102fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * DO NOT USE THIS COLUMN. 103fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * This column is kept for preventing demo apps. 104fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * TODO: Remove once nobody uses this column. 105fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * @hide 106fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * @removed 107b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 108b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final String STYLE = "font_style"; 109bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 110bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to request data from a font provider. The cursor returned from the query 111fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * should have this column populated with the int weight for the resulting font. This value 112fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * should be between 100 and 900. The most common values are 400 for regular weight and 700 113fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * for bold weight. 114fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka */ 115fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka public static final String WEIGHT = "font_weight"; 116fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka /** 117fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 118fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * should have this column populated with the int italic for the resulting font. This should 119fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * be 0 for regular style and 1 for italic. 120fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka */ 121fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka public static final String ITALIC = "font_italic"; 122fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka /** 123fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 124bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * should have this column populated to indicate the result status of the 125bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * query. This will be checked before any other data in the cursor. Possible values are 126bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * {@link #RESULT_CODE_OK}, {@link #RESULT_CODE_FONT_NOT_FOUND}, 127bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * {@link #RESULT_CODE_MALFORMED_QUERY} and {@link #RESULT_CODE_FONT_UNAVAILABLE}. If not 128bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * present, {@link #RESULT_CODE_OK} will be assumed. 129bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 130bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final String RESULT_CODE = "result_code"; 131bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri 132bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 133bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to represent a result was retrieved successfully. The given fonts will be 134bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * attempted to retrieve immediately via 135bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * {@link android.content.ContentProvider#openFile(Uri, String)}. See {@link #RESULT_CODE}. 136bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 137bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_OK = 0; 138bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 139bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to represent a result was not found. See {@link #RESULT_CODE}. 140bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 141bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_FONT_NOT_FOUND = 1; 142bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 143bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to represent a result was found, but cannot be provided at this moment. Use 144bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * this to indicate, for example, that a font needs to be fetched from the network. See 145bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * {@link #RESULT_CODE}. 146bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 147bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; 148bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 149bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to represent that the query was not in a supported format by the provider. 150bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * See {@link #RESULT_CODE}. 151bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 152bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_MALFORMED_QUERY = 3; 153b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 154b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 155b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 156b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Constant used to identify the List of {@link ParcelFileDescriptor} item in the Bundle 157b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * returned to the ResultReceiver in getFont. 158b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * @hide 159b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 160b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final String PARCEL_FONT_RESULTS = "font_results"; 161bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri // Error codes internal to the system, which can not come from a provider. To keep the number 162bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri // space open for new provider codes, these should all be negative numbers. 163b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** @hide */ 164bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_PROVIDER_NOT_FOUND = -1; 165b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** @hide */ 166bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_WRONG_CERTIFICATES = -2; 167bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri // Note -3 is used by Typeface to indicate the font failed to load. 168b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 169b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private static final int THREAD_RENEWAL_THRESHOLD_MS = 10000; 170b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 171b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final Context mContext; 172b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final PackageManager mPackageManager; 173b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final Object mLock = new Object(); 174b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri @GuardedBy("mLock") 175b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private Handler mHandler; 176b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri @GuardedBy("mLock") 177b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private HandlerThread mThread; 178b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 179b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** @hide */ 180ff221613ec1c328489a303491e1aa88850e4a273Clara Bayarri public FontsContract(Context context) { 181ff221613ec1c328489a303491e1aa88850e4a273Clara Bayarri mContext = context.getApplicationContext(); 182b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mPackageManager = mContext.getPackageManager(); 183b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 184b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 18569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 18669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Object represent a font entry in the family returned from {@link #fetchFonts}. 18769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 18869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static class FontInfo { 18969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final Uri mUri; 19069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final int mTtcIndex; 19169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final FontVariationAxis[] mAxes; 19269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final int mWeight; 19369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final boolean mItalic; 19469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final int mResultCode; 19569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 19669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 19769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Creates a Font with all the information needed about a provided font. 19869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param uri A URI associated to the font file. 19969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0. 20069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param axes If providing a variation font, the settings for it. May be null. 20169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param weight An integer that indicates the font weight. 20269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param italic A boolean that indicates the font is italic style or not. 20369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param resultCode A boolean that indicates the font contents is ready. 20469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 20569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** @hide */ 20669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public FontInfo(@NonNull Uri uri, @IntRange(from = 0) int ttcIndex, 20769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @Nullable FontVariationAxis[] axes, @IntRange(from = 1, to = 1000) int weight, 20869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka boolean italic, int resultCode) { 20969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mUri = Preconditions.checkNotNull(uri); 21069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mTtcIndex = ttcIndex; 21169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mAxes = axes; 21269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mWeight = weight; 21369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mItalic = italic; 21469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mResultCode = resultCode; 21569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 21669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 21769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 21869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Returns a URI associated to this record. 21969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 22069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public @NonNull Uri getUri() { 22169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mUri; 22269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 22369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 22469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 22569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Returns the index to be used to access this font when accessing a TTC file. 22669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 22769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public @IntRange(from = 0) int getTtcIndex() { 22869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mTtcIndex; 22969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 23069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 23169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 23269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Returns the list of axes associated to this font. 23369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 23469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public @Nullable FontVariationAxis[] getAxes() { 23569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mAxes; 23669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 23769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 23869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 23969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Returns the weight value for this font. 24069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 24169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public @IntRange(from = 1, to = 1000) int getWeight() { 24269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mWeight; 24369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 24469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 24569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 24669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Returns whether this font is italic. 24769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 24869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public boolean isItalic() { 24969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mItalic; 25069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 25169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 25269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 25369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Returns result code. 25469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 25569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * {@link FontsContract.Columns#RESULT_CODE} 25669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 25769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public int getResultCode() { 25869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mResultCode; 25969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 26069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 26169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 26269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 26369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Object returned from {@link #fetchFonts}. 26469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 26569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static class FontFamilyResult { 26669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 26769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Constant represents that the font was successfully retrieved. Note that when this value 26869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * is set and {@link #getFonts} returns an empty array, it means there were no fonts 26969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * matching the given query. 27069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 27169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static final int STATUS_OK = 0; 27269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 27369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 27469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Constant represents that the given certificate was not matched with the provider's 27569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * signature. {@link #getFonts} returns null if this status was set. 27669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 27769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static final int STATUS_WRONG_CERTIFICATES = 1; 27869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 27969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 28069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Constant represents that the provider returns unexpected data. {@link #getFonts} returns 28169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * null if this status was set. For example, this value is set when the font provider 28269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * gives invalid format of variation settings. 28369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 28469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static final int STATUS_UNEXPECTED_DATA_PROVIDED = 2; 28569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 286ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka /** 287ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka * Constant represents that the fetching font data was rejected by system. This happens if 288ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka * the passed context is restricted. 289ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka */ 290ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka public static final int STATUS_REJECTED = 3; 291ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka 29269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** @hide */ 29369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @IntDef({STATUS_OK, STATUS_WRONG_CERTIFICATES, STATUS_UNEXPECTED_DATA_PROVIDED}) 29469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @Retention(RetentionPolicy.SOURCE) 29569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @interface FontResultStatus {} 29669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 29769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final @FontResultStatus int mStatusCode; 29869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final FontInfo[] mFonts; 29969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 30069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** @hide */ 30169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public FontFamilyResult(@FontResultStatus int statusCode, @Nullable FontInfo[] fonts) { 30269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mStatusCode = statusCode; 30369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mFonts = fonts; 30469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 30569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 30669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public @FontResultStatus int getStatusCode() { 30769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mStatusCode; 30869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 30969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 31069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public @NonNull FontInfo[] getFonts() { 31169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mFonts; 31269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 3133c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 3143c4be77db95ea716889568bde853be082e764da9Clara Bayarri 315b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // We use a background thread to post the content resolving work for all requests on. This 316b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // thread should be quit/stopped after all requests are done. 317b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final Runnable mReplaceDispatcherThreadRunnable = new Runnable() { 318b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri @Override 319b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public void run() { 320b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri synchronized (mLock) { 321b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (mThread != null) { 322b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread.quitSafely(); 323b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread = null; 324b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler = null; 325b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 326b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 327b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 328b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri }; 329b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 330bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** @hide */ 331b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public void getFont(FontRequest request, ResultReceiver receiver) { 332b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri synchronized (mLock) { 333b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (mHandler == null) { 334b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND); 335b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread.start(); 336b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler = new Handler(mThread.getLooper()); 337b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 338b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.post(() -> { 33969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ProviderInfo providerInfo; 34069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 34169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka providerInfo = getProvider(mPackageManager, request); 34269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (providerInfo == null) { 34369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 34469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return; 34569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 34669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (PackageManager.NameNotFoundException e) { 34769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 34869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return; 34969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 35069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontInfo[] fonts; 35169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 35269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka fonts = getFontFromProvider(mContext, request, providerInfo.authority, 35369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka null /* cancellation signal */); 35469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (InvalidFormatException e) { 35569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 356b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri return; 357b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 35869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 35969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ArrayList<FontResult> result = new ArrayList<>(); 36069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka int resultCode = -1; 36169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka for (FontInfo font : fonts) { 36269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 36369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka resultCode = font.getResultCode(); 36469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (resultCode != Columns.RESULT_CODE_OK) { 36569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (resultCode < 0) { 36669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // Negative values are reserved for the internal errors. 36769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND; 36869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 36969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka for (int i = 0; i < result.size(); ++i) { 37069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 37169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka result.get(i).getFileDescriptor().close(); 37269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (IOException e) { 37369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // Ignore, as we are closing fds for cleanup. 37469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 37569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 37669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(resultCode, null); 37769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return; 37869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 37969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor( 38069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka font.getUri(), "r"); 38169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka result.add(new FontResult(pfd, font.getTtcIndex(), 38269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontVariationAxis.toFontVariationSettings(font.getAxes()), 38369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka font.getWeight(), font.isItalic())); 38469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (FileNotFoundException e) { 38569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Log.e(TAG, "FileNotFoundException raised when interacting with content " 38669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka + "provider " + providerInfo.authority, e); 38769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 38869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 38969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (!result.isEmpty()) { 39069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Bundle bundle = new Bundle(); 39169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result); 39269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(Columns.RESULT_CODE_OK, bundle); 39369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return; 39469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 39569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null); 396b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri }); 397b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable); 398b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS); 399b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 400b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 401b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 40269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 4030b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Interface used to receive asynchronously fetched typefaces. 4040b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4050b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public static class FontRequestCallback { 4060b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4070b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given 4080b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * provider was not found on the device. 4090b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4100b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public static final int FAIL_REASON_PROVIDER_NOT_FOUND = RESULT_CODE_PROVIDER_NOT_FOUND; 4110b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4120b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given 4130b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * provider must be authenticated and the given certificates do not match its signature. 4140b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4150b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public static final int FAIL_REASON_WRONG_CERTIFICATES = RESULT_CODE_WRONG_CERTIFICATES; 4160b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4170b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font 4180b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * returned by the provider was not loaded properly. 4190b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4200b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; 4210b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4220b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font 4230b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * provider did not return any results for the given query. 4240b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4250b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public static final int FAIL_REASON_FONT_NOT_FOUND = Columns.RESULT_CODE_FONT_NOT_FOUND; 4260b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4270b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font 4280b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * provider found the queried font, but it is currently unavailable. 4290b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4300b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public static final int FAIL_REASON_FONT_UNAVAILABLE = Columns.RESULT_CODE_FONT_UNAVAILABLE; 4310b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4320b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given 4330b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * query was not supported by the provider. 4340b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4350b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public static final int FAIL_REASON_MALFORMED_QUERY = Columns.RESULT_CODE_MALFORMED_QUERY; 4360b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 4370b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** @hide */ 4380b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR, 4390b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE, 4400b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FAIL_REASON_MALFORMED_QUERY }) 4410b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka @Retention(RetentionPolicy.SOURCE) 4420b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka @interface FontRequestFailReason {} 4430b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 4440b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public FontRequestCallback() {} 4450b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 4460b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4470b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Called then a Typeface request done via {@link Typeface#create(FontRequest, 4480b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * FontRequestCallback)} is complete. Note that this method will not be called if 4490b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * {@link #onTypefaceRequestFailed(int)} is called instead. 4500b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * @param typeface The Typeface object retrieved. 4510b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4520b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public void onTypefaceRetrieved(Typeface typeface) {} 4530b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 4540b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4550b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Called when a Typeface request done via {@link Typeface#create(FontRequest, 4560b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * FontRequestCallback)} fails. 4570b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * @param reason One of {@link #FAIL_REASON_PROVIDER_NOT_FOUND}, 4580b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * {@link #FAIL_REASON_FONT_NOT_FOUND}, 4590b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * {@link #FAIL_REASON_FONT_LOAD_ERROR}, 4600b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * {@link #FAIL_REASON_FONT_UNAVAILABLE} or 4610b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * {@link #FAIL_REASON_MALFORMED_QUERY}. 4620b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4630b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public void onTypefaceRequestFailed(@FontRequestFailReason int reason) {} 4640b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 4650b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 4660b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 4670b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Create a typeface object given a font request. The font will be asynchronously fetched, 4680b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * therefore the result is delivered to the given callback. See {@link FontRequest}. 4690b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * Only one of the methods in callback will be invoked, depending on whether the request 4700b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * succeeds or fails. These calls will happen on the caller thread. 4710b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * @param context A context to be used for fetching from font provider. 4720b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * @param request A {@link FontRequest} object that identifies the provider and query for the 4730b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * request. May not be null. 4740b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * @param callback A callback that will be triggered when results are obtained. May not be null. 4750b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka * @param handler A handler to be processed the font fetching. 4760b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka */ 4770b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka public static void requestFont(@NonNull Context context, @NonNull FontRequest request, 4780b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka @NonNull FontRequestCallback callback, @NonNull Handler handler) { 4790b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 4800b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka final Handler callerThreadHandler = new Handler(); 4810b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka handler.post(() -> { 4820b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka // TODO: Cache the result. 4830b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FontFamilyResult result; 4840b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka try { 4850b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka result = fetchFonts(context, null /* cancellation signal */, request); 4860b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } catch (NameNotFoundException e) { 4870b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRequestFailed( 4880b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND)); 4890b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka return; 4900b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 4910b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 4920b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka if (result.getStatusCode() != FontFamilyResult.STATUS_OK) { 4930b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka switch (result.getStatusCode()) { 4940b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka case FontFamilyResult.STATUS_WRONG_CERTIFICATES: 4950b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRequestFailed( 4960b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FontRequestCallback.FAIL_REASON_WRONG_CERTIFICATES)); 4970b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka return; 4980b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka case FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED: 4990b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRequestFailed( 5000b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR)); 5010b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka return; 5020b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka default: 5030b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka // fetchFont returns unexpected status type. Fallback to load error. 5040b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRequestFailed( 5050b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR)); 5060b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka return; 5070b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 5080b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 5090b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 5100b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka final FontInfo[] fonts = result.getFonts(); 5110b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka if (fonts == null || fonts.length == 0) { 5120b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRequestFailed( 5130b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND)); 5140b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka return; 5150b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 5160b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka for (final FontInfo font : fonts) { 5170b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka if (font.getResultCode() != Columns.RESULT_CODE_OK) { 5180b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka // We proceed if all font entry is ready to use. Otherwise report the first 5190b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka // error. 5200b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka final int resultCode = font.getResultCode(); 5210b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka if (resultCode < 0) { 5220b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka // Negative values are reserved for internal errors. Fallback to load error. 5230b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRequestFailed( 5240b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR)); 5250b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } else { 5260b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRequestFailed( 5270b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka resultCode)); 5280b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 5290b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka return; 5300b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 5310b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 5320b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 5330b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka final Typeface typeface = buildTypeface(context, null /* cancellation signal */, fonts); 5340b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka if (typeface == null) { 5350b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka // Something went wrong during reading font files. This happens if the given font 5360b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka // file is an unsupported font type. 5370b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRequestFailed( 5380b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR)); 5390b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka return; 5400b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 5410b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 5420b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka callerThreadHandler.post(() -> callback.onTypefaceRetrieved(typeface)); 5430b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka }); 5440b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka } 5450b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka 5460b73a4287e8f630c45bf7ef0a7e0b2541d6b4067Seigo Nonaka /** 54769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Fetch fonts given a font request. 54869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 54969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param context A {@link Context} to be used for fetching fonts. 55069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If 55169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * the operation is canceled, then {@link 55269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * android.os.OperationCanceledException} will be thrown when the 55369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * query is executed. 55469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param request A {@link FontRequest} object that identifies the provider and query for the 55569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * request. 55669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 55769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @return {@link FontFamilyResult} 55869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 55969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @throws NameNotFoundException If requested package or authority was not found in system. 56069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 56169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static @NonNull FontFamilyResult fetchFonts( 56269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @NonNull Context context, @Nullable CancellationSignal cancellationSignal, 56369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @NonNull FontRequest request) throws NameNotFoundException { 564ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka if (context.isRestricted()) { 565ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka // TODO: Should we allow if the peer process is system or myself? 566ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_REJECTED, null); 567ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka } 56869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ProviderInfo providerInfo = getProvider(context.getPackageManager(), request); 56969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (providerInfo == null) { 57069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_WRONG_CERTIFICATES, null); 57169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 57269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 57369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 57469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontInfo[] fonts = getFontFromProvider( 57569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka context, request, providerInfo.authority, cancellationSignal); 57669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_OK, fonts); 57769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (InvalidFormatException e) { 57869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED, null); 57969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 58069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 58169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 58269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 58369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Build a Typeface from an array of {@link FontInfo}. Results that are marked as not ready 58469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * will be skipped. 58569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 58669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param context A {@link Context} that will be used to fetch the font contents. 58769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If 58869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * the operation is canceled, then {@link 58969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * android.os.OperationCanceledException} will be thrown. 59069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param fonts An array of {@link FontInfo} to be used to create a Typeface. 59169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param weight A weight value to be used for selecting a font from a font family. 59269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param italic {@code true} if this font is of italic style. This will be used for font 59369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * selection from a font family. 59469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param fallbackFontName A fallback font name used if this method fails to create the 59569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Typeface. By passing {@code null}, this method returns {@code null} 59669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * if typeface creation fails. 59769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @return A Typeface object. May return {@code null} if that is the value passed to {@code 59869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * fallBackFontName}. 59969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 60069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static Typeface buildTypeface(@NonNull Context context, 60169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, 60269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka int weight, boolean italic, @Nullable String fallbackFontName) { 603ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka if (context.isRestricted()) { 604ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka // TODO: Should we allow if the peer process is system or myself? 605ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka return null; 606ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka } 60769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final Map<Uri, ByteBuffer> uriBuffer = 60869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka prepareFontData(context, fonts, cancellationSignal); 6095b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka return new Typeface.Builder(fonts, uriBuffer) 6105b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka .setFallback(fallbackFontName) 61169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka .setWeight(weight) 61269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka .setItalic(italic) 61369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka .build(); 61469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 61569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 61669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 61769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Build a Typeface from an array of {@link FontInfo} 61869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 61969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Results that are marked as not ready will be skipped. 62069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 62169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param context A {@link Context} that will be used to fetch the font contents. 62269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If 62369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * the operation is canceled, then {@link 62469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * android.os.OperationCanceledException} will be thrown. 62569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param fonts An array of {@link FontInfo} to be used to create a Typeface. 62669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @return A Typeface object. Returns null if typeface creation fails. 62769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 62869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static Typeface buildTypeface(@NonNull Context context, 62969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts) { 630ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka if (context.isRestricted()) { 631ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka // TODO: Should we allow if the peer process is system or myself? 632ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka return null; 633ebecd7e802cd65bfc5cf1d8de1e6ea031580ae79Seigo Nonaka } 63469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final Map<Uri, ByteBuffer> uriBuffer = 63569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka prepareFontData(context, fonts, cancellationSignal); 63669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return new Typeface.Builder(fonts, uriBuffer).build(); 63769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 63869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 63969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 64069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * A helper function to create a mapping from {@link Uri} to {@link ByteBuffer}. 64169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 64269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Skip if the file contents is not ready to be read. 64369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 64469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param context A {@link Context} to be used for resolving content URI in 64569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * {@link FontInfo}. 64669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param fonts An array of {@link FontInfo}. 64769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @return A map from {@link Uri} to {@link ByteBuffer}. 64869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 64969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private static Map<Uri, ByteBuffer> prepareFontData(Context context, FontInfo[] fonts, 65069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka CancellationSignal cancellationSignal) { 65169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final HashMap<Uri, ByteBuffer> out = new HashMap<>(); 65269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final ContentResolver resolver = context.getContentResolver(); 65369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 65469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka for (FontInfo font : fonts) { 65569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (font.getResultCode() != Columns.RESULT_CODE_OK) { 65669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka continue; 65769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 65869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 65969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final Uri uri = font.getUri(); 66069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (out.containsKey(uri)) { 66169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka continue; 66269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 66369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 66469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ByteBuffer buffer = null; 66569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try (final ParcelFileDescriptor pfd = 66669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka resolver.openFileDescriptor(uri, "r", cancellationSignal); 66769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final FileInputStream fis = new FileInputStream(pfd.getFileDescriptor())) { 66869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final FileChannel fileChannel = fis.getChannel(); 66969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final long size = fileChannel.size(); 67069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, size); 67169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (IOException e) { 67269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // ignore 67369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 67469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 67569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // TODO: try other approach?, e.g. read all contents instead of mmap. 67669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 67769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka out.put(uri, buffer); 67869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 67969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return Collections.unmodifiableMap(out); 68069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 68169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 6823c4be77db95ea716889568bde853be082e764da9Clara Bayarri /** @hide */ 6833c4be77db95ea716889568bde853be082e764da9Clara Bayarri @VisibleForTesting 68469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static @Nullable ProviderInfo getProvider( 68569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka PackageManager packageManager, FontRequest request) throws NameNotFoundException { 6863c4be77db95ea716889568bde853be082e764da9Clara Bayarri String providerAuthority = request.getProviderAuthority(); 68769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ProviderInfo info = packageManager.resolveContentProvider(providerAuthority, 0); 6883c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (info == null) { 68969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka throw new NameNotFoundException("No package found for authority: " + providerAuthority); 6903c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 6913c4be77db95ea716889568bde853be082e764da9Clara Bayarri 6923c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (!info.packageName.equals(request.getProviderPackage())) { 69369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka throw new NameNotFoundException("Found content provider " + providerAuthority 69469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka + ", but package was not " + request.getProviderPackage()); 6953c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 6963c4be77db95ea716889568bde853be082e764da9Clara Bayarri // Trust system apps without signature checks 6973c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (info.applicationInfo.isSystemApp()) { 6983c4be77db95ea716889568bde853be082e764da9Clara Bayarri return info; 6993c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 7003c4be77db95ea716889568bde853be082e764da9Clara Bayarri 701fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> signatures; 70269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka PackageInfo packageInfo = packageManager.getPackageInfo(info.packageName, 70369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka PackageManager.GET_SIGNATURES); 70469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka signatures = convertToByteArrayList(packageInfo.signatures); 70569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Collections.sort(signatures, sByteArrayComparator); 70669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 7073c4be77db95ea716889568bde853be082e764da9Clara Bayarri List<List<byte[]>> requestCertificatesList = request.getCertificates(); 7083c4be77db95ea716889568bde853be082e764da9Clara Bayarri for (int i = 0; i < requestCertificatesList.size(); ++i) { 709fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri // Make a copy so we can sort it without modifying the incoming data. 710fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> requestSignatures = new ArrayList<>(requestCertificatesList.get(i)); 711fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri Collections.sort(requestSignatures, sByteArrayComparator); 712fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (equalsByteArrayList(signatures, requestSignatures)) { 7133c4be77db95ea716889568bde853be082e764da9Clara Bayarri return info; 7143c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 7153c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 7163c4be77db95ea716889568bde853be082e764da9Clara Bayarri return null; 7173c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 7183c4be77db95ea716889568bde853be082e764da9Clara Bayarri 719fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri private static final Comparator<byte[]> sByteArrayComparator = (l, r) -> { 720fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (l.length != r.length) { 721fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return l.length - r.length; 7223c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 723fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < l.length; ++i) { 724fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (l[i] != r[i]) { 725fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return l[i] - r[i]; 726fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 727fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 728fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return 0; 729fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri }; 730fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri 73169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private static boolean equalsByteArrayList( 73269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka List<byte[]> signatures, List<byte[]> requestSignatures) { 733fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (signatures.size() != requestSignatures.size()) { 734fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return false; 735fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 736fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < signatures.size(); ++i) { 737fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (!Arrays.equals(signatures.get(i), requestSignatures.get(i))) { 738fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return false; 739fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 740fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 741fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return true; 7423c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 7433c4be77db95ea716889568bde853be082e764da9Clara Bayarri 74469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private static List<byte[]> convertToByteArrayList(Signature[] signatures) { 745fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> shas = new ArrayList<>(); 746fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < signatures.length; ++i) { 747fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri shas.add(signatures[i].toByteArray()); 748fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 7493c4be77db95ea716889568bde853be082e764da9Clara Bayarri return shas; 7503c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 7513c4be77db95ea716889568bde853be082e764da9Clara Bayarri 7523c4be77db95ea716889568bde853be082e764da9Clara Bayarri /** @hide */ 7533c4be77db95ea716889568bde853be082e764da9Clara Bayarri @VisibleForTesting 75469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static @NonNull FontInfo[] getFontFromProvider( 75569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Context context, FontRequest request, String authority, 75669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka CancellationSignal cancellationSignal) throws InvalidFormatException { 75769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ArrayList<FontInfo> result = new ArrayList<>(); 75843c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 7593c4be77db95ea716889568bde853be082e764da9Clara Bayarri .authority(authority) 760b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri .build(); 76143c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final Uri fileBaseUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 76243c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .authority(authority) 76343c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .appendPath("file") 76443c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .build(); 76569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try (Cursor cursor = context.getContentResolver().query(uri, new String[] { Columns._ID, 76643c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Columns.FILE_ID, Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, 76743c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Columns.STYLE, Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE }, 76869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka "query = ?", new String[] { request.getQuery() }, null, cancellationSignal);) { 769b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // TODO: Should we restrict the amount of fonts that can be returned? 770b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // TODO: Write documentation explaining that all results should be from the same family. 771b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (cursor != null && cursor.getCount() > 0) { 772bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri final int resultCodeColumnIndex = cursor.getColumnIndex(Columns.RESULT_CODE); 773b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri result = new ArrayList<>(); 774bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID); 77543c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final int fileIdColumnIndex = cursor.getColumnIndex(Columns.FILE_ID); 776b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX); 777b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS); 778fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT); 779fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC); 780b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE); 781b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri while (cursor.moveToNext()) { 78269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka int resultCode = resultCodeColumnIndex != -1 783bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri ? cursor.getInt(resultCodeColumnIndex) : Columns.RESULT_CODE_OK; 78469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final int ttcIndex = ttcIndexColumnIndex != -1 78569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ? cursor.getInt(ttcIndexColumnIndex) : 0; 78669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final String variationSettings = vsColumnIndex != -1 78769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ? cursor.getString(vsColumnIndex) : null; 78869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 78943c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Uri fileUri; 79043c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka if (fileIdColumnIndex == -1) { 79143c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka long id = cursor.getLong(idColumnIndex); 79243c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka fileUri = ContentUris.withAppendedId(uri, id); 79343c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka } else { 79443c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka long id = cursor.getLong(fileIdColumnIndex); 79543c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka fileUri = ContentUris.withAppendedId(fileBaseUri, id); 79643c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka } 79769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column. 79869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka int weight; 79969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka boolean italic; 80069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (weightColumnIndex != -1 && italicColumnIndex != -1) { 80169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka weight = cursor.getInt(weightColumnIndex); 80269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka italic = cursor.getInt(italicColumnIndex) == 1; 80369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } else if (styleColumnIndex != -1) { 80469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final int style = cursor.getInt(styleColumnIndex); 80569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka weight = (style & Typeface.BOLD) != 0 ? 80669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Typeface.Builder.BOLD_WEIGHT : Typeface.Builder.NORMAL_WEIGHT; 80769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka italic = (style & Typeface.ITALIC) != 0; 80869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } else { 80969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka weight = Typeface.Builder.NORMAL_WEIGHT; 81069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka italic = false; 811b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 81269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontVariationAxis[] axes = 81369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontVariationAxis.fromFontVariationSettings(variationSettings); 81469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka result.add(new FontInfo(fileUri, ttcIndex, axes, weight, italic, resultCode)); 815b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 816b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 817b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 81869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return result.toArray(new FontInfo[0]); 819b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 820b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri} 821