Add PostScript name and font revision retrival method

Bug: 176939176
Test: Manually done (will add in subsequent CL.)
Change-Id: I2acbec7ee4362a91c1e6b3b765894106775ef2c4
diff --git a/graphics/java/android/graphics/fonts/FontFileUtil.java b/graphics/java/android/graphics/fonts/FontFileUtil.java
index f8b456b..2896c46 100644
--- a/graphics/java/android/graphics/fonts/FontFileUtil.java
+++ b/graphics/java/android/graphics/fonts/FontFileUtil.java
@@ -20,6 +20,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
+import dalvik.annotation.optimization.FastNative;
+
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
@@ -131,4 +133,44 @@
             buffer.order(originalOrder);
         }
     }
+
+    /**
+     * Analyze head OpenType table and return fontRevision value as 32bit integer.
+     *
+     * The font revision is stored in 16.16 bit fixed point value. This function returns this fixed
+     * point value as 32 bit integer, i.e. the value multiplied with 65536.
+     *
+     * IllegalArgumentException will be thrown for invalid font data.
+     * If the font file is invalid, returns -1L.
+     *
+     * @param buffer a buffer of OpenType font
+     * @param index a font index
+     * @return font revision that shifted 16 bits left.
+     */
+    public static long getRevision(@NonNull ByteBuffer buffer, @IntRange(from = 0) int index) {
+        return nGetFontRevision(buffer, index);
+    }
+
+    /**
+     * Analyze name OpenType table and return PostScript name.
+     *
+     * IllegalArgumentException will be thrown for invalid font data.
+     * null will be returned if not found or the PostScript name is invalid.
+     *
+     * @param buffer a buffer of OpenType font
+     * @param index a font index
+     * @return a post script name or null if it is invalid or not found.
+     */
+    public static String getPostScriptName(@NonNull ByteBuffer buffer,
+            @IntRange(from = 0) int index) {
+        return nGetFontPostScriptName(buffer, index);
+    }
+
+    @FastNative
+    private static native long nGetFontRevision(@NonNull ByteBuffer buffer,
+            @IntRange(from = 0) int index);
+
+    @FastNative
+    private static native String nGetFontPostScriptName(@NonNull ByteBuffer buffer,
+            @IntRange(from = 0) int index);
 }
diff --git a/libs/hwui/jni/fonts/Font.cpp b/libs/hwui/jni/fonts/Font.cpp
index f612bce..943423f 100644
--- a/libs/hwui/jni/fonts/Font.cpp
+++ b/libs/hwui/jni/fonts/Font.cpp
@@ -33,6 +33,7 @@
 #include <hwui/Paint.h>
 #include <hwui/Typeface.h>
 #include <minikin/FontFamily.h>
+#include <minikin/FontFileParser.h>
 #include <ui/FatVector.h>
 
 #include <memory>
@@ -233,6 +234,51 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+// Fast Native
+static jlong FontFileUtil_getFontRevision(JNIEnv* env, jobject, jobject buffer, jint index) {
+    NPE_CHECK_RETURN_ZERO(env, buffer);
+    const void* fontPtr = env->GetDirectBufferAddress(buffer);
+    if (fontPtr == nullptr) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
+        return 0;
+    }
+    jlong fontSize = env->GetDirectBufferCapacity(buffer);
+    if (fontSize <= 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "buffer size must not be zero or negative");
+        return 0;
+    }
+    minikin::FontFileParser parser(fontPtr, fontSize, index);
+    std::optional<uint32_t> revision = parser.getFontRevision();
+    if (!revision.has_value()) {
+        return -1L;
+    }
+    return revision.value();
+}
+
+static jstring FontFileUtil_getFontPostScriptName(JNIEnv* env, jobject, jobject buffer,
+                                                  jint index) {
+    NPE_CHECK_RETURN_ZERO(env, buffer);
+    const void* fontPtr = env->GetDirectBufferAddress(buffer);
+    if (fontPtr == nullptr) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", "Not a direct buffer");
+        return nullptr;
+    }
+    jlong fontSize = env->GetDirectBufferCapacity(buffer);
+    if (fontSize <= 0) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                          "buffer size must not be zero or negative");
+        return nullptr;
+    }
+    minikin::FontFileParser parser(fontPtr, fontSize, index);
+    std::optional<std::string> psName = parser.getPostScriptName();
+    if (!psName.has_value()) {
+        return nullptr;  // null
+    }
+    return env->NewStringUTF(psName->c_str());
+}
+///////////////////////////////////////////////////////////////////////////////
+
 static const JNINativeMethod gFontBuilderMethods[] = {
     { "nInitBuilder", "()J", (void*) Font_Builder_initBuilder },
     { "nAddAxis", "(JIF)V", (void*) Font_Builder_addAxis },
@@ -254,13 +300,21 @@
     { "nGetReleaseFunc", "()J", (void*) FontBufferHelper_getReleaseFunc },
 };
 
+static const JNINativeMethod gFontFileUtilMethods[] = {
+    { "nGetFontRevision", "(Ljava/nio/ByteBuffer;I)J", (void*) FontFileUtil_getFontRevision },
+    { "nGetFontPostScriptName", "(Ljava/nio/ByteBuffer;I)Ljava/lang/String;",
+        (void*) FontFileUtil_getFontPostScriptName },
+};
+
 int register_android_graphics_fonts_Font(JNIEnv* env) {
     return RegisterMethodsOrDie(env, "android/graphics/fonts/Font$Builder", gFontBuilderMethods,
             NELEM(gFontBuilderMethods)) +
             RegisterMethodsOrDie(env, "android/graphics/fonts/Font", gFontMethods,
             NELEM(gFontMethods)) +
             RegisterMethodsOrDie(env, "android/graphics/fonts/NativeFontBufferHelper",
-            gFontBufferHelperMethods, NELEM(gFontBufferHelperMethods));
+            gFontBufferHelperMethods, NELEM(gFontBufferHelperMethods)) +
+            RegisterMethodsOrDie(env, "android/graphics/fonts/FontFileUtil", gFontFileUtilMethods,
+            NELEM(gFontFileUtilMethods));
 }
 
 namespace fonts {