Use buffer size for NativeAllocationRegistry instead of a fixed value

When calling NativeAllocationRegistry for HardwareBuffer, it needs the
correct size so GC knows how much memory has been allocated and when to
run. The current behavior uses a fixed size so it's likely the buffer is
actually consuming more memory than what GC thinks.

Test: atest ContentCapturePerfTests:LoginTest
Bug: 168149157
Bug: 168154840
Change-Id: Ife174478b2b76214b438de2757289a973330c979
diff --git a/core/java/android/hardware/HardwareBuffer.java b/core/java/android/hardware/HardwareBuffer.java
index dd34930..a9b6132 100644
--- a/core/java/android/hardware/HardwareBuffer.java
+++ b/core/java/android/hardware/HardwareBuffer.java
@@ -26,6 +26,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import dalvik.annotation.optimization.CriticalNative;
 import dalvik.annotation.optimization.FastNative;
 import dalvik.system.CloseGuard;
 
@@ -141,8 +142,6 @@
     /** Usage: The buffer contains a complete mipmap hierarchy */
     public static final long USAGE_GPU_MIPMAP_COMPLETE    = 1 << 26;
 
-    // The approximate size of a native AHardwareBuffer object.
-    private static final long NATIVE_HARDWARE_BUFFER_SIZE = 232;
     /**
      * Creates a new <code>HardwareBuffer</code> instance.
      *
@@ -239,10 +238,10 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private HardwareBuffer(long nativeObject) {
         mNativeObject = nativeObject;
-
+        long bufferSize = nEstimateSize(nativeObject);
         ClassLoader loader = HardwareBuffer.class.getClassLoader();
         NativeAllocationRegistry registry = new NativeAllocationRegistry(
-                loader, nGetNativeFinalizer(), NATIVE_HARDWARE_BUFFER_SIZE);
+                loader, nGetNativeFinalizer(), bufferSize);
         mCleaner = registry.registerNativeAllocation(this, mNativeObject);
         mCloseGuard.open("close");
     }
@@ -429,4 +428,6 @@
     private static native long nGetUsage(long nativeObject);
     private static native boolean nIsSupported(int width, int height, int format, int layers,
             long usage);
+    @CriticalNative
+    private static native long nEstimateSize(long nativeObject);
 }
diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp
index e78e08e..2944f72 100644
--- a/core/jni/android_hardware_HardwareBuffer.cpp
+++ b/core/jni/android_hardware_HardwareBuffer.cpp
@@ -30,8 +30,9 @@
 
 #include <binder/Parcel.h>
 
-#include <ui/GraphicBuffer.h>
 #include <private/gui/ComposerService.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/PixelFormat.h>
 
 #include <hardware/gralloc1.h>
 #include <grallocusage/GrallocUsageConversion.h>
@@ -166,6 +167,20 @@
     return AHardwareBuffer_convertFromGrallocUsageBits(buffer->getUsage());
 }
 
+static jlong android_hardware_HardwareBuffer_estimateSize(jlong nativeObject) {
+    GraphicBuffer* buffer = GraphicBufferWrapper_to_GraphicBuffer(nativeObject);
+
+    uint32_t bpp = bytesPerPixel(buffer->getPixelFormat());
+    if (bpp == 0) {
+        // If the pixel format is not recognized, use 1 as default.
+        bpp = 1;
+    }
+
+    const uint32_t bufferStride =
+            buffer->getStride() > 0 ? buffer->getStride() : buffer->getWidth();
+    return static_cast<jlong>(buffer->getHeight() * bufferStride * bpp);
+}
+
 // ----------------------------------------------------------------------------
 // Serialization
 // ----------------------------------------------------------------------------
@@ -247,6 +262,7 @@
 
 const char* const kClassPathName = "android/hardware/HardwareBuffer";
 
+// clang-format off
 static const JNINativeMethod gMethods[] = {
     { "nCreateHardwareBuffer",  "(IIIIJ)J",
             (void*) android_hardware_HardwareBuffer_create },
@@ -267,7 +283,11 @@
     { "nGetFormat", "(J)I",     (void*) android_hardware_HardwareBuffer_getFormat },
     { "nGetLayers", "(J)I",     (void*) android_hardware_HardwareBuffer_getLayers },
     { "nGetUsage", "(J)J",      (void*) android_hardware_HardwareBuffer_getUsage },
+
+    // --------------- @CriticalNative ----------------------
+    { "nEstimateSize", "(J)J",  (void*) android_hardware_HardwareBuffer_estimateSize },
 };
+// clang-format on
 
 int register_android_hardware_HardwareBuffer(JNIEnv* env) {
     int err = RegisterMethodsOrDie(env, kClassPathName, gMethods,