FontsContract.java revision 43c20cf6d4bd661d85bed76c78953aa656dbcc62
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 18b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.ContentResolver; 19b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.ContentUris; 20b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.Context; 213c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport android.content.pm.PackageInfo; 22b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.pm.PackageManager; 23b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.content.pm.ProviderInfo; 243c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport android.content.pm.Signature; 25b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.database.Cursor; 263c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport android.graphics.Typeface; 27b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.graphics.fonts.FontRequest; 28b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.graphics.fonts.FontResult; 29b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.net.Uri; 30b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.Bundle; 31b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.Handler; 32b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.HandlerThread; 33b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.ParcelFileDescriptor; 34b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.Process; 35b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.os.ResultReceiver; 36b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.util.Log; 37b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 38b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport com.android.internal.annotations.GuardedBy; 393c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport com.android.internal.annotations.VisibleForTesting; 40b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 41b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport java.io.FileNotFoundException; 42bacf2352ab892724551431551ae973ae3b68db35Clara Bayarriimport java.io.IOException; 43b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport java.util.ArrayList; 44fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarriimport java.util.Arrays; 45fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarriimport java.util.Collections; 46fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarriimport java.util.Comparator; 473c4be77db95ea716889568bde853be082e764da9Clara Bayarriimport java.util.List; 48b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 49b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri/** 50b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Utility class to deal with Font ContentProviders. 51b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 52b0812a30499376e09e2deb5995e998c629f24985Clara Bayarripublic class FontsContract { 53b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private static final String TAG = "FontsContract"; 54b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 55b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 56b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Defines the constants used in a response from a Font Provider. The cursor returned from the 57b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * query should have the ID column populated with the content uri ID for the resulting font. 58b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * This should point to a real file or shared memory, as the client will mmap the given file 59b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * descriptor. Pipes, sockets and other non-mmap-able file descriptors will fail to load in the 60b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * client application. 61b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 62b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final class Columns implements BaseColumns { 63b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 64b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Constant used to request data from a font provider. The cursor returned from the query 6543c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * may populate this column with a long for the font file ID. The client will request a file 6643c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * descriptor to "file/FILE_ID" with this ID immediately under the top-level content URI. If 6743c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * not present, the client will request a file descriptor to the top-level URI with the 6843c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * given base font ID. Note that several results may return the same file ID, e.g. for TTC 6943c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * files with different indices. 7043c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka */ 7143c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka public static final String FILE_ID = "file_id"; 7243c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka /** 7343c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 74b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * should have this column populated with an int for the ttc index for the resulting font. 75b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 76b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final String TTC_INDEX = "font_ttc_index"; 77b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 78b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Constant used to request data from a font provider. The cursor returned from the query 79b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * may populate this column with the font variation settings String information for the 80b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * font. 81b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 82b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final String VARIATION_SETTINGS = "font_variation_settings"; 83b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 84fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * DO NOT USE THIS COLUMN. 85fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * This column is kept for preventing demo apps. 86fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * TODO: Remove once nobody uses this column. 87fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * @hide 88fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * @removed 89b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 90b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final String STYLE = "font_style"; 91bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 92bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to request data from a font provider. The cursor returned from the query 93fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * should have this column populated with the int weight for the resulting font. This value 94fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * should be between 100 and 900. The most common values are 400 for regular weight and 700 95fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * for bold weight. 96fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka */ 97fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka public static final String WEIGHT = "font_weight"; 98fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka /** 99fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 100fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * should have this column populated with the int italic for the resulting font. This should 101fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * be 0 for regular style and 1 for italic. 102fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka */ 103fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka public static final String ITALIC = "font_italic"; 104fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka /** 105fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka * Constant used to request data from a font provider. The cursor returned from the query 106bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * should have this column populated to indicate the result status of the 107bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * query. This will be checked before any other data in the cursor. Possible values are 108bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * {@link #RESULT_CODE_OK}, {@link #RESULT_CODE_FONT_NOT_FOUND}, 109bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * {@link #RESULT_CODE_MALFORMED_QUERY} and {@link #RESULT_CODE_FONT_UNAVAILABLE}. If not 110bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * present, {@link #RESULT_CODE_OK} will be assumed. 111bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 112bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final String RESULT_CODE = "result_code"; 113bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri 114bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 115bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to represent a result was retrieved successfully. The given fonts will be 116bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * attempted to retrieve immediately via 117bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * {@link android.content.ContentProvider#openFile(Uri, String)}. See {@link #RESULT_CODE}. 118bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 119bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_OK = 0; 120bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 121bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to represent a result was not found. See {@link #RESULT_CODE}. 122bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 123bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_FONT_NOT_FOUND = 1; 124bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 125bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to represent a result was found, but cannot be provided at this moment. Use 126bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * this to indicate, for example, that a font needs to be fetched from the network. See 127bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * {@link #RESULT_CODE}. 128bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 129bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_FONT_UNAVAILABLE = 2; 130bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** 131bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * Constant used to represent that the query was not in a supported format by the provider. 132bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri * See {@link #RESULT_CODE}. 133bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri */ 134bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_MALFORMED_QUERY = 3; 135b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 136b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 137b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** 138b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * Constant used to identify the List of {@link ParcelFileDescriptor} item in the Bundle 139b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * returned to the ResultReceiver in getFont. 140b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri * @hide 141b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri */ 142b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public static final String PARCEL_FONT_RESULTS = "font_results"; 143b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 144bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri // Error codes internal to the system, which can not come from a provider. To keep the number 145bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri // space open for new provider codes, these should all be negative numbers. 146b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** @hide */ 147bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_PROVIDER_NOT_FOUND = -1; 148b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** @hide */ 149bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public static final int RESULT_CODE_WRONG_CERTIFICATES = -2; 150bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri // Note -3 is used by Typeface to indicate the font failed to load. 151b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 152b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private static final int THREAD_RENEWAL_THRESHOLD_MS = 10000; 153b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 154b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final Context mContext; 155b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final PackageManager mPackageManager; 156b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final Object mLock = new Object(); 157b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri @GuardedBy("mLock") 158b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private Handler mHandler; 159b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri @GuardedBy("mLock") 160b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private HandlerThread mThread; 161b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 162b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri /** @hide */ 163ff221613ec1c328489a303491e1aa88850e4a273Clara Bayarri public FontsContract(Context context) { 164ff221613ec1c328489a303491e1aa88850e4a273Clara Bayarri mContext = context.getApplicationContext(); 165b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mPackageManager = mContext.getPackageManager(); 166b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 167b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 1683c4be77db95ea716889568bde853be082e764da9Clara Bayarri /** @hide */ 1693c4be77db95ea716889568bde853be082e764da9Clara Bayarri @VisibleForTesting 1703c4be77db95ea716889568bde853be082e764da9Clara Bayarri public FontsContract(Context context, PackageManager packageManager) { 1713c4be77db95ea716889568bde853be082e764da9Clara Bayarri mContext = context; 1723c4be77db95ea716889568bde853be082e764da9Clara Bayarri mPackageManager = packageManager; 1733c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 1743c4be77db95ea716889568bde853be082e764da9Clara Bayarri 175b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // We use a background thread to post the content resolving work for all requests on. This 176b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // thread should be quit/stopped after all requests are done. 177b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri private final Runnable mReplaceDispatcherThreadRunnable = new Runnable() { 178b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri @Override 179b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public void run() { 180b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri synchronized (mLock) { 181b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (mThread != null) { 182b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread.quitSafely(); 183b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread = null; 184b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler = null; 185b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 186b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 187b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 188b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri }; 189b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 190bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri /** @hide */ 191b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri public void getFont(FontRequest request, ResultReceiver receiver) { 192b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri synchronized (mLock) { 193b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (mHandler == null) { 194b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND); 195b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mThread.start(); 196b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler = new Handler(mThread.getLooper()); 197b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 198b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.post(() -> { 199bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri ProviderInfo providerInfo = getProvider(request, receiver); 200b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (providerInfo == null) { 201b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri return; 202b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 2033c4be77db95ea716889568bde853be082e764da9Clara Bayarri getFontFromProvider(request, receiver, providerInfo.authority); 204b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri }); 205b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable); 206b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS); 207b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 208b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 209b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri 2103c4be77db95ea716889568bde853be082e764da9Clara Bayarri /** @hide */ 2113c4be77db95ea716889568bde853be082e764da9Clara Bayarri @VisibleForTesting 212bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri public ProviderInfo getProvider(FontRequest request, ResultReceiver receiver) { 2133c4be77db95ea716889568bde853be082e764da9Clara Bayarri String providerAuthority = request.getProviderAuthority(); 2143c4be77db95ea716889568bde853be082e764da9Clara Bayarri ProviderInfo info = mPackageManager.resolveContentProvider(providerAuthority, 0); 2153c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (info == null) { 2163c4be77db95ea716889568bde853be082e764da9Clara Bayarri Log.e(TAG, "Can't find content provider " + providerAuthority); 217bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 2183c4be77db95ea716889568bde853be082e764da9Clara Bayarri return null; 2193c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2203c4be77db95ea716889568bde853be082e764da9Clara Bayarri 2213c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (!info.packageName.equals(request.getProviderPackage())) { 2223c4be77db95ea716889568bde853be082e764da9Clara Bayarri Log.e(TAG, "Found content provider " + providerAuthority + ", but package was not " 2233c4be77db95ea716889568bde853be082e764da9Clara Bayarri + request.getProviderPackage()); 224bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 2253c4be77db95ea716889568bde853be082e764da9Clara Bayarri return null; 2263c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2273c4be77db95ea716889568bde853be082e764da9Clara Bayarri // Trust system apps without signature checks 2283c4be77db95ea716889568bde853be082e764da9Clara Bayarri if (info.applicationInfo.isSystemApp()) { 2293c4be77db95ea716889568bde853be082e764da9Clara Bayarri return info; 2303c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2313c4be77db95ea716889568bde853be082e764da9Clara Bayarri 232fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> signatures; 2333c4be77db95ea716889568bde853be082e764da9Clara Bayarri try { 2343c4be77db95ea716889568bde853be082e764da9Clara Bayarri PackageInfo packageInfo = mPackageManager.getPackageInfo(info.packageName, 2353c4be77db95ea716889568bde853be082e764da9Clara Bayarri PackageManager.GET_SIGNATURES); 236fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri signatures = convertToByteArrayList(packageInfo.signatures); 237fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri Collections.sort(signatures, sByteArrayComparator); 2383c4be77db95ea716889568bde853be082e764da9Clara Bayarri } catch (PackageManager.NameNotFoundException e) { 2393c4be77db95ea716889568bde853be082e764da9Clara Bayarri Log.e(TAG, "Can't find content provider " + providerAuthority, e); 240bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null); 2413c4be77db95ea716889568bde853be082e764da9Clara Bayarri return null; 2423c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2433c4be77db95ea716889568bde853be082e764da9Clara Bayarri List<List<byte[]>> requestCertificatesList = request.getCertificates(); 2443c4be77db95ea716889568bde853be082e764da9Clara Bayarri for (int i = 0; i < requestCertificatesList.size(); ++i) { 245fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri // Make a copy so we can sort it without modifying the incoming data. 246fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> requestSignatures = new ArrayList<>(requestCertificatesList.get(i)); 247fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri Collections.sort(requestSignatures, sByteArrayComparator); 248fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (equalsByteArrayList(signatures, requestSignatures)) { 2493c4be77db95ea716889568bde853be082e764da9Clara Bayarri return info; 2503c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2513c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2523c4be77db95ea716889568bde853be082e764da9Clara Bayarri Log.e(TAG, "Certificates don't match for given provider " + providerAuthority); 253bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri receiver.send(RESULT_CODE_WRONG_CERTIFICATES, null); 2543c4be77db95ea716889568bde853be082e764da9Clara Bayarri return null; 2553c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2563c4be77db95ea716889568bde853be082e764da9Clara Bayarri 257fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri private static final Comparator<byte[]> sByteArrayComparator = (l, r) -> { 258fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (l.length != r.length) { 259fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return l.length - r.length; 2603c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 261fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < l.length; ++i) { 262fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (l[i] != r[i]) { 263fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return l[i] - r[i]; 264fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 265fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 266fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return 0; 267fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri }; 268fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri 269fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri private boolean equalsByteArrayList(List<byte[]> signatures, List<byte[]> requestSignatures) { 270fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (signatures.size() != requestSignatures.size()) { 271fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return false; 272fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 273fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < signatures.size(); ++i) { 274fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri if (!Arrays.equals(signatures.get(i), requestSignatures.get(i))) { 275fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return false; 276fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 277fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 278fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri return true; 2793c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2803c4be77db95ea716889568bde853be082e764da9Clara Bayarri 281fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri private List<byte[]> convertToByteArrayList(Signature[] signatures) { 282fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri List<byte[]> shas = new ArrayList<>(); 283fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri for (int i = 0; i < signatures.length; ++i) { 284fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri shas.add(signatures[i].toByteArray()); 285fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri } 2863c4be77db95ea716889568bde853be082e764da9Clara Bayarri return shas; 2873c4be77db95ea716889568bde853be082e764da9Clara Bayarri } 2883c4be77db95ea716889568bde853be082e764da9Clara Bayarri 2893c4be77db95ea716889568bde853be082e764da9Clara Bayarri /** @hide */ 2903c4be77db95ea716889568bde853be082e764da9Clara Bayarri @VisibleForTesting 2913c4be77db95ea716889568bde853be082e764da9Clara Bayarri public void getFontFromProvider(FontRequest request, ResultReceiver receiver, 2923c4be77db95ea716889568bde853be082e764da9Clara Bayarri String authority) { 293b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri ArrayList<FontResult> result = null; 29443c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 2953c4be77db95ea716889568bde853be082e764da9Clara Bayarri .authority(authority) 296b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri .build(); 29743c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final Uri fileBaseUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT) 29843c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .authority(authority) 29943c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .appendPath("file") 30043c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka .build(); 301b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID, 30243c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Columns.FILE_ID, Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, 30343c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Columns.STYLE, Columns.WEIGHT, Columns.ITALIC, Columns.RESULT_CODE }, 304b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri "query = ?", new String[] { request.getQuery() }, null);) { 305b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // TODO: Should we restrict the amount of fonts that can be returned? 306b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri // TODO: Write documentation explaining that all results should be from the same family. 307b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (cursor != null && cursor.getCount() > 0) { 308bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri final int resultCodeColumnIndex = cursor.getColumnIndex(Columns.RESULT_CODE); 309bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri int resultCode = -1; 310b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri result = new ArrayList<>(); 311bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri final int idColumnIndex = cursor.getColumnIndexOrThrow(Columns._ID); 31243c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka final int fileIdColumnIndex = cursor.getColumnIndex(Columns.FILE_ID); 313b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX); 314b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS); 315fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka final int weightColumnIndex = cursor.getColumnIndex(Columns.WEIGHT); 316fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka final int italicColumnIndex = cursor.getColumnIndex(Columns.ITALIC); 317b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE); 318b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri while (cursor.moveToNext()) { 319bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri resultCode = resultCodeColumnIndex != -1 320bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri ? cursor.getInt(resultCodeColumnIndex) : Columns.RESULT_CODE_OK; 321bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri if (resultCode != Columns.RESULT_CODE_OK) { 322bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri if (resultCode < 0) { 323bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri // Negative values are reserved for the internal errors. 324bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri resultCode = Columns.RESULT_CODE_FONT_NOT_FOUND; 325bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri } 326bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri for (int i = 0; i < result.size(); ++i) { 327bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri try { 328bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri result.get(i).getFileDescriptor().close(); 329bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri } catch (IOException e) { 330bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri // Ignore, as we are closing fds for cleanup. 331bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri } 332bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri } 333bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri receiver.send(resultCode, null); 334bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri return; 335bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri } 33643c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka Uri fileUri; 33743c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka if (fileIdColumnIndex == -1) { 33843c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka long id = cursor.getLong(idColumnIndex); 33943c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka fileUri = ContentUris.withAppendedId(uri, id); 34043c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka } else { 34143c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka long id = cursor.getLong(fileIdColumnIndex); 34243c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka fileUri = ContentUris.withAppendedId(fileBaseUri, id); 34343c20cf6d4bd661d85bed76c78953aa656dbcc62Seigo Nonaka } 344b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri try { 345b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri ParcelFileDescriptor pfd = 346b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri mContext.getContentResolver().openFileDescriptor(fileUri, "r"); 3473c4be77db95ea716889568bde853be082e764da9Clara Bayarri final int ttcIndex = ttcIndexColumnIndex != -1 3483c4be77db95ea716889568bde853be082e764da9Clara Bayarri ? cursor.getInt(ttcIndexColumnIndex) : 0; 3493c4be77db95ea716889568bde853be082e764da9Clara Bayarri final String variationSettings = vsColumnIndex != -1 3503c4be77db95ea716889568bde853be082e764da9Clara Bayarri ? cursor.getString(vsColumnIndex) : null; 351fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka // TODO: Stop using STYLE column and enforce WEIGHT/ITALIC column. 352fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka int weight; 353fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka boolean italic; 354fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka if (weightColumnIndex != -1 && italicColumnIndex != -1) { 355fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka weight = cursor.getInt(weightColumnIndex); 356fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka italic = cursor.getInt(italicColumnIndex) == 1; 357fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka } else if (styleColumnIndex != -1) { 358fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka final int style = cursor.getInt(styleColumnIndex); 359fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka weight = (style & Typeface.BOLD) != 0 ? 700 : 400; 360fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka italic = (style & Typeface.ITALIC) != 0; 361fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka } else { 362fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka weight = 400; 363fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka italic = false; 364fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka } 365fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka result.add( 366fe04aa840e0682e9813e1ac4958772f898eb02caSeigo Nonaka new FontResult(pfd, ttcIndex, variationSettings, weight, italic)); 367b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } catch (FileNotFoundException e) { 368b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri Log.e(TAG, "FileNotFoundException raised when interacting with content " 3693c4be77db95ea716889568bde853be082e764da9Clara Bayarri + "provider " + authority, e); 370b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 371b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 372b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 373b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 374b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri if (result != null && !result.isEmpty()) { 375b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri Bundle bundle = new Bundle(); 376b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result); 377bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri receiver.send(Columns.RESULT_CODE_OK, bundle); 3783c4be77db95ea716889568bde853be082e764da9Clara Bayarri return; 379b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 380bacf2352ab892724551431551ae973ae3b68db35Clara Bayarri receiver.send(Columns.RESULT_CODE_FONT_NOT_FOUND, null); 381b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri } 382b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri} 383