1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.text;
18 
19 import static java.lang.annotation.RetentionPolicy.SOURCE;
20 
21 import android.annotation.CurrentTimeMillisLong;
22 import android.annotation.IntDef;
23 import android.annotation.IntRange;
24 import android.annotation.NonNull;
25 import android.annotation.Nullable;
26 import android.annotation.SystemApi;
27 import android.annotation.TestApi;
28 import android.compat.annotation.UnsupportedAppUsage;
29 import android.graphics.fonts.FontStyle;
30 import android.graphics.fonts.FontVariationAxis;
31 import android.os.Build;
32 import android.os.LocaleList;
33 import android.os.Parcel;
34 import android.os.Parcelable;
35 
36 import java.io.File;
37 import java.lang.annotation.Retention;
38 import java.util.ArrayList;
39 import java.util.Collections;
40 import java.util.List;
41 import java.util.Objects;
42 
43 
44 /**
45  * Font configuration descriptions for System fonts.
46  *
47  * FontConfig represents the configuration for the fonts installed on the system. It is made of list
48  * of font families and aliases.
49  *
50  * @see FontFamily
51  * @see Alias
52  * @hide
53  */
54 @SystemApi
55 @TestApi
56 public final class FontConfig implements Parcelable {
57     private final @NonNull List<FontFamily> mFamilies;
58     private final @NonNull List<Alias> mAliases;
59     private final @NonNull List<NamedFamilyList> mNamedFamilyLists;
60     private final long mLastModifiedTimeMillis;
61     private final int mConfigVersion;
62 
63     /**
64      * Construct a FontConfig instance.
65      *
66      * @param families a list of font families.
67      * @param aliases a list of aliases.
68      *
69      * @hide Only system server can create this instance and passed via IPC.
70      */
FontConfig(@onNull List<FontFamily> families, @NonNull List<Alias> aliases, @NonNull List<NamedFamilyList> namedFamilyLists, long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion)71     public FontConfig(@NonNull List<FontFamily> families, @NonNull List<Alias> aliases,
72             @NonNull List<NamedFamilyList> namedFamilyLists,
73             long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion) {
74         mFamilies = families;
75         mAliases = aliases;
76         mNamedFamilyLists = namedFamilyLists;
77         mLastModifiedTimeMillis = lastModifiedTimeMillis;
78         mConfigVersion = configVersion;
79     }
80 
81     /**
82      * @hide Keep this constructor for reoborectric.
83      */
FontConfig(@onNull List<FontFamily> families, @NonNull List<Alias> aliases, long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion)84     public FontConfig(@NonNull List<FontFamily> families, @NonNull List<Alias> aliases,
85             long lastModifiedTimeMillis, @IntRange(from = 0) int configVersion) {
86         this(families, aliases, Collections.emptyList(), lastModifiedTimeMillis, configVersion);
87     }
88 
89 
90     /**
91      * Returns the ordered list of font families available in the system.
92      *
93      * @return a list of font families.
94      * @see FontFamily
95      */
getFontFamilies()96     public @NonNull List<FontFamily> getFontFamilies() {
97         return mFamilies;
98     }
99 
100     /**
101      * Returns the list of aliases for mapping font families with other names.
102      *
103      * @return a list of font families.
104      * @see Alias
105      */
getAliases()106     public @NonNull List<Alias> getAliases() {
107         return mAliases;
108     }
109 
getNamedFamilyLists()110     public @NonNull List<NamedFamilyList> getNamedFamilyLists() {
111         return mNamedFamilyLists;
112     }
113 
114     /**
115      * Returns the last modified time in milliseconds.
116      *
117      * This is a value of {@link System#currentTimeMillis()} when the system font configuration was
118      * modified last time.
119      *
120      * If there is no update, this return 0.
121      */
getLastModifiedTimeMillis()122     public @CurrentTimeMillisLong long getLastModifiedTimeMillis() {
123         return mLastModifiedTimeMillis;
124     }
125 
126     /**
127      * Returns the monotonically increasing config version value.
128      *
129      * The config version is reset to 0 when the system is restarted.
130      */
getConfigVersion()131     public @IntRange(from = 0) int getConfigVersion() {
132         return mConfigVersion;
133     }
134 
135     /**
136      * Returns the ordered list of families included in the system fonts.
137      * @deprecated Use getFontFamilies instead.
138      * @hide
139      */
140     @Deprecated
141     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getFamilies()142     public @NonNull FontFamily[] getFamilies() {
143         return mFamilies.toArray(new FontFamily[0]);
144     }
145 
146     @Override
describeContents()147     public int describeContents() {
148         return 0;
149     }
150 
151     @Override
writeToParcel(@onNull Parcel dest, int flags)152     public void writeToParcel(@NonNull Parcel dest, int flags) {
153         dest.writeTypedList(mFamilies, flags);
154         dest.writeTypedList(mAliases, flags);
155         dest.writeTypedList(mNamedFamilyLists, flags);
156         dest.writeLong(mLastModifiedTimeMillis);
157         dest.writeInt(mConfigVersion);
158     }
159 
160     public static final @NonNull Creator<FontConfig> CREATOR = new Creator<FontConfig>() {
161         @Override
162         public FontConfig createFromParcel(Parcel source) {
163             final List<FontFamily> families = new ArrayList<>();
164             source.readTypedList(families, FontFamily.CREATOR);
165             final List<Alias> aliases = new ArrayList<>();
166             source.readTypedList(aliases, Alias.CREATOR);
167             final List<NamedFamilyList> familyLists = new ArrayList<>();
168             source.readTypedList(familyLists, NamedFamilyList.CREATOR);
169             long lastModifiedDate = source.readLong();
170             int configVersion = source.readInt();
171             return new FontConfig(families, aliases, familyLists, lastModifiedDate, configVersion);
172         }
173 
174         @Override
175         public FontConfig[] newArray(int size) {
176             return new FontConfig[size];
177         }
178     };
179 
180     @Override
equals(Object o)181     public boolean equals(Object o) {
182         if (this == o) return true;
183         if (o == null || getClass() != o.getClass()) return false;
184         FontConfig that = (FontConfig) o;
185         return mLastModifiedTimeMillis == that.mLastModifiedTimeMillis
186                 && mConfigVersion == that.mConfigVersion
187                 && Objects.equals(mFamilies, that.mFamilies)
188                 && Objects.equals(mAliases, that.mAliases);
189     }
190 
191     @Override
hashCode()192     public int hashCode() {
193         return Objects.hash(mFamilies, mAliases, mLastModifiedTimeMillis, mConfigVersion);
194     }
195 
196     @Override
toString()197     public String toString() {
198         return "FontConfig{"
199                 + "mFamilies=" + mFamilies
200                 + ", mAliases=" + mAliases
201                 + ", mLastModifiedTimeMillis=" + mLastModifiedTimeMillis
202                 + ", mConfigVersion=" + mConfigVersion
203                 + '}';
204     }
205 
206     /**
207      * Represents single font entry in system font configuration.
208      *
209      * A font is the most primitive unit of drawing character shapes. A font in system configuration
210      * is always referring a single OpenType compliant regular file in the file system.
211      *
212      * @see android.graphics.fonts.Font
213      */
214     public static final class Font implements Parcelable {
215         private final @NonNull File mFile;
216         private final @Nullable File mOriginalFile;
217         private final @NonNull String mPostScriptName;
218         private final @NonNull FontStyle mStyle;
219         private final @IntRange(from = 0) int mIndex;
220         private final @NonNull String mFontVariationSettings;
221         private final @Nullable String mFontFamilyName;
222 
223         /**
224          * Construct a Font instance.
225          *
226          * @hide Only system server can create this instance and passed via IPC.
227          */
Font(@onNull File file, @Nullable File originalFile, @NonNull String postScriptName, @NonNull FontStyle style, @IntRange(from = 0) int index, @NonNull String fontVariationSettings, @Nullable String fontFamilyName)228         public Font(@NonNull File file, @Nullable File originalFile, @NonNull String postScriptName,
229                 @NonNull FontStyle style, @IntRange(from = 0) int index,
230                 @NonNull String fontVariationSettings, @Nullable String fontFamilyName) {
231             mFile = file;
232             mOriginalFile = originalFile;
233             mPostScriptName = postScriptName;
234             mStyle = style;
235             mIndex = index;
236             mFontVariationSettings = fontVariationSettings;
237             mFontFamilyName = fontFamilyName;
238         }
239 
240         @Override
describeContents()241         public int describeContents() {
242             return 0;
243         }
244 
245         @Override
writeToParcel(@onNull Parcel dest, int flags)246         public void writeToParcel(@NonNull Parcel dest, int flags) {
247             dest.writeString8(mFile.getAbsolutePath());
248             dest.writeString8(mOriginalFile == null ? null : mOriginalFile.getAbsolutePath());
249             dest.writeString8(mPostScriptName);
250             dest.writeInt(mStyle.getWeight());
251             dest.writeInt(mStyle.getSlant());
252             dest.writeInt(mIndex);
253             dest.writeString8(mFontVariationSettings);
254             dest.writeString8(mFontFamilyName);
255         }
256 
257         public static final @NonNull Creator<Font> CREATOR = new Creator<Font>() {
258 
259             @Override
260             public Font createFromParcel(Parcel source) {
261                 File path = new File(source.readString8());
262                 String originalPathStr = source.readString8();
263                 File originalPath = originalPathStr == null ? null : new File(originalPathStr);
264                 String postScriptName = source.readString8();
265                 int weight = source.readInt();
266                 int slant = source.readInt();
267                 int index = source.readInt();
268                 String varSettings = source.readString8();
269                 String fallback = source.readString8();
270 
271                 return new Font(path, originalPath, postScriptName, new FontStyle(weight, slant),
272                         index, varSettings, fallback);
273             }
274 
275             @Override
276             public Font[] newArray(int size) {
277                 return new Font[size];
278             }
279         };
280 
281         /**
282          * Returns the font file.
283          */
getFile()284         public @NonNull File getFile() {
285             return mFile;
286         }
287 
288         /**
289          * Returns the original font file in the system directory.
290          *
291          * If the font file is not updated, returns null.
292          *
293          * @return returns the original font file in the system if the font file is updated. Returns
294          *         null if the font file is not updated.
295          * @hide
296          */
getOriginalFile()297         public @Nullable File getOriginalFile() {
298             return mOriginalFile;
299         }
300 
301         /**
302          * Returns the font style.
303          */
getStyle()304         public @NonNull FontStyle getStyle() {
305             return mStyle;
306         }
307 
308 
309         /**
310          * Return a font variation settings.
311          */
getFontVariationSettings()312         public @NonNull String getFontVariationSettings() {
313             return mFontVariationSettings;
314         }
315 
316         /**
317          * A {@link Font} can be configured to be in the {@code Fallback List} for a
318          * {@link FontFamily}.
319          *
320          * For example a serif Hebrew [Font] can be defined in the {@code Fallback List} for
321          * {@code "serif"} {@link FontFamily}.
322          *
323          * If the return value is not {@code null}, then the font will be used in the
324          * {@code Fallback List} of that {@link FontFamily}.
325          *
326          * If the return value is {@code null}, then the font will be used in {@code Fallback List}
327          * of all {@link FontFamily}s.
328          */
getFontFamilyName()329         public @Nullable String getFontFamilyName() {
330             return mFontFamilyName;
331         }
332 
333         /**
334          * Returns the index to be used to access this font when accessing a TTC file.
335          */
getTtcIndex()336         public int getTtcIndex() {
337             return mIndex;
338         }
339 
340         /**
341          * Returns the PostScript name of this font.
342          */
getPostScriptName()343         public @NonNull String getPostScriptName() {
344             return mPostScriptName;
345         }
346 
347         /**
348          * Returns the list of axes associated to this font.
349          * @deprecated Use getFontVariationSettings
350          * @hide
351          */
352         @Deprecated
353         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getAxes()354         public @NonNull FontVariationAxis[] getAxes() {
355             return FontVariationAxis.fromFontVariationSettings(mFontVariationSettings);
356         }
357 
358         /**
359          * Returns the weight value for this font.
360          * @deprecated Use getStyle instead.
361          * @hide
362          */
363         @Deprecated
364         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getWeight()365         public int getWeight() {
366             return getStyle().getWeight();
367         }
368 
369         /**
370          * Returns whether this font is italic.
371          * @deprecated Use getStyle instead.
372          * @hide
373          */
374         @Deprecated
375         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isItalic()376         public boolean isItalic() {
377             return getStyle().getSlant() == FontStyle.FONT_SLANT_ITALIC;
378         }
379 
380         @Override
equals(Object o)381         public boolean equals(Object o) {
382             if (this == o) return true;
383             if (o == null || getClass() != o.getClass()) return false;
384             Font font = (Font) o;
385             return mIndex == font.mIndex
386                     && Objects.equals(mFile, font.mFile)
387                     && Objects.equals(mOriginalFile, font.mOriginalFile)
388                     && Objects.equals(mStyle, font.mStyle)
389                     && Objects.equals(mFontVariationSettings, font.mFontVariationSettings)
390                     && Objects.equals(mFontFamilyName, font.mFontFamilyName);
391         }
392 
393         @Override
hashCode()394         public int hashCode() {
395             return Objects.hash(mFile, mOriginalFile, mStyle, mIndex, mFontVariationSettings,
396                     mFontFamilyName);
397         }
398 
399         @Override
toString()400         public String toString() {
401             return "Font{"
402                     + "mFile=" + mFile
403                     + ", mOriginalFile=" + mOriginalFile
404                     + ", mStyle=" + mStyle
405                     + ", mIndex=" + mIndex
406                     + ", mFontVariationSettings='" + mFontVariationSettings + '\''
407                     + ", mFontFamilyName='" + mFontFamilyName + '\''
408                     + '}';
409         }
410     }
411 
412     /**
413      * Alias provides an alternative name for an existing font family.
414      *
415      * In the system font configuration, a font family can be an alias of another font family with
416      * different font weight. For example, "sans-serif-medium" can be a medium weight of
417      * "sans-serif" font family. In this example, {@link #getName()} returns "sans-serif-medium" and
418      * {@link #getOriginal()} return "sans-serif". The font family that doesn't have name can not be
419      * an original of the alias.
420      */
421     public static final class Alias implements Parcelable {
422         private final @NonNull String mName;
423         private final @NonNull String mOriginal;
424         private final @IntRange(from = 0, to = 1000) int mWeight;
425 
426         /**
427          * Construct an alias instance.
428          *
429          * @param name alias for the font family.
430          * @param original original font family name.
431          * @param weight font weight of the original font family.
432          * @hide Only system server can create this instance and passed via IPC.
433          */
Alias(@onNull String name, @NonNull String original, @IntRange(from = 0, to = 1000) int weight)434         public Alias(@NonNull String name, @NonNull String original,
435                 @IntRange(from = 0, to = 1000) int weight) {
436             mName = name;
437             mOriginal = original;
438             mWeight = weight;
439         }
440 
441         /**
442          * Alias for the font family
443          */
getName()444         public @NonNull String getName() {
445             return mName;
446         }
447 
448         /**
449          * The name of the original font family.
450          */
getOriginal()451         public @NonNull String getOriginal() {
452             return mOriginal;
453         }
454 
455         /**
456          * A font weight of the referring font family.
457          *
458          * @return a font weight of the referring font family.
459          */
getWeight()460         public @IntRange(from = 0, to = 1000) int getWeight() {
461             return mWeight;
462         }
463 
464         @Override
describeContents()465         public int describeContents() {
466             return 0;
467         }
468 
469         @Override
writeToParcel(@onNull Parcel dest, int flags)470         public void writeToParcel(@NonNull Parcel dest, int flags) {
471             dest.writeString8(mName);
472             dest.writeString8(mOriginal);
473             dest.writeInt(mWeight);
474         }
475 
476         public static final @NonNull Creator<Alias> CREATOR = new Creator<Alias>() {
477 
478             @Override
479             public Alias createFromParcel(Parcel source) {
480                 String alias = source.readString8();
481                 String referName = source.readString8();
482                 int weight = source.readInt();
483                 return new Alias(alias, referName, weight);
484             }
485 
486             @Override
487             public Alias[] newArray(int size) {
488                 return new Alias[size];
489             }
490         };
491 
492         @Override
equals(Object o)493         public boolean equals(Object o) {
494             if (this == o) return true;
495             if (o == null || getClass() != o.getClass()) return false;
496             Alias alias = (Alias) o;
497             return mWeight == alias.mWeight
498                     && Objects.equals(mName, alias.mName)
499                     && Objects.equals(mOriginal, alias.mOriginal);
500         }
501 
502         @Override
hashCode()503         public int hashCode() {
504             return Objects.hash(mName, mOriginal, mWeight);
505         }
506 
507         @Override
toString()508         public String toString() {
509             return "Alias{"
510                     + "mName='" + mName + '\''
511                     + ", mOriginal='" + mOriginal + '\''
512                     + ", mWeight=" + mWeight
513                     + '}';
514         }
515     }
516 
517     /**
518      * Represents a font family in the system font configuration.
519      *
520      * A {@link FontFamily} is a list of {@link Font}s for drawing text in various styles such as
521      * weight, slant.
522      *
523      * For example, a {@link FontFamily} can include the regular and bold styles of a {@link Font}.
524      *
525      * @see android.graphics.fonts.FontFamily
526      */
527     public static final class FontFamily implements Parcelable {
528         private final @NonNull List<Font> mFonts;
529         private final @NonNull LocaleList mLocaleList;
530         private final @Variant int mVariant;
531 
532         /** @hide */
533         @Retention(SOURCE)
534         @IntDef(prefix = { "VARIANT_" }, value = {
535                 VARIANT_DEFAULT,
536                 VARIANT_COMPACT,
537                 VARIANT_ELEGANT
538         })
539         public @interface Variant {}
540 
541         /**
542          * Value for font variant.
543          *
544          * Indicates the font has no variant attribute.
545          */
546         public static final int VARIANT_DEFAULT = 0;
547 
548         /**
549          * Value for font variant.
550          *
551          * Indicates the font is for compact variant.
552          * @see android.graphics.Paint#setElegantTextHeight
553          */
554         public static final int VARIANT_COMPACT = 1;
555 
556         /**
557          * Value for font variant.
558          *
559          * Indicates the font is for elegant variant.
560          * @see android.graphics.Paint#setElegantTextHeight
561          */
562         public static final int VARIANT_ELEGANT = 2;
563 
564         /**
565          * Construct a family instance.
566          *
567          * @hide Only system server can create this instance and passed via IPC.
568          */
FontFamily(@onNull List<Font> fonts, @NonNull LocaleList localeList, @Variant int variant)569         public FontFamily(@NonNull List<Font> fonts, @NonNull LocaleList localeList,
570                 @Variant int variant) {
571             mFonts = fonts;
572             mLocaleList = localeList;
573             mVariant = variant;
574         }
575 
576         /**
577          * Returns the list of {@link Font}s in this {@link FontFamily}.
578          *
579          * @return a list of font files.
580          */
getFontList()581         public @NonNull List<Font> getFontList() {
582             return mFonts;
583         }
584 
585         /**
586          * Returns the name of the {@link FontFamily}.
587          *
588          * When the name of a {@link FontFamily} is not null, this name is used to create a new
589          * {@code Fallback List}, and that {@code Fallback List}. Fallback List is the
590          * main building block for a {@link android.graphics.Typeface}.
591          *
592          * For example, if the {@link FontFamily} has the name "serif", then the system will create
593          * a “serif” {@code Fallback List} and it can be used by creating a Typeface via
594          * {@code Typeface.create("serif", Typeface.NORMAL);}
595          *
596          * When the name of a {@link FontFamily} is null, it will be appended to all of the
597          * {@code Fallback List}s.
598          *
599          * @deprecated From API 34, this function always returns null. All font families which have
600          *             name attribute will be reported as a {@link NamedFamilyList}.
601          */
602         @Deprecated
getName()603         public @Nullable String getName() {
604             return null;
605         }
606 
607         /**
608          * Returns the locale list if available.
609          *
610          * The locale list will be used for deciding which font family should be used in fallback
611          * list.
612          */
getLocaleList()613         public @NonNull LocaleList getLocaleList() {
614             return mLocaleList;
615         }
616 
617         /**
618          * Returns the text height variant.
619          */
getVariant()620         public @Variant int getVariant() {
621             return mVariant;
622         }
623 
624         @Override
describeContents()625         public int describeContents() {
626             return 0;
627         }
628 
629         @Override
writeToParcel(@onNull Parcel dest, int flags)630         public void writeToParcel(@NonNull Parcel dest, int flags) {
631             dest.writeTypedList(mFonts, flags);
632             dest.writeString8(mLocaleList.toLanguageTags());
633             dest.writeInt(mVariant);
634         }
635 
636         public static final @NonNull Creator<FontFamily> CREATOR = new Creator<FontFamily>() {
637 
638             @Override
639             public FontFamily createFromParcel(Parcel source) {
640                 List<Font> fonts = new ArrayList<>();
641                 source.readTypedList(fonts, Font.CREATOR);
642                 String langTags = source.readString8();
643                 int variant = source.readInt();
644 
645                 return new FontFamily(fonts, LocaleList.forLanguageTags(langTags), variant);
646             }
647 
648             @Override
649             public FontFamily[] newArray(int size) {
650                 return new FontFamily[size];
651             }
652         };
653 
654         /**
655          * Returns the list of fonts included in this family.
656          * @deprecated Use getFontList instead
657          * @hide
658          */
659         @Deprecated
660         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getFonts()661         public @Nullable Font[] getFonts() {
662             return mFonts.toArray(new Font[0]);
663         }
664 
665         /**
666          * Returns the comma separated BCP47 compliant languages for this family. May be null.
667          * @deprecated Use getLocaleList instead
668          * @hide
669          */
670         @Deprecated
getLanguages()671         public @NonNull String getLanguages() {
672             return mLocaleList.toLanguageTags();
673         }
674 
675         @Override
equals(Object o)676         public boolean equals(Object o) {
677             if (this == o) return true;
678             if (o == null || getClass() != o.getClass()) return false;
679             FontFamily that = (FontFamily) o;
680             return mVariant == that.mVariant
681                     && Objects.equals(mFonts, that.mFonts)
682                     && Objects.equals(mLocaleList, that.mLocaleList);
683         }
684 
685         @Override
hashCode()686         public int hashCode() {
687             return Objects.hash(mFonts, mLocaleList, mVariant);
688         }
689 
690         @Override
toString()691         public String toString() {
692             return "FontFamily{"
693                     + "mFonts=" + mFonts
694                     + ", mLocaleList=" + mLocaleList
695                     + ", mVariant=" + mVariant
696                     + '}';
697         }
698     }
699 
700     /**
701      * Represents list of font family in the system font configuration.
702      *
703      * In the fonts_customization.xml, it can define the list of FontFamily as a named family. The
704      * list of FontFamily is treated as a fallback list when drawing.
705      *
706      * @see android.graphics.fonts.FontFamily
707      */
708     public static final class NamedFamilyList implements Parcelable {
709         private final List<FontFamily> mFamilies;
710         private final String mName;
711 
712         /** @hide */
NamedFamilyList(@onNull List<FontFamily> families, @NonNull String name)713         public NamedFamilyList(@NonNull List<FontFamily> families, @NonNull String name) {
714             mFamilies = families;
715             mName = name;
716         }
717 
718         /** @hide */
NamedFamilyList(@onNull FontFamily family)719         public NamedFamilyList(@NonNull FontFamily family) {
720             mFamilies = new ArrayList<>();
721             mFamilies.add(family);
722             mName = family.getName();
723         }
724 
725         /**
726          * A list of font families.
727          *
728          * @return a list of font families.
729          */
getFamilies()730         public @NonNull List<FontFamily> getFamilies() {
731             return mFamilies;
732         }
733 
734         /**
735          * Returns the name of the {@link FontFamily}.
736          *
737          * This name is used to create a new {@code Fallback List}.
738          *
739          * For example, if the {@link FontFamily} has the name "serif", then the system will create
740          * a “serif” {@code Fallback List} and it can be used by creating a Typeface via
741          * {@code Typeface.create("serif", Typeface.NORMAL);}
742          */
getName()743         public @NonNull String getName() {
744             return mName;
745         }
746 
747         @Override
describeContents()748         public int describeContents() {
749             return 0;
750         }
751 
752         @Override
writeToParcel(@ndroidx.annotation.NonNull Parcel dest, int flags)753         public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
754             dest.writeTypedList(mFamilies, flags);
755             dest.writeString8(mName);
756         }
757 
758         public static final @NonNull Creator<NamedFamilyList> CREATOR = new Creator<>() {
759 
760             @Override
761             public NamedFamilyList createFromParcel(Parcel source) {
762                 final List<FontFamily> families = new ArrayList<>();
763                 source.readTypedList(families, FontFamily.CREATOR);
764                 String name = source.readString8();
765                 return new NamedFamilyList(families, name);
766             }
767 
768             @Override
769             public NamedFamilyList[] newArray(int size) {
770                 return new NamedFamilyList[size];
771             }
772         };
773 
774         @Override
equals(Object o)775         public boolean equals(Object o) {
776             if (this == o) return true;
777             if (o == null || getClass() != o.getClass()) return false;
778             NamedFamilyList that = (NamedFamilyList) o;
779             return Objects.equals(mFamilies, that.mFamilies) && Objects.equals(mName,
780                     that.mName);
781         }
782 
783         @Override
hashCode()784         public int hashCode() {
785             return Objects.hash(mFamilies, mName);
786         }
787 
788         @Override
toString()789         public String toString() {
790             return "NamedFamilyList{"
791                     + "mFamilies=" + mFamilies
792                     + ", mName='" + mName + '\''
793                     + '}';
794         }
795     }
796 }
797