Merge "Introduce FontsContract.requestFont and deprecate Typeface.create" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 45fb4d9..84ebdf3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13762,7 +13762,7 @@
}
public class Typeface {
- method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+ method public static deprecated 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);
@@ -13796,7 +13796,7 @@
method public android.graphics.Typeface.Builder setWeight(int);
}
- public static abstract interface Typeface.FontRequestCallback {
+ public static abstract deprecated 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 = -3; // 0xfffffffd
@@ -34505,6 +34505,7 @@
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
}
public static final class FontsContract.Columns implements android.provider.BaseColumns {
@@ -34538,6 +34539,18 @@
method public boolean isItalic();
}
+ public static class FontsContract.FontRequestCallback {
+ ctor public FontsContract.FontRequestCallback();
+ method public void onTypefaceRequestFailed(int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ }
+
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 8ae3f51..7b0e10b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -14529,7 +14529,7 @@
}
public class Typeface {
- method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+ method public static deprecated 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);
@@ -14563,7 +14563,7 @@
method public android.graphics.Typeface.Builder setWeight(int);
}
- public static abstract interface Typeface.FontRequestCallback {
+ public static abstract deprecated 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 = -3; // 0xfffffffd
@@ -37482,6 +37482,7 @@
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
}
public static final class FontsContract.Columns implements android.provider.BaseColumns {
@@ -37515,6 +37516,18 @@
method public boolean isItalic();
}
+ public static class FontsContract.FontRequestCallback {
+ ctor public FontsContract.FontRequestCallback();
+ method public void onTypefaceRequestFailed(int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ }
+
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 fd8c2d0..f3a5adc 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -13813,7 +13813,7 @@
}
public class Typeface {
- method public static void create(android.graphics.fonts.FontRequest, android.graphics.Typeface.FontRequestCallback);
+ method public static deprecated 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);
@@ -13847,7 +13847,7 @@
method public android.graphics.Typeface.Builder setWeight(int);
}
- public static abstract interface Typeface.FontRequestCallback {
+ public static abstract deprecated 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 = -3; // 0xfffffffd
@@ -34649,6 +34649,7 @@
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[], int, boolean, java.lang.String);
method public static android.graphics.Typeface buildTypeface(android.content.Context, android.os.CancellationSignal, android.provider.FontsContract.FontInfo[]);
method public static android.provider.FontsContract.FontFamilyResult fetchFonts(android.content.Context, android.os.CancellationSignal, android.graphics.fonts.FontRequest) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public static void requestFont(android.content.Context, android.graphics.fonts.FontRequest, android.provider.FontsContract.FontRequestCallback, android.os.Handler);
}
public static final class FontsContract.Columns implements android.provider.BaseColumns {
@@ -34682,6 +34683,18 @@
method public boolean isItalic();
}
+ public static class FontsContract.FontRequestCallback {
+ ctor public FontsContract.FontRequestCallback();
+ method public void onTypefaceRequestFailed(int);
+ method public void onTypefaceRetrieved(android.graphics.Typeface);
+ field public static final int FAIL_REASON_FONT_LOAD_ERROR = -3; // 0xfffffffd
+ field public static final int FAIL_REASON_FONT_NOT_FOUND = 1; // 0x1
+ field public static final int FAIL_REASON_FONT_UNAVAILABLE = 2; // 0x2
+ field public static final int FAIL_REASON_MALFORMED_QUERY = 3; // 0x3
+ field public static final int FAIL_REASON_PROVIDER_NOT_FOUND = -1; // 0xffffffff
+ field public static final int FAIL_REASON_WRONG_CERTIFICATES = -2; // 0xfffffffe
+ }
+
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
index f9508902..7e56ff9 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -394,6 +394,150 @@
}
/**
+ * Interface used to receive asynchronously fetched typefaces.
+ */
+ public static class FontRequestCallback {
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * provider was not found on the device.
+ */
+ public static final int FAIL_REASON_PROVIDER_NOT_FOUND = RESULT_CODE_PROVIDER_NOT_FOUND;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * provider must be authenticated and the given certificates do not match its signature.
+ */
+ public static final int FAIL_REASON_WRONG_CERTIFICATES = RESULT_CODE_WRONG_CERTIFICATES;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+ * returned by the provider was not loaded properly.
+ */
+ public static final int FAIL_REASON_FONT_LOAD_ERROR = -3;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+ * provider did not return any results for the given query.
+ */
+ public static final int FAIL_REASON_FONT_NOT_FOUND = Columns.RESULT_CODE_FONT_NOT_FOUND;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the font
+ * provider found the queried font, but it is currently unavailable.
+ */
+ public static final int FAIL_REASON_FONT_UNAVAILABLE = Columns.RESULT_CODE_FONT_UNAVAILABLE;
+ /**
+ * Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given
+ * query was not supported by the provider.
+ */
+ public static final int FAIL_REASON_MALFORMED_QUERY = Columns.RESULT_CODE_MALFORMED_QUERY;
+
+ /** @hide */
+ @IntDef({ FAIL_REASON_PROVIDER_NOT_FOUND, FAIL_REASON_FONT_LOAD_ERROR,
+ FAIL_REASON_FONT_NOT_FOUND, FAIL_REASON_FONT_UNAVAILABLE,
+ FAIL_REASON_MALFORMED_QUERY })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FontRequestFailReason {}
+
+ public FontRequestCallback() {}
+
+ /**
+ * 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.
+ */
+ public 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},
+ * {@link #FAIL_REASON_FONT_LOAD_ERROR},
+ * {@link #FAIL_REASON_FONT_UNAVAILABLE} or
+ * {@link #FAIL_REASON_MALFORMED_QUERY}.
+ */
+ public void onTypefaceRequestFailed(@FontRequestFailReason int reason) {}
+ }
+
+ /**
+ * 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 caller thread.
+ * @param context A context to be used for fetching from font provider.
+ * @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.
+ * @param handler A handler to be processed the font fetching.
+ */
+ public static void requestFont(@NonNull Context context, @NonNull FontRequest request,
+ @NonNull FontRequestCallback callback, @NonNull Handler handler) {
+
+ final Handler callerThreadHandler = new Handler();
+ handler.post(() -> {
+ // TODO: Cache the result.
+ FontFamilyResult result;
+ try {
+ result = fetchFonts(context, null /* cancellation signal */, request);
+ } catch (NameNotFoundException e) {
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_PROVIDER_NOT_FOUND));
+ return;
+ }
+
+ if (result.getStatusCode() != FontFamilyResult.STATUS_OK) {
+ switch (result.getStatusCode()) {
+ case FontFamilyResult.STATUS_WRONG_CERTIFICATES:
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_WRONG_CERTIFICATES));
+ return;
+ case FontFamilyResult.STATUS_UNEXPECTED_DATA_PROVIDED:
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+ return;
+ default:
+ // fetchFont returns unexpected status type. Fallback to load error.
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+ return;
+ }
+ }
+
+ final FontInfo[] fonts = result.getFonts();
+ if (fonts == null || fonts.length == 0) {
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_NOT_FOUND));
+ return;
+ }
+ for (final FontInfo font : fonts) {
+ if (font.getResultCode() != Columns.RESULT_CODE_OK) {
+ // We proceed if all font entry is ready to use. Otherwise report the first
+ // error.
+ final int resultCode = font.getResultCode();
+ if (resultCode < 0) {
+ // Negative values are reserved for internal errors. Fallback to load error.
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+ } else {
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ resultCode));
+ }
+ return;
+ }
+ }
+
+ final Typeface typeface = buildTypeface(context, null /* cancellation signal */, fonts);
+ if (typeface == null) {
+ // Something went wrong during reading font files. This happens if the given font
+ // file is an unsupported font type.
+ callerThreadHandler.post(() -> callback.onTypefaceRequestFailed(
+ FontRequestCallback.FAIL_REASON_FONT_LOAD_ERROR));
+ return;
+ }
+
+ callerThreadHandler.post(() -> callback.onTypefaceRetrieved(typeface));
+ });
+ }
+
+ /**
* Fetch fonts given a font request.
*
* @param context A {@link Context} to be used for fetching fonts.
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 21533f8..c3588dc 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -292,6 +292,7 @@
* request. May not be null.
* @param callback A callback that will be triggered when results are obtained. May not be null.
*/
+ @Deprecated
public static void create(@NonNull FontRequest request, @NonNull FontRequestCallback callback) {
// Check the cache first
// TODO: would the developer want to avoid a cache hit and always ask for the freshest
@@ -404,6 +405,7 @@
/**
* Interface used to receive asynchronously fetched typefaces.
*/
+ @Deprecated
public interface FontRequestCallback {
/**
* Constant returned by {@link #onTypefaceRequestFailed(int)} signaling that the given