Allow the same producer to gain a buffer twice.

This change makes the same producer gaining the same buffer the second
time a no-op, and prevent other clients of the buffer from gaining it.

Currently, EALREADY error will return if a producer gain a buffer which
is already gained by the producer. Problem: there is an actual use case
in passthrough processor that a producer may need to gain a buffer to
mimic a "release" of a buffer in the consumer point of view.

Test: buffer_hub-test
Bug: 118718713
Change-Id: If958c95165a5ad62f51c46b01fa43b576d3b20ae
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 2d9a42b..9bcfaa1 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -212,9 +212,8 @@
   LocalHandle fence;
   EXPECT_EQ(0, p->GainAsync());
 
-  // Acquire and gain in gained state should fail.
+  // Acquire in gained state should fail.
   EXPECT_EQ(-EBUSY, c->Acquire(&fence));
-  EXPECT_EQ(-EALREADY, p->Gain(&fence));
 
   // Post in gained state should succeed.
   EXPECT_EQ(0, p->Post(LocalHandle()));
@@ -242,9 +241,8 @@
   // Gain in released state should succeed.
   EXPECT_EQ(0, p->Gain(&fence));
 
-  // Acquire and gain in gained state should fail.
+  // Acquire in gained state should fail.
   EXPECT_EQ(-EBUSY, c->Acquire(&fence));
-  EXPECT_EQ(-EALREADY, p->Gain(&fence));
 }
 
 TEST_F(LibBufferHubTest, TestAsyncStateTransitions) {
@@ -259,10 +257,9 @@
   LocalHandle invalid_fence;
   EXPECT_EQ(0, p->GainAsync());
 
-  // Acquire and gain in gained state should fail.
+  // Acquire in gained state should fail.
   EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
   EXPECT_FALSE(invalid_fence.IsValid());
-  EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
   EXPECT_FALSE(invalid_fence.IsValid());
 
   // Post in gained state should succeed.
@@ -309,8 +306,15 @@
   // Acquire and gain in gained state should fail.
   EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
   EXPECT_FALSE(invalid_fence.IsValid());
-  EXPECT_EQ(-EALREADY, p->GainAsync(&metadata, &invalid_fence));
-  EXPECT_FALSE(invalid_fence.IsValid());
+}
+
+TEST_F(LibBufferHubTest, TestGainTwiceByTheSameProducer) {
+  std::unique_ptr<ProducerBuffer> p = ProducerBuffer::Create(
+      kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
+  ASSERT_TRUE(p.get() != nullptr);
+
+  ASSERT_EQ(0, p->GainAsync());
+  ASSERT_EQ(0, p->GainAsync());
 }
 
 TEST_F(LibBufferHubTest, TestGainPostedBuffer) {
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index 1bfdc8f..c177970 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -172,9 +172,10 @@
   if (BufferHubDefs::IsClientGained(current_buffer_state,
                                     client_state_mask())) {
     ALOGI("%s: already gained id=%d.", __FUNCTION__, id());
-    return -EALREADY;
+    return 0;
   }
   if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
+      BufferHubDefs::AnyClientGained(current_buffer_state) ||
       (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
        !gain_posted_buffer)) {
     ALOGE("%s: not released id=%d state=%" PRIx64 ".", __FUNCTION__, id(),
@@ -196,6 +197,7 @@
         __FUNCTION__, current_buffer_state, updated_buffer_state);
 
     if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
+        BufferHubDefs::AnyClientGained(current_buffer_state) ||
         (BufferHubDefs::AnyClientPosted(current_buffer_state) &&
          !gain_posted_buffer)) {
       ALOGE(