BufferQueue: Test remote producer and consumer

Adds a test that puts the BufferQueue into its own process and
connects to it over remote binder interfaces. This exposed the fact
that while IGBC was technically binderized, it didn't actually work
when flattened, so this change also fixes that.

Change-Id: I728cdb662a4273ddd3440ed6040a12560313fe68
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 3598a86..cdd06f3 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -71,11 +71,11 @@
     size_t c = 0;
     if (mGraphicBuffer != 0) {
         c += mGraphicBuffer->getFlattenedSize();
-        FlattenableUtils::align<4>(c);
+        c = FlattenableUtils::align<4>(c);
     }
     if (mFence != 0) {
         c += mFence->getFlattenedSize();
-        FlattenableUtils::align<4>(c);
+        c = FlattenableUtils::align<4>(c);
     }
     return sizeof(int32_t) + c + getPodSize();
 }
@@ -91,11 +91,21 @@
     return c;
 }
 
+static void writeBoolAsInt(void*& buffer, size_t& size, bool b) {
+    FlattenableUtils::write(buffer, size, static_cast<int32_t>(b));
+}
+
+static bool readBoolFromInt(void const*& buffer, size_t& size) {
+    int32_t i;
+    FlattenableUtils::read(buffer, size, i);
+    return static_cast<bool>(i);
+}
+
 status_t IGraphicBufferConsumer::BufferItem::flatten(
         void*& buffer, size_t& size, int*& fds, size_t& count) const {
 
     // make sure we have enough space
-    if (count < BufferItem::getFlattenedSize()) {
+    if (size < BufferItem::getFlattenedSize()) {
         return NO_MEMORY;
     }
 
@@ -128,12 +138,12 @@
     FlattenableUtils::write(buffer, size, mTransform);
     FlattenableUtils::write(buffer, size, mScalingMode);
     FlattenableUtils::write(buffer, size, mTimestamp);
-    FlattenableUtils::write(buffer, size, mIsAutoTimestamp);
+    writeBoolAsInt(buffer, size, mIsAutoTimestamp);
     FlattenableUtils::write(buffer, size, mFrameNumber);
     FlattenableUtils::write(buffer, size, mBuf);
-    FlattenableUtils::write(buffer, size, mIsDroppable);
-    FlattenableUtils::write(buffer, size, mAcquireCalled);
-    FlattenableUtils::write(buffer, size, mTransformToDisplayInverse);
+    writeBoolAsInt(buffer, size, mIsDroppable);
+    writeBoolAsInt(buffer, size, mAcquireCalled);
+    writeBoolAsInt(buffer, size, mTransformToDisplayInverse);
 
     return NO_ERROR;
 }
@@ -170,12 +180,12 @@
     FlattenableUtils::read(buffer, size, mTransform);
     FlattenableUtils::read(buffer, size, mScalingMode);
     FlattenableUtils::read(buffer, size, mTimestamp);
-    FlattenableUtils::read(buffer, size, mIsAutoTimestamp);
+    mIsAutoTimestamp = readBoolFromInt(buffer, size);
     FlattenableUtils::read(buffer, size, mFrameNumber);
     FlattenableUtils::read(buffer, size, mBuf);
-    FlattenableUtils::read(buffer, size, mIsDroppable);
-    FlattenableUtils::read(buffer, size, mAcquireCalled);
-    FlattenableUtils::read(buffer, size, mTransformToDisplayInverse);
+    mIsDroppable = readBoolFromInt(buffer, size);
+    mAcquireCalled = readBoolFromInt(buffer, size);
+    mTransformToDisplayInverse = readBoolFromInt(buffer, size);
 
     return NO_ERROR;
 }
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 5aa34a5..7943476 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -24,7 +24,9 @@
 
 #include <ui/GraphicBuffer.h>
 
+#include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
 #include <gui/BufferQueue.h>
 
 namespace android {
@@ -32,20 +34,12 @@
 class BufferQueueTest : public ::testing::Test {
 
 public:
-    static const String16 PRODUCER_NAME;
-    static const String16 CONSUMER_NAME;
-
 protected:
     BufferQueueTest() {
         const ::testing::TestInfo* const testInfo =
             ::testing::UnitTest::GetInstance()->current_test_info();
         ALOGV("Begin test: %s.%s", testInfo->test_case_name(),
                 testInfo->name());
-
-        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
-        sp<IServiceManager> serviceManager = defaultServiceManager();
-        serviceManager->addService(PRODUCER_NAME, mProducer.get());
-        serviceManager->addService(CONSUMER_NAME, mConsumer.get());
     }
 
     ~BufferQueueTest() {
@@ -62,12 +56,13 @@
         ASSERT_GE(*bufferCount, 0);
     }
 
-    sp<BnGraphicBufferProducer> mProducer;
-    sp<BnGraphicBufferConsumer> mConsumer;
-};
+    void createBufferQueue() {
+        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+    }
 
-const String16 BufferQueueTest::PRODUCER_NAME = String16("BQTestProducer");
-const String16 BufferQueueTest::CONSUMER_NAME = String16("BQTestConsumer");
+    sp<IGraphicBufferProducer> mProducer;
+    sp<IGraphicBufferConsumer> mConsumer;
+};
 
 struct DummyConsumer : public BnConsumerListener {
     virtual void onFrameAvailable() {}
@@ -75,7 +70,74 @@
     virtual void onSidebandStreamChanged() {}
 };
 
+// XXX: Tests that fork a process to hold the BufferQueue must run before tests
+// that use a local BufferQueue, or else Binder will get unhappy
+TEST_F(BufferQueueTest, BufferQueueInAnotherProcess) {
+    const String16 PRODUCER_NAME = String16("BQTestProducer");
+    const String16 CONSUMER_NAME = String16("BQTestConsumer");
+
+    pid_t forkPid = fork();
+    ASSERT_NE(forkPid, -1);
+
+    if (forkPid == 0) {
+        // Child process
+        sp<BnGraphicBufferProducer> producer;
+        sp<BnGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+        sp<IServiceManager> serviceManager = defaultServiceManager();
+        serviceManager->addService(PRODUCER_NAME, producer.get());
+        serviceManager->addService(CONSUMER_NAME, consumer.get());
+        ProcessState::self()->startThreadPool();
+        IPCThreadState::self()->joinThreadPool();
+        LOG_ALWAYS_FATAL("Shouldn't be here");
+    }
+
+    sp<IServiceManager> serviceManager = defaultServiceManager();
+    sp<IBinder> binderProducer =
+        serviceManager->getService(PRODUCER_NAME);
+    mProducer = interface_cast<IGraphicBufferProducer>(binderProducer);
+    EXPECT_TRUE(mProducer != NULL);
+    sp<IBinder> binderConsumer =
+        serviceManager->getService(CONSUMER_NAME);
+    mConsumer = interface_cast<IGraphicBufferConsumer>(binderConsumer);
+    EXPECT_TRUE(mConsumer != NULL);
+
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK,
+            mProducer->connect(NULL, NATIVE_WINDOW_API_CPU, false, &output));
+
+    int slot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+                    GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+
+    uint32_t* dataIn;
+    ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
+            reinterpret_cast<void**>(&dataIn)));
+    *dataIn = 0x12345678;
+    ASSERT_EQ(OK, buffer->unlock());
+
+    IGraphicBufferProducer::QueueBufferInput input(0, false, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+    IGraphicBufferConsumer::BufferItem item;
+    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+
+    uint32_t* dataOut;
+    ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
+            reinterpret_cast<void**>(&dataOut)));
+    ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
+}
+
 TEST_F(BufferQueueTest, AcquireBuffer_ExceedsMaxAcquireCount_Fails) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
     IGraphicBufferProducer::QueueBufferOutput qbo;
@@ -109,6 +171,7 @@
 }
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
 
@@ -125,6 +188,7 @@
 }
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
 
@@ -139,6 +203,7 @@
 }
 
 TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -187,9 +252,11 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
 TEST_F(BufferQueueTest, DetachAndReattachOnConsumerSide) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -243,9 +310,11 @@
     ASSERT_EQ(OK, buffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, buffer->unlock());
 }
 
 TEST_F(BufferQueueTest, MoveFromConsumerToProducer) {
+    createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
     ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
     IGraphicBufferProducer::QueueBufferOutput output;
@@ -283,6 +352,7 @@
     ASSERT_EQ(OK, item.mGraphicBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN,
             reinterpret_cast<void**>(&dataOut)));
     ASSERT_EQ(*dataOut, 0x12345678);
+    ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 }
 
 } // namespace android