Adding lock function that obtains bytesPerPixel and bytesPerStride

Bug: 123423521
Test: build, boot, manual
Change-Id: I480d60fe4975c5ffee6d6c253c37ffd20cea79c3
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 52fc9d5..bf80481 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -93,8 +93,57 @@
     outDesc->rfu1 = 0;
 }
 
+int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
+        int32_t fence, const ARect* rect, void** outVirtualAddress,
+        int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
+    if (!buffer) return BAD_VALUE;
+
+    if (usage & ~(AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
+                  AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) {
+        ALOGE("Invalid usage flags passed to AHardwareBuffer_lock; only "
+                "AHARDWAREBUFFER_USAGE_CPU_* flags are allowed");
+        return BAD_VALUE;
+    }
+
+    usage = AHardwareBuffer_convertToGrallocUsageBits(usage);
+    GraphicBuffer* gbuffer = AHardwareBuffer_to_GraphicBuffer(buffer);
+
+    //Mapper implementations before 3.0 will not return bytes per pixel or
+    //bytes per stride information.
+    if (gbuffer->getBufferMapperVersion() == GraphicBufferMapper::Version::GRALLOC_2) {
+        ALOGE("Mapper versions before 3.0 cannot retrieve bytes per pixel and bytes per stride info");
+        return INVALID_OPERATION;
+    }
+
+    if (gbuffer->getLayerCount() > 1) {
+        ALOGE("Buffer with multiple layers passed to AHardwareBuffer_lock; "
+                "only buffers with one layer are allowed");
+        return INVALID_OPERATION;
+    }
+
+    Rect bounds;
+    if (!rect) {
+        bounds.set(Rect(gbuffer->getWidth(), gbuffer->getHeight()));
+    } else {
+        bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom));
+    }
+    int result = gbuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence, outBytesPerPixel, outBytesPerStride);
+
+    // if hardware returns -1 for bytes per pixel or bytes per stride, we fail
+    // and unlock the buffer
+    if (*outBytesPerPixel == -1 || *outBytesPerStride == -1) {
+        gbuffer->unlock();
+        return INVALID_OPERATION;
+    }
+
+    return result;
+}
+
 int AHardwareBuffer_lock(AHardwareBuffer* buffer, uint64_t usage,
-        int32_t fence, const ARect* rect, void** outVirtualAddress) {
+                         int32_t fence, const ARect* rect, void** outVirtualAddress) {
+    int32_t bytesPerPixel;
+    int32_t bytesPerStride;
+
     if (!buffer) return BAD_VALUE;
 
     if (usage & ~(AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
@@ -119,7 +168,7 @@
     } else {
         bounds.set(Rect(rect->left, rect->top, rect->right, rect->bottom));
     }
-    return gbuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence);
+    return gbuffer->lockAsync(usage, usage, bounds, outVirtualAddress, fence, &bytesPerPixel, &bytesPerStride);
 }
 
 int AHardwareBuffer_lockPlanes(AHardwareBuffer* buffer, uint64_t usage,
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 02c7c1b..165b75a 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -422,6 +422,18 @@
         int32_t fence, const ARect* rect, void** outVirtualAddress) __INTRODUCED_IN(26);
 
 /**
+ * Lock an AHardwareBuffer for direct CPU access.
+ *
+ * This function is the same as the above lock function, but passes back
+ * additional information about the bytes per pixel and the bytes per stride
+ * of the locked buffer.  If the bytes per pixel or bytes per stride are unknown
+ * or variable, or if the underlying mapper implementation does not support returning
+ * additional information, then this call will fail with INVALID_OPERATION
+ */
+int AHardwareBuffer_lockAndGetInfo(AHardwareBuffer* buffer, uint64_t usage,
+        int32_t fence, const ARect* rect, void** outVirtualAddress,
+        int32_t* outBytesPerPixel, int32_t* outBytesPerStride) __INTRODUCED_IN(29);
+/**
  * Lock a potentially multi-planar AHardwareBuffer for direct CPU access.
  *
  * This function is similar to AHardwareBuffer_lock, but can lock multi-planar
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index a796e97..23a05f3 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -7,6 +7,7 @@
     AHardwareBuffer_getNativeHandle; # vndk
     AHardwareBuffer_isSupported; # introduced=29
     AHardwareBuffer_lock;
+    AHardwareBuffer_lockAndGetInfo; # introduced=29
     AHardwareBuffer_recvHandleFromUnixSocket;
     AHardwareBuffer_release;
     AHardwareBuffer_sendHandleToUnixSocket;
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index 06981c3..25b7247 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -53,6 +53,9 @@
     mMapper = std::make_unique<const Gralloc3Mapper>();
     if (!mMapper->isLoaded()) {
         mMapper = std::make_unique<const Gralloc2Mapper>();
+        mMapperVersion = Version::GRALLOC_2;
+    } else {
+        mMapperVersion = Version::GRALLOC_3;
     }
 
     if (!mMapper->isLoaded()) {
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index e0c6558..1c88777 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -24,6 +24,7 @@
 
 #include <android/hardware_buffer.h>
 #include <ui/ANativeObjectBase.h>
+#include <ui/GraphicBufferMapper.h>
 #include <ui/PixelFormat.h>
 #include <ui/Rect.h>
 #include <utils/Flattenable.h>
@@ -214,6 +215,10 @@
     status_t flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const;
     status_t unflatten(void const*& buffer, size_t& size, int const*& fds, size_t& count);
 
+    GraphicBufferMapper::Version getBufferMapperVersion() const {
+        return mBufferMapper.getMapperVersion();
+    }
+
 #ifndef LIBUI_IN_VNDK
     // Returns whether this GraphicBuffer is backed by BufferHubBuffer.
     bool isBufferHubBuffer() const;
diff --git a/libs/ui/include/ui/GraphicBufferMapper.h b/libs/ui/include/ui/GraphicBufferMapper.h
index 77c99cc..2461454 100644
--- a/libs/ui/include/ui/GraphicBufferMapper.h
+++ b/libs/ui/include/ui/GraphicBufferMapper.h
@@ -41,6 +41,10 @@
 class GraphicBufferMapper : public Singleton<GraphicBufferMapper>
 {
 public:
+    enum Version {
+        GRALLOC_2,
+        GRALLOC_3,
+    };
     static void preloadHal();
     static inline GraphicBufferMapper& get() { return getInstance(); }
 
@@ -85,12 +89,16 @@
         return reinterpret_cast<const GrallocMapper&>(*mMapper);
     }
 
+    Version getMapperVersion() const { return mMapperVersion; }
+
 private:
     friend class Singleton<GraphicBufferMapper>;
 
     GraphicBufferMapper();
 
     std::unique_ptr<const GrallocMapper> mMapper;
+
+    Version mMapperVersion;
 };
 
 // ---------------------------------------------------------------------------