Merge "Consolidate AssetManager calls in Font/FontFamily"

This commit is contained in:
Derek Sollenberger
2020-02-11 13:11:42 +00:00
committed by Android (Google) Code Review
4 changed files with 75 additions and 173 deletions

View File

@@ -27,8 +27,6 @@
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedUtfChars.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_util_AssetManager.h>
#include <androidfw/AssetManager2.h>
#include "Utils.h"
#include "FontUtils.h"
@@ -212,63 +210,6 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong
return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
}
static void releaseAsset(const void* ptr, void* context) {
delete static_cast<Asset*>(context);
}
static jboolean FontFamily_addFontFromAssetManager(JNIEnv* env, jobject, jlong builderPtr,
jobject jassetMgr, jstring jpath, jint cookie, jboolean isAsset, jint ttcIndex,
jint weight, jint isItalic) {
#ifdef __ANDROID__ // Layoutlib does not support native AssetManager
NPE_CHECK_RETURN_ZERO(env, jassetMgr);
NPE_CHECK_RETURN_ZERO(env, jpath);
NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
if (NULL == mgr) {
builder->axes.clear();
return false;
}
ScopedUtfChars str(env, jpath);
if (str.c_str() == nullptr) {
builder->axes.clear();
return false;
}
std::unique_ptr<Asset> asset;
{
ScopedLock<AssetManager2> locked_mgr(*mgr);
if (isAsset) {
asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
} else if (cookie > 0) {
// Valid java cookies are 1-based, but AssetManager cookies are 0-based.
asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
Asset::ACCESS_BUFFER);
} else {
asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
}
}
if (nullptr == asset) {
builder->axes.clear();
return false;
}
const void* buf = asset->getBuffer(false);
if (NULL == buf) {
builder->axes.clear();
return false;
}
sk_sp<SkData> data(SkData::MakeWithProc(buf, asset->getLength(), releaseAsset,
asset.release()));
return addSkTypeface(builder, std::move(data), ttcIndex, weight, isItalic);
#else
return false;
#endif
}
static void FontFamily_addAxisValue(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr, jint tag, jfloat value) {
NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
builder->axes.push_back({static_cast<minikin::AxisTag>(tag), value});
@@ -284,8 +225,6 @@ static const JNINativeMethod gFontFamilyMethods[] = {
{ "nAddFont", "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
{ "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;III)Z",
(void*)FontFamily_addFontWeightStyle },
{ "nAddFontFromAssetManager", "(JLandroid/content/res/AssetManager;Ljava/lang/String;IZIII)Z",
(void*)FontFamily_addFontFromAssetManager },
{ "nAddAxisValue", "(JIF)V", (void*)FontFamily_addAxisValue },
};

View File

@@ -26,8 +26,6 @@
#include "GraphicsJNI.h"
#include <nativehelper/ScopedUtfChars.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_util_AssetManager.h>
#include <androidfw/AssetManager2.h>
#include "Utils.h"
#include "FontUtils.h"
@@ -48,14 +46,6 @@ static inline NativeFontBuilder* toBuilder(jlong ptr) {
return reinterpret_cast<NativeFontBuilder*>(ptr);
}
static inline Asset* toAsset(jlong ptr) {
return reinterpret_cast<Asset*>(ptr);
}
static void releaseAsset(jlong asset) {
delete toAsset(asset);
}
static void releaseFont(jlong font) {
delete reinterpret_cast<FontWrapper*>(font);
}
@@ -78,54 +68,6 @@ static void release_global_ref(const void* /*data*/, void* context) {
env->DeleteGlobalRef(obj);
}
// Regular JNI
static jlong Font_Builder_getNativeAsset(
JNIEnv* env, jobject clazz, jobject assetMgr, jstring path, jboolean isAsset, jint cookie) {
#ifdef __ANDROID__ // Layoutlib does not support native AssetManager
NPE_CHECK_RETURN_ZERO(env, assetMgr);
NPE_CHECK_RETURN_ZERO(env, path);
Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, assetMgr);
if (mgr == nullptr) {
return 0;
}
ScopedUtfChars str(env, path);
if (str.c_str() == nullptr) {
return 0;
}
std::unique_ptr<Asset> asset;
{
ScopedLock<AssetManager2> locked_mgr(*mgr);
if (isAsset) {
asset = locked_mgr->Open(str.c_str(), Asset::ACCESS_BUFFER);
} else if (cookie > 0) {
// Valid java cookies are 1-based, but AssetManager cookies are 0-based.
asset = locked_mgr->OpenNonAsset(str.c_str(), static_cast<ApkAssetsCookie>(cookie - 1),
Asset::ACCESS_BUFFER);
} else {
asset = locked_mgr->OpenNonAsset(str.c_str(), Asset::ACCESS_BUFFER);
}
}
return reinterpret_cast<jlong>(asset.release());
#else
return 0;
#endif
}
// Regular JNI
static jobject Font_Builder_getAssetBuffer(JNIEnv* env, jobject clazz, jlong nativeAsset) {
Asset* asset = toAsset(nativeAsset);
return env->NewDirectByteBuffer(const_cast<void*>(asset->getBuffer(false)), asset->getLength());
}
// CriticalNative
static jlong Font_Builder_getReleaseNativeAssetFunc(CRITICAL_JNI_PARAMS) {
return reinterpret_cast<jlong>(&releaseAsset);
}
// Regular JNI
static jlong Font_Builder_initBuilder(JNIEnv*, jobject) {
return reinterpret_cast<jlong>(new NativeFontBuilder());
@@ -196,11 +138,6 @@ static const JNINativeMethod gFontBuilderMethods[] = {
{ "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis },
{ "nBuild", "(JLjava/nio/ByteBuffer;Ljava/lang/String;IZI)J", (void*) Font_Builder_build },
{ "nGetReleaseNativeFont", "()J", (void*) Font_Builder_getReleaseNativeFont },
{ "nGetNativeAsset", "(Landroid/content/res/AssetManager;Ljava/lang/String;ZI)J",
(void*) Font_Builder_getNativeAsset },
{ "nGetAssetBuffer", "(J)Ljava/nio/ByteBuffer;", (void*) Font_Builder_getAssetBuffer },
{ "nGetReleaseNativeAssetFunc", "()J", (void*) Font_Builder_getReleaseNativeAssetFunc },
};
int register_android_graphics_fonts_Font(JNIEnv* env) {

View File

@@ -19,6 +19,7 @@ package android.graphics;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontVariationAxis;
import android.os.Build;
import android.text.TextUtils;
@@ -195,18 +196,13 @@ public class FontFamily {
if (mBuilderPtr == 0) {
throw new IllegalStateException("Unable to call addFontFromAsset after freezing.");
}
if (axes != null) {
for (FontVariationAxis axis : axes) {
nAddAxisValue(mBuilderPtr, axis.getOpenTypeTagValue(), axis.getStyleValue());
}
}
return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset, ttcIndex, weight,
isItalic);
}
// TODO: Remove once internal user stop using private API.
private static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) {
return nAddFont(builderPtr, font, ttcIndex, -1, -1);
try {
ByteBuffer buffer = Font.Builder.createBuffer(mgr, path, isAsset, cookie);
return addFontFromBuffer(buffer, ttcIndex, axes, weight, isItalic);
} catch (IOException e) {
return false;
}
}
private static native long nInitBuilder(String langs, int variant);
@@ -225,8 +221,6 @@ public class FontFamily {
int weight, int isItalic);
private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font,
int ttcIndex, int weight, int isItalic);
private static native boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr,
String path, int cookie, boolean isAsset, int ttcIndex, int weight, int isItalic);
// The added axis values are only valid for the next nAddFont* method call.
@CriticalNative

View File

@@ -19,6 +19,7 @@ package android.graphics.fonts;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.LocaleList;
@@ -35,7 +36,9 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Objects;
@@ -54,10 +57,6 @@ public final class Font {
* A builder class for creating new Font.
*/
public static final class Builder {
private static final NativeAllocationRegistry sAssetByteBufferRegistry =
NativeAllocationRegistry.createMalloced(ByteBuffer.class.getClassLoader(),
nGetReleaseNativeAssetFunc());
private static final NativeAllocationRegistry sFontRegistry =
NativeAllocationRegistry.createMalloced(Font.class.getClassLoader(),
nGetReleaseNativeFont());
@@ -151,7 +150,11 @@ public final class Font {
* @param path the file name of the font data in the asset directory
*/
public Builder(@NonNull AssetManager am, @NonNull String path) {
this(am, path, true /* is asset */, 0 /* cookie */);
try {
mBuffer = createBuffer(am, path, true /* is asset */, 0 /* cookie */);
} catch (IOException e) {
mException = e;
}
}
/**
@@ -165,18 +168,11 @@ public final class Font {
*/
public Builder(@NonNull AssetManager am, @NonNull String path, boolean isAsset,
int cookie) {
final long nativeAsset = nGetNativeAsset(am, path, isAsset, cookie);
if (nativeAsset == 0) {
mException = new FileNotFoundException("Unable to open " + path);
return;
try {
mBuffer = createBuffer(am, path, isAsset, cookie);
} catch (IOException e) {
mException = e;
}
final ByteBuffer b = nGetAssetBuffer(nativeAsset);
sAssetByteBufferRegistry.registerNativeAllocation(b, nativeAsset);
if (b == null) {
mException = new FileNotFoundException(path + " not found");
return;
}
mBuffer = b;
}
/**
@@ -199,19 +195,64 @@ public final class Font {
mException = new FileNotFoundException(resId + " must be font file.");
return;
}
final long nativeAsset = nGetNativeAsset(res.getAssets(), str, false /* is asset */,
value.assetCookie);
if (nativeAsset == 0) {
mException = new FileNotFoundException("Unable to open " + str);
return;
try {
mBuffer = createBuffer(res.getAssets(), str, false, value.assetCookie);
} catch (IOException e) {
mException = e;
}
final ByteBuffer b = nGetAssetBuffer(nativeAsset);
sAssetByteBufferRegistry.registerNativeAllocation(b, nativeAsset);
if (b == null) {
mException = new FileNotFoundException(str + " not found");
return;
}
/**
* Creates a buffer containing font data using the assetManager and other
* provided inputs.
*
* @param am the application's asset manager
* @param path the file name of the font data in the asset directory
* @param isAsset true if the undelying data is in asset
* @param cookie set asset cookie
* @return buffer containing the contents of the file
*
* @hide
*/
public static ByteBuffer createBuffer(@NonNull AssetManager am, @NonNull String path,
boolean isAsset, int cookie) throws IOException {
Preconditions.checkNotNull(am, "assetManager can not be null");
Preconditions.checkNotNull(path, "path can not be null");
if (!isAsset) {
// Attempt to open as FD, which should work unless the asset is compressed
AssetFileDescriptor assetFD;
try {
if (cookie > 0) {
assetFD = am.openNonAssetFd(cookie, path);
} else {
assetFD = am.openNonAssetFd(path);
}
try (FileInputStream fis = assetFD.createInputStream()) {
final FileChannel fc = fis.getChannel();
return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
}
} catch (IOException e) {
// failed to open as FD so now we will attempt to open as an input stream
}
}
try (InputStream assetStream = isAsset ? am.open(path, AssetManager.ACCESS_BUFFER)
: am.openNonAsset(cookie, path, AssetManager.ACCESS_BUFFER)) {
int capacity = assetStream.available();
ByteBuffer buffer = ByteBuffer.allocateDirect(capacity);
buffer.order(ByteOrder.nativeOrder());
assetStream.read(buffer.array(), buffer.arrayOffset(), assetStream.available());
if (assetStream.read() != -1) {
throw new IOException("Unable to access full contents of " + path);
}
return buffer;
}
mBuffer = b;
}
/**
@@ -395,15 +436,6 @@ public final class Font {
return font;
}
/**
* Native methods for accessing underlying buffer in Asset
*/
private static native long nGetNativeAsset(
@NonNull AssetManager am, @NonNull String path, boolean isAsset, int cookie);
private static native ByteBuffer nGetAssetBuffer(long nativeAsset);
@CriticalNative
private static native long nGetReleaseNativeAssetFunc();
/**
* Native methods for creating Font
*/