Introduce Fonts Content Provider

This change exposes to developers the ability to request fonts
from a provider via Typeface.

Until further security is implemented, only system apps can
provide fonts.

Test: See topic for CTS change
Change-Id: Ic7d5e2648340ee561f4d4c2d73a673748d2af076
This commit is contained in:
Clara Bayarri
2016-10-20 10:42:13 +01:00
parent 2cff9319e8
commit b0812a3049
8 changed files with 665 additions and 2 deletions

View File

@@ -13226,6 +13226,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);
@@ -13246,6 +13247,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();
}
@@ -13800,6 +13809,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 {
@@ -32951,6 +32973,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";

View File

@@ -13771,6 +13771,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);
@@ -13791,6 +13792,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();
}
@@ -14345,6 +14354,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 {
@@ -35774,6 +35796,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";

View File

@@ -13258,6 +13258,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);
@@ -13278,6 +13279,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();
}
@@ -13832,6 +13841,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 {
@@ -33067,6 +33089,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";

View File

@@ -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;
}
}

View File

@@ -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;
@@ -134,6 +153,138 @@ public class Typeface {
throw new RuntimeException("Font resource not found " + path);
}
/**
* 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.

View File

@@ -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
+ "}";
}
}

View File

@@ -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];
}
};
}

View File

@@ -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;