BufferQueue: add a setMaxAcquiredBufferCount check

This change adds a check to verify the validity of the value passed to
setMaxAcquiredBufferCount.

Change-Id: I39730557aa58261e678bd6e4fce11bab78e98362
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 0a95bb3..3481c6f 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -41,6 +41,10 @@
     enum { INVALID_BUFFER_SLOT = -1 };
     enum { STALE_BUFFER_SLOT = 1, NO_BUFFER_AVAILABLE };
 
+    // When in async mode we reserve two slots in order to guarantee that the
+    // producer and consumer can run asynchronously.
+    enum { MAX_MAX_ACQUIRED_BUFFERS = NUM_BUFFER_SLOTS - 2 };
+
     // ConsumerListener is the interface through which the BufferQueue notifies
     // the consumer of events that the consumer may wish to react to.  Because
     // the consumer will generally have a mutex that is locked during calls from
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 4640149..2eee6f5 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -974,6 +974,11 @@
 status_t BufferQueue::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
     ATRACE_CALL();
     Mutex::Autolock lock(mMutex);
+    if (maxAcquiredBuffers < 1 || maxAcquiredBuffers > MAX_MAX_ACQUIRED_BUFFERS) {
+        ST_LOGE("setMaxAcquiredBufferCount: invalid count specified: %d",
+                maxAcquiredBuffers);
+        return BAD_VALUE;
+    }
     if (mConnectedApi != NO_CONNECTED_API) {
         return INVALID_OPERATION;
     }
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 8601789..817abb4 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -93,4 +93,25 @@
     ASSERT_EQ(INVALID_OPERATION, mBQ->acquireBuffer(&item));
 }
 
+TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithIllegalValues_ReturnsError) {
+    sp<DummyConsumer> dc(new DummyConsumer);
+    mBQ->consumerConnect(dc);
+
+    ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(0));
+    ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(-3));
+    ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(
+            BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
+    ASSERT_EQ(BAD_VALUE, mBQ->setMaxAcquiredBufferCount(100));
+}
+
+TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
+    sp<DummyConsumer> dc(new DummyConsumer);
+    mBQ->consumerConnect(dc);
+
+    ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(1));
+    ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(2));
+    ASSERT_EQ(OK, mBQ->setMaxAcquiredBufferCount(
+            BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
+}
+
 } // namespace android