FontsContract.java revision 69754bf66dae9d047d5a0ff2c71820aa35b9cc70
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 28669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** @hide */ 28769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @IntDef({STATUS_OK, STATUS_WRONG_CERTIFICATES, STATUS_UNEXPECTED_DATA_PROVIDED}) 28869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @Retention(RetentionPolicy.SOURCE) 28969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @interface FontResultStatus {} 29069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 29169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final @FontResultStatus int mStatusCode; 29269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private final FontInfo[] mFonts; 29369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 29469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** @hide */ 29569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public FontFamilyResult(@FontResultStatus int statusCode, @Nullable FontInfo[] fonts) { 29669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mStatusCode = statusCode; 29769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka mFonts = fonts; 29869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 29969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 30069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public @FontResultStatus int getStatusCode() { 30169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mStatusCode; 30269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 30369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 30469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public @NonNull FontInfo[] getFonts() { 30569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return mFonts; 30669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 3073c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 3083c4be77db95ea716889568bde853be082e764da9Clara Bayarri 309b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // We use a background thread to post the content resolving work for all requests on. This 310b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // thread should be quit/stopped after all requests are done. 311b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final Runnable mReplaceDispatcherThreadRunnable = new Runnable() { 312b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri @Override 313b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public void run() { 314b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri synchronized (mLock) { 315b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (mThread != null) { 316b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread.quitSafely(); 317b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread = null; 318b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler = null; 319b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 320b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 321b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 322b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri }; 323b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 324bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** @hide */ 325b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public void getFont(FontRequest request, ResultReceiver receiver) { 326b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri synchronized (mLock) { 327b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (mHandler == null) { 328b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND); 329b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread.start(); 330b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler = new Handler(mThread.getLooper()); 331b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 332b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.post(() -> { 33369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ProviderInfo providerInfo; 33469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 33569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka providerInfo = getProvider(mPackageManager, request); 33669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (providerInfo == null) { 33769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 33869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return; 33969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 34069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (PackageManager.NameNotFoundException e) { 34169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 34269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return; 34369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 34469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontInfo[] fonts; 34569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 34669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka fonts = getFontFromProvider(mContext, request, providerInfo.authority, 34769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka null /* cancellation signal */); 34869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (InvalidFormatException e) { 34969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 350b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri return; 351b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 35269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 35369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ArrayList<FontResult> result = new ArrayList<>(); 35469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka int resultCode = -1; 35569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka for (FontInfo font : fonts) { 35669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 35769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka resultCode = font.getResultCode(); 35869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (resultCode != Columns.RESULT_CODE_OK) { 35969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (resultCode < 0) { 36069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // Negative values are reserved for the internal errors. 36169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND; 36269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 36369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka for (int i = 0; i < result.size(); ++i) { 36469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 36569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka result.get(i).getFileDescriptor().close(); 36669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (IOException e) { 36769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // Ignore, as we are closing fds for cleanup. 36869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 36969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 37069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(resultCode, null); 37169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return; 37269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 37369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor( 37469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka font.getUri(), "r"); 37569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka result.add(new FontResult(pfd, font.getTtcIndex(), 37669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontVariationAxis.toFontVariationSettings(font.getAxes()), 37769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka font.getWeight(), font.isItalic())); 37869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (FileNotFoundException e) { 37969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Log.e(TAG, "FileNotFoundException raised when interacting with content " 38069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka + "provider " + providerInfo.authority, e); 38169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 38269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 38369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (!result.isEmpty()) { 38469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Bundle bundle = new Bundle(); 38569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result); 38669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(Columns.RESULT_CODE_OK, bundle); 38769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return; 38869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 38969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null); 390b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri }); 391b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable); 392b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS); 393b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 394b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 395b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 39669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 39769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Fetch fonts given a font request. 39869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 39969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param context A {@link Context} to be used for fetching fonts. 40069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If 40169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * the operation is canceled, then {@link 40269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * android.os.OperationCanceledException} will be thrown when the 40369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * query is executed. 40469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param request A {@link FontRequest} object that identifies the provider and query for the 40569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * request. 40669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 40769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @return {@link FontFamilyResult} 40869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 40969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @throws NameNotFoundException If requested package or authority was not found in system. 41069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 41169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static @NonNull FontFamilyResult fetchFonts( 41269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @NonNull Context context, @Nullable CancellationSignal cancellationSignal, 41369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @NonNull FontRequest request) throws NameNotFoundException { 41469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ProviderInfo providerInfo = getProvider(context.getPackageManager(), request); 41569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (providerInfo == null) { 41669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_WRONG_CERTIFICATES, null); 41769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 41869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 41969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try { 42069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontInfo[] fonts = getFontFromProvider( 42169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka context, request, providerInfo.authority, cancellationSignal); 42269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_OK, fonts); 42369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (InvalidFormatException e) { 42469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return new FontFamilyResult(FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED, null); 42569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 42669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 42769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 42869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 42969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Build a Typeface from an array of {@link FontInfo}. Results that are marked as not ready 43069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * will be skipped. 43169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 43269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param context A {@link Context} that will be used to fetch the font contents. 43369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If 43469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * the operation is canceled, then {@link 43569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * android.os.OperationCanceledException} will be thrown. 43669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param fonts An array of {@link FontInfo} to be used to create a Typeface. 43769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param weight A weight value to be used for selecting a font from a font family. 43869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param italic {@code true} if this font is of italic style. This will be used for font 43969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * selection from a font family. 44069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param fallbackFontName A fallback font name used if this method fails to create the 44169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Typeface. By passing {@code null}, this method returns {@code null} 44269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * if typeface creation fails. 44369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @return A Typeface object. May return {@code null} if that is the value passed to {@code 44469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * fallBackFontName}. 44569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 44669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static Typeface buildTypeface(@NonNull Context context, 44769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, 44869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka int weight, boolean italic, @Nullable String fallbackFontName) { 44969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final Map<Uri, ByteBuffer> uriBuffer = 45069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka prepareFontData(context, fonts, cancellationSignal); 45169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Typeface typeface = new Typeface.Builder(fonts, uriBuffer) 45269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka .setWeight(weight) 45369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka .setItalic(italic) 45469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka .build(); 45569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // TODO: Use Typeface fallback instead. 45669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (typeface == null) { 45769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka typeface = Typeface.create(fallbackFontName, Typeface.NORMAL); 45869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 45969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return typeface; 46069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 46169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 46269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 46369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Build a Typeface from an array of {@link FontInfo} 46469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 46569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Results that are marked as not ready will be skipped. 46669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 46769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param context A {@link Context} that will be used to fetch the font contents. 46869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param cancellationSignal A signal to cancel the operation in progress, or null if none. If 46969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * the operation is canceled, then {@link 47069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * android.os.OperationCanceledException} will be thrown. 47169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param fonts An array of {@link FontInfo} to be used to create a Typeface. 47269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @return A Typeface object. Returns null if typeface creation fails. 47369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 47469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static Typeface buildTypeface(@NonNull Context context, 47569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka @Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts) { 47669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final Map<Uri, ByteBuffer> uriBuffer = 47769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka prepareFontData(context, fonts, cancellationSignal); 47869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return new Typeface.Builder(fonts, uriBuffer).build(); 47969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 48069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 48169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka /** 48269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * A helper function to create a mapping from {@link Uri} to {@link ByteBuffer}. 48369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 48469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * Skip if the file contents is not ready to be read. 48569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * 48669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param context A {@link Context} to be used for resolving content URI in 48769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * {@link FontInfo}. 48869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @param fonts An array of {@link FontInfo}. 48969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka * @return A map from {@link Uri} to {@link ByteBuffer}. 49069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka */ 49169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private static Map<Uri, ByteBuffer> prepareFontData(Context context, FontInfo[] fonts, 49269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka CancellationSignal cancellationSignal) { 49369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final HashMap<Uri, ByteBuffer> out = new HashMap<>(); 49469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final ContentResolver resolver = context.getContentResolver(); 49569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 49669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka for (FontInfo font : fonts) { 49769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (font.getResultCode() != Columns.RESULT_CODE_OK) { 49869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka continue; 49969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 50069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 50169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final Uri uri = font.getUri(); 50269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (out.containsKey(uri)) { 50369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka continue; 50469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 50569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 50669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ByteBuffer buffer = null; 50769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try (final ParcelFileDescriptor pfd = 50869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka resolver.openFileDescriptor(uri, "r", cancellationSignal); 50969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final FileInputStream fis = new FileInputStream(pfd.getFileDescriptor())) { 51069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final FileChannel fileChannel = fis.getChannel(); 51169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final long size = fileChannel.size(); 51269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, size); 51369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } catch (IOException e) { 51469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // ignore 51569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 51669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 51769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // TODO: try other approach?, e.g. read all contents instead of mmap. 51869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 51969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka out.put(uri, buffer); 52069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 52169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return Collections.unmodifiableMap(out); 52269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } 52369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 5243c4be77db95ea716889568bde853be082e764da9Clara Bayarri /** @hide */ 5253c4be77db95ea716889568bde853be082e764da9Clara Bayarri @VisibleForTesting 52669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static @Nullable ProviderInfo getProvider( 52769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka PackageManager packageManager, FontRequest request) throws NameNotFoundException { 5283c4be77db95ea716889568bde853be082e764da9Clara Bayarri String providerAuthority = request.getProviderAuthority(); 52969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ProviderInfo info = packageManager.resolveContentProvider(providerAuthority, 0); 5303c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (info == null) { 53169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka throw new NameNotFoundException("No package found for authority: " + providerAuthority); 5323c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 5333c4be77db95ea716889568bde853be082e764da9Clara Bayarri 5343c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (!info.packageName.equals(request.getProviderPackage())) { 53569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka throw new NameNotFoundException("Found content provider " + providerAuthority 53669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka + ", but package was not " + request.getProviderPackage()); 5373c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 5383c4be77db95ea716889568bde853be082e764da9Clara Bayarri // Trust system apps without signature checks 5393c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (info.applicationInfo.isSystemApp()) { 5403c4be77db95ea716889568bde853be082e764da9Clara Bayarri return info; 5413c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 5423c4be77db95ea716889568bde853be082e764da9Clara Bayarri 543fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> signatures; 54469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka PackageInfo packageInfo = packageManager.getPackageInfo(info.packageName, 54569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka PackageManager.GET_SIGNATURES); 54669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka signatures = convertToByteArrayList(packageInfo.signatures); 54769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Collections.sort(signatures, sByteArrayComparator); 54869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 5493c4be77db95ea716889568bde853be082e764da9Clara Bayarri List<List<byte[]>> requestCertificatesList = request.getCertificates(); 5503c4be77db95ea716889568bde853be082e764da9Clara Bayarri for (int i = 0; i < requestCertificatesList.size(); ++i) { 551fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri // Make a copy so we can sort it without modifying the incoming data. 552fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> requestSignatures = new ArrayList<>(requestCertificatesList.get(i)); 553fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri Collections.sort(requestSignatures, sByteArrayComparator); 554fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (equalsByteArrayList(signatures, requestSignatures)) { 5553c4be77db95ea716889568bde853be082e764da9Clara Bayarri return info; 5563c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 5573c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 5583c4be77db95ea716889568bde853be082e764da9Clara Bayarri return null; 5593c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 5603c4be77db95ea716889568bde853be082e764da9Clara Bayarri 561fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri private static final Comparator<byte[]> sByteArrayComparator = (l, r) -> { 562fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (l.length != r.length) { 563fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return l.length - r.length; 5643c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 565fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < l.length; ++i) { 566fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (l[i] != r[i]) { 567fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return l[i] - r[i]; 568fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 569fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 570fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return 0; 571fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri }; 572fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri 57369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private static boolean equalsByteArrayList( 57469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka List<byte[]> signatures, List<byte[]> requestSignatures) { 575fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (signatures.size() != requestSignatures.size()) { 576fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return false; 577fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 578fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < signatures.size(); ++i) { 579fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (!Arrays.equals(signatures.get(i), requestSignatures.get(i))) { 580fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return false; 581fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 582fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 583fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return true; 5843c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 5853c4be77db95ea716889568bde853be082e764da9Clara Bayarri 58669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka private static List<byte[]> convertToByteArrayList(Signature[] signatures) { 587fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> shas = new ArrayList<>(); 588fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < signatures.length; ++i) { 589fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri shas.add(signatures[i].toByteArray()); 590fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 5913c4be77db95ea716889568bde853be082e764da9Clara Bayarri return shas; 5923c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 5933c4be77db95ea716889568bde853be082e764da9Clara Bayarri 5943c4be77db95ea716889568bde853be082e764da9Clara Bayarri /** @hide */ 5953c4be77db95ea716889568bde853be082e764da9Clara Bayarri @VisibleForTesting 59669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka public static @NonNull FontInfo[] getFontFromProvider( 59769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Context context, FontRequest request, String authority, 59869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka CancellationSignal cancellationSignal) throws InvalidFormatException { 59969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ArrayList<FontInfo> result = new ArrayList<>(); 60043c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 6013c4be77db95ea716889568bde853be082e764da9Clara Bayarri .authority(authority) 602b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri .build(); 60343c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final Uri fileBaseUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 60443c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .authority(authority) 60543c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .appendPath("file") 60643c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .build(); 60769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka try (Cursor cursor = context.getContentResolver().query(uri, new String[] { Columns._ID, 60843c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Columns.FILE_ID, Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, 60943c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Columns.STYLE, Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE }, 61069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka "query = ?", new String[] { request.getQuery() }, null, cancellationSignal);) { 611b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // TODO: Should we restrict the amount of fonts that can be returned? 612b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // TODO: Write documentation explaining that all results should be from the same family. 613b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (cursor != null && cursor.getCount() > 0) { 614bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri final int resultCodeColumnIndex = cursor.getColumnIndex(Columns.RESULT_CODE); 615b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri result = new ArrayList<>(); 616bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID); 61743c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final int fileIdColumnIndex = cursor.getColumnIndex(Columns.FILE_ID); 618b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX); 619b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS); 620fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT); 621fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC); 622b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE); 623b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri while (cursor.moveToNext()) { 62469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka int resultCode = resultCodeColumnIndex != -1 625bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri ? cursor.getInt(resultCodeColumnIndex) : Columns.RESULT_CODE_OK; 62669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final int ttcIndex = ttcIndexColumnIndex != -1 62769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ? cursor.getInt(ttcIndexColumnIndex) : 0; 62869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final String variationSettings = vsColumnIndex != -1 62969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka ? cursor.getString(vsColumnIndex) : null; 63069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka 63143c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Uri fileUri; 63243c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka if (fileIdColumnIndex == -1) { 63343c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka long id = cursor.getLong(idColumnIndex); 63443c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka fileUri = ContentUris.withAppendedId(uri, id); 63543c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka } else { 63643c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka long id = cursor.getLong(fileIdColumnIndex); 63743c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka fileUri = ContentUris.withAppendedId(fileBaseUri, id); 63843c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka } 63969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column. 64069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka int weight; 64169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka boolean italic; 64269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka if (weightColumnIndex != -1 && italicColumnIndex != -1) { 64369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka weight = cursor.getInt(weightColumnIndex); 64469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka italic = cursor.getInt(italicColumnIndex) == 1; 64569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } else if (styleColumnIndex != -1) { 64669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka final int style = cursor.getInt(styleColumnIndex); 64769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka weight = (style & Typeface.BOLD) != 0 ? 64869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka Typeface.Builder.BOLD_WEIGHT : Typeface.Builder.NORMAL_WEIGHT; 64969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka italic = (style & Typeface.ITALIC) != 0; 65069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka } else { 65169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka weight = Typeface.Builder.NORMAL_WEIGHT; 65269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka italic = false; 653b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 65469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontVariationAxis[] axes = 65569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka FontVariationAxis.fromFontVariationSettings(variationSettings); 65669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka result.add(new FontInfo(fileUri, ttcIndex, axes, weight, italic, resultCode)); 657b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 658b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 659b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 66069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka return result.toArray(new FontInfo[0]); 661b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 662b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri} 663