summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt32
-rw-r--r--api/system-current.txt32
-rw-r--r--api/test-current.txt32
-rw-r--r--core/java/android/provider/FontsContract.java197
-rw-r--r--graphics/java/android/graphics/Typeface.java155
-rw-r--r--graphics/java/android/graphics/fonts/FontRequest.java93
-rw-r--r--graphics/java/android/graphics/fonts/FontResult.java108
-rw-r--r--graphics/java/android/graphics/fonts/FontSpec.aidl18
8 files changed, 665 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt
index 93f9973126a5..b964a60beead 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13227,6 +13227,7 @@ package android.graphics {
}
public class Typeface {
+ method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
method public static android.graphics.Typeface create(java.lang.String, int);
method public static android.graphics.Typeface create(android.graphics.Typeface, int);
method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13247,6 +13248,14 @@ package android.graphics {
field public static final android.graphics.Typeface SERIF;
}
+ public static abstract interface Typeface.FontRequestCallback {
+ method public abstract void onTypefaceRequestFailed(int);
+ method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 2; // 0x2
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = 0; // 0x0
+ }
+
public class Xfermode {
ctor public Xfermode();
}
@@ -13801,6 +13810,19 @@ package android.graphics.drawable.shapes {
}
+package android.graphics.fonts {
+
+ public final class FontRequest implements android.os.Parcelable {
+ ctor public FontRequest(java.lang.String, java.lang.String);
+ method public int describeContents();
+ method public java.lang.String getProviderAuthority();
+ method public java.lang.String getQuery();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
+ }
+
+}
+
package android.graphics.pdf {
public class PdfDocument {
@@ -33046,6 +33068,16 @@ package android.provider {
method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
}
+ public class FontsContract {
+ }
+
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ ctor public FontsContract.Columns();
+ field public static final java.lang.String STYLE = "font_style";
+ field public static final java.lang.String TTC_INDEX = "font_ttc_index";
+ field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ }
+
public final deprecated class LiveFolders implements android.provider.BaseColumns {
field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
field public static final java.lang.String DESCRIPTION = "description";
diff --git a/api/system-current.txt b/api/system-current.txt
index af63cbb693a3..d7c8f5aee4e4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -13774,6 +13774,7 @@ package android.graphics {
}
public class Typeface {
+ method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
method public static android.graphics.Typeface create(java.lang.String, int);
method public static android.graphics.Typeface create(android.graphics.Typeface, int);
method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13794,6 +13795,14 @@ package android.graphics {
field public static final android.graphics.Typeface SERIF;
}
+ public static abstract interface Typeface.FontRequestCallback {
+ method public abstract void onTypefaceRequestFailed(int);
+ method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 2; // 0x2
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = 0; // 0x0
+ }
+
public class Xfermode {
ctor public Xfermode();
}
@@ -14348,6 +14357,19 @@ package android.graphics.drawable.shapes {
}
+package android.graphics.fonts {
+
+ public final class FontRequest implements android.os.Parcelable {
+ ctor public FontRequest(java.lang.String, java.lang.String);
+ method public int describeContents();
+ method public java.lang.String getProviderAuthority();
+ method public java.lang.String getQuery();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
+ }
+
+}
+
package android.graphics.pdf {
public class PdfDocument {
@@ -35914,6 +35936,16 @@ package android.provider {
method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
}
+ public class FontsContract {
+ }
+
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ ctor public FontsContract.Columns();
+ field public static final java.lang.String STYLE = "font_style";
+ field public static final java.lang.String TTC_INDEX = "font_ttc_index";
+ field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ }
+
public final deprecated class LiveFolders implements android.provider.BaseColumns {
field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
field public static final java.lang.String DESCRIPTION = "description";
diff --git a/api/test-current.txt b/api/test-current.txt
index ab94c0bcad25..c2ae08194263 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -13259,6 +13259,7 @@ package android.graphics {
}
public class Typeface {
+ method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
method public static android.graphics.Typeface create(java.lang.String, int);
method public static android.graphics.Typeface create(android.graphics.Typeface, int);
method public static android.graphics.Typeface createFromAsset(android.content.res.AssetManager, java.lang.String);
@@ -13279,6 +13280,14 @@ package android.graphics {
field public static final android.graphics.Typeface SERIF;
}
+ public static abstract interface Typeface.FontRequestCallback {
+ method public abstract void onTypefaceRequestFailed(int);
+ method public abstract void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 2; // 0x2
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = 0; // 0x0
+ }
+
public class Xfermode {
ctor public Xfermode();
}
@@ -13833,6 +13842,19 @@ package android.graphics.drawable.shapes {
}
+package android.graphics.fonts {
+
+ public final class FontRequest implements android.os.Parcelable {
+ ctor public FontRequest(java.lang.String, java.lang.String);
+ method public int describeContents();
+ method public java.lang.String getProviderAuthority();
+ method public java.lang.String getQuery();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.graphics.fonts.FontRequest> CREATOR;
+ }
+
+}
+
package android.graphics.pdf {
public class PdfDocument {
@@ -33162,6 +33184,16 @@ package android.provider {
method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
}
+ public class FontsContract {
+ }
+
+ public static final class FontsContract.Columns implements android.provider.BaseColumns {
+ ctor public FontsContract.Columns();
+ field public static final java.lang.String STYLE = "font_style";
+ field public static final java.lang.String TTC_INDEX = "font_ttc_index";
+ field public static final java.lang.String VARIATION_SETTINGS = "font_variation_settings";
+ }
+
public final deprecated class LiveFolders implements android.provider.BaseColumns {
field public static final java.lang.String ACTION_CREATE_LIVE_FOLDER = "android.intent.action.CREATE_LIVE_FOLDER";
field public static final java.lang.String DESCRIPTION = "description";
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
new file mode 100644
index 000000000000..90e710f12c08
--- /dev/null
+++ b/core/java/android/provider/FontsContract.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.provider;
+
+import android.app.ActivityThread;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.database.Cursor;
+import android.graphics.fonts.FontRequest;
+import android.graphics.fonts.FontResult;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+import android.os.ResultReceiver;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+
+/**
+ * Utility class to deal with Font ContentProviders.
+ */
+public class FontsContract {
+ private static final String TAG = "FontsContract";
+
+ /**
+ * Defines the constants used in a response from a Font Provider. The cursor returned from the
+ * query should have the ID column populated with the content uri ID for the resulting font.
+ * This should point to a real file or shared memory, as the client will mmap the given file
+ * descriptor. Pipes, sockets and other non-mmap-able file descriptors will fail to load in the
+ * client application.
+ */
+ public static final class Columns implements BaseColumns {
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
+ * should have this column populated with an int for the ttc index for the resulting font.
+ */
+ public static final String TTC_INDEX = "font_ttc_index";
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
+ * may populate this column with the font variation settings String information for the
+ * font.
+ */
+ public static final String VARIATION_SETTINGS = "font_variation_settings";
+ /**
+ * Constant used to request data from a font provider. The cursor returned from the query
+ * should have this column populated with the int style for the resulting font. This should
+ * be one of {@link android.graphics.Typeface#NORMAL},
+ * {@link android.graphics.Typeface#BOLD}, {@link android.graphics.Typeface#ITALIC} or
+ * {@link android.graphics.Typeface#BOLD_ITALIC}
+ */
+ public static final String STYLE = "font_style";
+ }
+
+ /**
+ * Constant used to identify the List of {@link ParcelFileDescriptor} item in the Bundle
+ * returned to the ResultReceiver in getFont.
+ * @hide
+ */
+ public static final String PARCEL_FONT_RESULTS = "font_results";
+
+ /** @hide */
+ public static final int RESULT_CODE_OK = 0;
+ /** @hide */
+ public static final int RESULT_CODE_FONT_NOT_FOUND = 1;
+ /** @hide */
+ public static final int RESULT_CODE_PROVIDER_NOT_FOUND = 2;
+
+ private static final int THREAD_RENEWAL_THRESHOLD_MS = 10000;
+
+ private final Context mContext;
+ private final PackageManager mPackageManager;
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private Handler mHandler;
+ @GuardedBy("mLock")
+ private HandlerThread mThread;
+
+ /** @hide */
+ public FontsContract() {
+ // TODO: investigate if the system context is the best option here. ApplicationContext or
+ // the one passed by developer?
+ // TODO: Looks like ActivityThread.currentActivityThread() can return null. Check when it
+ // returns null and check if we need to handle null case.
+ mContext = ActivityThread.currentActivityThread().getSystemContext();
+ mPackageManager = mContext.getPackageManager();
+ }
+
+ // We use a background thread to post the content resolving work for all requests on. This
+ // thread should be quit/stopped after all requests are done.
+ private final Runnable mReplaceDispatcherThreadRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ if (mThread != null) {
+ mThread.quitSafely();
+ mThread = null;
+ mHandler = null;
+ }
+ }
+ }
+ };
+
+ /**
+ * @hide
+ */
+ public void getFont(FontRequest request, ResultReceiver receiver) {
+ synchronized (mLock) {
+ if (mHandler == null) {
+ mThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND);
+ mThread.start();
+ mHandler = new Handler(mThread.getLooper());
+ }
+ mHandler.post(() -> {
+ String providerAuthority = request.getProviderAuthority();
+ // TODO: Implement cert checking for non-system apps
+ ProviderInfo providerInfo = mPackageManager.resolveContentProvider(
+ providerAuthority, PackageManager.MATCH_SYSTEM_ONLY);
+ if (providerInfo == null) {
+ receiver.send(RESULT_CODE_PROVIDER_NOT_FOUND, null);
+ return;
+ }
+ Bundle result = getFontFromProvider(request, receiver, providerInfo);
+ if (result == null) {
+ receiver.send(RESULT_CODE_FONT_NOT_FOUND, null);
+ return;
+ }
+ receiver.send(RESULT_CODE_OK, result);
+ });
+ mHandler.removeCallbacks(mReplaceDispatcherThreadRunnable);
+ mHandler.postDelayed(mReplaceDispatcherThreadRunnable, THREAD_RENEWAL_THRESHOLD_MS);
+ }
+ }
+
+ private Bundle getFontFromProvider(FontRequest request, ResultReceiver receiver,
+ ProviderInfo providerInfo) {
+ ArrayList<FontResult> result = null;
+ Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(providerInfo.authority)
+ .build();
+ try (Cursor cursor = mContext.getContentResolver().query(uri, new String[] { Columns._ID,
+ Columns.TTC_INDEX, Columns.VARIATION_SETTINGS, Columns.STYLE },
+ "query = ?", new String[] { request.getQuery() }, null);) {
+ // TODO: Should we restrict the amount of fonts that can be returned?
+ // TODO: Write documentation explaining that all results should be from the same family.
+ if (cursor != null && cursor.getCount() > 0) {
+ result = new ArrayList<>();
+ final int idColumnIndex = cursor.getColumnIndex(Columns._ID);
+ final int ttcIndexColumnIndex = cursor.getColumnIndex(Columns.TTC_INDEX);
+ final int vsColumnIndex = cursor.getColumnIndex(Columns.VARIATION_SETTINGS);
+ final int styleColumnIndex = cursor.getColumnIndex(Columns.STYLE);
+ while (cursor.moveToNext()) {
+ long id = cursor.getLong(idColumnIndex);
+ Uri fileUri = ContentUris.withAppendedId(uri, id);
+ try {
+ ParcelFileDescriptor pfd =
+ mContext.getContentResolver().openFileDescriptor(fileUri, "r");
+ final int ttcIndex = cursor.getInt(ttcIndexColumnIndex);
+ final String variationSettings = cursor.getString(vsColumnIndex);
+ final int style = cursor.getInt(styleColumnIndex);
+ result.add(new FontResult(pfd, ttcIndex, variationSettings, style));
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "FileNotFoundException raised when interacting with content "
+ + "provider " + providerInfo.authority, e);
+ }
+ }
+ }
+ }
+ if (result != null && !result.isEmpty()) {
+ Bundle bundle = new Bundle();
+ bundle.putParcelableArrayList(PARCEL_FONT_RESULTS, result);
+ return bundle;
+ }
+ return null;
+ }
+}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 0a349e91ad1e..4e863e37f363 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -16,20 +16,34 @@
package android.graphics;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.content.res.AssetManager;
+import android.graphics.fonts.FontRequest;
+import android.graphics.fonts.FontResult;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.os.ResultReceiver;
+import android.provider.FontsContract;
import android.text.FontConfig;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.LruCache;
import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.io.IoUtils;
+
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
@@ -64,7 +78,11 @@ public class Typeface {
static Typeface[] sDefaults;
private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache =
- new LongSparseArray<SparseArray<Typeface>>(3);
+ new LongSparseArray<>(3);
+ @GuardedBy("sLock")
+ private static FontsContract sFontsContract;
+ @GuardedBy("sLock")
+ private static Handler mHandler;
/**
* Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
@@ -74,6 +92,7 @@ public class Typeface {
static Typeface sDefaultTypeface;
static Map<String, Typeface> sSystemFontMap;
static FontFamily[] sFallbackFonts;
+ private static final Object sLock = new Object();
static final String FONTS_CONFIG = "fonts.xml";
@@ -124,7 +143,7 @@ public class Typeface {
FontFamily fontFamily = new FontFamily();
if (fontFamily.addFontFromAssetManager(mgr, path, cookie, false /* isAsset */)) {
- FontFamily[] families = { fontFamily };
+ FontFamily[] families = {fontFamily};
typeface = createFromFamiliesWithDefault(families);
sDynamicTypefaceCache.put(key, typeface);
return typeface;
@@ -135,6 +154,138 @@ public class Typeface {
}
/**
+ * Create a typeface object given a font request. The font will be asynchronously fetched,
+ * therefore the result is delivered to the given callback. See {@link FontRequest}.
+ * Only one of the methods in callback will be invoked, depending on whether the request
+ * succeeds or fails. These calls will happen on the main thread.
+ * @param request A {@link FontRequest} object that identifies the provider and query for the
+ * request. May not be null.
+ * @param callback A callback that will be triggered when results are obtained. May not be null.
+ */
+ public static void create(@NonNull FontRequest request, @NonNull FontRequestCallback callback) {
+ synchronized (sLock) {
+ if (sFontsContract == null) {
+ sFontsContract = new FontsContract();
+ mHandler = new Handler();
+ }
+ final ResultReceiver receiver = new ResultReceiver(null) {
+ @Override
+ public void onReceiveResult(int resultCode, Bundle resultData) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ receiveResult(request, callback, resultCode, resultData);
+ }
+ });
+ }
+ };
+ sFontsContract.getFont(request, receiver);
+ }
+ }
+
+ private static void receiveResult(FontRequest request, FontRequestCallback callback,
+ int resultCode, Bundle resultData) {
+ if (resultCode == FontsContract.RESULT_CODE_PROVIDER_NOT_FOUND) {
+ callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND);
+ return;
+ }
+ if (resultCode == FontsContract.RESULT_CODE_FONT_NOT_FOUND
+ || resultData == null) {
+ callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND);
+ return;
+ }
+ List<FontResult> resultList =
+ resultData.getParcelableArrayList(FontsContract.PARCEL_FONT_RESULTS);
+ if (resultList == null || resultList.isEmpty()) {
+ callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND);
+ return;
+ }
+ FontFamily fontFamily = new FontFamily();
+ for (int i = 0; i < resultList.size(); ++i) {
+ FontResult result = resultList.get(i);
+ ParcelFileDescriptor fd = result.getFileDescriptor();
+ if (fd == null) {
+ callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
+ return;
+ }
+ try (FileInputStream is = new FileInputStream(fd.getFileDescriptor())) {
+ FileChannel fileChannel = is.getChannel();
+ long fontSize = fileChannel.size();
+ ByteBuffer fontBuffer = fileChannel.map(
+ FileChannel.MapMode.READ_ONLY, 0, fontSize);
+ int style = result.getStyle();
+ int weight = (style & BOLD) != 0 ? 700 : 400;
+ // TODO: this method should be
+ // create(fd, ttcIndex, fontVariationSettings, style).
+ if (!fontFamily.addFontWeightStyle(fontBuffer, result.getTtcIndex(),
+ null, weight, (style & ITALIC) != 0)) {
+ Log.e(TAG, "Error creating font " + request.getQuery());
+ callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
+ return;
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Error reading font " + request.getQuery(), e);
+ callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR);
+ return;
+ } finally {
+ IoUtils.closeQuietly(fd);
+ }
+ }
+ callback.onTypefaceRetrieved(Typeface.createFromFamiliesWithDefault(
+ new FontFamily[] {fontFamily}));
+ }
+
+ /**
+ * Interface used to receive asynchronously fetched typefaces.
+ */
+ public interface FontRequestCallback {
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * provider was not found on the device.
+ */
+ int FAIL_REASON_PROVIDER_NOT_FOUND = 0;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+ * returned by the provider was not loaded properly.
+ */
+ int FAIL_REASON_FONT_LOAD_ERROR = 1;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * provider did not return any results for the given query.
+ */
+ int FAIL_REASON_FONT_NOT_FOUND = 2;
+
+ /** @hide */
+ @IntDef({FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR,
+ FAIL_REASON_FONT_NOT_FOUND})
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FontRequestFailReason {}
+
+ /**
+ * Called then a Typeface request done via {@link Typeface#create(FontRequest,
+ * FontRequestCallback)} is complete. Note that this method will not be called if
+ * {@link #onTypefaceRequestFailed(int)} is called instead.
+ * @param typeface The Typeface object retrieved.
+ */
+ void onTypefaceRetrieved(Typeface typeface);
+
+ /**
+ * Called when a Typeface request done via {@link Typeface#create(FontRequest,
+ * FontRequestCallback)} fails.
+ * @param reason One of {@link #FAIL_REASON_PROVIDER_NOT_FOUND},
+ * {@link #FAIL_REASON_FONT_NOT_FOUND} or
+ * {@link #FAIL_REASON_FONT_LOAD_ERROR}.
+ */
+ void onTypefaceRequestFailed(@FontRequestFailReason int reason);
+ }
+
+ /**
* Create a typeface object given a family name, and option style information.
* If null is passed for the name, then the "default" font will be chosen.
* The resulting typeface object can be queried (getStyle()) to discover what
diff --git a/graphics/java/android/graphics/fonts/FontRequest.java b/graphics/java/android/graphics/fonts/FontRequest.java
new file mode 100644
index 000000000000..e50df6faa38e
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontRequest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Information about a font request that may be sent to a Font Provider.
+ */
+public final class FontRequest implements Parcelable {
+ private final String mProviderAuthority;
+ private final String mQuery;
+
+ /**
+ * @param providerAuthority The authority of the Font Provider to be used for the request.
+ * @param query The query to be sent over to the provider. Refer to your font provider's
+ * documentation on the format of this string.
+ */
+ public FontRequest(@NonNull String providerAuthority, @NonNull String query) {
+ mProviderAuthority = Preconditions.checkNotNull(providerAuthority);
+ mQuery = Preconditions.checkNotNull(query);
+ }
+
+ /**
+ * Returns the selected font provider's authority. This tells the system what font provider
+ * it should request the font from.
+ */
+ public String getProviderAuthority() {
+ return mProviderAuthority;
+ }
+
+ /**
+ * Returns the query string. Refer to your font provider's documentation on the format of this
+ * string.
+ */
+ public String getQuery() {
+ return mQuery;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mProviderAuthority);
+ dest.writeString(mQuery);
+ }
+
+ private FontRequest(Parcel in) {
+ mProviderAuthority = in.readString();
+ mQuery = in.readString();
+ }
+
+ public static final Parcelable.Creator<FontRequest> CREATOR =
+ new Parcelable.Creator<FontRequest>() {
+ @Override
+ public FontRequest createFromParcel(Parcel in) {
+ return new FontRequest(in);
+ }
+
+ @Override
+ public FontRequest[] newArray(int size) {
+ return new FontRequest[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "FontRequest {"
+ + "mProviderAuthority: " + mProviderAuthority
+ + ", mQuery: " + mQuery
+ + "}";
+ }
+}
diff --git a/graphics/java/android/graphics/fonts/FontResult.java b/graphics/java/android/graphics/fonts/FontResult.java
new file mode 100644
index 000000000000..3ef99fdd62b7
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontResult.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.graphics.fonts;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.Paint;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+/**
+ * Results returned from a Font Provider to the system.
+ * @hide
+ */
+public final class FontResult implements Parcelable {
+ private final ParcelFileDescriptor mFileDescriptor;
+ private final int mTtcIndex;
+ private final String mFontVariationSettings;
+ private final int mStyle;
+
+ /**
+ * Creates a FontResult with all the information needed about a provided font.
+ * @param fileDescriptor A ParcelFileDescriptor pointing to the font file. This shoult point to
+ * a real file or shared memory, as the client will mmap the given file
+ * descriptor. Pipes, sockets and other non-mmap-able file descriptors
+ * will fail to load in the client application.
+ * @param ttcIndex If providing a TTC_INDEX file, the index to point to. Otherwise, 0.
+ * @param fontVariationSettings If providing a variation font, the settings for it. May be null.
+ * @param style One of {@link android.graphics.Typeface#NORMAL},
+ * {@link android.graphics.Typeface#BOLD}, {@link android.graphics.Typeface#ITALIC}
+ * or {@link android.graphics.Typeface#BOLD_ITALIC}
+ */
+ public FontResult(@NonNull ParcelFileDescriptor fileDescriptor, int ttcIndex,
+ @Nullable String fontVariationSettings, int style) {
+ mFileDescriptor = Preconditions.checkNotNull(fileDescriptor);
+ mTtcIndex = ttcIndex;
+ mFontVariationSettings = fontVariationSettings;
+ mStyle = style;
+ }
+
+ public ParcelFileDescriptor getFileDescriptor() {
+ return mFileDescriptor;
+ }
+
+ public int getTtcIndex() {
+ return mTtcIndex;
+ }
+
+ public String getFontVariationSettings() {
+ return mFontVariationSettings;
+ }
+
+ public int getStyle() {
+ return mStyle;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mFileDescriptor, flags);
+ dest.writeInt(mTtcIndex);
+ dest.writeString(mFontVariationSettings);
+ dest.writeInt(mStyle);
+ }
+
+ private FontResult(Parcel in) {
+ mFileDescriptor = in.readParcelable(null);
+ mTtcIndex = in.readInt();
+ mFontVariationSettings = in.readString();
+ mStyle = in.readInt();
+ }
+
+ public static final Parcelable.Creator<FontResult> CREATOR =
+ new Parcelable.Creator<FontResult>() {
+ @Override
+ public FontResult createFromParcel(Parcel in) {
+ return new FontResult(in);
+ }
+
+ @Override
+ public FontResult[] newArray(int size) {
+ return new FontResult[size];
+ }
+ };
+}
diff --git a/graphics/java/android/graphics/fonts/FontSpec.aidl b/graphics/java/android/graphics/fonts/FontSpec.aidl
new file mode 100644
index 000000000000..dddea2560d3d
--- /dev/null
+++ b/graphics/java/android/graphics/fonts/FontSpec.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.graphics.fonts;
+
+parcelable FontSpec; \ No newline at end of file