Pass buffer base address to minikin::BufferReader.

Bug: 174672300
Test: atest CtsGraphicsTestCases:android.graphics.cts.TypefaceTest
Change-Id: Ie6bf1bb01ccc2803bc6206a0d2276ac59c6877a1
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index f4f5e1e..8ae0d3d 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1244,14 +1244,16 @@
             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 @@
             @NonNull ByteBuffer buffer, @NonNull Map<String, Typeface> 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 @@
     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 19efc5f..6325226 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -305,7 +305,8 @@
     }
 }
 
-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<Typeface*> typefaces;
@@ -314,7 +315,12 @@
         typefaces.push_back(toTypeface(faces[i]));
     }
     void* addr = buffer == nullptr ? nullptr : env->GetDirectBufferAddress(buffer);
-    minikin::BufferWriter writer(addr);
+    if (addr != nullptr &&
+        reinterpret_cast<intptr_t>(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<std::shared_ptr<minikin::FontCollection>> fontCollections;
     std::unordered_map<std::shared_ptr<minikin::FontCollection>, size_t> fcToIndex;
     for (Typeface* typeface : typefaces) {
@@ -334,11 +340,18 @@
     return static_cast<jint>(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<intptr_t>(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<std::shared_ptr<minikin::FontCollection>> fontCollections =
             minikin::FontCollection::readVector(&reader);
     uint32_t typefaceCount = reader.read<uint32_t>();
@@ -357,7 +370,6 @@
     return result;
 }
 
-
 static void Typeface_forceSetStaticFinalField(JNIEnv *env, jclass cls, jstring fieldName,
         jobject typeface) {
     ScopedUtfChars fieldNameChars(env, fieldName);
@@ -417,8 +429,8 @@
         {"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 2c421f8..f17129c 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -228,7 +228,7 @@
 static jstring Font_getFontPath(JNIEnv* env, jobject, jlong fontPtr) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(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_getIndex(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
     minikin::BufferReader reader = font->font->typefaceMetadataReader();
-    if (reader.data() != nullptr) {
+    if (reader.current() != nullptr) {
         reader.skipString();  // fontPath
         return reader.read<int>();
     } else {
@@ -283,7 +283,7 @@
 static jint Font_getAxisCount(CRITICAL_JNI_PARAMS_COMMA jlong fontPtr) {
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
     minikin::BufferReader reader = font->font->typefaceMetadataReader();
-    if (reader.data() != nullptr) {
+    if (reader.current() != nullptr) {
         reader.skipString();  // fontPath
         reader.skip<int>();   // fontIndex
         return reader.readArray<minikin::FontVariation>().second;
@@ -298,7 +298,7 @@
     FontWrapper* font = reinterpret_cast<FontWrapper*>(fontPtr);
     minikin::BufferReader reader = font->font->typefaceMetadataReader();
     minikin::FontVariation var;
-    if (reader.data() != nullptr) {
+    if (reader.current() != nullptr) {
         reader.skipString();  // fontPath
         reader.skip<int>();   // fontIndex
         var = reader.readArray<minikin::FontVariation>().first[index];