diff options
22 files changed, 1037 insertions, 147 deletions
diff --git a/Android.mk b/Android.mk index 21bd76b76a62..2539c3dfbda6 100644 --- a/Android.mk +++ b/Android.mk @@ -346,6 +346,7 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \ core/java/com/android/internal/backup/IBackupTransport.aidl \ core/java/com/android/internal/backup/IObbBackupService.aidl \ + core/java/com/android/internal/font/IFontManager.aidl \ core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl \ core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl \ core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl \ diff --git a/api/current.txt b/api/current.txt index 2b07a5c54acf..be0cab84bdd5 100644 --- a/api/current.txt +++ b/api/current.txt @@ -8472,6 +8472,7 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; + field public static final java.lang.String FONT_SERVICE = "font"; field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; @@ -39449,6 +39450,65 @@ package android.text { method public android.text.Editable newEditable(java.lang.CharSequence); } + public final class FontConfig implements android.os.Parcelable { + ctor public FontConfig(); + ctor public FontConfig(android.text.FontConfig); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Alias> getAliases(); + method public java.util.List<android.text.FontConfig.Family> getFamilies(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR; + } + + public static final class FontConfig.Alias implements android.os.Parcelable { + ctor public FontConfig.Alias(java.lang.String, java.lang.String, int); + method public int describeContents(); + method public java.lang.String getName(); + method public java.lang.String getToName(); + method public int getWeight(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR; + } + + public static final class FontConfig.Axis implements android.os.Parcelable { + ctor public FontConfig.Axis(int, float); + method public int describeContents(); + method public float getStyleValue(); + method public int getTag(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR; + } + + public static final class FontConfig.Family implements android.os.Parcelable { + ctor public FontConfig.Family(java.lang.String, java.util.List<android.text.FontConfig.Font>, java.lang.String, java.lang.String); + ctor public FontConfig.Family(android.text.FontConfig.Family); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Font> getFonts(); + method public java.lang.String getLanguage(); + method public java.lang.String getName(); + method public java.lang.String getVariant(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR; + } + + public static final class FontConfig.Font implements android.os.Parcelable { + ctor public FontConfig.Font(java.lang.String, int, java.util.List<android.text.FontConfig.Axis>, int, boolean); + ctor public FontConfig.Font(android.text.FontConfig.Font); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Axis> getAxes(); + method public android.os.ParcelFileDescriptor getFd(); + method public java.lang.String getFontName(); + method public int getTtcIndex(); + method public int getWeight(); + method public boolean isItalic(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR; + } + + public final class FontManager { + method public android.text.FontConfig getSystemFonts(); + } + public abstract interface GetChars implements java.lang.CharSequence { method public abstract void getChars(int, int, char[], int); } diff --git a/api/system-current.txt b/api/system-current.txt index 7cb8aaf06be4..bb8d7fca3780 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8847,6 +8847,7 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; + field public static final java.lang.String FONT_SERVICE = "font"; field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; @@ -42724,6 +42725,65 @@ package android.text { method public android.text.Editable newEditable(java.lang.CharSequence); } + public final class FontConfig implements android.os.Parcelable { + ctor public FontConfig(); + ctor public FontConfig(android.text.FontConfig); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Alias> getAliases(); + method public java.util.List<android.text.FontConfig.Family> getFamilies(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR; + } + + public static final class FontConfig.Alias implements android.os.Parcelable { + ctor public FontConfig.Alias(java.lang.String, java.lang.String, int); + method public int describeContents(); + method public java.lang.String getName(); + method public java.lang.String getToName(); + method public int getWeight(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR; + } + + public static final class FontConfig.Axis implements android.os.Parcelable { + ctor public FontConfig.Axis(int, float); + method public int describeContents(); + method public float getStyleValue(); + method public int getTag(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR; + } + + public static final class FontConfig.Family implements android.os.Parcelable { + ctor public FontConfig.Family(java.lang.String, java.util.List<android.text.FontConfig.Font>, java.lang.String, java.lang.String); + ctor public FontConfig.Family(android.text.FontConfig.Family); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Font> getFonts(); + method public java.lang.String getLanguage(); + method public java.lang.String getName(); + method public java.lang.String getVariant(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR; + } + + public static final class FontConfig.Font implements android.os.Parcelable { + ctor public FontConfig.Font(java.lang.String, int, java.util.List<android.text.FontConfig.Axis>, int, boolean); + ctor public FontConfig.Font(android.text.FontConfig.Font); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Axis> getAxes(); + method public android.os.ParcelFileDescriptor getFd(); + method public java.lang.String getFontName(); + method public int getTtcIndex(); + method public int getWeight(); + method public boolean isItalic(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR; + } + + public final class FontManager { + method public android.text.FontConfig getSystemFonts(); + } + public abstract interface GetChars implements java.lang.CharSequence { method public abstract void getChars(int, int, char[], int); } diff --git a/api/test-current.txt b/api/test-current.txt index 82715b3b4a2e..bd530fc671e9 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -8496,6 +8496,7 @@ package android.content { field public static final java.lang.String DOWNLOAD_SERVICE = "download"; field public static final java.lang.String DROPBOX_SERVICE = "dropbox"; field public static final java.lang.String FINGERPRINT_SERVICE = "fingerprint"; + field public static final java.lang.String FONT_SERVICE = "font"; field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; @@ -39573,6 +39574,65 @@ package android.text { method public android.text.Editable newEditable(java.lang.CharSequence); } + public final class FontConfig implements android.os.Parcelable { + ctor public FontConfig(); + ctor public FontConfig(android.text.FontConfig); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Alias> getAliases(); + method public java.util.List<android.text.FontConfig.Family> getFamilies(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig> CREATOR; + } + + public static final class FontConfig.Alias implements android.os.Parcelable { + ctor public FontConfig.Alias(java.lang.String, java.lang.String, int); + method public int describeContents(); + method public java.lang.String getName(); + method public java.lang.String getToName(); + method public int getWeight(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Alias> CREATOR; + } + + public static final class FontConfig.Axis implements android.os.Parcelable { + ctor public FontConfig.Axis(int, float); + method public int describeContents(); + method public float getStyleValue(); + method public int getTag(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Axis> CREATOR; + } + + public static final class FontConfig.Family implements android.os.Parcelable { + ctor public FontConfig.Family(java.lang.String, java.util.List<android.text.FontConfig.Font>, java.lang.String, java.lang.String); + ctor public FontConfig.Family(android.text.FontConfig.Family); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Font> getFonts(); + method public java.lang.String getLanguage(); + method public java.lang.String getName(); + method public java.lang.String getVariant(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Family> CREATOR; + } + + public static final class FontConfig.Font implements android.os.Parcelable { + ctor public FontConfig.Font(java.lang.String, int, java.util.List<android.text.FontConfig.Axis>, int, boolean); + ctor public FontConfig.Font(android.text.FontConfig.Font); + method public int describeContents(); + method public java.util.List<android.text.FontConfig.Axis> getAxes(); + method public android.os.ParcelFileDescriptor getFd(); + method public java.lang.String getFontName(); + method public int getTtcIndex(); + method public int getWeight(); + method public boolean isItalic(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.text.FontConfig.Font> CREATOR; + } + + public final class FontManager { + method public android.text.FontConfig getSystemFonts(); + } + public abstract interface GetChars implements java.lang.CharSequence { method public abstract void getChars(int, int, char[], int); } diff --git a/compiled-classes-phone b/compiled-classes-phone index ebc54f2128e9..ed0a4a6a33cc 100644 --- a/compiled-classes-phone +++ b/compiled-classes-phone @@ -1195,13 +1195,13 @@ android.graphics.DashPathEffect android.graphics.DiscretePathEffect android.graphics.DrawFilter android.graphics.EmbossMaskFilter +android.graphics.FontConfig +android.graphics.FontConfig$Alias +android.graphics.FontConfig$Axis +android.graphics.FontConfig$Family +android.graphics.FontConfig$Font android.graphics.FontFamily android.graphics.FontListParser -android.graphics.FontListParser$Alias -android.graphics.FontListParser$Axis -android.graphics.FontListParser$Config -android.graphics.FontListParser$Family -android.graphics.FontListParser$Font android.graphics.ImageFormat android.graphics.Insets android.graphics.Interpolator diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 9387019bc651..a37f22b888b0 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -118,6 +118,7 @@ import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.FontManager; import android.text.TextClassificationManager; import android.util.Log; import android.view.ContextThemeWrapper; @@ -133,6 +134,7 @@ import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.internal.app.ISoundTriggerService; import com.android.internal.appwidget.IAppWidgetService; +import com.android.internal.font.IFontManager; import com.android.internal.os.IDropBoxManagerService; import com.android.internal.policy.PhoneLayoutInflater; @@ -793,6 +795,15 @@ final class SystemServiceRegistry { public IncidentManager createService(ContextImpl ctx) throws ServiceNotFoundException { return new IncidentManager(ctx); }}); + + registerService(Context.FONT_SERVICE, FontManager.class, + new CachedServiceFetcher<FontManager>() { + @Override + public FontManager createService(ContextImpl ctx) + throws ServiceNotFoundException { + IBinder b = ServiceManager.getServiceOrThrow(Context.FONT_SERVICE); + return new FontManager(IFontManager.Stub.asInterface(b)); + }}); } /** diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 596a9fd0610a..f41d7f2f168d 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3744,6 +3744,11 @@ public abstract class Context { public static final String DEVICE_IDENTIFIERS_SERVICE = "device_identifiers"; /** + * Service that provides System font data. + */ + public static final String FONT_SERVICE = "font"; + + /** * Service to report a system health "incident" * @hide */ diff --git a/core/java/android/text/FontConfig.aidl b/core/java/android/text/FontConfig.aidl new file mode 100644 index 000000000000..17a5ca2d7830 --- /dev/null +++ b/core/java/android/text/FontConfig.aidl @@ -0,0 +1,20 @@ +/** + * 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.text; + +/** @hide */ +parcelable FontConfig; diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java new file mode 100644 index 000000000000..df694ff6af31 --- /dev/null +++ b/core/java/android/text/FontConfig.java @@ -0,0 +1,466 @@ +/* + * 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.text; + +import android.os.Parcel; +import android.os.ParcelFileDescriptor; +import android.os.Parcelable; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * Font configuration descriptions for System fonts. + */ +public final class FontConfig implements Parcelable { + private final List<Family> mFamilies = new ArrayList<>(); + private final List<Alias> mAliases = new ArrayList<>(); + + public FontConfig() { + } + + public FontConfig(FontConfig config) { + for (int i = 0; i < config.mFamilies.size(); i++) { + mFamilies.add(new Family(config.mFamilies.get(i))); + } + mAliases.addAll(config.mAliases); + } + + /** + * Returns the ordered list of families included in the system fonts. + */ + public List<Family> getFamilies() { + return mFamilies; + } + + /** + * Returns the list of aliases defined for the font families in the system fonts. + */ + public List<Alias> getAliases() { + return mAliases; + } + + /** + * @hide + */ + public FontConfig(Parcel in) { + readFromParcel(in); + } + + @Override + public void writeToParcel(Parcel out, int flag) { + out.writeInt(mFamilies.size()); + for (int i = 0; i < mFamilies.size(); i++) { + mFamilies.get(i).writeToParcel(out, flag); + } + out.writeInt(mAliases.size()); + for (int i = 0; i < mAliases.size(); i++) { + mAliases.get(i).writeToParcel(out, flag); + } + } + + /** + * @hide + */ + public void readFromParcel(Parcel in) { + int size = in.readInt(); + for (int i = 0; i < size; i++) { + mFamilies.add(new Family(in)); + } + size = in.readInt(); + for (int i = 0; i < size; i++) { + mAliases.add(new Alias(in)); + } + } + + @Override + public int describeContents() { + return 0; + } + + public static final Parcelable.Creator<FontConfig> CREATOR = new Parcelable.Creator() { + public FontConfig createFromParcel(Parcel in) { + return new FontConfig(in); + } + public FontConfig[] newArray(int size) { + return new FontConfig[size]; + } + }; + + /** + * Class that holds information about a Font axis. + */ + public static final class Axis implements Parcelable { + private final int mTag; + private final float mStyleValue; + + public Axis(int tag, float styleValue) { + this.mTag = tag; + this.mStyleValue = styleValue; + } + + /** + * Returns the variable font axis tag associated to this axis. + */ + public int getTag() { + return mTag; + } + + /** + * Returns the style value associated to the given axis for this font. + */ + public float getStyleValue() { + return mStyleValue; + } + + /** + * @hide + */ + public Axis(Parcel in) { + mTag = in.readInt(); + mStyleValue = in.readFloat(); + } + + @Override + public void writeToParcel(Parcel out, int flag) { + out.writeInt(mTag); + out.writeFloat(mStyleValue); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<Axis> CREATOR = new Creator<Axis>() { + @Override + public Axis createFromParcel(Parcel in) { + return new Axis(in); + } + + @Override + public Axis[] newArray(int size) { + return new Axis[size]; + } + }; + } + + /** + * Class that holds information about a Font. + */ + public static final class Font implements Parcelable { + private final String mFontName; + private final int mTtcIndex; + private final List<Axis> mAxes; + private final int mWeight; + private final boolean mIsItalic; + private ParcelFileDescriptor mFd; + + public Font(String fontName, int ttcIndex, List<Axis> axes, int weight, boolean isItalic) { + mFontName = fontName; + mTtcIndex = ttcIndex; + mAxes = axes; + mWeight = weight; + mIsItalic = isItalic; + mFd = null; + } + + public Font(Font origin) { + mFontName = origin.mFontName; + mTtcIndex = origin.mTtcIndex; + mAxes = new ArrayList<>(origin.mAxes); + mWeight = origin.mWeight; + mIsItalic = origin.mIsItalic; + if (origin.mFd != null) { + try { + mFd = origin.mFd.dup(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * Returns the name associated by the system to this font. + */ + public String getFontName() { + return mFontName; + } + + /** + * Returns the index to be used to access this font when accessing a TTC file. + */ + public int getTtcIndex() { + return mTtcIndex; + } + + /** + * Returns the list of axes associated to this font. + */ + public List<Axis> getAxes() { + return mAxes; + } + + /** + * Returns the weight value for this font. + */ + public int getWeight() { + return mWeight; + } + + /** + * Returns whether this font is italic. + */ + public boolean isItalic() { + return mIsItalic; + } + + /** + * Returns a file descriptor to access the specified font. This should be closed after use. + */ + public ParcelFileDescriptor getFd() { + return mFd; + } + + /** + * @hide + */ + public void setFd(ParcelFileDescriptor fd) { + mFd = fd; + } + + /** + * @hide + */ + public Font(Parcel in) { + mFontName = in.readString(); + mTtcIndex = in.readInt(); + final int numAxes = in.readInt(); + mAxes = new ArrayList<>(); + for (int i = 0; i < numAxes; i++) { + mAxes.add(new Axis(in)); + } + mWeight = in.readInt(); + mIsItalic = in.readInt() == 1; + if (in.readInt() == 1) { /* has FD */ + mFd = ParcelFileDescriptor.CREATOR.createFromParcel(in); + } else { + mFd = null; + } + } + + @Override + public void writeToParcel(Parcel out, int flag) { + out.writeString(mFontName); + out.writeInt(mTtcIndex); + out.writeInt(mAxes.size()); + for (int i = 0; i < mAxes.size(); i++) { + mAxes.get(i).writeToParcel(out, flag); + } + out.writeInt(mWeight); + out.writeInt(mIsItalic ? 1 : 0); + out.writeInt(mFd == null ? 0 : 1); + if (mFd != null) { + mFd.writeToParcel(out, flag); + } + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<Font> CREATOR = new Creator<Font>() { + @Override + public Font createFromParcel(Parcel in) { + return new Font(in); + } + + @Override + public Font[] newArray(int size) { + return new Font[size]; + } + }; + } + + /** + * Class that holds information about a Font alias. + */ + public static final class Alias implements Parcelable { + private final String mName; + private final String mToName; + private final int mWeight; + + public Alias(String name, String toName, int weight) { + this.mName = name; + this.mToName = toName; + this.mWeight = weight; + } + + /** + * Returns the new name for the alias. + */ + public String getName() { + return mName; + } + + /** + * Returns the existing name to which this alias points to. + */ + public String getToName() { + return mToName; + } + + /** + * Returns the weight associated with this alias. + */ + public int getWeight() { + return mWeight; + } + + /** + * @hide + */ + public Alias(Parcel in) { + mName = in.readString(); + mToName = in.readString(); + mWeight = in.readInt(); + } + + @Override + public void writeToParcel(Parcel out, int flag) { + out.writeString(mName); + out.writeString(mToName); + out.writeInt(mWeight); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<Alias> CREATOR = new Creator<Alias>() { + @Override + public Alias createFromParcel(Parcel in) { + return new Alias(in); + } + + @Override + public Alias[] newArray(int size) { + return new Alias[size]; + } + }; + } + + /** + * Class that holds information about a Font family. + */ + public static final class Family implements Parcelable { + private final String mName; + private final List<Font> mFonts; + private final String mLanguage; + private final String mVariant; + + public Family(String name, List<Font> fonts, String language, String variant) { + this.mName = name; + this.mFonts = fonts; + this.mLanguage = language; + this.mVariant = variant; + } + + public Family(Family origin) { + this.mName = origin.mName; + this.mLanguage = origin.mLanguage; + this.mVariant = origin.mVariant; + this.mFonts = new ArrayList<>(); + for (int i = 0; i < origin.mFonts.size(); i++) { + mFonts.add(new Font(origin.mFonts.get(i))); + } + } + + /** + * Returns the name given by the system to this font family. + */ + public String getName() { + return mName; + } + + /** + * Returns the list of fonts included in this family. + */ + public List<Font> getFonts() { + return mFonts; + } + + /** + * Returns the language for this family. May be null. + */ + public String getLanguage() { + return mLanguage; + } + + /** + * Returns the font variant for this family, e.g. "elegant" or "compact". May be null. + */ + public String getVariant() { + return mVariant; + } + + /** + * @hide + */ + public Family(Parcel in) { + mName = in.readString(); + final int size = in.readInt(); + mFonts = new ArrayList<>(); + for (int i = 0; i < size; i++) { + mFonts.add(new Font(in)); + } + mLanguage = in.readString(); + mVariant = in.readString(); + } + + @Override + public void writeToParcel(Parcel out, int flag) { + out.writeString(mName); + out.writeInt(mFonts.size()); + for (int i = 0; i < mFonts.size(); i++) { + mFonts.get(i).writeToParcel(out, flag); + } + out.writeString(mLanguage); + out.writeString(mVariant); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<Family> CREATOR = new Creator<Family>() { + @Override + public Family createFromParcel(Parcel in) { + return new Family(in); + } + + @Override + public Family[] newArray(int size) { + return new Family[size]; + } + }; + } +} diff --git a/core/java/android/text/FontManager.java b/core/java/android/text/FontManager.java new file mode 100644 index 000000000000..b61cbf3018ef --- /dev/null +++ b/core/java/android/text/FontManager.java @@ -0,0 +1,49 @@ +/* + * 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.text; + +import android.os.RemoteException; + +import com.android.internal.font.IFontManager; + +/** + * Interact with the Font service. + */ +public final class FontManager { + private static final String TAG = "FontManager"; + + private final IFontManager mService; + + /** + * @hide + */ + public FontManager(IFontManager service) { + mService = service; + } + + /** + * Retrieve the system fonts data. This loads the fonts.xml data if needed and loads all system + * fonts in to memory, providing file descriptors for them. + */ + public FontConfig getSystemFonts() { + try { + return mService.getSystemFonts(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } +} diff --git a/core/java/com/android/internal/font/IFontManager.aidl b/core/java/com/android/internal/font/IFontManager.aidl new file mode 100644 index 000000000000..52a626288caf --- /dev/null +++ b/core/java/com/android/internal/font/IFontManager.aidl @@ -0,0 +1,27 @@ +/* + * 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 com.android.internal.font; + +import android.text.FontConfig; + +/** + * Interface to the font manager. + * @hide + */ +interface IFontManager { + FontConfig getSystemFonts(); +} diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp index 15e7165210ae..15df2190ce3c 100644 --- a/core/jni/android/graphics/FontFamily.cpp +++ b/core/jni/android/graphics/FontFamily.cpp @@ -247,9 +247,9 @@ int register_android_graphics_FontFamily(JNIEnv* env) gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;"); gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I"); - jclass axisClass = FindClassOrDie(env, "android/graphics/FontListParser$Axis"); - gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "tag", "I"); - gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "styleValue", "F"); + jclass axisClass = FindClassOrDie(env, "android/text/FontConfig$Axis"); + gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "mTag", "I"); + gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "mStyleValue", "F"); return err; } diff --git a/core/jni/android/graphics/FontUtils.cpp b/core/jni/android/graphics/FontUtils.cpp new file mode 100644 index 000000000000..91fec2a75e2c --- /dev/null +++ b/core/jni/android/graphics/FontUtils.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 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. + */ + +#include "FontUtils.h" + +#include "JNIHelp.h" +#include <core_jni_helpers.h> + +namespace android { +namespace { + +static struct { + jmethodID mGet; + jmethodID mSize; +} gListClassInfo; + +static struct { + jfieldID mTag; + jfieldID mStyleValue; +} gAxisClassInfo; + +} // namespace + +jint ListHelper::size() const { + return mEnv->CallIntMethod(mList, gListClassInfo.mSize); +} + +jobject ListHelper::get(jint index) const { + return mEnv->CallObjectMethod(mList, gListClassInfo.mGet, index); +} + +jint AxisHelper::getTag() const { + return mEnv->GetIntField(mAxis, gAxisClassInfo.mTag); +} + +jfloat AxisHelper::getStyleValue() const { + return mEnv->GetFloatField(mAxis, gAxisClassInfo.mStyleValue); +} + +void init_FontUtils(JNIEnv* env) { + jclass listClass = FindClassOrDie(env, "java/util/List"); + gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;"); + gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I"); + + jclass axisClass = FindClassOrDie(env, "android/text/FontConfig$Axis"); + gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "mTag", "I"); + gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "mStyleValue", "F"); +} + +} // namespace android diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index e48bf7956df3..07acd5992c1d 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -17,6 +17,7 @@ package android.graphics; import android.content.res.AssetManager; +import android.text.FontConfig; import android.util.Log; import java.io.FileInputStream; @@ -80,7 +81,7 @@ public class FontFamily { } } - public boolean addFontWeightStyle(ByteBuffer font, int ttcIndex, List<FontListParser.Axis> axes, + public boolean addFontWeightStyle(ByteBuffer font, int ttcIndex, List<FontConfig.Axis> axes, int weight, boolean style) { return nAddFontWeightStyle(mNativePtr, font, ttcIndex, axes, weight, style); } @@ -93,7 +94,7 @@ public class FontFamily { private static native void nUnrefFamily(long nativePtr); private static native boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex); private static native boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font, - int ttcIndex, List<FontListParser.Axis> listOfAxis, + int ttcIndex, List<FontConfig.Axis> listOfAxis, int weight, boolean isItalic); private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path); diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index 9490436d4f04..4ec564ac5809 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -16,6 +16,7 @@ package android.graphics; +import android.text.FontConfig; import android.util.Xml; import org.xmlpull.v1.XmlPullParser; @@ -36,61 +37,8 @@ import java.util.regex.Pattern; */ public class FontListParser { - public static class Config { - Config() { - families = new ArrayList<Family>(); - aliases = new ArrayList<Alias>(); - } - public List<Family> families; - public List<Alias> aliases; - } - - public static class Axis { - Axis(int tag, float styleValue) { - this.tag = tag; - this.styleValue = styleValue; - } - public final int tag; - public final float styleValue; - } - - public static class Font { - Font(String fontName, int ttcIndex, List<Axis> axes, int weight, boolean isItalic) { - this.fontName = fontName; - this.ttcIndex = ttcIndex; - this.axes = axes; - this.weight = weight; - this.isItalic = isItalic; - } - public String fontName; - public int ttcIndex; - public final List<Axis> axes; - public int weight; - public boolean isItalic; - } - - public static class Alias { - public String name; - public String toName; - public int weight; - } - - public static class Family { - public Family(String name, List<Font> fonts, String lang, String variant) { - this.name = name; - this.fonts = fonts; - this.lang = lang; - this.variant = variant; - } - - public String name; - public List<Font> fonts; - public String lang; - public String variant; - } - /* Parse fallback list (no names) */ - public static Config parse(InputStream in) throws XmlPullParserException, IOException { + public static FontConfig parse(InputStream in) throws XmlPullParserException, IOException { try { XmlPullParser parser = Xml.newPullParser(); parser.setInput(in, null); @@ -104,9 +52,9 @@ public class FontListParser { // Note that a well-formed variation contains a four-character tag and a float as styleValue, // with spacers in between. The tag is enclosd either by double quotes or single quotes. @VisibleForTesting - public static Axis[] parseFontVariationSettings(String settings) { + public static FontConfig.Axis[] parseFontVariationSettings(String settings) { String[] settingList = settings.split(","); - ArrayList<Axis> axisList = new ArrayList<>(); + ArrayList<FontConfig.Axis> axisList = new ArrayList<>(); settingLoop: for (String setting : settingList) { int pos = 0; @@ -148,9 +96,9 @@ public class FontListParser { } int tag = makeTag(tagString.charAt(0), tagString.charAt(1), tagString.charAt(2), tagString.charAt(3)); - axisList.add(new Axis(tag, styleValue)); + axisList.add(new FontConfig.Axis(tag, styleValue)); } - return axisList.toArray(new Axis[axisList.size()]); + return axisList.toArray(new FontConfig.Axis[axisList.size()]); } @VisibleForTesting @@ -162,17 +110,17 @@ public class FontListParser { return c == ' ' || c == '\r' || c == '\t' || c == '\n'; } - private static Config readFamilies(XmlPullParser parser) + private static FontConfig readFamilies(XmlPullParser parser) throws XmlPullParserException, IOException { - Config config = new Config(); + FontConfig config = new FontConfig(); parser.require(XmlPullParser.START_TAG, null, "familyset"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) continue; String tag = parser.getName(); if (tag.equals("family")) { - config.families.add(readFamily(parser)); + config.getFamilies().add(readFamily(parser)); } else if (tag.equals("alias")) { - config.aliases.add(readAlias(parser)); + config.getAliases().add(readAlias(parser)); } else { skip(parser); } @@ -180,12 +128,12 @@ public class FontListParser { return config; } - private static Family readFamily(XmlPullParser parser) + private static FontConfig.Family readFamily(XmlPullParser parser) throws XmlPullParserException, IOException { String name = parser.getAttributeValue(null, "name"); String lang = parser.getAttributeValue(null, "lang"); String variant = parser.getAttributeValue(null, "variant"); - List<Font> fonts = new ArrayList<Font>(); + List<FontConfig.Font> fonts = new ArrayList<FontConfig.Font>(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) continue; String tag = parser.getName(); @@ -195,18 +143,18 @@ public class FontListParser { skip(parser); } } - return new Family(name, fonts, lang, variant); + return new FontConfig.Family(name, fonts, lang, variant); } /** Matches leading and trailing XML whitespace. */ private static final Pattern FILENAME_WHITESPACE_PATTERN = Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$"); - private static Font readFont(XmlPullParser parser) + private static FontConfig.Font readFont(XmlPullParser parser) throws XmlPullParserException, IOException { String indexStr = parser.getAttributeValue(null, "index"); int index = indexStr == null ? 0 : Integer.parseInt(indexStr); - List<Axis> axes = new ArrayList<Axis>(); + List<FontConfig.Axis> axes = new ArrayList<FontConfig.Axis>(); String weightStr = parser.getAttributeValue(null, "weight"); int weight = weightStr == null ? 400 : Integer.parseInt(weightStr); boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style")); @@ -225,7 +173,7 @@ public class FontListParser { } String fullFilename = "/system/fonts/" + FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll(""); - return new Font(fullFilename, index, axes, weight, isItalic); + return new FontConfig.Font(fullFilename, index, axes, weight, isItalic); } /** The 'tag' attribute value is read as four character values between U+0020 and U+007E @@ -239,7 +187,7 @@ public class FontListParser { private static final Pattern STYLE_VALUE_PATTERN = Pattern.compile("-?(([0-9]+(\\.[0-9]+)?)|(\\.[0-9]+))"); - private static Axis readAxis(XmlPullParser parser) + private static FontConfig.Axis readAxis(XmlPullParser parser) throws XmlPullParserException, IOException { int tag = 0; String tagStr = parser.getAttributeValue(null, "tag"); @@ -258,22 +206,22 @@ public class FontListParser { } skip(parser); // axis tag is empty, ignore any contents and consume end tag - return new Axis(tag, styleValue); + return new FontConfig.Axis(tag, styleValue); } - private static Alias readAlias(XmlPullParser parser) + private static FontConfig.Alias readAlias(XmlPullParser parser) throws XmlPullParserException, IOException { - Alias alias = new Alias(); - alias.name = parser.getAttributeValue(null, "name"); - alias.toName = parser.getAttributeValue(null, "to"); + String name = parser.getAttributeValue(null, "name"); + String toName = parser.getAttributeValue(null, "to"); String weightStr = parser.getAttributeValue(null, "weight"); + int weight; if (weightStr == null) { - alias.weight = 400; + weight = 400; } else { - alias.weight = Integer.parseInt(weightStr); + weight = Integer.parseInt(weightStr); } skip(parser); // alias tag is empty, ignore any contents and consume end tag - return alias; + return new FontConfig.Alias(name, toName, weight); } private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException { diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 2886f0dd4a2e..764ab1c0a56e 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -17,6 +17,7 @@ package android.graphics; import android.content.res.AssetManager; +import android.text.FontConfig; import android.util.Log; import android.util.LongSparseArray; import android.util.LruCache; @@ -294,25 +295,25 @@ public class Typeface { mStyle = nativeGetStyle(ni); } - private static FontFamily makeFamilyFromParsed(FontListParser.Family family, + private static FontFamily makeFamilyFromParsed(FontConfig.Family family, Map<String, ByteBuffer> bufferForPath) { - FontFamily fontFamily = new FontFamily(family.lang, family.variant); - for (FontListParser.Font font : family.fonts) { - ByteBuffer fontBuffer = bufferForPath.get(font.fontName); + FontFamily fontFamily = new FontFamily(family.getLanguage(), family.getVariant()); + for (FontConfig.Font font : family.getFonts()) { + ByteBuffer fontBuffer = bufferForPath.get(font.getFontName()); if (fontBuffer == null) { - try (FileInputStream file = new FileInputStream(font.fontName)) { + try (FileInputStream file = new FileInputStream(font.getFontName())) { FileChannel fileChannel = file.getChannel(); long fontSize = fileChannel.size(); fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize); - bufferForPath.put(font.fontName, fontBuffer); + bufferForPath.put(font.getFontName(), fontBuffer); } catch (IOException e) { - Log.e(TAG, "Error mapping font file " + font.fontName); + Log.e(TAG, "Error mapping font file " + font.getFontName()); continue; } } - if (!fontFamily.addFontWeightStyle(fontBuffer, font.ttcIndex, font.axes, - font.weight, font.isItalic)) { - Log.e(TAG, "Error creating font " + font.fontName + "#" + font.ttcIndex); + if (!fontFamily.addFontWeightStyle(fontBuffer, font.getTtcIndex(), font.getAxes(), + font.getWeight(), font.isItalic())) { + Log.e(TAG, "Error creating font " + font.getFontName() + "#" + font.getTtcIndex()); } } return fontFamily; @@ -329,16 +330,16 @@ public class Typeface { File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG); try { FileInputStream fontsIn = new FileInputStream(configFilename); - FontListParser.Config fontConfig = FontListParser.parse(fontsIn); + FontConfig fontConfig = FontListParser.parse(fontsIn); Map<String, ByteBuffer> bufferForPath = new HashMap<String, ByteBuffer>(); List<FontFamily> familyList = new ArrayList<FontFamily>(); // Note that the default typeface is always present in the fallback list; // this is an enhancement from pre-Minikin behavior. - for (int i = 0; i < fontConfig.families.size(); i++) { - FontListParser.Family f = fontConfig.families.get(i); - if (i == 0 || f.name == null) { + for (int i = 0; i < fontConfig.getFamilies().size(); i++) { + FontConfig.Family f = fontConfig.getFamilies().get(i); + if (i == 0 || f.getName() == null) { familyList.add(makeFamilyFromParsed(f, bufferForPath)); } } @@ -346,10 +347,10 @@ public class Typeface { setDefault(Typeface.createFromFamilies(sFallbackFonts)); Map<String, Typeface> systemFonts = new HashMap<String, Typeface>(); - for (int i = 0; i < fontConfig.families.size(); i++) { + for (int i = 0; i < fontConfig.getFamilies().size(); i++) { Typeface typeface; - FontListParser.Family f = fontConfig.families.get(i); - if (f.name != null) { + FontConfig.Family f = fontConfig.getFamilies().get(i); + if (f.getName() != null) { if (i == 0) { // The first entry is the default typeface; no sense in // duplicating the corresponding FontFamily. @@ -359,17 +360,17 @@ public class Typeface { FontFamily[] families = { fontFamily }; typeface = Typeface.createFromFamiliesWithDefault(families); } - systemFonts.put(f.name, typeface); + systemFonts.put(f.getName(), typeface); } } - for (FontListParser.Alias alias : fontConfig.aliases) { - Typeface base = systemFonts.get(alias.toName); + for (FontConfig.Alias alias : fontConfig.getAliases()) { + Typeface base = systemFonts.get(alias.getToName()); Typeface newFace = base; - int weight = alias.weight; + int weight = alias.getWeight(); if (weight != 400) { newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight)); } - systemFonts.put(alias.name, newFace); + systemFonts.put(alias.getName(), newFace); } sSystemFontMap = systemFonts; diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java index d046c1103efc..2b4e6c27f193 100644 --- a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java +++ b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java @@ -17,50 +17,53 @@ package android.graphics; import android.test.suitebuilder.annotation.SmallTest; +import android.text.FontConfig; import junit.framework.TestCase; +import java.util.List; + public class VariationParserTest extends TestCase { @SmallTest public void testParseFontVariationSetting() { int tag = FontListParser.makeTag('w', 'd', 't', 'h'); - FontListParser.Axis[] axis = FontListParser.parseFontVariationSettings("'wdth' 1"); - assertEquals(tag, axis[0].tag); - assertEquals(1.0f, axis[0].styleValue); + FontConfig.Axis[] axis = FontListParser.parseFontVariationSettings("'wdth' 1"); + assertEquals(tag, axis[0].getTag()); + assertEquals(1.0f, axis[0].getStyleValue()); axis = FontListParser.parseFontVariationSettings("\"wdth\" 100"); - assertEquals(tag, axis[0].tag); - assertEquals(100.0f, axis[0].styleValue); + assertEquals(tag, axis[0].getTag()); + assertEquals(100.0f, axis[0].getStyleValue()); axis = FontListParser.parseFontVariationSettings(" 'wdth' 100"); - assertEquals(tag, axis[0].tag); - assertEquals(100.0f, axis[0].styleValue); + assertEquals(tag, axis[0].getTag()); + assertEquals(100.0f, axis[0].getStyleValue()); axis = FontListParser.parseFontVariationSettings("\t'wdth' 0.5"); - assertEquals(tag, axis[0].tag); - assertEquals(0.5f, axis[0].styleValue); + assertEquals(tag, axis[0].getTag()); + assertEquals(0.5f, axis[0].getStyleValue()); tag = FontListParser.makeTag('A', 'X', ' ', ' '); axis = FontListParser.parseFontVariationSettings("'AX ' 1"); - assertEquals(tag, axis[0].tag); - assertEquals(1.0f, axis[0].styleValue); + assertEquals(tag, axis[0].getTag()); + assertEquals(1.0f, axis[0].getStyleValue()); axis = FontListParser.parseFontVariationSettings("'AX '\t1"); - assertEquals(tag, axis[0].tag); - assertEquals(1.0f, axis[0].styleValue); + assertEquals(tag, axis[0].getTag()); + assertEquals(1.0f, axis[0].getStyleValue()); axis = FontListParser.parseFontVariationSettings("'AX '\n1"); - assertEquals(tag, axis[0].tag); - assertEquals(1.0f, axis[0].styleValue); + assertEquals(tag, axis[0].getTag()); + assertEquals(1.0f, axis[0].getStyleValue()); axis = FontListParser.parseFontVariationSettings("'AX '\r1"); - assertEquals(tag, axis[0].tag); - assertEquals(1.0f, axis[0].styleValue); + assertEquals(tag, axis[0].getTag()); + assertEquals(1.0f, axis[0].getStyleValue()); axis = FontListParser.parseFontVariationSettings("'AX '\r\t\n 1"); - assertEquals(tag, axis[0].tag); - assertEquals(1.0f, axis[0].styleValue); + assertEquals(tag, axis[0].getTag()); + assertEquals(1.0f, axis[0].getStyleValue()); // Test for invalid input axis = FontListParser.parseFontVariationSettings(""); @@ -87,26 +90,26 @@ public class VariationParserTest extends TestCase { @SmallTest public void testParseFontVariationStyleSettings() { - FontListParser.Axis[] axis = + FontConfig.Axis[] axis = FontListParser.parseFontVariationSettings("'wdth' 10,'AX '\r1"); int tag1 = FontListParser.makeTag('w', 'd', 't', 'h'); int tag2 = FontListParser.makeTag('A', 'X', ' ', ' '); - assertEquals(tag1, axis[0].tag); - assertEquals(10.0f, axis[0].styleValue); - assertEquals(tag2, axis[1].tag); - assertEquals(1.0f, axis[1].styleValue); + assertEquals(tag1, axis[0].getTag()); + assertEquals(10.0f, axis[0].getStyleValue()); + assertEquals(tag2, axis[1].getTag()); + assertEquals(1.0f, axis[1].getStyleValue()); // Test only spacers are allowed before tag axis = FontListParser.parseFontVariationSettings(" 'wdth' 10,ab'wdth' 1"); tag1 = FontListParser.makeTag('w', 'd', 't', 'h'); - assertEquals(tag1, axis[0].tag); - assertEquals(10.0f, axis[0].styleValue); + assertEquals(tag1, axis[0].getTag()); + assertEquals(10.0f, axis[0].getStyleValue()); assertEquals(1, axis.length); } @SmallTest public void testInvalidTagCharacters() { - FontListParser.Axis[] axis = + FontConfig.Axis[] axis = FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10"); assertEquals(0, axis.length); axis = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10"); diff --git a/preloaded-classes b/preloaded-classes index 86cbb69bdd9e..c9b3c6f43ae4 100644 --- a/preloaded-classes +++ b/preloaded-classes @@ -823,11 +823,6 @@ android.graphics.DrawFilter android.graphics.EmbossMaskFilter android.graphics.FontFamily android.graphics.FontListParser -android.graphics.FontListParser$Alias -android.graphics.FontListParser$Axis -android.graphics.FontListParser$Config -android.graphics.FontListParser$Family -android.graphics.FontListParser$Font android.graphics.Insets android.graphics.Interpolator android.graphics.Interpolator$Result @@ -1847,6 +1842,11 @@ android.text.DynamicLayout android.text.DynamicLayout$ChangeWatcher android.text.Editable android.text.Editable$Factory +android.text.FontConfig +android.text.FontConfig$Alias +android.text.FontConfig$Axis +android.text.FontConfig$Family +android.text.FontConfig$Font android.text.GetChars android.text.GraphicsOperations android.text.Html diff --git a/services/core/java/com/android/server/FontManagerService.java b/services/core/java/com/android/server/FontManagerService.java new file mode 100644 index 000000000000..593c3220fdb5 --- /dev/null +++ b/services/core/java/com/android/server/FontManagerService.java @@ -0,0 +1,107 @@ +/* + * 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 com.android.server; + +import android.content.Context; +import android.graphics.FontListParser; +import android.os.ParcelFileDescriptor; +import android.text.FontConfig; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.font.IFontManager; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +public class FontManagerService extends IFontManager.Stub { + private static final String TAG = "FontManagerService"; + private static final String FONTS_CONFIG = "/system/etc/fonts.xml"; + + @GuardedBy("mLock") + private FontConfig mConfig; + private final Object mLock = new Object(); + + public static final class Lifecycle extends SystemService { + private final FontManagerService mService; + + public Lifecycle(Context context) { + super(context); + mService = new FontManagerService(); + } + + @Override + public void onStart() { + try { + publishBinderService(Context.FONT_SERVICE, mService); + } catch (Throwable t) { + // Starting this service is not critical to the running of this device and should + // therefore not crash the device. If it fails, log the error and continue. + Slog.e(TAG, "Could not start the FontManagerService.", t); + } + } + } + + @Override + public FontConfig getSystemFonts() { + synchronized (mLock) { + if (mConfig != null) { + return new FontConfig(mConfig); + } + + FontConfig config = loadFromSystem(); + if (config == null) { + return null; + } + + final int size = config.getFamilies().size(); + for (int i = 0; i < size; ++i) { + FontConfig.Family family = config.getFamilies().get(i); + for (int j = 0; j < family.getFonts().size(); ++j) { + FontConfig.Font font = family.getFonts().get(j); + File fontFile = new File(font.getFontName()); + try { + font.setFd(ParcelFileDescriptor.open( + fontFile, ParcelFileDescriptor.MODE_READ_ONLY)); + } catch (IOException e) { + Slog.e(TAG, "Error opening font file " + font.getFontName(), e); + } + } + } + + mConfig = config; + return new FontConfig(mConfig); + } + } + + private FontConfig loadFromSystem() { + File configFilename = new File(FONTS_CONFIG); + try { + FileInputStream fontsIn = new FileInputStream(configFilename); + return FontListParser.parse(fontsIn); + } catch (IOException | XmlPullParserException e) { + Slog.e(TAG, "Error opening " + configFilename, e); + } + return null; + } + + public FontManagerService() { + } +} diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index bedc6e1d9057..951da3770852 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -936,6 +936,12 @@ public final class SystemServer { traceEnd(); } + if (!disableNonCoreServices) { + traceBeginAndSlog("StartFontServiceManager"); + mSystemServiceManager.startService(FontManagerService.Lifecycle.class); + traceEnd(); + } + if (!disableNonCoreServices && !disableTextServices) { traceBeginAndSlog("StartTextServicesManager"); mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class); diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java index 50efc7f7db86..d0c959972b13 100644 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java @@ -16,6 +16,7 @@ package android.graphics; +import android.text.FontConfig; import com.android.ide.common.rendering.api.AssetRepository; import com.android.ide.common.rendering.api.LayoutLog; import com.android.layoutlib.bridge.Bridge; @@ -284,7 +285,7 @@ public class FontFamily_Delegate { @LayoutlibDelegate /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font, - int ttcIndex, List<FontListParser.Axis> listOfAxis, + int ttcIndex, List<FontConfig.Axis> listOfAxis, int weight, boolean isItalic) { assert false : "The only client of this method has been overriden."; return false; diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java index 5cd34f6e000f..6e337d50a31f 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java @@ -16,6 +16,7 @@ package android.graphics; +import android.text.FontConfig; import com.android.layoutlib.bridge.impl.DelegateManager; import com.android.tools.layoutlib.annotations.LayoutlibDelegate; @@ -208,12 +209,12 @@ public final class Typeface_Delegate { } @LayoutlibDelegate - /*package*/ static FontFamily makeFamilyFromParsed(FontListParser.Family family, + /*package*/ static FontFamily makeFamilyFromParsed(FontConfig.Family family, Map<String, ByteBuffer> bufferForPath) { - FontFamily fontFamily = new FontFamily(family.lang, family.variant); - for (FontListParser.Font font : family.fonts) { - FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.fontName, font.weight, - font.isItalic); + FontFamily fontFamily = new FontFamily(family.getLanguage(), family.getVariant()); + for (FontConfig.Font font : family.getFonts()) { + FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.getFontName(), + font.getWeight(), font.isItalic()); } return fontFamily; } |