Add FontManager#updateFontFamily() API.
Bug: 179103383 Test: atest CtsGraphicsTestCases:FontFamilyUpdateRequestTest Test: atest CtsGraphicsTestCases:FontFileUpdateRequestTest Test: atest CtsGraphicsTestCases:FontManagerTest Test: atest FrameworksServicesTests:UpdatableFontDirTest Test: atest UpdatableSystemFontTest Change-Id: I0103784c72d60567675daf73e95e4d716f091e4a
This commit is contained in:
@@ -2810,16 +2810,48 @@ package android.debug {
|
||||
|
||||
package android.graphics.fonts {
|
||||
|
||||
public final class FontFamilyUpdateRequest {
|
||||
method @NonNull public java.util.List<android.graphics.fonts.FontFamilyUpdateRequest.FontFamily> getFontFamilies();
|
||||
method @NonNull public java.util.List<android.graphics.fonts.FontFileUpdateRequest> getFontFileUpdateRequests();
|
||||
}
|
||||
|
||||
public static final class FontFamilyUpdateRequest.Builder {
|
||||
ctor public FontFamilyUpdateRequest.Builder();
|
||||
method @NonNull public android.graphics.fonts.FontFamilyUpdateRequest.Builder addFontFamily(@NonNull android.graphics.fonts.FontFamilyUpdateRequest.FontFamily);
|
||||
method @NonNull public android.graphics.fonts.FontFamilyUpdateRequest.Builder addFontFileUpdateRequest(@NonNull android.graphics.fonts.FontFileUpdateRequest);
|
||||
method @NonNull public android.graphics.fonts.FontFamilyUpdateRequest build();
|
||||
}
|
||||
|
||||
public static final class FontFamilyUpdateRequest.Font {
|
||||
ctor public FontFamilyUpdateRequest.Font(@NonNull String, @NonNull android.graphics.fonts.FontStyle, @NonNull java.util.List<android.graphics.fonts.FontVariationAxis>);
|
||||
method @NonNull public java.util.List<android.graphics.fonts.FontVariationAxis> getAxes();
|
||||
method @NonNull public String getPostScriptName();
|
||||
method @NonNull public android.graphics.fonts.FontStyle getStyle();
|
||||
}
|
||||
|
||||
public static final class FontFamilyUpdateRequest.FontFamily {
|
||||
ctor public FontFamilyUpdateRequest.FontFamily(@NonNull String, @NonNull java.util.List<android.graphics.fonts.FontFamilyUpdateRequest.Font>);
|
||||
method @NonNull public java.util.List<android.graphics.fonts.FontFamilyUpdateRequest.Font> getFonts();
|
||||
method @NonNull public String getName();
|
||||
}
|
||||
|
||||
public final class FontFileUpdateRequest {
|
||||
ctor public FontFileUpdateRequest(@NonNull android.os.ParcelFileDescriptor, @NonNull byte[]);
|
||||
method @NonNull public android.os.ParcelFileDescriptor getParcelFileDescriptor();
|
||||
method @NonNull public byte[] getSignature();
|
||||
}
|
||||
|
||||
public class FontManager {
|
||||
method @Nullable public android.text.FontConfig getFontConfig();
|
||||
method @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFamily(@NonNull android.graphics.fonts.FontFamilyUpdateRequest, @IntRange(from=0) int);
|
||||
method @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFile(@NonNull android.os.ParcelFileDescriptor, @NonNull byte[], @IntRange(from=0) int);
|
||||
field public static final int RESULT_ERROR_DOWNGRADING = -5; // 0xfffffffb
|
||||
field public static final int RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE = -1; // 0xffffffff
|
||||
field public static final int RESULT_ERROR_FAILED_UPDATE_CONFIG = -6; // 0xfffffffa
|
||||
field public static final int RESULT_ERROR_FONT_NOT_FOUND = -9; // 0xfffffff7
|
||||
field public static final int RESULT_ERROR_FONT_UPDATER_DISABLED = -7; // 0xfffffff9
|
||||
field public static final int RESULT_ERROR_INVALID_FONT_FILE = -3; // 0xfffffffd
|
||||
field public static final int RESULT_ERROR_INVALID_FONT_NAME = -4; // 0xfffffffc
|
||||
field public static final int RESULT_ERROR_REMOTE_EXCEPTION = -9; // 0xfffffff7
|
||||
field public static final int RESULT_ERROR_VERIFICATION_FAILURE = -2; // 0xfffffffe
|
||||
field public static final int RESULT_ERROR_VERSION_MISMATCH = -8; // 0xfffffff8
|
||||
field public static final int RESULT_SUCCESS = 0; // 0x0
|
||||
|
||||
@@ -836,14 +836,15 @@ package android.graphics.fonts {
|
||||
|
||||
public class FontManager {
|
||||
method @Nullable public android.text.FontConfig getFontConfig();
|
||||
method @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFamily(@NonNull android.graphics.fonts.FontFamilyUpdateRequest, @IntRange(from=0) int);
|
||||
method @RequiresPermission(android.Manifest.permission.UPDATE_FONTS) public int updateFontFile(@NonNull android.os.ParcelFileDescriptor, @NonNull byte[], @IntRange(from=0) int);
|
||||
field public static final int RESULT_ERROR_DOWNGRADING = -5; // 0xfffffffb
|
||||
field public static final int RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE = -1; // 0xffffffff
|
||||
field public static final int RESULT_ERROR_FAILED_UPDATE_CONFIG = -6; // 0xfffffffa
|
||||
field public static final int RESULT_ERROR_FONT_NOT_FOUND = -9; // 0xfffffff7
|
||||
field public static final int RESULT_ERROR_FONT_UPDATER_DISABLED = -7; // 0xfffffff9
|
||||
field public static final int RESULT_ERROR_INVALID_FONT_FILE = -3; // 0xfffffffd
|
||||
field public static final int RESULT_ERROR_INVALID_FONT_NAME = -4; // 0xfffffffc
|
||||
field public static final int RESULT_ERROR_REMOTE_EXCEPTION = -9; // 0xfffffff7
|
||||
field public static final int RESULT_ERROR_VERIFICATION_FAILURE = -2; // 0xfffffffe
|
||||
field public static final int RESULT_ERROR_VERSION_MISMATCH = -8; // 0xfffffff8
|
||||
field public static final int RESULT_SUCCESS = 0; // 0x0
|
||||
|
||||
264
core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
Normal file
264
core/java/android/graphics/fonts/FontFamilyUpdateRequest.java
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.SystemApi;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Request for updating or adding a font family on the system.
|
||||
*
|
||||
* <p>You can update or add a font family with custom style parameters. The following example
|
||||
* defines a font family called "roboto" using "Roboto-Regular" font file that is already available
|
||||
* on the system by preloading or {@link FontManager#updateFontFile}.
|
||||
* <pre>
|
||||
* FontManager fm = getContext().getSystemService(FontManager.class);
|
||||
* fm.updateFontFamily(new FontFamilyUpdateRequest.Builder()
|
||||
* .addFontFamily(new FontFamilyUpdateRequest.FontFamily("roboto", Arrays.asList(
|
||||
* new FontFamilyUpdateRequest.Font(
|
||||
* "Roboto-Regular",
|
||||
* new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
|
||||
* Collections.emptyList()),
|
||||
* new FontFamilyUpdateRequest.Font(
|
||||
* "Roboto-Regular",
|
||||
* new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_ITALIC),
|
||||
* Collections.emptyList()))))
|
||||
* .build(), fm.getFontConfig().getConfigVersion());
|
||||
* </pre>
|
||||
*
|
||||
* <p>You can update or add font files in the same request by calling
|
||||
* {@link FontFamilyUpdateRequest.Builder#addFontFileUpdateRequest(FontFileUpdateRequest)}.
|
||||
* The following example adds "YourFont" font file and defines "your-font" font family in the same
|
||||
* request. In this case, the font file represented by {@code yourFontFd} should be an OpenType
|
||||
* compliant font file and have "YourFont" as PostScript name (ID=6) in 'name' table.
|
||||
* <pre>
|
||||
* FontManager fm = getContext().getSystemService(FontManager.class);
|
||||
* fm.updateFontFamily(new FontFamilyUpdateRequest.Builder()
|
||||
* .addFontFileUpdateRequest(new FontFileUpdateRequest(yourFontFd, signature))
|
||||
* .addFontFamily(new FontFamilyUpdateRequest.FontFamily("your-font", Arrays.asList(
|
||||
* new FontFamilyUpdateRequest.Font(
|
||||
* "YourFont",
|
||||
* new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
|
||||
* Collections.emptyList()))))
|
||||
* .build(), fm.getFontConfig().getConfigVersion());
|
||||
* </pre>
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public final class FontFamilyUpdateRequest {
|
||||
|
||||
/**
|
||||
* A font family definition.
|
||||
*/
|
||||
public static final class FontFamily {
|
||||
@NonNull
|
||||
private final String mName;
|
||||
@NonNull
|
||||
private final List<Font> mFonts;
|
||||
|
||||
/**
|
||||
* Constructs a FontFamily.
|
||||
*
|
||||
* <p>A font family has a name to identify the font family. Apps can use
|
||||
* {@link android.graphics.Typeface#create(String, int)} or XML resources to use a specific
|
||||
* font family.
|
||||
*
|
||||
* <p>A font family consists of multiple fonts with different styles. The style information
|
||||
* can be specified by {@link Font}.
|
||||
*
|
||||
* @see android.graphics.Typeface#create(String, int)
|
||||
* @see Font
|
||||
*/
|
||||
public FontFamily(@NonNull String name, @NonNull List<Font> fonts) {
|
||||
Objects.requireNonNull(name);
|
||||
Preconditions.checkStringNotEmpty(name);
|
||||
Objects.requireNonNull(fonts);
|
||||
Preconditions.checkCollectionElementsNotNull(fonts, "fonts");
|
||||
Preconditions.checkCollectionNotEmpty(fonts, "fonts");
|
||||
mName = name;
|
||||
mFonts = fonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of this family.
|
||||
*/
|
||||
@NonNull
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fonts in this family.
|
||||
*/
|
||||
@NonNull
|
||||
public List<Font> getFonts() {
|
||||
return mFonts;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A single entry in a font family representing a font.
|
||||
*/
|
||||
public static final class Font {
|
||||
|
||||
@NonNull
|
||||
private final String mPostScriptName;
|
||||
@NonNull
|
||||
private final FontStyle mStyle;
|
||||
@NonNull
|
||||
private final List<FontVariationAxis> mAxes;
|
||||
|
||||
/**
|
||||
* Constructs a FontStyleVariation.
|
||||
*
|
||||
* <p>A font has a PostScript name to identify the font file to use, a {@link FontStyle}
|
||||
* to specify the style, and a list of {@link FontVariationAxis} to specify axis tags and
|
||||
* values for variable fonts. If the font file identified by {@code postScriptName} is not a
|
||||
* variable font, {@code axes} must be empty.
|
||||
*
|
||||
* @param postScriptName The PostScript name of the font file to use. PostScript name is in
|
||||
* Name ID 6 field in 'name' table, as specified by OpenType
|
||||
* specification.
|
||||
* @param style The style for this font.
|
||||
* @param axes A list of {@link FontVariationAxis} to specify axis tags and values
|
||||
* for variable fonts.
|
||||
*/
|
||||
public Font(@NonNull String postScriptName, @NonNull FontStyle style,
|
||||
@NonNull List<FontVariationAxis> axes) {
|
||||
Objects.requireNonNull(postScriptName);
|
||||
Preconditions.checkStringNotEmpty(postScriptName);
|
||||
Objects.requireNonNull(style);
|
||||
Objects.requireNonNull(axes);
|
||||
Preconditions.checkCollectionElementsNotNull(axes, "axes");
|
||||
mPostScriptName = postScriptName;
|
||||
mStyle = style;
|
||||
mAxes = axes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns PostScript name of the font file to use.
|
||||
*/
|
||||
@NonNull
|
||||
public String getPostScriptName() {
|
||||
return mPostScriptName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the style.
|
||||
*/
|
||||
@NonNull
|
||||
public FontStyle getStyle() {
|
||||
return mStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of {@link FontVariationAxis}.
|
||||
*/
|
||||
@NonNull
|
||||
public List<FontVariationAxis> getAxes() {
|
||||
return mAxes;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link FontFamilyUpdateRequest}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
@NonNull
|
||||
private final List<FontFileUpdateRequest> mFontFileUpdateRequests = new ArrayList<>();
|
||||
@NonNull
|
||||
private final List<FontFamily> mFontFamilies = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Constructs a FontFamilyUpdateRequest.Builder.
|
||||
*/
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link FontFileUpdateRequest} to execute as a part of the constructed
|
||||
* {@link FontFamilyUpdateRequest}.
|
||||
*
|
||||
* @param request A font file update request.
|
||||
* @return This builder object.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder addFontFileUpdateRequest(@NonNull FontFileUpdateRequest request) {
|
||||
Objects.requireNonNull(request);
|
||||
mFontFileUpdateRequests.add(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a font family to update an existing font family in the system font config or
|
||||
* add as a new font family to the system font config.
|
||||
*
|
||||
* @param fontFamily An font family definition to add or update.
|
||||
* @return This builder object.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder addFontFamily(@NonNull FontFamily fontFamily) {
|
||||
Objects.requireNonNull(fontFamily);
|
||||
mFontFamilies.add(fontFamily);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link FontFamilyUpdateRequest}.
|
||||
*/
|
||||
@NonNull
|
||||
public FontFamilyUpdateRequest build() {
|
||||
return new FontFamilyUpdateRequest(mFontFileUpdateRequests, mFontFamilies);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private final List<FontFileUpdateRequest> mFontFiles;
|
||||
|
||||
@NonNull
|
||||
private final List<FontFamily> mFontFamilies;
|
||||
|
||||
private FontFamilyUpdateRequest(@NonNull List<FontFileUpdateRequest> fontFiles,
|
||||
@NonNull List<FontFamily> fontFamilies) {
|
||||
mFontFiles = fontFiles;
|
||||
mFontFamilies = fontFamilies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of {@link FontFileUpdateRequest} that will be executed as a part of this
|
||||
* request.
|
||||
*/
|
||||
@NonNull
|
||||
public List<FontFileUpdateRequest> getFontFileUpdateRequests() {
|
||||
return mFontFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of {@link FontFamily} that will be updated in this request.
|
||||
*/
|
||||
@NonNull
|
||||
public List<FontFamily> getFontFamilies() {
|
||||
return mFontFamilies;
|
||||
}
|
||||
}
|
||||
65
core/java/android/graphics/fonts/FontFileUpdateRequest.java
Normal file
65
core/java/android/graphics/fonts/FontFileUpdateRequest.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.SystemApi;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Request for updating a font file on the system.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public final class FontFileUpdateRequest {
|
||||
|
||||
private final ParcelFileDescriptor mParcelFileDescriptor;
|
||||
private final byte[] mSignature;
|
||||
|
||||
/**
|
||||
* Creates a FontFileUpdateRequest with the given file and signature.
|
||||
*
|
||||
* @param parcelFileDescriptor A file descriptor of the font file.
|
||||
* @param signature A PKCS#7 detached signature for verifying the font file.
|
||||
*/
|
||||
public FontFileUpdateRequest(@NonNull ParcelFileDescriptor parcelFileDescriptor,
|
||||
@NonNull byte[] signature) {
|
||||
Objects.requireNonNull(parcelFileDescriptor);
|
||||
Objects.requireNonNull(signature);
|
||||
mParcelFileDescriptor = parcelFileDescriptor;
|
||||
mSignature = signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file descriptor of the font file.
|
||||
*/
|
||||
@NonNull
|
||||
public ParcelFileDescriptor getParcelFileDescriptor() {
|
||||
return mParcelFileDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PKCS#7 detached signature for verifying the font file.
|
||||
*/
|
||||
@NonNull
|
||||
public byte[] getSignature() {
|
||||
return mSignature;
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,8 @@ import com.android.internal.graphics.fonts.IFontManager;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -58,7 +60,7 @@ public class FontManager {
|
||||
RESULT_ERROR_VERIFICATION_FAILURE, RESULT_ERROR_VERSION_MISMATCH,
|
||||
RESULT_ERROR_INVALID_FONT_FILE, RESULT_ERROR_INVALID_FONT_NAME,
|
||||
RESULT_ERROR_DOWNGRADING, RESULT_ERROR_FAILED_UPDATE_CONFIG,
|
||||
RESULT_ERROR_FONT_UPDATER_DISABLED, RESULT_ERROR_REMOTE_EXCEPTION })
|
||||
RESULT_ERROR_FONT_UPDATER_DISABLED, RESULT_ERROR_FONT_NOT_FOUND })
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ResultCode {}
|
||||
|
||||
@@ -131,9 +133,10 @@ public class FontManager {
|
||||
public static final int RESULT_ERROR_VERSION_MISMATCH = -8;
|
||||
|
||||
/**
|
||||
* Indicates a failure due to IPC communication.
|
||||
* Indicates a failure occurred because a font with the specified PostScript name could not be
|
||||
* found.
|
||||
*/
|
||||
public static final int RESULT_ERROR_REMOTE_EXCEPTION = -9;
|
||||
public static final int RESULT_ERROR_FONT_NOT_FOUND = -9;
|
||||
|
||||
/**
|
||||
* Indicates a failure of opening font file.
|
||||
@@ -253,7 +256,6 @@ public class FontManager {
|
||||
* @see #RESULT_ERROR_DOWNGRADING
|
||||
* @see #RESULT_ERROR_FAILED_UPDATE_CONFIG
|
||||
* @see #RESULT_ERROR_FONT_UPDATER_DISABLED
|
||||
* @see #RESULT_ERROR_REMOTE_EXCEPTION
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.UPDATE_FONTS) public @ResultCode int updateFontFile(
|
||||
@NonNull ParcelFileDescriptor pfd,
|
||||
@@ -261,10 +263,69 @@ public class FontManager {
|
||||
@IntRange(from = 0) int baseVersion
|
||||
) {
|
||||
try {
|
||||
return mIFontManager.updateFont(baseVersion, new FontUpdateRequest(pfd, signature));
|
||||
return mIFontManager.updateFontFile(new FontUpdateRequest(pfd, signature), baseVersion);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to call updateFont API", e);
|
||||
return RESULT_ERROR_REMOTE_EXCEPTION;
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update or add system wide font families.
|
||||
*
|
||||
* <p>This method will update existing font families or add new font families. The updated
|
||||
* font family definitions will be used when creating {@link android.graphics.Typeface} objects
|
||||
* with using {@link android.graphics.Typeface#create(String, int)} specifying the family name,
|
||||
* or through XML resources. Note that system fallback fonts cannot be modified by this method.
|
||||
* Apps must use {@link android.graphics.Typeface.CustomFallbackBuilder} to use custom fallback
|
||||
* fonts.
|
||||
*
|
||||
* <p>Font files can be updated by including {@link FontFileUpdateRequest} to {@code request}
|
||||
* via {@link FontFamilyUpdateRequest.Builder#addFontFileUpdateRequest(FontFileUpdateRequest)}.
|
||||
* The same constraints as {@link #updateFontFile} will apply when updating font files.
|
||||
*
|
||||
* <p>The caller must specify the base config version for keeping the font configuration
|
||||
* consistent. If the font configuration is updated for some reason between the time you get
|
||||
* a configuration with {@link #getFontConfig()} and the time when you call this method,
|
||||
* {@link #RESULT_ERROR_VERSION_MISMATCH} will be returned. Get the latest font configuration by
|
||||
* calling {@link #getFontConfig()} and call this method again with the latest config version.
|
||||
*
|
||||
* @param request A {@link FontFamilyUpdateRequest} to execute.
|
||||
* @param baseVersion A base config version to be updated. You can get the latest config version
|
||||
* by {@link FontConfig#getConfigVersion()} via {@link #getFontConfig()}. If
|
||||
* the system has a newer config version, the update will fail with
|
||||
* {@link #RESULT_ERROR_VERSION_MISMATCH}.
|
||||
* @return A result code.
|
||||
* @see FontConfig#getConfigVersion()
|
||||
* @see #getFontConfig()
|
||||
* @see #RESULT_SUCCESS
|
||||
* @see #RESULT_ERROR_FAILED_TO_WRITE_FONT_FILE
|
||||
* @see #RESULT_ERROR_VERIFICATION_FAILURE
|
||||
* @see #RESULT_ERROR_VERSION_MISMATCH
|
||||
* @see #RESULT_ERROR_INVALID_FONT_FILE
|
||||
* @see #RESULT_ERROR_INVALID_FONT_NAME
|
||||
* @see #RESULT_ERROR_DOWNGRADING
|
||||
* @see #RESULT_ERROR_FAILED_UPDATE_CONFIG
|
||||
* @see #RESULT_ERROR_FONT_UPDATER_DISABLED
|
||||
* @see #RESULT_ERROR_FONT_NOT_FOUND
|
||||
*/
|
||||
@RequiresPermission(Manifest.permission.UPDATE_FONTS) public @ResultCode int updateFontFamily(
|
||||
@NonNull FontFamilyUpdateRequest request, @IntRange(from = 0) int baseVersion) {
|
||||
List<FontUpdateRequest> requests = new ArrayList<>();
|
||||
List<FontFileUpdateRequest> fontFileUpdateRequests = request.getFontFileUpdateRequests();
|
||||
for (int i = 0; i < fontFileUpdateRequests.size(); i++) {
|
||||
FontFileUpdateRequest fontFile = fontFileUpdateRequests.get(i);
|
||||
requests.add(new FontUpdateRequest(fontFile.getParcelFileDescriptor(),
|
||||
fontFile.getSignature()));
|
||||
}
|
||||
List<FontFamilyUpdateRequest.FontFamily> fontFamilies = request.getFontFamilies();
|
||||
for (int i = 0; i < fontFamilies.size(); i++) {
|
||||
FontFamilyUpdateRequest.FontFamily fontFamily = fontFamilies.get(i);
|
||||
requests.add(new FontUpdateRequest(fontFamily.getName(), fontFamily.getFonts()));
|
||||
}
|
||||
try {
|
||||
return mIFontManager.updateFontFamily(requests, baseVersion);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,17 @@ package android.graphics.fonts;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.LocaleList;
|
||||
import android.os.Parcel;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.Parcelable;
|
||||
import android.text.FontConfig;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Represents a font update request. Currently only font install request is supported.
|
||||
@@ -80,6 +84,26 @@ public final class FontUpdateRequest implements Parcelable {
|
||||
mFontFamily = fontFamily;
|
||||
}
|
||||
|
||||
public FontUpdateRequest(@NonNull String postScriptName,
|
||||
@NonNull List<FontFamilyUpdateRequest.Font> variations) {
|
||||
// TODO: Serialize the request directly instead of reusing FontConfig.FontFamily.
|
||||
this(createFontFamily(postScriptName, variations));
|
||||
}
|
||||
|
||||
private static FontConfig.FontFamily createFontFamily(@NonNull String postScriptName,
|
||||
@NonNull List<FontFamilyUpdateRequest.Font> fonts) {
|
||||
List<FontConfig.Font> configFonts = new ArrayList<>(fonts.size());
|
||||
for (FontFamilyUpdateRequest.Font font : fonts) {
|
||||
// TODO: Support .otf.
|
||||
configFonts.add(new FontConfig.Font(new File(font.getPostScriptName() + ".ttf"), null,
|
||||
font.getStyle(), 0 /* index */,
|
||||
FontVariationAxis.toFontVariationSettings(font.getAxes()),
|
||||
null /* fontFamilyName */));
|
||||
}
|
||||
return new FontConfig.FontFamily(configFonts, postScriptName,
|
||||
LocaleList.getEmptyLocaleList(), FontConfig.FontFamily.VARIANT_DEFAULT);
|
||||
}
|
||||
|
||||
protected FontUpdateRequest(Parcel in) {
|
||||
mType = in.readInt();
|
||||
mFd = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.os.ParcelFileDescriptor;
|
||||
import android.graphics.fonts.FontUpdateRequest;
|
||||
import android.text.FontConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* System private interface for talking with
|
||||
* {@link com.android.server.graphics.fonts.FontManagerService}.
|
||||
@@ -28,5 +30,7 @@ import android.text.FontConfig;
|
||||
interface IFontManager {
|
||||
FontConfig getFontConfig();
|
||||
|
||||
int updateFont(int baseVersion, in FontUpdateRequest request);
|
||||
int updateFontFile(in FontUpdateRequest request, int baseVersion);
|
||||
|
||||
int updateFontFamily(in List<FontUpdateRequest> request, int baseVersion);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -189,6 +190,17 @@ public final class FontVariationAxis {
|
||||
return TextUtils.join(",", axes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stringify the array of FontVariationAxis.
|
||||
* @hide
|
||||
*/
|
||||
public static @NonNull String toFontVariationSettings(@Nullable List<FontVariationAxis> axes) {
|
||||
if (axes == null) {
|
||||
return "";
|
||||
}
|
||||
return TextUtils.join(",", axes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (o == this) {
|
||||
|
||||
@@ -72,11 +72,11 @@ public final class FontManagerService extends IFontManager.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateFont(int baseVersion, @NonNull FontUpdateRequest request) {
|
||||
public int updateFontFile(@NonNull FontUpdateRequest request, int baseVersion) {
|
||||
Preconditions.checkArgumentNonnegative(baseVersion);
|
||||
Objects.requireNonNull(request);
|
||||
Objects.requireNonNull(request.getFd());
|
||||
Objects.requireNonNull(request.getSignature());
|
||||
Preconditions.checkArgumentNonnegative(baseVersion);
|
||||
getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS,
|
||||
"UPDATE_FONTS permission required.");
|
||||
try {
|
||||
@@ -88,6 +88,21 @@ public final class FontManagerService extends IFontManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int updateFontFamily(@NonNull List<FontUpdateRequest> requests, int baseVersion) {
|
||||
Preconditions.checkArgumentNonnegative(baseVersion);
|
||||
Objects.requireNonNull(requests);
|
||||
getContext().enforceCallingPermission(Manifest.permission.UPDATE_FONTS,
|
||||
"UPDATE_FONTS permission required.");
|
||||
try {
|
||||
update(baseVersion, requests);
|
||||
return FontManager.RESULT_SUCCESS;
|
||||
} catch (SystemFontException e) {
|
||||
Slog.e(TAG, "Failed to update font family", e);
|
||||
return e.getErrorCode();
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ static class SystemFontException extends AndroidException {
|
||||
private final int mErrorCode;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Manages set of updatable font files.
|
||||
@@ -182,8 +183,12 @@ final class UpdatableFontDir {
|
||||
List<FontConfig.FontFamily> fontFamilies = config.fontFamilies;
|
||||
for (int i = 0; i < fontFamilies.size(); i++) {
|
||||
FontConfig.FontFamily fontFamily = fontFamilies.get(i);
|
||||
// Ignore failures as updated fonts may be obsoleted by system OTA update.
|
||||
addFontFamily(fontFamily);
|
||||
try {
|
||||
addFontFamily(fontFamily);
|
||||
} catch (SystemFontException e) {
|
||||
// Ignore failures as updated fonts may be obsoleted by system OTA update.
|
||||
Slog.i(TAG, "Obsolete font family: " + fontFamily.getName());
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
} catch (Throwable t) {
|
||||
@@ -236,10 +241,7 @@ final class UpdatableFontDir {
|
||||
request.getFd().getFileDescriptor(), request.getSignature());
|
||||
break;
|
||||
case FontUpdateRequest.TYPE_UPDATE_FONT_FAMILY:
|
||||
// TODO: define error code.
|
||||
if (!addFontFamily(request.getFontFamily())) {
|
||||
throw new IllegalArgumentException("Invalid font family");
|
||||
}
|
||||
addFontFamily(request.getFontFamily());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -495,18 +497,15 @@ final class UpdatableFontDir {
|
||||
* Unnamed font families are used as other named font family's fallback fonts to guarantee a
|
||||
* complete glyph coverage.
|
||||
*/
|
||||
private boolean addFontFamily(FontConfig.FontFamily fontFamily) {
|
||||
if (fontFamily.getName() == null) {
|
||||
Slog.e(TAG, "Name is null.");
|
||||
return false;
|
||||
}
|
||||
private void addFontFamily(FontConfig.FontFamily fontFamily) throws SystemFontException {
|
||||
Objects.requireNonNull(fontFamily.getName());
|
||||
FontConfig.FontFamily resolvedFontFamily = resolveFontFiles(fontFamily);
|
||||
if (resolvedFontFamily == null) {
|
||||
Slog.e(TAG, "Required fonts are not available");
|
||||
return false;
|
||||
throw new SystemFontException(
|
||||
FontManager.RESULT_ERROR_FONT_NOT_FOUND,
|
||||
"Required fonts are not available");
|
||||
}
|
||||
mFontFamilyMap.put(resolvedFontFamily.getName(), resolvedFontFamily);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -684,8 +684,8 @@ public final class UpdatableFontDirTest {
|
||||
newAddFontFamilyRequest("<family lang='en'>"
|
||||
+ " <font>test.ttf</font>"
|
||||
+ "</family>")));
|
||||
fail("Expect IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
fail("Expect NullPointerException");
|
||||
} catch (NullPointerException e) {
|
||||
// Expect
|
||||
}
|
||||
}
|
||||
@@ -703,9 +703,10 @@ public final class UpdatableFontDirTest {
|
||||
dir.update(Arrays.asList(newAddFontFamilyRequest("<family name='test'>"
|
||||
+ " <font>test.ttf</font>"
|
||||
+ "</family>")));
|
||||
fail("Expect IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Expect
|
||||
fail("Expect SystemFontException");
|
||||
} catch (FontManagerService.SystemFontException e) {
|
||||
assertThat(e.getErrorCode())
|
||||
.isEqualTo(FontManager.RESULT_ERROR_FONT_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user