From 711a120d16188b69a75792dcbf053c91916ca980 Mon Sep 17 00:00:00 2001 From: Kohsuke Yatoh Date: Fri, 29 Jul 2022 00:46:39 +0000 Subject: [PATCH] Pass buffer base address to minikin::BufferReader. Bug: 174672300 Test: atest CtsGraphicsTestCases:android.graphics.cts.TypefaceTest Change-Id: Ie6bf1bb01ccc2803bc6206a0d2276ac59c6877a1 --- graphics/java/android/graphics/Typeface.java | 17 +++++++----- libs/hwui/jni/Typeface.cpp | 28 ++++++++++++++------ libs/hwui/jni/fonts/Font.cpp | 8 +++--- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index f4f5e1e792ec5..8ae0d3d48d6d8 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -1244,14 +1244,16 @@ public class Typeface { nativePtrs[i++] = entry.getValue().native_instance; writeString(namesBytes, entry.getKey()); } - int typefacesBytesCount = nativeWriteTypefaces(null, nativePtrs); // int (typefacesBytesCount), typefaces, namesBytes + final int typefaceBytesCountSize = Integer.BYTES; + int typefacesBytesCount = nativeWriteTypefaces(null, typefaceBytesCountSize, nativePtrs); SharedMemory sharedMemory = SharedMemory.create( - "fontMap", Integer.BYTES + typefacesBytesCount + namesBytes.size()); + "fontMap", typefaceBytesCountSize + typefacesBytesCount + namesBytes.size()); ByteBuffer writableBuffer = sharedMemory.mapReadWrite().order(ByteOrder.BIG_ENDIAN); try { writableBuffer.putInt(typefacesBytesCount); - int writtenBytesCount = nativeWriteTypefaces(writableBuffer.slice(), nativePtrs); + int writtenBytesCount = + nativeWriteTypefaces(writableBuffer, writableBuffer.position(), nativePtrs); if (writtenBytesCount != typefacesBytesCount) { throw new IOException(String.format("Unexpected bytes written: %d, expected: %d", writtenBytesCount, typefacesBytesCount)); @@ -1276,7 +1278,9 @@ public class Typeface { @NonNull ByteBuffer buffer, @NonNull Map out) throws IOException { int typefacesBytesCount = buffer.getInt(); - long[] nativePtrs = nativeReadTypefaces(buffer.slice()); + // Note: Do not call buffer.slice(), as nativeReadTypefaces() expects + // that buffer.address() is page-aligned. + long[] nativePtrs = nativeReadTypefaces(buffer, buffer.position()); if (nativePtrs == null) { throw new IOException("Could not read typefaces"); } @@ -1598,9 +1602,10 @@ public class Typeface { private static native void nativeRegisterGenericFamily(String str, long nativePtr); private static native int nativeWriteTypefaces( - @Nullable ByteBuffer buffer, @NonNull long[] nativePtrs); + @Nullable ByteBuffer buffer, int position, @NonNull long[] nativePtrs); - private static native @Nullable long[] nativeReadTypefaces(@NonNull ByteBuffer buffer); + private static native + @Nullable long[] nativeReadTypefaces(@NonNull ByteBuffer buffer, int position); private static native void nativeForceSetStaticFinalField(String fieldName, Typeface typeface); diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp index 19efc5f09d114..6325226068dd8 100644 --- a/libs/hwui/jni/Typeface.cpp +++ b/libs/hwui/jni/Typeface.cpp @@ -305,7 +305,8 @@ void MinikinFontSkiaFactory::write(minikin::BufferWriter* writer, } } -static jint Typeface_writeTypefaces(JNIEnv *env, jobject, jobject buffer, jlongArray faceHandles) { +static jint Typeface_writeTypefaces(JNIEnv* env, jobject, jobject buffer, jint position, + jlongArray faceHandles) { MinikinFontSkiaFactory::init(); ScopedLongArrayRO faces(env, faceHandles); std::vector typefaces; @@ -314,7 +315,12 @@ static jint Typeface_writeTypefaces(JNIEnv *env, jobject, jobject buffer, jlongA typefaces.push_back(toTypeface(faces[i])); } void* addr = buffer == nullptr ? nullptr : env->GetDirectBufferAddress(buffer); - minikin::BufferWriter writer(addr); + if (addr != nullptr && + reinterpret_cast(addr) % minikin::BufferReader::kMaxAlignment != 0) { + ALOGE("addr (%p) must be aligned at kMaxAlignment, but it was not.", addr); + return 0; + } + minikin::BufferWriter writer(addr, position); std::vector> fontCollections; std::unordered_map, size_t> fcToIndex; for (Typeface* typeface : typefaces) { @@ -334,11 +340,18 @@ static jint Typeface_writeTypefaces(JNIEnv *env, jobject, jobject buffer, jlongA return static_cast(writer.size()); } -static jlongArray Typeface_readTypefaces(JNIEnv *env, jobject, jobject buffer) { +static jlongArray Typeface_readTypefaces(JNIEnv* env, jobject, jobject buffer, jint position) { MinikinFontSkiaFactory::init(); void* addr = buffer == nullptr ? nullptr : env->GetDirectBufferAddress(buffer); - if (addr == nullptr) return nullptr; - minikin::BufferReader reader(addr); + if (addr == nullptr) { + ALOGE("Passed a null buffer."); + return nullptr; + } + if (reinterpret_cast(addr) % minikin::BufferReader::kMaxAlignment != 0) { + ALOGE("addr (%p) must be aligned at kMaxAlignment, but it was not.", addr); + return nullptr; + } + minikin::BufferReader reader(addr, position); std::vector> fontCollections = minikin::FontCollection::readVector(&reader); uint32_t typefaceCount = reader.read(); @@ -357,7 +370,6 @@ static jlongArray Typeface_readTypefaces(JNIEnv *env, jobject, jobject buffer) { return result; } - static void Typeface_forceSetStaticFinalField(JNIEnv *env, jclass cls, jstring fieldName, jobject typeface) { ScopedUtfChars fieldNameChars(env, fieldName); @@ -417,8 +429,8 @@ static const JNINativeMethod gTypefaceMethods[] = { {"nativeGetSupportedAxes", "(J)[I", (void*)Typeface_getSupportedAxes}, {"nativeRegisterGenericFamily", "(Ljava/lang/String;J)V", (void*)Typeface_registerGenericFamily}, - {"nativeWriteTypefaces", "(Ljava/nio/ByteBuffer;[J)I", (void*)Typeface_writeTypefaces}, - {"nativeReadTypefaces", "(Ljava/nio/ByteBuffer;)[J", (void*)Typeface_readTypefaces}, + {"nativeWriteTypefaces", "(Ljava/nio/ByteBuffer;I[J)I", (void*)Typeface_writeTypefaces}, + {"nativeReadTypefaces", "(Ljava/nio/ByteBuffer;I)[J", (void*)Typeface_readTypefaces}, {"nativeForceSetStaticFinalField", "(Ljava/lang/String;Landroid/graphics/Typeface;)V", (void*)Typeface_forceSetStaticFinalField}, {"nativeGetFamilySize", "(J)I", (void*)Typeface_getFamilySize}, diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp index 2c421f8727a8f..f17129c8d953b 100644 --- a/libs/hwui/jni/fonts/Font.cpp +++ b/libs/hwui/jni/fonts/Font.cpp @@ -228,7 +228,7 @@ static jlong Font_getReleaseNativeFontFunc(CRITICAL_JNI_PARAMS) { static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) { FontWrapper* font = reinterpret_cast(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); - if (reader.data() != nullptr) { + if (reader.current() != nullptr) { std::string path = std::string(reader.readString()); if (path.empty()) { return nullptr; @@ -270,7 +270,7 @@ static jint Font_getPackedStyle(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); - if (reader.data() != nullptr) { + if (reader.current() != nullptr) { reader.skipString(); // fontPath return reader.read(); } else { @@ -283,7 +283,7 @@ static jint Font_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) { FontWrapper* font = reinterpret_cast(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); - if (reader.data() != nullptr) { + if (reader.current() != nullptr) { reader.skipString(); // fontPath reader.skip(); // fontIndex return reader.readArray().second; @@ -298,7 +298,7 @@ static jlong Font_getAxisInfo(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr, jint inde FontWrapper* font = reinterpret_cast(fontPtr); minikin::BufferReader reader = font->font->typefaceMetadataReader(); minikin::FontVariation var; - if (reader.data() != nullptr) { + if (reader.current() != nullptr) { reader.skipString(); // fontPath reader.skip(); // fontIndex var = reader.readArray().first[index];