Surface: Provide more useful/platform-y buffer methods

These will be easier to use than having to use ANativeWindow
equivalents.

BYPASS_IGBP_IGBC_API_REASON=warren buffers

Flag: com.android.graphics.libgui.flags.wb_platform_api_improvements
Bug: 340933794
Test: new libgui_test tests, atest
Change-Id: I0343abb45aadf708ef6115fa108a3b4c402cfd47
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 88168e3..0aa5216 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -24,23 +24,26 @@
 #include <android/gui/ISurfaceComposer.h>
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <binder/ProcessState.h>
+#include <com_android_graphics_libgui_flags.h>
 #include <configstore/Utils.h>
 #include <gui/AidlStatusUtil.h>
 #include <gui/BufferItemConsumer.h>
+#include <gui/CpuConsumer.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SyncScreenCaptureListener.h>
-#include <inttypes.h>
 #include <private/gui/ComposerService.h>
 #include <private/gui/ComposerServiceAIDL.h>
 #include <sys/types.h>
 #include <ui/BufferQueueDefs.h>
 #include <ui/DisplayMode.h>
+#include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 #include <utils/Errors.h>
 #include <utils/String8.h>
 
+#include <cstddef>
 #include <limits>
 #include <thread>
 
@@ -2225,4 +2228,64 @@
     ASSERT_EQ(NO_ERROR, surface->disconnect(NATIVE_WINDOW_API_CPU));
 }
 
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
+TEST_F(SurfaceTest, PlatformBufferMethods) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<CpuConsumer> cpuConsumer = sp<CpuConsumer>::make(consumer, 1);
+    sp<Surface> surface = sp<Surface>::make(producer);
+    sp<StubSurfaceListener> listener = sp<StubSurfaceListener>::make();
+    sp<GraphicBuffer> buffer;
+    sp<Fence> fence;
+
+    EXPECT_EQ(OK,
+              surface->connect(NATIVE_WINDOW_API_CPU, listener, /* reportBufferRemoval */ false));
+
+    //
+    // Verify nullptrs are handled safely:
+    //
+
+    EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer((sp<GraphicBuffer>*)nullptr, nullptr));
+    EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer((sp<GraphicBuffer>*)nullptr, &fence));
+    EXPECT_EQ(BAD_VALUE, surface->dequeueBuffer(&buffer, nullptr));
+    EXPECT_EQ(BAD_VALUE, surface->queueBuffer(nullptr, nullptr));
+    EXPECT_EQ(BAD_VALUE, surface->detachBuffer(nullptr));
+
+    //
+    // Verify dequeue/queue:
+    //
+
+    EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence));
+    EXPECT_NE(nullptr, buffer);
+    EXPECT_EQ(OK, surface->queueBuffer(buffer, fence));
+
+    //
+    // Verify dequeue/detach:
+    //
+
+    wp<GraphicBuffer> weakBuffer;
+    {
+        EXPECT_EQ(OK, surface->dequeueBuffer(&buffer, &fence));
+
+        EXPECT_EQ(OK, surface->detachBuffer(buffer));
+
+        weakBuffer = buffer;
+        buffer = nullptr;
+    }
+    EXPECT_EQ(nullptr, weakBuffer.promote()) << "Weak buffer still held by Surface.";
+
+    //
+    // Verify detach without borrowing the buffer does not work:
+    //
+
+    sp<GraphicBuffer> heldTooLongBuffer;
+    EXPECT_EQ(OK, surface->dequeueBuffer(&heldTooLongBuffer, &fence));
+    EXPECT_EQ(OK, surface->queueBuffer(heldTooLongBuffer));
+    EXPECT_EQ(BAD_VALUE, surface->detachBuffer(heldTooLongBuffer));
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
 } // namespace android