Merge "Stop using finalizer in Typeface and FontFamily" into pi-dev
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index ed032c7..c7ad2a4 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -51,6 +51,18 @@
     std::vector<minikin::FontVariation> axes;
 };
 
+static inline NativeFamilyBuilder* toNativeBuilder(jlong ptr) {
+    return reinterpret_cast<NativeFamilyBuilder*>(ptr);
+}
+
+static inline FontFamilyWrapper* toFamily(jlong ptr) {
+    return reinterpret_cast<FontFamilyWrapper*>(ptr);
+}
+
+template<typename Ptr> static inline jlong toJLong(Ptr ptr) {
+    return reinterpret_cast<jlong>(ptr);
+}
+
 static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring langs, jint variant) {
     NativeFamilyBuilder* builder;
     if (langs != nullptr) {
@@ -59,15 +71,14 @@
     } else {
         builder = new NativeFamilyBuilder(minikin::registerLocaleList(""), variant);
     }
-    return reinterpret_cast<jlong>(builder);
+    return toJLong(builder);
 }
 
 static jlong FontFamily_create(jlong builderPtr) {
     if (builderPtr == 0) {
         return 0;
     }
-    std::unique_ptr<NativeFamilyBuilder> builder(
-            reinterpret_cast<NativeFamilyBuilder*>(builderPtr));
+    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
     if (builder->fonts.empty()) {
         return 0;
     }
@@ -76,17 +87,23 @@
     if (family->getCoverage().length() == 0) {
         return 0;
     }
-    return reinterpret_cast<jlong>(new FontFamilyWrapper(std::move(family)));
+    return toJLong(new FontFamilyWrapper(std::move(family)));
 }
 
-static void FontFamily_abort(jlong builderPtr) {
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-    delete builder;
+static void releaseBuilder(jlong builderPtr) {
+    delete toNativeBuilder(builderPtr);
 }
 
-static void FontFamily_unref(jlong familyPtr) {
-    FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(familyPtr);
-    delete family;
+static jlong FontFamily_getBuilderReleaseFunc() {
+    return toJLong(&releaseBuilder);
+}
+
+static void releaseFamily(jlong familyPtr) {
+    delete toFamily(familyPtr);
+}
+
+static jlong FontFamily_getFamilyReleaseFunc() {
+    return toJLong(&releaseFamily);
 }
 
 static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, int ttcIndex,
@@ -175,7 +192,7 @@
 static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong builderPtr,
         jobject font, jint ttcIndex, jint weight, jint isItalic) {
     NPE_CHECK_RETURN_ZERO(env, font);
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
+    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
     const void* fontPtr = env->GetDirectBufferAddress(font);
     if (fontPtr == NULL) {
         ALOGE("addFont failed to create font, buffer invalid");
@@ -204,8 +221,7 @@
     NPE_CHECK_RETURN_ZERO(env, jassetMgr);
     NPE_CHECK_RETURN_ZERO(env, jpath);
 
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
-
+    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
     Guarded<AssetManager2>* mgr = AssetManagerForJavaObject(env, jassetMgr);
     if (NULL == mgr) {
         builder->axes.clear();
@@ -249,19 +265,19 @@
 }
 
 static void FontFamily_addAxisValue(jlong builderPtr, jint tag, jfloat value) {
-    NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr);
+    NativeFamilyBuilder* builder = toNativeBuilder(builderPtr);
     builder->axes.push_back({static_cast<minikin::AxisTag>(tag), value});
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 static const JNINativeMethod gFontFamilyMethods[] = {
-    { "nInitBuilder",          "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
-    { "nCreateFamily",         "(J)J", (void*)FontFamily_create },
-    { "nAbort",                "(J)V", (void*)FontFamily_abort },
-    { "nUnrefFamily",          "(J)V", (void*)FontFamily_unref },
-    { "nAddFont",              "(JLjava/nio/ByteBuffer;III)Z", (void*)FontFamily_addFont },
-    { "nAddFontWeightStyle",   "(JLjava/nio/ByteBuffer;III)Z",
+    { "nInitBuilder",           "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder },
+    { "nCreateFamily",          "(J)J", (void*)FontFamily_create },
+    { "nGetBuilderReleaseFunc", "()J", (void*)FontFamily_getBuilderReleaseFunc },
+    { "nGetFamilyReleaseFunc",  "()J", (void*)FontFamily_getFamilyReleaseFunc },
+    { "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 },
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index d67c0b0..34ec365 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -28,8 +28,16 @@
 
 using namespace android;
 
+static inline Typeface* toTypeface(jlong ptr) {
+    return reinterpret_cast<Typeface*>(ptr);
+}
+
+template<typename Ptr> static inline jlong toJLong(Ptr ptr) {
+    return reinterpret_cast<jlong>(ptr);
+}
+
 static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandle, jint style) {
-    Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
+    Typeface* family = toTypeface(familyHandle);
     Typeface* face = Typeface::createRelative(family, (Typeface::Style)style);
     // TODO: the following logic shouldn't be necessary, the above should always succeed.
     // Try to find the closest matching font, using the standard heuristic
@@ -39,13 +47,12 @@
     for (int i = 0; NULL == face && i < 4; i++) {
         face = Typeface::createRelative(family, (Typeface::Style)i);
     }
-    return reinterpret_cast<jlong>(face);
+    return toJLong(face);
 }
 
 static jlong Typeface_createFromTypefaceWithExactStyle(JNIEnv* env, jobject, jlong nativeInstance,
         jint weight, jboolean italic) {
-    Typeface* baseTypeface = reinterpret_cast<Typeface*>(nativeInstance);
-    return reinterpret_cast<jlong>(Typeface::createAbsolute(baseTypeface, weight, italic));
+    return toJLong(Typeface::createAbsolute(toTypeface(nativeInstance), weight, italic));
 }
 
 static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
@@ -60,30 +67,30 @@
         AxisHelper axis(env, axisObject);
         variations.push_back(minikin::FontVariation(axis.getTag(), axis.getStyleValue()));
     }
-    Typeface* baseTypeface = reinterpret_cast<Typeface*>(familyHandle);
-    Typeface* result = Typeface::createFromTypefaceWithVariation(baseTypeface, variations);
-    return reinterpret_cast<jlong>(result);
+    return toJLong(Typeface::createFromTypefaceWithVariation(toTypeface(familyHandle), variations));
 }
 
 static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
-    Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
-    Typeface* face = Typeface::createWithDifferentBaseWeight(family, weight);
-    return reinterpret_cast<jlong>(face);
+    return toJLong(Typeface::createWithDifferentBaseWeight(toTypeface(familyHandle), weight));
 }
 
-static void Typeface_unref(JNIEnv* env, jobject obj, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    delete face;
+static void releaseFunc(jlong ptr) {
+    delete toTypeface(ptr);
 }
 
-static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    return face->fAPIStyle;
+// CriticalNative
+static jlong Typeface_getReleaseFunc() {
+    return toJLong(&releaseFunc);
 }
 
-static jint Typeface_getWeight(JNIEnv* env, jobject obj, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    return face->fStyle.weight();
+// CriticalNative
+static jint Typeface_getStyle(jlong faceHandle) {
+    return toTypeface(faceHandle)->fAPIStyle;
+}
+
+// CriticalNative
+static jint Typeface_getWeight(jlong faceHandle) {
+    return toTypeface(faceHandle)->fStyle.weight();
 }
 
 static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray,
@@ -95,17 +102,16 @@
         FontFamilyWrapper* family = reinterpret_cast<FontFamilyWrapper*>(families[i]);
         familyVec.emplace_back(family->family);
     }
-    return reinterpret_cast<jlong>(
-            Typeface::createFromFamilies(std::move(familyVec), weight, italic));
+    return toJLong(Typeface::createFromFamilies(std::move(familyVec), weight, italic));
 }
 
-static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
-    Typeface::setDefault(face);
+// CriticalNative
+static void Typeface_setDefault(jlong faceHandle) {
+    Typeface::setDefault(toTypeface(faceHandle));
 }
 
 static jobject Typeface_getSupportedAxes(JNIEnv *env, jobject, jlong faceHandle) {
-    Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+    Typeface* face = toTypeface(faceHandle);
     const std::unordered_set<minikin::AxisTag>& tagSet = face->fFontCollection->getSupportedTags();
     const size_t length = tagSet.size();
     if (length == 0) {
@@ -131,7 +137,7 @@
     { "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
             (void*)Typeface_createFromTypefaceWithVariation },
     { "nativeCreateWeightAlias",  "(JI)J", (void*)Typeface_createWeightAlias },
-    { "nativeUnref",              "(J)V",  (void*)Typeface_unref },
+    { "nativeGetReleaseFunc",     "()J",  (void*)Typeface_getReleaseFunc },
     { "nativeGetStyle",           "(J)I",  (void*)Typeface_getStyle },
     { "nativeGetWeight",      "(J)I",  (void*)Typeface_getWeight },
     { "nativeCreateFromArray",    "([JII)J",
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index e7cfcfd..c69eb32 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -24,6 +24,8 @@
 
 import dalvik.annotation.optimization.CriticalNative;
 
+import libcore.util.NativeAllocationRegistry;
+
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
@@ -38,6 +40,14 @@
 
     private static String TAG = "FontFamily";
 
+    private static final NativeAllocationRegistry sBuilderRegistry = new NativeAllocationRegistry(
+            FontFamily.class.getClassLoader(), nGetBuilderReleaseFunc(), 64);
+
+    private @Nullable Runnable mNativeBuilderCleaner;
+
+    private static final NativeAllocationRegistry sFamilyRegistry = new NativeAllocationRegistry(
+            FontFamily.class.getClassLoader(), nGetFamilyReleaseFunc(), 64);
+
     /**
      * @hide
      */
@@ -48,6 +58,7 @@
 
     public FontFamily() {
         mBuilderPtr = nInitBuilder(null, 0);
+        mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
     }
 
     public FontFamily(@Nullable String[] langs, int variant) {
@@ -60,6 +71,7 @@
             langsString = TextUtils.join(",", langs);
         }
         mBuilderPtr = nInitBuilder(langsString, variant);
+        mNativeBuilderCleaner = sBuilderRegistry.registerNativeAllocation(this, mBuilderPtr);
     }
 
     /**
@@ -73,7 +85,11 @@
             throw new IllegalStateException("This FontFamily is already frozen");
         }
         mNativePtr = nCreateFamily(mBuilderPtr);
+        mNativeBuilderCleaner.run();
         mBuilderPtr = 0;
+        if (mNativePtr != 0) {
+            sFamilyRegistry.registerNativeAllocation(this, mNativePtr);
+        }
         return mNativePtr != 0;
     }
 
@@ -81,24 +97,10 @@
         if (mBuilderPtr == 0) {
             throw new IllegalStateException("This FontFamily is already frozen or abandoned");
         }
-        nAbort(mBuilderPtr);
+        mNativeBuilderCleaner.run();
         mBuilderPtr = 0;
     }
 
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            if (mNativePtr != 0) {
-                nUnrefFamily(mNativePtr);
-            }
-            if (mBuilderPtr != 0) {
-                nAbort(mBuilderPtr);
-            }
-        } finally {
-            super.finalize();
-        }
-    }
-
     public boolean addFont(String path, int ttcIndex, FontVariationAxis[] axes, int weight,
             int italic) {
         if (mBuilderPtr == 0) {
@@ -171,10 +173,10 @@
     private static native long nCreateFamily(long mBuilderPtr);
 
     @CriticalNative
-    private static native void nAbort(long mBuilderPtr);
+    private static native long nGetBuilderReleaseFunc();
 
     @CriticalNative
-    private static native void nUnrefFamily(long nativePtr);
+    private static native long nGetFamilyReleaseFunc();
     // By passing -1 to weigth argument, the weight value is resolved by OS/2 table in the font.
     // By passing -1 to italic argument, the italic value is resolved by OS/2 table in the font.
     private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex,
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 38beebd..f27c11d 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -42,6 +42,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
+import dalvik.annotation.optimization.CriticalNative;
+
+import libcore.util.NativeAllocationRegistry;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.File;
@@ -71,6 +75,9 @@
 
     private static String TAG = "Typeface";
 
+    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
+            Typeface.class.getClassLoader(), nativeGetReleaseFunc(), 64);
+
     /** The default NORMAL typeface object */
     public static final Typeface DEFAULT;
     /**
@@ -911,6 +918,7 @@
         }
 
         native_instance = ni;
+        sRegistry.registerNativeAllocation(this, native_instance);
         mStyle = nativeGetStyle(ni);
         mWeight = nativeGetWeight(ni);
     }
@@ -1120,16 +1128,6 @@
     }
 
     @Override
-    protected void finalize() throws Throwable {
-        try {
-            nativeUnref(native_instance);
-            native_instance = 0;  // Other finalizers can still call us.
-        } finally {
-            super.finalize();
-        }
-    }
-
-    @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
@@ -1173,10 +1171,18 @@
     private static native long nativeCreateFromTypefaceWithVariation(
             long native_instance, List<FontVariationAxis> axes);
     private static native long nativeCreateWeightAlias(long native_instance, int weight);
-    private static native void nativeUnref(long native_instance);
-    private static native int  nativeGetStyle(long native_instance);
-    private static native int  nativeGetWeight(long native_instance);
     private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
-    private static native void nativeSetDefault(long native_instance);
     private static native int[] nativeGetSupportedAxes(long native_instance);
+
+    @CriticalNative
+    private static native void nativeSetDefault(long nativePtr);
+
+    @CriticalNative
+    private static native int  nativeGetStyle(long nativePtr);
+
+    @CriticalNative
+    private static native int  nativeGetWeight(long nativePtr);
+
+    @CriticalNative
+    private static native long nativeGetReleaseFunc();
 }