Use AHardwareBuffer_getAllocationSize

Test: android.graphics.cts.BitmapTest#testGetAllocationSizeWrappedBuffer
Bug: 280338223
Change-Id: I3baf204e59988c11a58a06fcb90a5e14525492e9
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 34af1f9..db58147 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -129,6 +129,7 @@
                 "libandroidfw",
                 "libcrypto",
                 "libsync",
+                "libui",
             ],
             static_libs: [
                 "libEGL_blobCache",
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index b3eaa0c..92d875b 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -18,6 +18,10 @@
 #include "HardwareBitmapUploader.h"
 #include "Properties.h"
 #ifdef __ANDROID__  // Layoutlib does not support render thread
+#include <private/android/AHardwareBufferHelpers.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/GraphicBufferMapper.h>
+
 #include "renderthread/RenderProxy.h"
 #endif
 #include "utils/Color.h"
@@ -51,6 +55,34 @@
 
 namespace android {
 
+#ifdef __ANDROID__
+static uint64_t AHardwareBuffer_getAllocationSize(AHardwareBuffer* aHardwareBuffer) {
+    GraphicBuffer* buffer = AHardwareBuffer_to_GraphicBuffer(aHardwareBuffer);
+    auto& mapper = GraphicBufferMapper::get();
+    uint64_t size = 0;
+    auto err = mapper.getAllocationSize(buffer->handle, &size);
+    if (err == OK) {
+        if (size > 0) {
+            return size;
+        } else {
+            ALOGW("Mapper returned size = 0 for buffer format: 0x%x size: %d x %d", buffer->format,
+                  buffer->width, buffer->height);
+            // Fall-through to estimate
+        }
+    }
+
+    // Estimation time!
+    // Stride could be = 0 if it's ill-defined (eg, compressed buffer), in which case we use the
+    // width of the buffer instead
+    size = std::max(buffer->width, buffer->stride) * buffer->height;
+    // Require bpp to be at least 1. This is too low for many formats, but it's better than 0
+    // Also while we could make increasingly better estimates, the reality is that mapper@4
+    // should be common enough at this point that we won't ever hit this anyway
+    size *= std::max(1u, bytesPerPixel(buffer->format));
+    return size;
+}
+#endif
+
 bool Bitmap::computeAllocationSize(size_t rowBytes, int height, size_t* size) {
     return 0 <= height && height <= std::numeric_limits<size_t>::max() &&
            !__builtin_mul_overflow(rowBytes, (size_t)height, size) &&
@@ -261,6 +293,7 @@
         , mPalette(palette)
         , mPaletteGenerationId(getGenerationID()) {
     mPixelStorage.hardware.buffer = buffer;
+    mPixelStorage.hardware.size = AHardwareBuffer_getAllocationSize(buffer);
     AHardwareBuffer_acquire(buffer);
     setImmutable();  // HW bitmaps are always immutable
     mImage = SkImage::MakeFromAHardwareBuffer(buffer, mInfo.alphaType(), mInfo.refColorSpace());
@@ -317,6 +350,10 @@
             return mPixelStorage.heap.size;
         case PixelStorageType::Ashmem:
             return mPixelStorage.ashmem.size;
+#ifdef __ANDROID__
+        case PixelStorageType::Hardware:
+            return mPixelStorage.hardware.size;
+#endif
         default:
             return rowBytes() * height();
     }
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 912d311..dd344e2 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -221,6 +221,7 @@
 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
         struct {
             AHardwareBuffer* buffer;
+            uint64_t size;
         } hardware;
 #endif
     } mPixelStorage;