Merge changes from topic "read heatmap"

* changes:
  Consume video frames
  Add video device to epoll in EventHub
diff --git a/libs/binder/Value.cpp b/libs/binder/Value.cpp
index a28a618..19c57ba 100644
--- a/libs/binder/Value.cpp
+++ b/libs/binder/Value.cpp
@@ -97,7 +97,7 @@
 template<typename T> class Value::Content : public Value::ContentBase {
 public:
     Content() = default;
-    Content(const T & value) : mValue(value) { }
+    explicit Content(const T & value) : mValue(value) { }
 
     virtual ~Content() = default;
 
diff --git a/libs/binder/include/binder/BufferedTextOutput.h b/libs/binder/include/binder/BufferedTextOutput.h
index 9a7c43b..feae93d 100644
--- a/libs/binder/include/binder/BufferedTextOutput.h
+++ b/libs/binder/include/binder/BufferedTextOutput.h
@@ -32,7 +32,7 @@
         MULTITHREADED = 0x0001
     };
     
-                        BufferedTextOutput(uint32_t flags = 0);
+    explicit            BufferedTextOutput(uint32_t flags = 0);
     virtual             ~BufferedTextOutput();
     
     virtual status_t    print(const char* txt, size_t len);
diff --git a/libs/binder/include/binder/IpPrefix.h b/libs/binder/include/binder/IpPrefix.h
index dd5bc3a..c7e7a50 100644
--- a/libs/binder/include/binder/IpPrefix.h
+++ b/libs/binder/include/binder/IpPrefix.h
@@ -74,8 +74,8 @@
 private:
     union InternalUnion {
         InternalUnion() = default;
-        InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
-        InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
+        explicit InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
+        explicit InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
         struct in6_addr mIn6Addr;
         struct in_addr mInAddr;
     } mUnion;
diff --git a/libs/binder/include/binder/MemoryDealer.h b/libs/binder/include/binder/MemoryDealer.h
index fe5a31d..b483be0 100644
--- a/libs/binder/include/binder/MemoryDealer.h
+++ b/libs/binder/include/binder/MemoryDealer.h
@@ -34,7 +34,7 @@
 class MemoryDealer : public RefBase
 {
 public:
-    MemoryDealer(size_t size, const char* name = nullptr,
+    explicit MemoryDealer(size_t size, const char* name = nullptr,
             uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */ );
 
     virtual sp<IMemory> allocate(size_t size);
diff --git a/libs/binder/include/binder/MemoryHeapBase.h b/libs/binder/include/binder/MemoryHeapBase.h
index 2f5039d..100d784 100644
--- a/libs/binder/include/binder/MemoryHeapBase.h
+++ b/libs/binder/include/binder/MemoryHeapBase.h
@@ -47,12 +47,12 @@
     /*
      * maps memory from the given device
      */
-    MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
+    explicit MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
 
     /*
      * maps memory from ashmem, with the given name for debugging
      */
-    MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
+    explicit MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = nullptr);
 
     virtual ~MemoryHeapBase();
 
diff --git a/libs/binder/include/binder/ParcelFileDescriptor.h b/libs/binder/include/binder/ParcelFileDescriptor.h
index ad950af..662e56e 100644
--- a/libs/binder/include/binder/ParcelFileDescriptor.h
+++ b/libs/binder/include/binder/ParcelFileDescriptor.h
@@ -31,7 +31,7 @@
 public:
     ParcelFileDescriptor();
     explicit ParcelFileDescriptor(android::base::unique_fd fd);
-    explicit ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
+    ParcelFileDescriptor(ParcelFileDescriptor&& other) : mFd(std::move(other.mFd)) { }
     ~ParcelFileDescriptor() override;
 
     int get() const { return mFd.get(); }
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index 13f67ba..3712c84 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -80,7 +80,7 @@
 private:
     friend class IPCThreadState;
     
-                                ProcessState(const char* driver);
+            explicit            ProcessState(const char* driver);
                                 ~ProcessState();
 
                                 ProcessState(const ProcessState& o);
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index 851e01f..5b5f766 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -38,7 +38,7 @@
     
     class Bundle {
     public:
-        inline Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
+        inline explicit Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
         inline ~Bundle() { mTO.popBundle(); }
     private:
         TextOutput&     mTO;
@@ -80,7 +80,7 @@
 class TypeCode
 {
 public:
-    inline TypeCode(uint32_t code);
+    inline explicit TypeCode(uint32_t code);
     inline ~TypeCode();
 
     inline uint32_t typeCode() const;
diff --git a/libs/binder/include/binder/Value.h b/libs/binder/include/binder/Value.h
index 4dee3d8..735f40e 100644
--- a/libs/binder/include/binder/Value.h
+++ b/libs/binder/include/binder/Value.h
@@ -74,20 +74,20 @@
     bool operator!=(const Value& rhs) const { return !this->operator==(rhs); }
 
     Value(const Value& value);
-    Value(const bool& value);
-    Value(const int8_t& value);
-    Value(const int32_t& value);
-    Value(const int64_t& value);
-    Value(const double& value);
-    Value(const String16& value);
-    Value(const std::vector<bool>& value);
-    Value(const std::vector<uint8_t>& value);
-    Value(const std::vector<int32_t>& value);
-    Value(const std::vector<int64_t>& value);
-    Value(const std::vector<double>& value);
-    Value(const std::vector<String16>& value);
-    Value(const os::PersistableBundle& value);
-    Value(const binder::Map& value);
+    Value(const bool& value); // NOLINT(google-explicit-constructor)
+    Value(const int8_t& value); // NOLINT(google-explicit-constructor)
+    Value(const int32_t& value); // NOLINT(google-explicit-constructor)
+    Value(const int64_t& value); // NOLINT(google-explicit-constructor)
+    Value(const double& value); // NOLINT(google-explicit-constructor)
+    Value(const String16& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<bool>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<uint8_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<int32_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<int64_t>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<double>& value); // NOLINT(google-explicit-constructor)
+    Value(const std::vector<String16>& value); // NOLINT(google-explicit-constructor)
+    Value(const os::PersistableBundle& value); // NOLINT(google-explicit-constructor)
+    Value(const binder::Map& value); // NOLINT(google-explicit-constructor)
 
     Value& operator=(const Value& rhs);
     Value& operator=(const int8_t& rhs);
@@ -153,8 +153,8 @@
     // String Convenience Adapters
     // ---------------------------
 
-    Value(const String8& value):               Value(String16(value)) { }
-    Value(const ::std::string& value):         Value(String8(value.c_str())) { }
+    explicit Value(const String8& value):               Value(String16(value)) { }
+    explicit Value(const ::std::string& value):         Value(String8(value.c_str())) { }
     void putString(const String8& value)       { return putString(String16(value)); }
     void putString(const ::std::string& value) { return putString(String8(value.c_str())); }
     Value& operator=(const String8& rhs)       { return *this = String16(rhs); }
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index ac592ea..7852298 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -34,7 +34,7 @@
 struct ABpBinder;
 
 struct AIBinder : public virtual ::android::RefBase {
-    AIBinder(const AIBinder_Class* clazz);
+    explicit AIBinder(const AIBinder_Class* clazz);
     virtual ~AIBinder();
 
     bool associateClass(const AIBinder_Class* clazz);
@@ -97,7 +97,7 @@
     ABpBinder* asABpBinder() override { return this; }
 
    private:
-    ABpBinder(const ::android::sp<::android::IBinder>& binder);
+    explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
 };
 
 struct AIBinder_Class {
@@ -141,7 +141,7 @@
         const AIBinder_DeathRecipient_onBinderDied& mOnDied;
     };
 
-    AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
+    explicit AIBinder_DeathRecipient(AIBinder_DeathRecipient_onBinderDied onDied);
     binder_status_t linkToDeath(AIBinder* binder, void* cookie);
     binder_status_t unlinkToDeath(AIBinder* binder, void* cookie);
 
diff --git a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
index ff1860e..80773f3 100644
--- a/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_auto_utils.h
@@ -51,7 +51,7 @@
      * Convenience operator for implicitly constructing an SpAIBinder from nullptr. This is not
      * explicit because it is not taking ownership of anything.
      */
-    SpAIBinder(std::nullptr_t) : SpAIBinder() {}
+    SpAIBinder(std::nullptr_t) : SpAIBinder() {}  // NOLINT(google-explicit-constructor)
 
     /**
      * This will delete the underlying object if it exists. See operator=.
diff --git a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
index 1532725..a42c60b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_interface_utils.h
@@ -137,7 +137,7 @@
 template <typename INTERFACE>
 class BpCInterface : public INTERFACE {
    public:
-    BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
+    explicit BpCInterface(const SpAIBinder& binder) : mBinder(binder) {}
     virtual ~BpCInterface() {}
 
     SpAIBinder asBinder() override;
diff --git a/libs/binder/ndk/parcel_internal.h b/libs/binder/ndk/parcel_internal.h
index f292309..6b7295e 100644
--- a/libs/binder/ndk/parcel_internal.h
+++ b/libs/binder/ndk/parcel_internal.h
@@ -27,7 +27,8 @@
     const ::android::Parcel* get() const { return mParcel; }
     ::android::Parcel* get() { return mParcel; }
 
-    AParcel(const AIBinder* binder) : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
+    explicit AParcel(const AIBinder* binder)
+        : AParcel(binder, new ::android::Parcel, true /*owns*/) {}
     AParcel(const AIBinder* binder, ::android::Parcel* parcel, bool owns)
         : mBinder(binder), mParcel(parcel), mOwns(owns) {}
 
diff --git a/libs/binder/ndk/status_internal.h b/libs/binder/ndk/status_internal.h
index d39f0d8..f6227f7 100644
--- a/libs/binder/ndk/status_internal.h
+++ b/libs/binder/ndk/status_internal.h
@@ -23,7 +23,7 @@
 
 struct AStatus {
     AStatus() {}  // ok
-    AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
+    explicit AStatus(::android::binder::Status&& status) : mStatus(std::move(status)) {}
 
     ::android::binder::Status* get() { return &mStatus; }
     const ::android::binder::Status* get() const { return &mStatus; }
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
index 6ef964e..64832f3 100644
--- a/libs/binder/ndk/test/iface.cpp
+++ b/libs/binder/ndk/test/iface.cpp
@@ -74,7 +74,7 @@
 
 class BpFoo : public IFoo {
    public:
-    BpFoo(AIBinder* binder) : mBinder(binder) {}
+    explicit BpFoo(AIBinder* binder) : mBinder(binder) {}
     virtual ~BpFoo() { AIBinder_decStrong(mBinder); }
 
     virtual binder_status_t doubleNumber(int32_t in, int32_t* out) {
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index ae04b0f..78f1159 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -233,7 +233,7 @@
 {
     public:
         BinderLibTestBundle(void) {}
-        BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
+        explicit BinderLibTestBundle(const Parcel *source) : m_isValid(false) {
             int32_t mark;
             int32_t bundleLen;
             size_t pos;
@@ -1079,7 +1079,7 @@
 class BinderLibTestService : public BBinder
 {
     public:
-        BinderLibTestService(int32_t id)
+        explicit BinderLibTestService(int32_t id)
             : m_id(id)
             , m_nextServerId(id + 1)
             , m_serverStartRequested(false)
diff --git a/libs/binder/tests/schd-dbg.cpp b/libs/binder/tests/schd-dbg.cpp
index 6cf7f36..ec9534a 100644
--- a/libs/binder/tests/schd-dbg.cpp
+++ b/libs/binder/tests/schd-dbg.cpp
@@ -218,7 +218,7 @@
   uint64_t m_total_time = 0;
   uint64_t m_miss = 0;
   bool tracing;
-  Results(bool _tracing) : tracing(_tracing) {
+  explicit Results(bool _tracing) : tracing(_tracing) {
   }
   inline bool miss_deadline(uint64_t nano) {
     return nano > deadline_us * 1000;
diff --git a/libs/gui/BufferHubProducer.cpp b/libs/gui/BufferHubProducer.cpp
index 16952a6..4be014f 100644
--- a/libs/gui/BufferHubProducer.cpp
+++ b/libs/gui/BufferHubProducer.cpp
@@ -64,13 +64,13 @@
     } else if (buffers_[slot].mGraphicBuffer != nullptr) {
         ALOGE("requestBuffer: slot %d is not empty.", slot);
         return BAD_VALUE;
-    } else if (buffers_[slot].mBufferProducer == nullptr) {
+    } else if (buffers_[slot].mProducerBuffer == nullptr) {
         ALOGE("requestBuffer: slot %d is not dequeued.", slot);
         return BAD_VALUE;
     }
 
-    const auto& buffer_producer = buffers_[slot].mBufferProducer;
-    sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+    const auto& producer_buffer = buffers_[slot].mProducerBuffer;
+    sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
 
     buffers_[slot].mGraphicBuffer = graphic_buffer;
     buffers_[slot].mRequestBufferCalled = true;
@@ -158,19 +158,19 @@
     }
 
     size_t slot = 0;
-    std::shared_ptr<BufferProducer> buffer_producer;
+    std::shared_ptr<ProducerBuffer> producer_buffer;
 
     for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) {
         LocalHandle fence;
         auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence);
         if (!buffer_status) return NO_MEMORY;
 
-        buffer_producer = buffer_status.take();
-        if (!buffer_producer) return NO_MEMORY;
+        producer_buffer = buffer_status.take();
+        if (!producer_buffer) return NO_MEMORY;
 
-        if (width == buffer_producer->width() && height == buffer_producer->height() &&
-            uint32_t(format) == buffer_producer->format()) {
-            // The producer queue returns a buffer producer matches the request.
+        if (width == producer_buffer->width() && height == producer_buffer->height() &&
+            uint32_t(format) == producer_buffer->format()) {
+            // The producer queue returns a producer buffer matches the request.
             break;
         }
 
@@ -179,8 +179,8 @@
         ALOGI("dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different "
               "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need "
               "re-allocattion.",
-              width, height, format, slot, buffer_producer->width(), buffer_producer->height(),
-              buffer_producer->format());
+              width, height, format, slot, producer_buffer->width(), producer_buffer->height(),
+              producer_buffer->format());
         // Mark the slot as reallocating, so that later we can set
         // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued.
         buffers_[slot].mIsReallocating = true;
@@ -249,18 +249,18 @@
         ALOGE("detachBuffer: buffer in slot %zu has not been requested", slot);
         return BAD_VALUE;
     }
-    std::shared_ptr<BufferProducer> buffer_producer = queue_->GetBuffer(slot);
-    if (buffer_producer == nullptr || buffer_producer->buffer() == nullptr) {
-        ALOGE("detachBuffer: Invalid BufferProducer at slot %zu.", slot);
+    std::shared_ptr<ProducerBuffer> producer_buffer = queue_->GetBuffer(slot);
+    if (producer_buffer == nullptr || producer_buffer->buffer() == nullptr) {
+        ALOGE("detachBuffer: Invalid ProducerBuffer at slot %zu.", slot);
         return BAD_VALUE;
     }
-    sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
+    sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
     if (graphic_buffer == nullptr) {
         ALOGE("detachBuffer: Invalid GraphicBuffer at slot %zu.", slot);
         return BAD_VALUE;
     }
 
-    // Remove the BufferProducer from the ProducerQueue.
+    // Remove the ProducerBuffer from the ProducerQueue.
     status_t error = RemoveBuffer(slot);
     if (error != NO_ERROR) {
         ALOGE("detachBuffer: Failed to remove buffer, slot=%zu, error=%d.", slot, error);
@@ -269,9 +269,9 @@
 
     // Here we need to convert the existing ProducerBuffer into a DetachedBufferHandle and inject
     // the handle into the GraphicBuffer object at the requested slot.
-    auto status_or_handle = buffer_producer->Detach();
+    auto status_or_handle = producer_buffer->Detach();
     if (!status_or_handle.ok()) {
-        ALOGE("detachBuffer: Failed to detach from a BufferProducer at slot %zu, error=%d.", slot,
+        ALOGE("detachBuffer: Failed to detach from a ProducerBuffer at slot %zu, error=%d.", slot,
               status_or_handle.error());
         return BAD_VALUE;
     }
@@ -301,14 +301,14 @@
     // sequence, except for two things:
     //
     // 1) It is unnecessary to know the dimensions, format, or usage of the next buffer, i.e. the
-    // function just returns whatever BufferProducer is available from the ProducerQueue and no
+    // function just returns whatever ProducerBuffer is available from the ProducerQueue and no
     // buffer allocation or re-allocation will happen.
     // 2) It will not block, since if it cannot find an appropriate buffer to return, it will return
     // an error instead.
     size_t slot = 0;
     LocalHandle fence;
 
-    // First, dequeue a BufferProducer from the ProducerQueue with no timeout. Report error
+    // First, dequeue a ProducerBuffer from the ProducerQueue with no timeout. Report error
     // immediately if ProducerQueue::Dequeue() fails.
     auto status_or_buffer = queue_->Dequeue(/*timeout=*/0, &slot, &fence);
     if (!status_or_buffer.ok()) {
@@ -316,8 +316,8 @@
         return NO_MEMORY;
     }
 
-    std::shared_ptr<BufferProducer> buffer_producer = status_or_buffer.take();
-    if (buffer_producer == nullptr) {
+    std::shared_ptr<ProducerBuffer> producer_buffer = status_or_buffer.take();
+    if (producer_buffer == nullptr) {
         ALOGE("detachNextBuffer: Dequeued buffer is null.");
         return NO_MEMORY;
     }
@@ -331,14 +331,14 @@
               buffers_[slot].mBufferState.string());
         return BAD_VALUE;
     }
-    if (buffers_[slot].mBufferProducer == nullptr) {
-        ALOGE("detachNextBuffer: BufferProducer at slot %zu is null.", slot);
+    if (buffers_[slot].mProducerBuffer == nullptr) {
+        ALOGE("detachNextBuffer: ProducerBuffer at slot %zu is null.", slot);
         return BAD_VALUE;
     }
-    if (buffers_[slot].mBufferProducer->id() != buffer_producer->id()) {
-        ALOGE("detachNextBuffer: BufferProducer at slot %zu has mismatched id, actual: "
+    if (buffers_[slot].mProducerBuffer->id() != producer_buffer->id()) {
+        ALOGE("detachNextBuffer: ProducerBuffer at slot %zu has mismatched id, actual: "
               "%d, expected: %d.",
-              slot, buffers_[slot].mBufferProducer->id(), buffer_producer->id());
+              slot, buffers_[slot].mProducerBuffer->id(), producer_buffer->id());
         return BAD_VALUE;
     }
 
@@ -347,8 +347,8 @@
     buffers_[slot].mBufferState.dequeue();
 
     // Second, request the buffer.
-    sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer();
-    buffers_[slot].mGraphicBuffer = buffer_producer->buffer()->buffer();
+    sp<GraphicBuffer> graphic_buffer = producer_buffer->buffer()->buffer();
+    buffers_[slot].mGraphicBuffer = producer_buffer->buffer()->buffer();
 
     // Finally, detach the buffer and then return.
     status_t error = DetachBufferLocked(slot);
@@ -452,11 +452,11 @@
         return BAD_VALUE;
     }
 
-    // Post the buffer producer with timestamp in the metadata.
-    const auto& buffer_producer = buffers_[slot].mBufferProducer;
+    // Post the producer buffer with timestamp in the metadata.
+    const auto& producer_buffer = buffers_[slot].mProducerBuffer;
 
     // Check input crop is not out of boundary of current buffer.
-    Rect buffer_rect(buffer_producer->width(), buffer_producer->height());
+    Rect buffer_rect(producer_buffer->width(), producer_buffer->height());
     Rect cropped_rect(Rect::EMPTY_RECT);
     crop.intersect(buffer_rect, &cropped_rect);
     if (cropped_rect != crop) {
@@ -477,11 +477,11 @@
     meta_data.scaling_mode = int32_t(scaling_mode);
     meta_data.transform = int32_t(transform);
 
-    buffer_producer->PostAsync(&meta_data, fence_fd);
+    producer_buffer->PostAsync(&meta_data, fence_fd);
     buffers_[slot].mBufferState.queue();
 
-    output->width = buffer_producer->width();
-    output->height = buffer_producer->height();
+    output->width = producer_buffer->width();
+    output->height = producer_buffer->height();
     output->transformHint = 0; // default value, we don't use it yet.
 
     // |numPendingBuffers| counts of the number of buffers that has been enqueued
@@ -519,8 +519,8 @@
         return BAD_VALUE;
     }
 
-    auto buffer_producer = buffers_[slot].mBufferProducer;
-    queue_->Enqueue(buffer_producer, size_t(slot), 0U);
+    auto producer_buffer = buffers_[slot].mProducerBuffer;
+    queue_->Enqueue(producer_buffer, size_t(slot), 0U);
     buffers_[slot].mBufferState.cancel();
     buffers_[slot].mFence = fence;
     ALOGV("cancelBuffer: slot %d", slot);
@@ -791,12 +791,12 @@
     }
 
     size_t slot = status.get();
-    auto buffer_producer = queue_->GetBuffer(slot);
+    auto producer_buffer = queue_->GetBuffer(slot);
 
-    LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr, "Failed to get buffer producer at slot: %zu",
-                        slot);
+    LOG_ALWAYS_FATAL_IF(producer_buffer == nullptr,
+                        "Failed to get the producer buffer at slot: %zu", slot);
 
-    buffers_[slot].mBufferProducer = buffer_producer;
+    buffers_[slot].mProducerBuffer = producer_buffer;
 
     return NO_ERROR;
 }
@@ -810,7 +810,7 @@
     }
 
     // Reset in memory objects related the the buffer.
-    buffers_[slot].mBufferProducer = nullptr;
+    buffers_[slot].mProducerBuffer = nullptr;
     buffers_[slot].mBufferState.detachProducer();
     buffers_[slot].mFence = Fence::NO_FENCE;
     buffers_[slot].mGraphicBuffer = nullptr;
@@ -821,7 +821,7 @@
 status_t BufferHubProducer::FreeAllBuffers() {
     for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) {
         // Reset in memory objects related the the buffer.
-        buffers_[slot].mBufferProducer = nullptr;
+        buffers_[slot].mProducerBuffer = nullptr;
         buffers_[slot].mBufferState.reset();
         buffers_[slot].mFence = Fence::NO_FENCE;
         buffers_[slot].mGraphicBuffer = nullptr;
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 2d6be26..799151a 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -73,11 +73,9 @@
         return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
     }
 
-    virtual void setTransactionState(
-            const Vector<ComposerState>& state,
-            const Vector<DisplayState>& displays,
-            uint32_t flags)
-    {
+    virtual void setTransactionState(const Vector<ComposerState>& state,
+                                     const Vector<DisplayState>& displays, uint32_t flags,
+                                     const sp<IBinder>& applyToken) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
 
@@ -92,6 +90,7 @@
         }
 
         data.writeUint32(flags);
+        data.writeStrongBinder(applyToken);
         remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
     }
 
@@ -750,7 +749,8 @@
             }
 
             uint32_t stateFlags = data.readUint32();
-            setTransactionState(state, displays, stateFlags);
+            sp<IBinder> applyToken = data.readStrongBinder();
+            setTransactionState(state, displays, stateFlags, applyToken);
             return NO_ERROR;
         }
         case BOOT_FINISHED: {
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
new file mode 100644
index 0000000..a7c7e79
--- /dev/null
+++ b/libs/gui/OWNERS
@@ -0,0 +1,8 @@
+brianderson@google.com
+jessehall@google.com
+jwcai@google.com
+mathias@google.com
+olv@google.com
+pceballos@google.com
+racarr@google.com
+stoza@google.com
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 9586219..5b004e2 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -264,7 +264,9 @@
     mAnimation = false;
     mEarlyWakeup = false;
 
-    sf->setTransactionState(composerStates, displayStates, flags);
+    sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
+
+    sf->setTransactionState(composerStates, displayStates, flags, applyToken);
     mStatus = NO_ERROR;
     return NO_ERROR;
 }
diff --git a/libs/gui/include/gui/BufferHubProducer.h b/libs/gui/include/gui/BufferHubProducer.h
index f7af19b..0e925ce 100644
--- a/libs/gui/include/gui/BufferHubProducer.h
+++ b/libs/gui/include/gui/BufferHubProducer.h
@@ -203,10 +203,10 @@
     // requested buffer usage or geometry differs from that of the buffer
     // allocated to a slot.
     struct BufferHubSlot : public BufferSlot {
-        BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {}
+        BufferHubSlot() : mProducerBuffer(nullptr), mIsReallocating(false) {}
         // BufferSlot comes from android framework, using m prefix to comply with
         // the name convention with the reset of data fields from BufferSlot.
-        std::shared_ptr<dvr::BufferProducer> mBufferProducer;
+        std::shared_ptr<dvr::ProducerBuffer> mProducerBuffer;
         bool mIsReallocating;
     };
     BufferHubSlot buffers_[dvr::BufferHubQueue::kMaxQueueCapacity];
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 3052c0b..8cb40e7 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -124,7 +124,8 @@
 
     /* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
     virtual void setTransactionState(const Vector<ComposerState>& state,
-            const Vector<DisplayState>& displays, uint32_t flags) = 0;
+                                     const Vector<DisplayState>& displays, uint32_t flags,
+                                     const sp<IBinder>& applyToken) = 0;
 
     /* signal that we're done booting.
      * Requires ACCESS_SURFACE_FLINGER permission
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 67afbd6..c56304f 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -558,8 +558,8 @@
     void destroyDisplay(const sp<IBinder>& /*display */) override {}
     sp<IBinder> getBuiltInDisplay(int32_t /*id*/) override { return nullptr; }
     void setTransactionState(const Vector<ComposerState>& /*state*/,
-            const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/)
-            override {}
+                             const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
+                             const sp<IBinder>& /*applyToken*/) override {}
     void bootFinished() override {}
     bool authenticateSurfaceTexture(
             const sp<IGraphicBufferProducer>& /*surface*/) const override {
diff --git a/libs/vr/OWNERS b/libs/vr/OWNERS
new file mode 100644
index 0000000..ec2d712
--- /dev/null
+++ b/libs/vr/OWNERS
@@ -0,0 +1,4 @@
+hendrikw@google.com
+jwcai@google.com
+steventhomas@google.com
+
diff --git a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
index 7aa50b1..726f035 100644
--- a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
@@ -6,16 +6,6 @@
 namespace android {
 namespace dvr {
 
-// BufferConsumer was originally poorly named and gets easily confused with
-// IGraphicBufferConsumer. Actually, BufferConsumer is a single buffer that can
-// consume (i.e. read) data from a buffer, but it doesn't consume buffer. On
-// the other hand, IGraphicBufferConsumer is the consumer end of a BufferQueue
-// and it is used to consume buffers.
-//
-// TODO(b/116855254): Remove this typedef once rename is complete in other
-// projects and/or branches.
-typedef class ConsumerBuffer BufferConsumer;
-
 // This is a connection to a producer buffer, which can be located in another
 // application. When that buffer is Post()ed, this fd will be signaled and
 // Acquire allows read access. The user is responsible for making sure that
diff --git a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
index 2761416..7ec345c 100644
--- a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
+++ b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
@@ -6,23 +6,13 @@
 namespace android {
 namespace dvr {
 
-// BufferProducer was originally poorly named and gets easily confused with
-// IGraphicBufferProducer. Actually, BufferProducer is a single buffer that can
-// produce (i.e. write) data into a buffer, but it doesn't produce buffer. On
-// the other hand, IGraphicBufferProducer is the producer end of a BufferQueue
-// and it is used to produce buffers.
-//
-// TODO(b/116855254): Remove this typedef once rename is complete in other
-// projects and/or branches.
-typedef class ProducerBuffer BufferProducer;
-
 // This represents a writable buffer. Calling Post notifies all clients and
 // makes the buffer read-only. Call Gain to acquire write access. A buffer
 // may have many consumers.
 //
 // The user of ProducerBuffer is responsible with making sure that the Post() is
 // done with the correct metadata type and size. The user is also responsible
-// for making sure that remote ends (BufferConsumers) are also using the correct
+// for making sure that remote ends (ConsumerBuffers) are also using the correct
 // metadata when acquiring the buffer. The API guarantees that a Post() with a
 // metadata of wrong size will fail. However, it currently does not do any
 // type checking.
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 9c4f73f..d7833f3 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -480,7 +480,7 @@
 
     // Note that import might (though very unlikely) fail. If so, buffer_handle
     // will be closed and included in returned buffer_slots.
-    if (AddBuffer(BufferProducer::Import(std::move(buffer_handle)),
+    if (AddBuffer(ProducerBuffer::Import(std::move(buffer_handle)),
                   buffer_slot)) {
       ALOGD_IF(TRACE, "ProducerQueue::AllocateBuffers: new buffer at slot: %zu",
                buffer_slot);
@@ -517,7 +517,7 @@
 }
 
 Status<void> ProducerQueue::AddBuffer(
-    const std::shared_ptr<BufferProducer>& buffer, size_t slot) {
+    const std::shared_ptr<ProducerBuffer>& buffer, size_t slot) {
   ALOGD_IF(TRACE, "ProducerQueue::AddBuffer: queue_id=%d buffer_id=%d slot=%zu",
            id(), buffer->id(), slot);
   // For producer buffer, we need to enqueue the newly added buffer
@@ -530,7 +530,7 @@
 }
 
 Status<size_t> ProducerQueue::InsertBuffer(
-    const std::shared_ptr<BufferProducer>& buffer) {
+    const std::shared_ptr<ProducerBuffer>& buffer) {
   if (buffer == nullptr ||
       !BufferHubDefs::IsClientGained(buffer->buffer_state(),
                                      buffer->client_state_mask())) {
@@ -554,7 +554,7 @@
   size_t slot = status_or_slot.get();
 
   // Note that we are calling AddBuffer() from the base class to explicitly
-  // avoid Enqueue() the BufferProducer.
+  // avoid Enqueue() the ProducerBuffer.
   auto status = BufferHubQueue::AddBuffer(buffer, slot);
   if (!status) {
     ALOGE("ProducerQueue::InsertBuffer: Failed to add buffer: %s.",
@@ -576,13 +576,13 @@
   return BufferHubQueue::RemoveBuffer(slot);
 }
 
-Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
+Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::Dequeue(
     int timeout, size_t* slot, LocalHandle* release_fence) {
   DvrNativeBufferMetadata canonical_meta;
   return Dequeue(timeout, slot, &canonical_meta, release_fence);
 }
 
-pdx::Status<std::shared_ptr<BufferProducer>> ProducerQueue::Dequeue(
+pdx::Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::Dequeue(
     int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
     pdx::LocalHandle* release_fence, bool gain_posted_buffer) {
   ATRACE_NAME("ProducerQueue::Dequeue");
@@ -591,14 +591,14 @@
     return ErrorStatus(EINVAL);
   }
 
-  std::shared_ptr<BufferProducer> buffer;
+  std::shared_ptr<ProducerBuffer> buffer;
   Status<std::shared_ptr<BufferHubBase>> dequeue_status =
       BufferHubQueue::Dequeue(timeout, slot);
   if (dequeue_status.ok()) {
-    buffer = std::static_pointer_cast<BufferProducer>(dequeue_status.take());
+    buffer = std::static_pointer_cast<ProducerBuffer>(dequeue_status.take());
   } else {
     if (gain_posted_buffer) {
-      Status<std::shared_ptr<BufferProducer>> dequeue_unacquired_status =
+      Status<std::shared_ptr<ProducerBuffer>> dequeue_unacquired_status =
           ProducerQueue::DequeueUnacquiredBuffer(slot);
       if (!dequeue_unacquired_status.ok()) {
         ALOGE("%s: DequeueUnacquiredBuffer returned error: %d", __FUNCTION__,
@@ -618,7 +618,7 @@
   return {std::move(buffer)};
 }
 
-Status<std::shared_ptr<BufferProducer>> ProducerQueue::DequeueUnacquiredBuffer(
+Status<std::shared_ptr<ProducerBuffer>> ProducerQueue::DequeueUnacquiredBuffer(
     size_t* slot) {
   if (unavailable_buffers_slot_.size() < 1) {
     ALOGE(
@@ -632,7 +632,7 @@
   // unavailable_buffers_slot_.
   for (auto iter = unavailable_buffers_slot_.begin();
        iter != unavailable_buffers_slot_.end(); iter++) {
-    std::shared_ptr<BufferProducer> buffer = ProducerQueue::GetBuffer(*iter);
+    std::shared_ptr<ProducerBuffer> buffer = ProducerQueue::GetBuffer(*iter);
     if (buffer == nullptr) {
       ALOGE("%s failed. Buffer slot %d is  null.", __FUNCTION__,
             static_cast<int>(*slot));
@@ -718,9 +718,9 @@
     ALOGD_IF(TRACE, ": buffer_handle=%d", __FUNCTION__,
              buffer_handle_slot.first.value());
 
-    std::unique_ptr<BufferConsumer> buffer_consumer =
-        BufferConsumer::Import(std::move(buffer_handle_slot.first));
-    if (!buffer_consumer) {
+    std::unique_ptr<ConsumerBuffer> consumer_buffer =
+        ConsumerBuffer::Import(std::move(buffer_handle_slot.first));
+    if (!consumer_buffer) {
       ALOGE("%s: Failed to import buffer: slot=%zu", __FUNCTION__,
             buffer_handle_slot.second);
       last_error = ErrorStatus(EPIPE);
@@ -728,7 +728,7 @@
     }
 
     auto add_status =
-        AddBuffer(std::move(buffer_consumer), buffer_handle_slot.second);
+        AddBuffer(std::move(consumer_buffer), buffer_handle_slot.second);
     if (!add_status) {
       ALOGE("%s: Failed to add buffer: %s", __FUNCTION__,
             add_status.GetErrorMessage().c_str());
@@ -745,13 +745,13 @@
 }
 
 Status<void> ConsumerQueue::AddBuffer(
-    const std::shared_ptr<BufferConsumer>& buffer, size_t slot) {
+    const std::shared_ptr<ConsumerBuffer>& buffer, size_t slot) {
   ALOGD_IF(TRACE, "%s: queue_id=%d buffer_id=%d slot=%zu", __FUNCTION__, id(),
            buffer->id(), slot);
   return BufferHubQueue::AddBuffer(buffer, slot);
 }
 
-Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
+Status<std::shared_ptr<ConsumerBuffer>> ConsumerQueue::Dequeue(
     int timeout, size_t* slot, void* meta, size_t user_metadata_size,
     LocalHandle* acquire_fence) {
   if (user_metadata_size != user_metadata_size_) {
@@ -780,7 +780,7 @@
   return status;
 }
 
-Status<std::shared_ptr<BufferConsumer>> ConsumerQueue::Dequeue(
+Status<std::shared_ptr<ConsumerBuffer>> ConsumerQueue::Dequeue(
     int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
     pdx::LocalHandle* acquire_fence) {
   ATRACE_NAME("ConsumerQueue::Dequeue");
@@ -793,7 +793,7 @@
   if (!status)
     return status.error_status();
 
-  auto buffer = std::static_pointer_cast<BufferConsumer>(status.take());
+  auto buffer = std::static_pointer_cast<ConsumerBuffer>(status.take());
   const int ret = buffer->AcquireAsync(out_meta, acquire_fence);
   if (ret < 0)
     return ErrorStatus(-ret);
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index 53ab2b2..d1f0564 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -307,12 +307,12 @@
     return BASE::Create(std::move(handle));
   }
 
-  // Get a buffer producer. Note that the method doesn't check whether the
+  // Get a producer buffer. Note that the method doesn't check whether the
   // buffer slot has a valid buffer that has been allocated already. When no
   // buffer has been imported before it returns nullptr; otherwise it returns
-  // a shared pointer to a BufferProducer.
-  std::shared_ptr<BufferProducer> GetBuffer(size_t slot) const {
-    return std::static_pointer_cast<BufferProducer>(
+  // a shared pointer to a ProducerBuffer.
+  std::shared_ptr<ProducerBuffer> GetBuffer(size_t slot) const {
+    return std::static_pointer_cast<ProducerBuffer>(
         BufferHubQueue::GetBuffer(slot));
   }
 
@@ -333,7 +333,7 @@
 
   // Add a producer buffer to populate the queue. Once added, a producer buffer
   // is available to use (i.e. in GAINED state).
-  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferProducer>& buffer,
+  pdx::Status<void> AddBuffer(const std::shared_ptr<ProducerBuffer>& buffer,
                               size_t slot);
 
   // Inserts a ProducerBuffer into the queue. On success, the method returns the
@@ -341,7 +341,7 @@
   // being inserted should be in Gain'ed state prior to the call and it's
   // considered as already Dequeued when the function returns.
   pdx::Status<size_t> InsertBuffer(
-      const std::shared_ptr<BufferProducer>& buffer);
+      const std::shared_ptr<ProducerBuffer>& buffer);
 
   // Remove producer buffer from the queue.
   pdx::Status<void> RemoveBuffer(size_t slot) override;
@@ -355,7 +355,7 @@
   // and caller should call Post() once it's done writing to release the buffer
   // to the consumer side.
   // @return a buffer in gained state, which was originally in released state.
-  pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+  pdx::Status<std::shared_ptr<ProducerBuffer>> Dequeue(
       int timeout, size_t* slot, pdx::LocalHandle* release_fence);
 
   // Dequeue a producer buffer to write. The returned buffer in |Gain|'ed mode,
@@ -363,7 +363,7 @@
   // to the consumer side.
   //
   // @param timeout to dequeue a buffer.
-  // @param slot is the slot of the output BufferProducer.
+  // @param slot is the slot of the output ProducerBuffer.
   // @param release_fence for gaining a buffer.
   // @param out_meta metadata of the output buffer.
   // @param gain_posted_buffer whether to gain posted buffer if no released
@@ -375,12 +375,12 @@
   // libdvrtracking from starving when there are non-responding clients. This
   // gain_posted_buffer param can be removed once libdvrtracking start to use
   // the new AHardwareBuffer API.
-  pdx::Status<std::shared_ptr<BufferProducer>> Dequeue(
+  pdx::Status<std::shared_ptr<ProducerBuffer>> Dequeue(
       int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
       pdx::LocalHandle* release_fence, bool gain_posted_buffer = false);
 
   // Enqueues a producer buffer in the queue.
-  pdx::Status<void> Enqueue(const std::shared_ptr<BufferProducer>& buffer,
+  pdx::Status<void> Enqueue(const std::shared_ptr<ProducerBuffer>& buffer,
                             size_t slot, uint64_t index) {
     return BufferHubQueue::Enqueue({buffer, slot, index});
   }
@@ -406,18 +406,18 @@
   // @param slot the slot of the returned buffer.
   // @return a buffer in gained state, which was originally in posted state or
   //     released state.
-  pdx::Status<std::shared_ptr<BufferProducer>> DequeueUnacquiredBuffer(
+  pdx::Status<std::shared_ptr<ProducerBuffer>> DequeueUnacquiredBuffer(
       size_t* slot);
 };
 
 class ConsumerQueue : public BufferHubQueue {
  public:
-  // Get a buffer consumer. Note that the method doesn't check whether the
+  // Get a consumer buffer. Note that the method doesn't check whether the
   // buffer slot has a valid buffer that has been imported already. When no
   // buffer has been imported before it returns nullptr; otherwise returns a
-  // shared pointer to a BufferConsumer.
-  std::shared_ptr<BufferConsumer> GetBuffer(size_t slot) const {
-    return std::static_pointer_cast<BufferConsumer>(
+  // shared pointer to a ConsumerBuffer.
+  std::shared_ptr<ConsumerBuffer> GetBuffer(size_t slot) const {
+    return std::static_pointer_cast<ConsumerBuffer>(
         BufferHubQueue::GetBuffer(slot));
   }
 
@@ -435,23 +435,23 @@
   // Dequeue a consumer buffer to read. The returned buffer in |Acquired|'ed
   // mode, and caller should call Releasse() once it's done writing to release
   // the buffer to the producer side. |meta| is passed along from BufferHub,
-  // The user of BufferProducer is responsible with making sure that the
+  // The user of ProducerBuffer is responsible with making sure that the
   // Dequeue() is done with the corect metadata type and size with those used
   // when the buffer is orignally created.
   template <typename Meta>
-  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
       int timeout, size_t* slot, Meta* meta, pdx::LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, meta, sizeof(*meta), acquire_fence);
   }
-  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
       int timeout, size_t* slot, pdx::LocalHandle* acquire_fence) {
     return Dequeue(timeout, slot, nullptr, 0, acquire_fence);
   }
 
-  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
       int timeout, size_t* slot, void* meta, size_t user_metadata_size,
       pdx::LocalHandle* acquire_fence);
-  pdx::Status<std::shared_ptr<BufferConsumer>> Dequeue(
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> Dequeue(
       int timeout, size_t* slot, DvrNativeBufferMetadata* out_meta,
       pdx::LocalHandle* acquire_fence);
 
@@ -464,7 +464,7 @@
   // is NOT available to use until the producer side |Post| it. |WaitForBuffers|
   // will catch the |Post| and |Acquire| the buffer to make it available for
   // consumer.
-  pdx::Status<void> AddBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+  pdx::Status<void> AddBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
                               size_t slot);
 
   pdx::Status<void> OnBufferAllocated() override;
diff --git a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
index 159d6dc..6ae603b 100644
--- a/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
+++ b/libs/vr/libbufferhubqueue/tests/buffer_hub_queue-test.cpp
@@ -125,7 +125,7 @@
 }
 
 TEST_F(BufferHubQueueTest,
-       TestDequeuePostedBufferIfNoAvailableReleasedBuffer_withBufferConsumer) {
+       TestDequeuePostedBufferIfNoAvailableReleasedBuffer_withConsumerBuffer) {
   ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate 3 buffers to use.
@@ -205,7 +205,7 @@
 }
 
 TEST_F(BufferHubQueueTest,
-       TestDequeuePostedBufferIfNoAvailableReleasedBuffer_noBufferConsumer) {
+       TestDequeuePostedBufferIfNoAvailableReleasedBuffer_noConsumerBuffer) {
   ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
 
   // Allocate 4 buffers to use.
@@ -332,7 +332,7 @@
   EXPECT_EQ(producer_queue_->capacity(), 0);
   EXPECT_EQ(consumer_queue_->capacity(), 0);
 
-  std::shared_ptr<BufferProducer> p1 = BufferProducer::Create(
+  std::shared_ptr<ProducerBuffer> p1 = ProducerBuffer::Create(
       kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage, 0);
   ASSERT_TRUE(p1 != nullptr);
   ASSERT_EQ(p1->GainAsync(), 0);
@@ -345,7 +345,7 @@
   EXPECT_EQ(status_or_slot.error(), EINVAL);
 
   // Inserting a gained buffer will succeed.
-  std::shared_ptr<BufferProducer> p2 = BufferProducer::Create(
+  std::shared_ptr<ProducerBuffer> p2 = ProducerBuffer::Create(
       kBufferWidth, kBufferHeight, kBufferFormat, kBufferUsage);
   ASSERT_EQ(p2->GainAsync(), 0);
   ASSERT_TRUE(p2 != nullptr);
@@ -382,7 +382,7 @@
   // Dequeue all the buffers and keep track of them in an array. This prevents
   // the producer queue ring buffer ref counts from interfering with the tests.
   struct Entry {
-    std::shared_ptr<BufferProducer> buffer;
+    std::shared_ptr<ProducerBuffer> buffer;
     LocalHandle fence;
     size_t slot;
   };
@@ -848,10 +848,10 @@
   size_t slot;
   LocalHandle fence;
   pdx::Status<void> status;
-  pdx::Status<std::shared_ptr<BufferConsumer>> consumer_status;
-  pdx::Status<std::shared_ptr<BufferProducer>> producer_status;
-  std::shared_ptr<BufferConsumer> consumer_buffer;
-  std::shared_ptr<BufferProducer> producer_buffer;
+  pdx::Status<std::shared_ptr<ConsumerBuffer>> consumer_status;
+  pdx::Status<std::shared_ptr<ProducerBuffer>> producer_status;
+  std::shared_ptr<ConsumerBuffer> consumer_buffer;
+  std::shared_ptr<ProducerBuffer> producer_buffer;
   DvrNativeBufferMetadata mi, mo;
 
   ASSERT_TRUE(CreateQueues(config_builder_.Build(), UsagePolicy{}));
@@ -994,7 +994,7 @@
   auto s3 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
   EXPECT_TRUE(s3.ok());
 
-  std::shared_ptr<BufferProducer> p1 = s3.take();
+  std::shared_ptr<ProducerBuffer> p1 = s3.take();
   ASSERT_NE(p1, nullptr);
 
   producer_meta.timestamp = 42;
@@ -1061,7 +1061,7 @@
   auto s2 = producer_queue_->Dequeue(0, &slot, &producer_meta, &fence);
   EXPECT_TRUE(s2.ok());
 
-  std::shared_ptr<BufferProducer> p1 = s2.take();
+  std::shared_ptr<ProducerBuffer> p1 = s2.take();
   ASSERT_NE(p1, nullptr);
 
   producer_meta.timestamp = 42;
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index f4c6600..1ca653c 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -8,10 +8,10 @@
 #include "dvr_buffer_queue_internal.h"
 
 using namespace android;
-using android::dvr::BufferConsumer;
 using android::dvr::BufferHubBase;
-using android::dvr::BufferProducer;
+using android::dvr::ConsumerBuffer;
 using android::dvr::ConsumerQueue;
+using android::dvr::ProducerBuffer;
 using android::dvr::ProducerQueue;
 using android::dvr::ProducerQueueConfigBuilder;
 using android::dvr::UsagePolicy;
@@ -103,13 +103,13 @@
         "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
     write_buffers_[slot]->write_buffer = std::move(buffer_status.take());
 
-    const auto& buffer_producer = write_buffers_[slot]->write_buffer;
-    if (!buffer_producer)
+    const auto& producer_buffer = write_buffers_[slot]->write_buffer;
+    if (!producer_buffer)
       return -ENOMEM;
 
-    if (width_ == buffer_producer->width() &&
-        height_ == buffer_producer->height() &&
-        format_ == buffer_producer->format()) {
+    if (width_ == producer_buffer->width() &&
+        height_ == producer_buffer->height() &&
+        format_ == producer_buffer->format()) {
       // Producer queue returns a buffer matches the current request.
       break;
     }
@@ -122,14 +122,14 @@
              "DvrWriteBufferQueue::Dequeue: requested buffer at slot: %zu "
              "(w=%u, h=%u, fmt=%u) is different from the buffer returned "
              "(w=%u, h=%u, fmt=%u). Need re-allocation.",
-             slot, width_, height_, format_, buffer_producer->width(),
-             buffer_producer->height(), buffer_producer->format());
+             slot, width_, height_, format_, producer_buffer->width(),
+             producer_buffer->height(), producer_buffer->format());
 
     // Currently, we are not storing |layer_count| and |usage| in queue
     // configuration. Copy those setup from the last buffer dequeued before we
     // remove it.
-    uint32_t old_layer_count = buffer_producer->layer_count();
-    uint64_t old_usage = buffer_producer->usage();
+    uint32_t old_layer_count = producer_buffer->layer_count();
+    uint64_t old_usage = producer_buffer->usage();
 
     // Allocate a new producer buffer with new buffer configs. Note that if
     // there are already multiple available buffers in the queue, the next one
@@ -443,7 +443,7 @@
           // When buffer is removed from the queue, the slot is already invalid.
           auto read_buffer = std::make_unique<DvrReadBuffer>();
           read_buffer->read_buffer =
-              std::static_pointer_cast<BufferConsumer>(buffer);
+              std::static_pointer_cast<ConsumerBuffer>(buffer);
           callback(read_buffer.release(), context);
         });
   }
diff --git a/libs/vr/libdvr/dvr_display_manager.cpp b/libs/vr/libdvr/dvr_display_manager.cpp
index fe91b14..7f631e3 100644
--- a/libs/vr/libdvr/dvr_display_manager.cpp
+++ b/libs/vr/libdvr/dvr_display_manager.cpp
@@ -10,10 +10,10 @@
 #include "dvr_internal.h"
 #include "dvr_buffer_queue_internal.h"
 
-using android::dvr::BufferConsumer;
+using android::dvr::ConsumerBuffer;
 using android::dvr::display::DisplayManagerClient;
-using android::dvr::display::SurfaceAttributes;
 using android::dvr::display::SurfaceAttribute;
+using android::dvr::display::SurfaceAttributes;
 using android::dvr::display::SurfaceState;
 using android::pdx::rpc::EmptyVariant;
 
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
index df8125a..f845cd8 100644
--- a/libs/vr/libdvr/dvr_internal.h
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -16,21 +16,11 @@
 namespace android {
 namespace dvr {
 
-// TODO(b/116855254): Remove this typedef once rename is complete in libdvr.
-// Note that the dvr::BufferProducer and dvr::BufferConsumer were poorly named,
-// they should really be named as ProducerBuffer and ConsumerBuffer.
-typedef class ProducerBuffer BufferProducer;
-typedef class ConsumerBuffer BufferConsumer;
 class IonBuffer;
 
 DvrBuffer* CreateDvrBufferFromIonBuffer(
     const std::shared_ptr<IonBuffer>& ion_buffer);
 
-DvrReadBuffer* CreateDvrReadBufferFromBufferConsumer(
-    const std::shared_ptr<BufferConsumer>& buffer_consumer);
-DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
-    const std::shared_ptr<BufferProducer>& buffer_producer);
-
 }  // namespace dvr
 }  // namespace android
 
@@ -42,7 +32,7 @@
   // DvrWriteBuffer acquired from a DvrWriteBufferQueue.
   int32_t slot = -1;
 
-  std::shared_ptr<android::dvr::BufferProducer> write_buffer;
+  std::shared_ptr<android::dvr::ProducerBuffer> write_buffer;
 };
 
 struct DvrReadBuffer {
@@ -51,7 +41,7 @@
   // DvrReadBuffer acquired from a DvrReadBufferQueue.
   int32_t slot = -1;
 
-  std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
+  std::shared_ptr<android::dvr::ConsumerBuffer> read_buffer;
 };
 
 struct DvrBuffer {
diff --git a/libs/vr/libdvr/dvr_surface.cpp b/libs/vr/libdvr/dvr_surface.cpp
index a3a47f1..0c7ec01 100644
--- a/libs/vr/libdvr/dvr_surface.cpp
+++ b/libs/vr/libdvr/dvr_surface.cpp
@@ -14,7 +14,6 @@
 using android::dvr::display::Surface;
 using android::dvr::display::SurfaceAttributes;
 using android::dvr::display::SurfaceAttributeValue;
-using android::dvr::CreateDvrReadBufferFromBufferConsumer;
 using android::pdx::rpc::EmptyVariant;
 
 namespace {
diff --git a/libs/vr/libvrflinger/acquired_buffer.cpp b/libs/vr/libvrflinger/acquired_buffer.cpp
index 5d873d1..c360dee 100644
--- a/libs/vr/libvrflinger/acquired_buffer.cpp
+++ b/libs/vr/libvrflinger/acquired_buffer.cpp
@@ -8,11 +8,11 @@
 namespace android {
 namespace dvr {
 
-AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
                                LocalHandle acquire_fence, std::size_t slot)
     : buffer_(buffer), acquire_fence_(std::move(acquire_fence)), slot_(slot) {}
 
-AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+AcquiredBuffer::AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
                                int* error) {
   LocalHandle fence;
   const int ret = buffer->Acquire(&fence);
@@ -75,7 +75,7 @@
   return std::move(acquire_fence_);
 }
 
-std::shared_ptr<BufferConsumer> AcquiredBuffer::ClaimBuffer() {
+std::shared_ptr<ConsumerBuffer> AcquiredBuffer::ClaimBuffer() {
   return std::move(buffer_);
 }
 
diff --git a/libs/vr/libvrflinger/acquired_buffer.h b/libs/vr/libvrflinger/acquired_buffer.h
index 9e35a39..7643e75 100644
--- a/libs/vr/libvrflinger/acquired_buffer.h
+++ b/libs/vr/libvrflinger/acquired_buffer.h
@@ -9,42 +9,42 @@
 namespace android {
 namespace dvr {
 
-// Manages the ACQUIRE/RELEASE ownership cycle of a BufferConsumer.
+// Manages the ACQUIRE/RELEASE ownership cycle of a ConsumerBuffer.
 class AcquiredBuffer {
  public:
   static constexpr int kEmptyFence = pdx::LocalHandle::kEmptyFileHandle;
 
   AcquiredBuffer() : buffer_(nullptr), acquire_fence_(kEmptyFence) {}
 
-  // Constructs an AcquiredBuffer from a BufferConsumer pointer and an acquire
-  // fence. The BufferConsumer MUST be in the ACQUIRED state prior to calling
+  // Constructs an AcquiredBuffer from a ConsumerBuffer pointer and an acquire
+  // fence. The ConsumerBuffer MUST be in the ACQUIRED state prior to calling
   // this constructor; the constructor does not attempt to ACQUIRE the buffer
   // itself.
-  AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer,
+  AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer,
                  pdx::LocalHandle acquire_fence, std::size_t slot = 0);
 
-  // Constructs an AcquiredBuffer from a BufferConsumer. The BufferConsumer MUST
+  // Constructs an AcquiredBuffer from a ConsumerBuffer. The ConsumerBuffer MUST
   // be in the POSTED state prior to calling this constructor, as this
   // constructor attempts to ACQUIRE the buffer. If ACQUIRING the buffer fails
   // this instance is left in the empty state. An optional error code is
   // returned in |error|, which may be nullptr if not needed.
-  AcquiredBuffer(const std::shared_ptr<BufferConsumer>& buffer, int* error);
+  AcquiredBuffer(const std::shared_ptr<ConsumerBuffer>& buffer, int* error);
 
   // Move constructor. Behaves similarly to the move assignment operator below.
   AcquiredBuffer(AcquiredBuffer&& other) noexcept;
 
   ~AcquiredBuffer();
 
-  // Move assignment operator. Moves the BufferConsumer and acquire fence from
-  // |other| into this instance after RELEASING the current BufferConsumer and
+  // Move assignment operator. Moves the ConsumerBuffer and acquire fence from
+  // |other| into this instance after RELEASING the current ConsumerBuffer and
   // closing the acquire fence. After the move |other| is left in the empty
   // state.
   AcquiredBuffer& operator=(AcquiredBuffer&& other) noexcept;
 
-  // Accessors for the underlying BufferConsumer, the acquire fence, and the
+  // Accessors for the underlying ConsumerBuffer, the acquire fence, and the
   // use-case specific sequence value from the acquisition (see
   // private/dvr/consumer_buffer.h).
-  std::shared_ptr<BufferConsumer> buffer() const { return buffer_; }
+  std::shared_ptr<ConsumerBuffer> buffer() const { return buffer_; }
   int acquire_fence() const { return acquire_fence_.Get(); }
 
   // When non-empty, returns true if the acquired fence was signaled (or if the
@@ -58,11 +58,11 @@
 
   // Returns the buffer, passing ownership to the caller. Caller is responsible
   // for calling Release on the returned buffer.
-  std::shared_ptr<BufferConsumer> ClaimBuffer();
+  std::shared_ptr<ConsumerBuffer> ClaimBuffer();
 
-  // Releases the BufferConsumer, passing the release fence in |release_fence|
-  // to the producer. On success, the BufferConsumer and acquire fence are set
-  // to empty state; if release fails, the BufferConsumer and acquire fence are
+  // Releases the ConsumerBuffer, passing the release fence in |release_fence|
+  // to the producer. On success, the ConsumerBuffer and acquire fence are set
+  // to empty state; if release fails, the ConsumerBuffer and acquire fence are
   // left in place and a negative error code is returned.
   int Release(pdx::LocalHandle release_fence = {});
 
@@ -71,7 +71,7 @@
   std::size_t slot() const { return slot_; }
 
  private:
-  std::shared_ptr<BufferConsumer> buffer_;
+  std::shared_ptr<ConsumerBuffer> buffer_;
   // Mutable so that the fence can be closed when it is determined to be
   // signaled during IsAvailable().
   mutable pdx::LocalHandle acquire_fence_;
diff --git a/libs/vr/libvrsensor/pose_client.cpp b/libs/vr/libvrsensor/pose_client.cpp
index c72f75e..4ff6a09 100644
--- a/libs/vr/libvrsensor/pose_client.cpp
+++ b/libs/vr/libvrsensor/pose_client.cpp
@@ -221,7 +221,7 @@
       return -status.error();
     }
 
-    auto buffer = BufferConsumer::Import(status.take());
+    auto buffer = ConsumerBuffer::Import(status.take());
     if (!buffer) {
       ALOGE("Pose failed to import ring buffer");
       return -EIO;
@@ -290,7 +290,7 @@
   const DvrVsyncPoseBuffer* mapped_vsync_pose_buffer_ = nullptr;
 
   struct ControllerClientState {
-    std::unique_ptr<BufferConsumer> pose_buffer;
+    std::unique_ptr<ConsumerBuffer> pose_buffer;
     const DvrPoseAsync* mapped_pose_buffer = nullptr;
   };
   ControllerClientState controllers_[MAX_CONTROLLERS];
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 3686dab..0a6ff55 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -183,7 +183,7 @@
     uint32_t lower(void) { return _l; }
     uint32_t upper(void) { return _u; }
 
-    operator string();
+    operator string(); // NOLINT(google-explicit-constructor)
 
 private:
     uint32_t _l; // lower
@@ -216,7 +216,9 @@
     static void double2Rational(double f, Range nRange, Range dRange,
                                Rational& lower, Rational& upper);
         
+    // NOLINTNEXTLINE(google-explicit-constructor)
     operator string() const;
+    // NOLINTNEXTLINE(google-explicit-constructor)
     operator double() const { return (double) _n / (double) _d; }
 
 
diff --git a/opengl/tests/hwc/hwcTestLib.h b/opengl/tests/hwc/hwcTestLib.h
index 922fc19..5a49393 100644
--- a/opengl/tests/hwc/hwcTestLib.h
+++ b/opengl/tests/hwc/hwcTestLib.h
@@ -58,7 +58,7 @@
     float c2(void) const { return _c2; }
     float c3(void) const { return _c3; }
 
-    operator std::string();
+    operator std::string(); // NOLINT(google-explicit-constructor)
 
   private:
     float _c1;
@@ -71,7 +71,7 @@
 class ColorRGB {
   public:
     ColorRGB(): _r(0.0), _g(0.0), _b(0.0) {};
-    ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(implicit)
+    ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(google-explicit-constructor)
     ColorRGB(float r, float g, float b): _r(r), _g(g), _b(b) {};
     float r(void) const { return _r; }
     float g(void) const { return _g; }
@@ -93,8 +93,8 @@
     void setWidth(uint32_t w) { _w = w; }
     void setHeight(uint32_t h) { _h = h; }
 
-    operator std::string();
-    operator hwc_rect() const;
+    operator std::string(); // NOLINT(google-explicit-constructor)
+    operator hwc_rect() const; // NOLINT(google-explicit-constructor)
 
   private:
     uint32_t _w;
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
new file mode 100644
index 0000000..dc2b300
--- /dev/null
+++ b/services/surfaceflinger/OWNERS
@@ -0,0 +1,5 @@
+chaviw@google.com
+lpy@google.com
+marissaw@google.com
+racarr@google.com
+stoza@google.com
\ No newline at end of file
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4a93be6..02cd9d9 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1568,11 +1568,23 @@
 
 bool SurfaceFlinger::handleMessageTransaction() {
     uint32_t transactionFlags = peekTransactionFlags();
+
+    // Apply any ready transactions in the queues if there are still transactions that have not been
+    // applied, wake up during the next vsync period and check again
+    bool transactionNeeded = false;
+    if (!flushTransactionQueues()) {
+        transactionNeeded = true;
+    }
+
     if (transactionFlags) {
         handleTransaction(transactionFlags);
-        return true;
     }
-    return false;
+
+    if (transactionNeeded) {
+        setTransactionFlags(eTransactionNeeded);
+    }
+
+    return transactionFlags;
 }
 
 void SurfaceFlinger::handleMessageRefresh() {
@@ -3314,6 +3326,26 @@
     return old;
 }
 
+bool SurfaceFlinger::flushTransactionQueues() {
+    Mutex::Autolock _l(mStateLock);
+    auto it = mTransactionQueues.begin();
+    while (it != mTransactionQueues.end()) {
+        auto& [applyToken, transactionQueue] = *it;
+
+        while (!transactionQueue.empty()) {
+            const auto& [states, displays, flags] = transactionQueue.front();
+            if (composerStateContainsUnsignaledFences(states)) {
+                break;
+            }
+            applyTransactionState(states, displays, flags);
+            transactionQueue.pop();
+        }
+
+        it = (transactionQueue.empty()) ? mTransactionQueues.erase(it) : std::next(it, 1);
+    }
+    return mTransactionQueues.empty();
+}
+
 bool SurfaceFlinger::containsAnyInvalidClientState(const Vector<ComposerState>& states) {
     for (const ComposerState& state : states) {
         // Here we need to check that the interface we're given is indeed
@@ -3336,19 +3368,44 @@
     return false;
 }
 
-void SurfaceFlinger::setTransactionState(
-        const Vector<ComposerState>& states,
-        const Vector<DisplayState>& displays,
-        uint32_t flags)
-{
+bool SurfaceFlinger::composerStateContainsUnsignaledFences(const Vector<ComposerState>& states) {
+    for (const ComposerState& state : states) {
+        const layer_state_t& s = state.state;
+        if (!(s.what & layer_state_t::eAcquireFenceChanged)) {
+            continue;
+        }
+        if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void SurfaceFlinger::setTransactionState(const Vector<ComposerState>& states,
+                                         const Vector<DisplayState>& displays, uint32_t flags,
+                                         const sp<IBinder>& applyToken) {
     ATRACE_CALL();
     Mutex::Autolock _l(mStateLock);
-    uint32_t transactionFlags = 0;
 
     if (containsAnyInvalidClientState(states)) {
         return;
     }
 
+    // If its TransactionQueue already has a pending TransactionState or if it is pending
+    if (mTransactionQueues.find(applyToken) != mTransactionQueues.end() ||
+        composerStateContainsUnsignaledFences(states)) {
+        mTransactionQueues[applyToken].emplace(states, displays, flags);
+        setTransactionFlags(eTransactionNeeded);
+        return;
+    }
+
+    applyTransactionState(states, displays, flags);
+}
+
+void SurfaceFlinger::applyTransactionState(const Vector<ComposerState>& states,
+                                           const Vector<DisplayState>& displays, uint32_t flags) {
+    uint32_t transactionFlags = 0;
+
     if (flags & eAnimation) {
         // For window updates that are part of an animation we must wait for
         // previous animation "frames" to be handled.
@@ -3938,7 +3995,7 @@
     d.width = 0;
     d.height = 0;
     displays.add(d);
-    setTransactionState(state, displays, 0);
+    setTransactionState(state, displays, 0, nullptr);
 
     const auto display = getDisplayDevice(displayToken);
     if (!display) return;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b1bfb3a..822bb18 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -442,7 +442,8 @@
     virtual void destroyDisplay(const sp<IBinder>& displayToken);
     virtual sp<IBinder> getBuiltInDisplay(int32_t id);
     virtual void setTransactionState(const Vector<ComposerState>& state,
-            const Vector<DisplayState>& displays, uint32_t flags);
+                                     const Vector<DisplayState>& displays, uint32_t flags,
+                                     const sp<IBinder>& applyToken);
     virtual void bootFinished();
     virtual bool authenticateSurfaceTexture(
         const sp<IGraphicBufferProducer>& bufferProducer) const;
@@ -553,6 +554,10 @@
     /* ------------------------------------------------------------------------
      * Transactions
      */
+    void applyTransactionState(const Vector<ComposerState>& state,
+                               const Vector<DisplayState>& displays, uint32_t flags)
+            REQUIRES(mStateLock);
+    bool flushTransactionQueues();
     uint32_t getTransactionFlags(uint32_t flags);
     uint32_t peekTransactionFlags();
     // Can only be called from the main thread or with mStateLock held
@@ -561,6 +566,7 @@
     void latchAndReleaseBuffer(const sp<Layer>& layer);
     void commitTransaction();
     bool containsAnyInvalidClientState(const Vector<ComposerState>& states);
+    bool composerStateContainsUnsignaledFences(const Vector<ComposerState>& states);
     uint32_t setClientStateLocked(const ComposerState& composerState);
     uint32_t setDisplayStateLocked(const DisplayState& s);
     void setDestroyStateLocked(const ComposerState& composerState);
@@ -965,6 +971,22 @@
     uint32_t mTexturePoolSize = 0;
     std::vector<uint32_t> mTexturePool;
 
+    struct IBinderHash {
+        std::size_t operator()(const sp<IBinder>& strongPointer) const {
+            return std::hash<IBinder*>{}(strongPointer.get());
+        }
+    };
+    struct TransactionState {
+        TransactionState(const Vector<ComposerState>& composerStates,
+                         const Vector<DisplayState>& displayStates, uint32_t transactionFlags)
+              : states(composerStates), displays(displayStates), flags(transactionFlags) {}
+
+        Vector<ComposerState> states;
+        Vector<DisplayState> displays;
+        uint32_t flags;
+    };
+    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IBinderHash> mTransactionQueues;
+
     /* ------------------------------------------------------------------------
      * Feature prototyping
      */
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 604aa7d..f121a95 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -17,6 +17,7 @@
     defaults: ["surfaceflinger_defaults"],
     test_suites: ["device-tests"],
     srcs: [
+        "BufferGenerator.cpp",
         "Credentials_test.cpp",
         "Stress_test.cpp",
         "SurfaceInterceptor_test.cpp",
diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp
new file mode 100644
index 0000000..8ddda60
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGenerator.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/BufferItemConsumer.h>
+#include <gui/Surface.h>
+
+#include <GLES3/gl3.h>
+#include <math/vec2.h>
+#include <math/vec3.h>
+#include <math/vec4.h>
+
+#include "BufferGenerator.h"
+#include "BufferGeneratorShader.h"
+
+namespace android {
+
+/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
+ * away. The fences are sent to the requester via a callback */
+class SurfaceManager {
+public:
+    /* Returns a fence from egl */
+    using BufferCallback = std::function<void(const sp<GraphicBuffer>& buffer, int32_t fence)>;
+
+    /* Listens for a new frame, detaches the buffer and returns the fence
+     * through saved callback. */
+    class BufferListener : public ConsumerBase::FrameAvailableListener {
+    public:
+        BufferListener(sp<IGraphicBufferConsumer> consumer, BufferCallback callback)
+              : mConsumer(consumer), mCallback(callback) {}
+
+        void onFrameAvailable(const BufferItem& /*item*/) {
+            BufferItem item;
+
+            if (mConsumer->acquireBuffer(&item, 0)) return;
+            if (mConsumer->detachBuffer(item.mSlot)) return;
+
+            mCallback(item.mGraphicBuffer, item.mFence->dup());
+        }
+
+    private:
+        sp<IGraphicBufferConsumer> mConsumer;
+        BufferCallback mCallback;
+    };
+
+    /* Creates a buffer listener that waits on a new frame from the buffer
+     * queue. */
+    void initialize(uint32_t width, uint32_t height, android_pixel_format_t format,
+                    BufferCallback callback) {
+        sp<IGraphicBufferProducer> producer;
+        sp<IGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+
+        consumer->setDefaultBufferSize(width, height);
+        consumer->setDefaultBufferFormat(format);
+
+        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
+
+        mListener = new BufferListener(consumer, callback);
+        mBufferItemConsumer->setFrameAvailableListener(mListener);
+
+        mSurface = new Surface(producer, true);
+    }
+
+    /* Used by Egl manager. The surface is never displayed. */
+    sp<Surface> getSurface() const { return mSurface; }
+
+private:
+    sp<BufferItemConsumer> mBufferItemConsumer;
+    sp<BufferListener> mListener;
+    /* Used by Egl manager. The surface is never displayed */
+    sp<Surface> mSurface;
+};
+
+/* Used to generate valid fences. It is not possible to create a dummy sync
+ * fence for testing. Egl can generate buffers along with a valid fence.
+ * The buffer cannot be guaranteed to be the same format across all devices so
+ * a CPU filled buffer is used instead. The Egl fence is used along with the
+ * CPU filled buffer. */
+class EglManager {
+public:
+    EglManager()
+          : mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT) {}
+
+    ~EglManager() { cleanup(); }
+
+    int initialize(sp<Surface> surface) {
+        mSurface = surface;
+
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        if (mEglDisplay == EGL_NO_DISPLAY) return false;
+
+        EGLint major;
+        EGLint minor;
+        if (!eglInitialize(mEglDisplay, &major, &minor)) {
+            ALOGW("Could not initialize EGL");
+            return false;
+        }
+
+        /* We're going to use a 1x1 pbuffer surface later on
+         * The configuration distance doesn't really matter for what we're
+         * trying to do */
+        EGLint configAttrs[] = {EGL_RENDERABLE_TYPE,
+                                EGL_OPENGL_ES2_BIT,
+                                EGL_RED_SIZE,
+                                8,
+                                EGL_GREEN_SIZE,
+                                8,
+                                EGL_BLUE_SIZE,
+                                8,
+                                EGL_ALPHA_SIZE,
+                                0,
+                                EGL_DEPTH_SIZE,
+                                24,
+                                EGL_STENCIL_SIZE,
+                                0,
+                                EGL_NONE};
+
+        EGLConfig configs[1];
+        EGLint configCnt;
+        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1, &configCnt)) {
+            ALOGW("Could not select EGL configuration");
+            eglReleaseThread();
+            eglTerminate(mEglDisplay);
+            return false;
+        }
+
+        if (configCnt <= 0) {
+            ALOGW("Could not find EGL configuration");
+            eglReleaseThread();
+            eglTerminate(mEglDisplay);
+            return false;
+        }
+
+        /* These objects are initialized below but the default "null" values are
+         * used to cleanup properly at any point in the initialization sequence */
+        EGLint attrs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
+        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT, attrs);
+        if (mEglContext == EGL_NO_CONTEXT) {
+            ALOGW("Could not create EGL context");
+            cleanup();
+            return false;
+        }
+
+        EGLint majorVersion;
+        if (!eglQueryContext(mEglDisplay, mEglContext, EGL_CONTEXT_CLIENT_VERSION, &majorVersion)) {
+            ALOGW("Could not query EGL version");
+            cleanup();
+            return false;
+        }
+
+        if (majorVersion != 3) {
+            ALOGW("Unsupported EGL version");
+            cleanup();
+            return false;
+        }
+
+        EGLint surfaceAttrs[] = {EGL_NONE};
+        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0], mSurface.get(), surfaceAttrs);
+        if (mEglSurface == EGL_NO_SURFACE) {
+            ALOGW("Could not create EGL surface");
+            cleanup();
+            return false;
+        }
+
+        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+            ALOGW("Could not change current EGL context");
+            cleanup();
+            return false;
+        }
+
+        return true;
+    }
+
+    void makeCurrent() const { eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext); }
+
+    void present() const { eglSwapBuffers(mEglDisplay, mEglSurface); }
+
+private:
+    void cleanup() {
+        if (mEglDisplay == EGL_NO_DISPLAY) return;
+        if (mEglSurface != EGL_NO_SURFACE) eglDestroySurface(mEglDisplay, mEglSurface);
+        if (mEglContext != EGL_NO_CONTEXT) eglDestroyContext(mEglDisplay, mEglContext);
+
+        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        eglReleaseThread();
+        eglTerminate(mEglDisplay);
+    }
+
+    sp<Surface> mSurface;
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurface;
+    EGLContext mEglContext;
+};
+
+class Program {
+public:
+    ~Program() {
+        if (mInitialized) {
+            glDetachShader(mProgram, mVertexShader);
+            glDetachShader(mProgram, mFragmentShader);
+
+            glDeleteShader(mVertexShader);
+            glDeleteShader(mFragmentShader);
+
+            glDeleteProgram(mProgram);
+        }
+    }
+
+    bool initialize(const char* vertex, const char* fragment) {
+        mVertexShader = buildShader(vertex, GL_VERTEX_SHADER);
+        if (!mVertexShader) {
+            return false;
+        }
+
+        mFragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
+        if (!mFragmentShader) {
+            return false;
+        }
+
+        mProgram = glCreateProgram();
+        glAttachShader(mProgram, mVertexShader);
+        glAttachShader(mProgram, mFragmentShader);
+
+        glLinkProgram(mProgram);
+
+        GLint status;
+        glGetProgramiv(mProgram, GL_LINK_STATUS, &status);
+        if (status != GL_TRUE) {
+            GLint length = 0;
+            glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &length);
+            if (length > 1) {
+                GLchar log[length];
+                glGetProgramInfoLog(mProgram, length, nullptr, &log[0]);
+                ALOGE("%s", log);
+            }
+            ALOGE("Error while linking shaders");
+            return false;
+        }
+        mInitialized = true;
+        return true;
+    }
+
+    void use() const { glUseProgram(mProgram); }
+
+    void bindVec4(GLint location, vec4 v) const { glUniform4f(location, v.x, v.y, v.z, v.w); }
+
+    void bindVec3(GLint location, const vec3* v, uint32_t count) const {
+        glUniform3fv(location, count, &(v->x));
+    }
+
+    void bindFloat(GLint location, float v) { glUniform1f(location, v); }
+
+private:
+    GLuint buildShader(const char* source, GLenum type) const {
+        GLuint shader = glCreateShader(type);
+        glShaderSource(shader, 1, &source, nullptr);
+        glCompileShader(shader);
+
+        GLint status;
+        glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+        if (status != GL_TRUE) {
+            ALOGE("Error while compiling shader of type 0x%x:\n===\n%s\n===", type, source);
+            // Some drivers return wrong values for GL_INFO_LOG_LENGTH
+            // use a fixed size instead
+            GLchar log[512];
+            glGetShaderInfoLog(shader, sizeof(log), nullptr, &log[0]);
+            ALOGE("Shader info log: %s", log);
+            return 0;
+        }
+
+        return shader;
+    }
+
+    GLuint mProgram = 0;
+    GLuint mVertexShader = 0;
+    GLuint mFragmentShader = 0;
+    bool mInitialized = false;
+};
+
+BufferGenerator::BufferGenerator()
+      : mSurfaceManager(new SurfaceManager), mEglManager(new EglManager), mProgram(new Program) {
+    const float width = 1000.0;
+    const float height = 1000.0;
+
+    auto setBufferWithContext =
+            std::bind(setBuffer, std::placeholders::_1, std::placeholders::_2, this);
+    mSurfaceManager->initialize(width, height, HAL_PIXEL_FORMAT_RGBA_8888, setBufferWithContext);
+
+    if (!mEglManager->initialize(mSurfaceManager->getSurface())) return;
+
+    mEglManager->makeCurrent();
+
+    if (!mProgram->initialize(VERTEX_SHADER, FRAGMENT_SHADER)) return;
+    mProgram->use();
+    mProgram->bindVec4(0, vec4{width, height, 1.0f / width, 1.0f / height});
+    mProgram->bindVec3(2, &SPHERICAL_HARMONICS[0], 4);
+
+    glEnableVertexAttribArray(0);
+    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &TRIANGLE[0]);
+
+    mInitialized = true;
+}
+
+BufferGenerator::~BufferGenerator() {
+    mEglManager->makeCurrent();
+}
+
+status_t BufferGenerator::get(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+    // mMutex is used to protect get() from getting called by multiple threads at the same time
+    static std::mutex mMutex;
+    std::lock_guard lock(mMutex);
+
+    if (!mInitialized) {
+        if (outBuffer) {
+            *outBuffer = nullptr;
+        }
+        if (*outFence) {
+            *outFence = nullptr;
+        }
+        return -EINVAL;
+    }
+
+    // Generate a buffer and fence. They will be returned through the setBuffer callback
+    mEglManager->makeCurrent();
+
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    const std::chrono::duration<float> time = std::chrono::steady_clock::now() - mEpoch;
+    mProgram->bindFloat(1, time.count());
+
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+
+    mPending = true;
+    mEglManager->present();
+
+    // Wait for the setBuffer callback
+    if (!mConditionVariable.wait_for(mMutex, std::chrono::seconds(2),
+                                     [this] { return !mPending; })) {
+        ALOGE("failed to set buffer and fence");
+        return -ETIME;
+    }
+
+    // Return buffer and fence
+    if (outBuffer) {
+        *outBuffer = mGraphicBuffer;
+    }
+    if (outFence) {
+        *outFence = new Fence(mFence);
+    } else {
+        close(mFence);
+    }
+    mGraphicBuffer = nullptr;
+    mFence = -1;
+
+    return NO_ERROR;
+}
+
+// static
+void BufferGenerator::setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence,
+                                void* bufferGenerator) {
+    BufferGenerator* generator = static_cast<BufferGenerator*>(bufferGenerator);
+    generator->mGraphicBuffer = buffer;
+    generator->mFence = fence;
+    generator->mPending = false;
+    generator->mConditionVariable.notify_all();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/BufferGenerator.h b/services/surfaceflinger/tests/BufferGenerator.h
new file mode 100644
index 0000000..a3ffe86
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGenerator.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <condition_variable>
+#include <mutex>
+
+#include <ui/GraphicBuffer.h>
+
+namespace android {
+
+class SurfaceManager;
+class EglManager;
+class Program;
+
+class BufferGenerator {
+public:
+    BufferGenerator();
+    ~BufferGenerator();
+
+    /* Get a new fence */
+    status_t get(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence);
+
+    /* Static callback that sets the fence on a particular instance */
+    static void setBuffer(const sp<GraphicBuffer>& buffer, int32_t fence, void* fenceGenerator);
+
+private:
+    bool mInitialized = false;
+
+    std::unique_ptr<SurfaceManager> mSurfaceManager;
+    std::unique_ptr<EglManager> mEglManager;
+    std::unique_ptr<Program> mProgram;
+
+    std::condition_variable_any mConditionVariable;
+
+    sp<GraphicBuffer> mGraphicBuffer;
+    int32_t mFence = -1;
+    bool mPending = false;
+
+    using Epoch = std::chrono::time_point<std::chrono::steady_clock>;
+    Epoch mEpoch = std::chrono::steady_clock::now();
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/BufferGeneratorShader.h b/services/surfaceflinger/tests/BufferGeneratorShader.h
new file mode 100644
index 0000000..564cda3
--- /dev/null
+++ b/services/surfaceflinger/tests/BufferGeneratorShader.h
@@ -0,0 +1,355 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <GLES3/gl3.h>
+#include <math/vec2.h>
+#include <math/vec3.h>
+#include <math/vec4.h>
+
+static const char* VERTEX_SHADER = R"SHADER__(#version 300 es
+precision highp float;
+
+layout(location = 0) in vec4 mesh_position;
+
+void main() {
+    gl_Position = mesh_position;
+}
+)SHADER__";
+
+static const char* FRAGMENT_SHADER = R"SHADER__(#version 300 es
+precision highp float;
+
+layout(location = 0) uniform vec4 resolution;
+layout(location = 1) uniform float time;
+layout(location = 2) uniform vec3[4] SPHERICAL_HARMONICS;
+
+layout(location = 0) out vec4 fragColor;
+
+#define saturate(x) clamp(x, 0.0, 1.0)
+#define PI 3.14159265359
+
+//------------------------------------------------------------------------------
+// Distance field functions
+//------------------------------------------------------------------------------
+
+float sdPlane(in vec3 p) {
+    return p.y;
+}
+
+float sdSphere(in vec3 p, float s) {
+    return length(p) - s;
+}
+
+float sdTorus(in vec3 p, in vec2 t) {
+    return length(vec2(length(p.xz) - t.x, p.y)) - t.y;
+}
+
+vec2 opUnion(vec2 d1, vec2 d2) {
+    return d1.x < d2.x ? d1 : d2;
+}
+
+vec2 scene(in vec3 position) {
+    vec2 scene = opUnion(
+          vec2(sdPlane(position), 1.0),
+          vec2(sdSphere(position - vec3(0.0, 0.4, 0.0), 0.4), 12.0)
+    );
+    return scene;
+}
+
+//------------------------------------------------------------------------------
+// Ray casting
+//------------------------------------------------------------------------------
+
+float shadow(in vec3 origin, in vec3 direction, in float tmin, in float tmax) {
+    float hit = 1.0;
+
+    for (float t = tmin; t < tmax; ) {
+        float h = scene(origin + direction * t).x;
+        if (h < 0.001) return 0.0;
+        t += h;
+        hit = min(hit, 10.0 * h / t);
+    }
+
+    return clamp(hit, 0.0, 1.0);
+}
+
+vec2 traceRay(in vec3 origin, in vec3 direction) {
+    float tmin = 0.02;
+    float tmax = 20.0;
+
+    float material = -1.0;
+    float t = tmin;
+
+    for ( ; t < tmax; ) {
+        vec2 hit = scene(origin + direction * t);
+        if (hit.x < 0.002 || t > tmax) break;
+        t += hit.x;
+        material = hit.y;
+    }
+
+    if (t > tmax) {
+        material = -1.0;
+    }
+
+    return vec2(t, material);
+}
+
+vec3 normal(in vec3 position) {
+    vec3 epsilon = vec3(0.001, 0.0, 0.0);
+    vec3 n = vec3(
+          scene(position + epsilon.xyy).x - scene(position - epsilon.xyy).x,
+          scene(position + epsilon.yxy).x - scene(position - epsilon.yxy).x,
+          scene(position + epsilon.yyx).x - scene(position - epsilon.yyx).x);
+    return normalize(n);
+}
+
+//------------------------------------------------------------------------------
+// BRDF
+//------------------------------------------------------------------------------
+
+float pow5(float x) {
+    float x2 = x * x;
+    return x2 * x2 * x;
+}
+
+float D_GGX(float linearRoughness, float NoH, const vec3 h) {
+    // Walter et al. 2007, "Microfacet Models for Refraction through Rough Surfaces"
+    float oneMinusNoHSquared = 1.0 - NoH * NoH;
+    float a = NoH * linearRoughness;
+    float k = linearRoughness / (oneMinusNoHSquared + a * a);
+    float d = k * k * (1.0 / PI);
+    return d;
+}
+
+float V_SmithGGXCorrelated(float linearRoughness, float NoV, float NoL) {
+    // Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"
+    float a2 = linearRoughness * linearRoughness;
+    float GGXV = NoL * sqrt((NoV - a2 * NoV) * NoV + a2);
+    float GGXL = NoV * sqrt((NoL - a2 * NoL) * NoL + a2);
+    return 0.5 / (GGXV + GGXL);
+}
+
+vec3 F_Schlick(const vec3 f0, float VoH) {
+    // Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
+    return f0 + (vec3(1.0) - f0) * pow5(1.0 - VoH);
+}
+
+float F_Schlick(float f0, float f90, float VoH) {
+    return f0 + (f90 - f0) * pow5(1.0 - VoH);
+}
+
+float Fd_Burley(float linearRoughness, float NoV, float NoL, float LoH) {
+    // Burley 2012, "Physically-Based Shading at Disney"
+    float f90 = 0.5 + 2.0 * linearRoughness * LoH * LoH;
+    float lightScatter = F_Schlick(1.0, f90, NoL);
+    float viewScatter  = F_Schlick(1.0, f90, NoV);
+    return lightScatter * viewScatter * (1.0 / PI);
+}
+
+float Fd_Lambert() {
+    return 1.0 / PI;
+}
+
+//------------------------------------------------------------------------------
+// Indirect lighting
+//------------------------------------------------------------------------------
+
+vec3 Irradiance_SphericalHarmonics(const vec3 n) {
+    return max(
+          SPHERICAL_HARMONICS[0]
+        + SPHERICAL_HARMONICS[1] * (n.y)
+        + SPHERICAL_HARMONICS[2] * (n.z)
+        + SPHERICAL_HARMONICS[3] * (n.x)
+        , 0.0);
+}
+
+vec2 PrefilteredDFG_Karis(float roughness, float NoV) {
+    // Karis 2014, "Physically Based Material on Mobile"
+    const vec4 c0 = vec4(-1.0, -0.0275, -0.572,  0.022);
+    const vec4 c1 = vec4( 1.0,  0.0425,  1.040, -0.040);
+
+    vec4 r = roughness * c0 + c1;
+    float a004 = min(r.x * r.x, exp2(-9.28 * NoV)) * r.x + r.y;
+
+    return vec2(-1.04, 1.04) * a004 + r.zw;
+}
+
+//------------------------------------------------------------------------------
+// Tone mapping and transfer functions
+//------------------------------------------------------------------------------
+
+vec3 Tonemap_ACES(const vec3 x) {
+    // Narkowicz 2015, "ACES Filmic Tone Mapping Curve"
+    const float a = 2.51;
+    const float b = 0.03;
+    const float c = 2.43;
+    const float d = 0.59;
+    const float e = 0.14;
+    return (x * (a * x + b)) / (x * (c * x + d) + e);
+}
+
+vec3 OECF_sRGBFast(const vec3 linear) {
+    return pow(linear, vec3(1.0 / 2.2));
+}
+
+//------------------------------------------------------------------------------
+// Rendering
+//------------------------------------------------------------------------------
+
+vec3 render(in vec3 origin, in vec3 direction, out float distance) {
+    // Sky gradient
+    vec3 color = vec3(0.65, 0.85, 1.0) + direction.y * 0.72;
+
+    // (distance, material)
+    vec2 hit = traceRay(origin, direction);
+    distance = hit.x;
+    float material = hit.y;
+
+    // We've hit something in the scene
+    if (material > 0.0) {
+        vec3 position = origin + distance * direction;
+
+        vec3 v = normalize(-direction);
+        vec3 n = normal(position);
+        vec3 l = normalize(vec3(0.6, 0.7, -0.7));
+        vec3 h = normalize(v + l);
+        vec3 r = normalize(reflect(direction, n));
+
+        float NoV = abs(dot(n, v)) + 1e-5;
+        float NoL = saturate(dot(n, l));
+        float NoH = saturate(dot(n, h));
+        float LoH = saturate(dot(l, h));
+
+        vec3 baseColor = vec3(0.0);
+        float roughness = 0.0;
+        float metallic = 0.0;
+
+        float intensity = 2.0;
+        float indirectIntensity = 0.64;
+
+        if (material < 4.0)  {
+            // Checkerboard floor
+            float f = mod(floor(6.0 * position.z) + floor(6.0 * position.x), 2.0);
+            baseColor = 0.4 + f * vec3(0.6);
+            roughness = 0.1;
+        } else if (material < 16.0) {
+            // Metallic objects
+            baseColor = vec3(0.3, 0.0, 0.0);
+            roughness = 0.2;
+        }
+
+        float linearRoughness = roughness * roughness;
+        vec3 diffuseColor = (1.0 - metallic) * baseColor.rgb;
+        vec3 f0 = 0.04 * (1.0 - metallic) + baseColor.rgb * metallic;
+
+        float attenuation = shadow(position, l, 0.02, 2.5);
+
+        // specular BRDF
+        float D = D_GGX(linearRoughness, NoH, h);
+        float V = V_SmithGGXCorrelated(linearRoughness, NoV, NoL);
+        vec3  F = F_Schlick(f0, LoH);
+        vec3 Fr = (D * V) * F;
+
+        // diffuse BRDF
+        vec3 Fd = diffuseColor * Fd_Burley(linearRoughness, NoV, NoL, LoH);
+
+        color = Fd + Fr;
+        color *= (intensity * attenuation * NoL) * vec3(0.98, 0.92, 0.89);
+
+        // diffuse indirect
+        vec3 indirectDiffuse = Irradiance_SphericalHarmonics(n) * Fd_Lambert();
+
+        vec2 indirectHit = traceRay(position, r);
+        vec3 indirectSpecular = vec3(0.65, 0.85, 1.0) + r.y * 0.72;
+        if (indirectHit.y > 0.0) {
+            if (indirectHit.y < 4.0)  {
+                vec3 indirectPosition = position + indirectHit.x * r;
+                // Checkerboard floor
+                float f = mod(floor(6.0 * indirectPosition.z) + floor(6.0 * indirectPosition.x), 2.0);
+                indirectSpecular = 0.4 + f * vec3(0.6);
+            } else if (indirectHit.y < 16.0) {
+                // Metallic objects
+                indirectSpecular = vec3(0.3, 0.0, 0.0);
+            }
+        }
+
+        // indirect contribution
+        vec2 dfg = PrefilteredDFG_Karis(roughness, NoV);
+        vec3 specularColor = f0 * dfg.x + dfg.y;
+        vec3 ibl = diffuseColor * indirectDiffuse + indirectSpecular * specularColor;
+
+        color += ibl * indirectIntensity;
+    }
+
+    return color;
+}
+
+//------------------------------------------------------------------------------
+// Setup and execution
+//------------------------------------------------------------------------------
+
+mat3 setCamera(in vec3 origin, in vec3 target, float rotation) {
+    vec3 forward = normalize(target - origin);
+    vec3 orientation = vec3(sin(rotation), cos(rotation), 0.0);
+    vec3 left = normalize(cross(forward, orientation));
+    vec3 up = normalize(cross(left, forward));
+    return mat3(left, up, forward);
+}
+
+void main() {
+    // Normalized coordinates
+    vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy;
+    // Aspect ratio
+    p.x *= resolution.x / resolution.y;
+
+    // Camera position and "look at"
+    vec3 origin = vec3(0.0, 1.0, 0.0);
+    vec3 target = vec3(0.0);
+
+    origin.x += 2.0 * cos(time * 0.2);
+    origin.z += 2.0 * sin(time * 0.2);
+
+    mat3 toWorld = setCamera(origin, target, 0.0);
+    vec3 direction = toWorld * normalize(vec3(p.xy, 2.0));
+
+    // Render scene
+    float distance;
+    vec3 color = render(origin, direction, distance);
+
+    // Tone mapping
+    color = Tonemap_ACES(color);
+
+    // Exponential distance fog
+    color = mix(color, 0.8 * vec3(0.7, 0.8, 1.0), 1.0 - exp2(-0.011 * distance * distance));
+
+    // Gamma compression
+    color = OECF_sRGBFast(color);
+
+    fragColor = vec4(color, 1.0);
+}
+)SHADER__";
+
+static const android::vec3 SPHERICAL_HARMONICS[4] =
+        {{0.754554516862612, 0.748542953903366, 0.790921515418539},
+         {-0.083856548007422, 0.092533500963210, 0.322764661032516},
+         {0.308152705331738, 0.366796330467391, 0.466698181299906},
+         {-0.188884931542396, -0.277402551592231, -0.377844212327557}};
+
+static const android::vec4 TRIANGLE[3] = {{-1.0f, -1.0f, 1.0f, 1.0f},
+                                          {3.0f, -1.0f, 1.0f, 1.0f},
+                                          {-1.0f, 3.0f, 1.0f, 1.0f}};
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 037d32f..d118ad6 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -28,7 +28,6 @@
 
 #include <gui/ISurfaceComposer.h>
 #include <gui/LayerState.h>
-
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <private/gui/ComposerService.h>
@@ -41,6 +40,8 @@
 #include <math.h>
 #include <math/vec3.h>
 
+#include "BufferGenerator.h"
+
 namespace android {
 
 namespace {
@@ -478,6 +479,11 @@
         return screenshot;
     }
 
+    static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) {
+        static BufferGenerator bufferGenerator;
+        return bufferGenerator.get(outBuffer, outFence);
+    }
+
     sp<SurfaceComposerClient> mClient;
 
     sp<IBinder> mDisplay;
@@ -2164,6 +2170,36 @@
 
 TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) {
     sp<SurfaceControl> layer;
+    Transaction transaction;
+    ASSERT_NO_FATAL_FAILURE(
+            layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+    sp<GraphicBuffer> buffer =
+            new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+                              BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                      BufferUsage::COMPOSER_OVERLAY,
+                              "test");
+    fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+    sp<Fence> fence;
+    if (getBuffer(nullptr, &fence) != NO_ERROR) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply();
+
+    status_t status = fence->wait(1000);
+    ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status);
+    std::this_thread::sleep_for(200ms);
+
+    auto shot = screenshot();
+    shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+    shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetFenceNull_BufferState) {
+    sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(
             layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
 
@@ -2514,7 +2550,7 @@
     }
 
     void addSurface(ExpectedResult::Transaction transactionResult, const sp<SurfaceControl>& layer,
-                    ExpectedResult::Buffer bufferResult = NOT_ACQUIRED,
+                    ExpectedResult::Buffer bufferResult = ACQUIRED,
                     ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
         mTransactionResult = transactionResult;
         mExpectedSurfaceResults.emplace(std::piecewise_construct,
@@ -2524,7 +2560,7 @@
 
     void addSurfaces(ExpectedResult::Transaction transactionResult,
                      const std::vector<sp<SurfaceControl>>& layers,
-                     ExpectedResult::Buffer bufferResult = NOT_ACQUIRED,
+                     ExpectedResult::Buffer bufferResult = ACQUIRED,
                      ExpectedResult::PreviousBuffer previousBufferResult = NOT_RELEASED) {
         for (const auto& layer : layers) {
             addSurface(transactionResult, layer, bufferResult, previousBufferResult);
@@ -2631,24 +2667,22 @@
         return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
     }
 
-    static void fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
-                                const sp<SurfaceControl>& layer = nullptr) {
+    static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
+                               const sp<SurfaceControl>& layer = nullptr) {
         if (layer) {
-            sp<GraphicBuffer> buffer =
-                    new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
-                                      BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
-                                              BufferUsage::COMPOSER_OVERLAY |
-                                              BufferUsage::GPU_TEXTURE,
-                                      "test");
-            fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
-
-            sp<Fence> fence = new Fence(-1);
+            sp<GraphicBuffer> buffer;
+            sp<Fence> fence;
+            int err = getBuffer(&buffer, &fence);
+            if (err != NO_ERROR) {
+                return err;
+            }
 
             transaction.setBuffer(layer, buffer).setAcquireFence(layer, fence);
         }
 
         transaction.addTransactionCompletedCallback(callbackHelper->function,
                                                     callbackHelper->getContext());
+        return NO_ERROR;
     }
 
     static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult,
@@ -2680,7 +2714,11 @@
 
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback, layer);
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.apply();
 
@@ -2695,19 +2733,28 @@
 
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback);
+    int err = fillTransaction(transaction, &callback);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
 
     ExpectedResult expected;
-    expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer);
+    expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+                        ExpectedResult::Buffer::NOT_ACQUIRED);
     EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
 }
 
 TEST_F(LayerCallbackTest, NoStateChange) {
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback);
+    int err = fillTransaction(transaction, &callback);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.apply();
 
@@ -2721,7 +2768,11 @@
 
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback, layer);
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply();
 
@@ -2737,8 +2788,16 @@
 
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2, layer2);
+    int err = fillTransaction(transaction1, &callback1, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2756,8 +2815,16 @@
 
     Transaction transaction1, transaction2;
     CallbackHelper callback;
-    fillTransaction(transaction1, &callback, layer1);
-    fillTransaction(transaction2, &callback, layer2);
+    int err = fillTransaction(transaction1, &callback, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction2.merge(std::move(transaction1)).apply();
 
@@ -2773,8 +2840,16 @@
 
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
-    fillTransaction(transaction1, &callback1, layer);
-    fillTransaction(transaction2, &callback2, layer);
+    int err = fillTransaction(transaction1, &callback1, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction2.merge(std::move(transaction1)).apply();
 
@@ -2784,25 +2859,6 @@
     EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
 }
 
-TEST_F(LayerCallbackTest, Merge_SingleBuffer) {
-    sp<SurfaceControl> layer1, layer2;
-    ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
-    ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
-
-    Transaction transaction1, transaction2;
-    CallbackHelper callback1, callback2;
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2);
-
-    transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
-    transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
-
-    ExpectedResult expected;
-    expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2});
-    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
-    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
-}
-
 TEST_F(LayerCallbackTest, Merge_DifferentClients) {
     sp<SurfaceComposerClient> client1(new SurfaceComposerClient),
             client2(new SurfaceComposerClient);
@@ -2818,8 +2874,16 @@
 
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2, layer2);
+    int err = fillTransaction(transaction1, &callback1, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2837,13 +2901,17 @@
     Transaction transaction;
     CallbackHelper callback;
     for (size_t i = 0; i < 10; i++) {
-        fillTransaction(transaction, &callback, layer);
+        int err = fillTransaction(transaction, &callback, layer);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction.apply();
 
         ExpectedResult expected;
         expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
-                            ExpectedResult::Buffer::NOT_ACQUIRED,
+                            ExpectedResult::Buffer::ACQUIRED,
                             (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
                                      : ExpectedResult::PreviousBuffer::RELEASED);
         EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected));
@@ -2861,10 +2929,18 @@
         ExpectedResult expected;
 
         if (i == 0) {
-            fillTransaction(transaction, &callback, layer);
+            int err = fillTransaction(transaction, &callback, layer);
+            if (err) {
+                GTEST_SUCCEED() << "test not supported";
+                return;
+            }
             expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
         } else {
-            fillTransaction(transaction, &callback);
+            int err = fillTransaction(transaction, &callback);
+            if (err) {
+                GTEST_SUCCEED() << "test not supported";
+                return;
+            }
         }
 
         transaction.apply();
@@ -2882,9 +2958,17 @@
     CallbackHelper callback;
     for (size_t i = 0; i < 10; i++) {
         if (i == 0) {
-            fillTransaction(transaction, &callback, layer);
+            int err = fillTransaction(transaction, &callback, layer);
+            if (err) {
+                GTEST_SUCCEED() << "test not supported";
+                return;
+            }
         } else {
-            fillTransaction(transaction, &callback);
+            int err = fillTransaction(transaction, &callback);
+            if (err) {
+                GTEST_SUCCEED() << "test not supported";
+                return;
+            }
         }
 
         transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
@@ -2892,7 +2976,9 @@
         ExpectedResult expected;
         expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED
                                      : ExpectedResult::Transaction::NOT_PRESENTED,
-                            layer);
+                            layer,
+                            (i == 0) ? ExpectedResult::Buffer::ACQUIRED
+                                     : ExpectedResult::Buffer::NOT_ACQUIRED);
         EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, i == 0));
     }
     ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState());
@@ -2906,15 +2992,23 @@
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
     for (size_t i = 0; i < 10; i++) {
-        fillTransaction(transaction1, &callback1, layer1);
-        fillTransaction(transaction2, &callback2, layer2);
+        int err = fillTransaction(transaction1, &callback1, layer1);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
+        err = fillTransaction(transaction2, &callback2, layer2);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
         transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
 
         ExpectedResult expected;
         expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
-                             ExpectedResult::Buffer::NOT_ACQUIRED,
+                             ExpectedResult::Buffer::ACQUIRED,
                              (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
                                       : ExpectedResult::PreviousBuffer::RELEASED);
         EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
@@ -2939,15 +3033,23 @@
     Transaction transaction1, transaction2;
     CallbackHelper callback1, callback2;
     for (size_t i = 0; i < 10; i++) {
-        fillTransaction(transaction1, &callback1, layer1);
-        fillTransaction(transaction2, &callback2, layer2);
+        int err = fillTransaction(transaction1, &callback1, layer1);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
+        err = fillTransaction(transaction2, &callback2, layer2);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
         transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
 
         ExpectedResult expected;
         expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
-                             ExpectedResult::Buffer::NOT_ACQUIRED,
+                             ExpectedResult::Buffer::ACQUIRED,
                              (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED
                                       : ExpectedResult::PreviousBuffer::RELEASED);
         EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
@@ -2973,8 +3075,16 @@
     CallbackHelper callback1, callback2;
 
     // Normal call to set up test
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2, layer2);
+    int err = fillTransaction(transaction1, &callback1, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -2986,8 +3096,16 @@
     expected.reset();
 
     // Test
-    fillTransaction(transaction1, &callback1);
-    fillTransaction(transaction2, &callback2);
+    err = fillTransaction(transaction1, &callback1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction2.merge(std::move(transaction1)).apply();
 
@@ -3012,8 +3130,16 @@
     CallbackHelper callback1, callback2;
 
     // Normal call to set up test
-    fillTransaction(transaction1, &callback1, layer1);
-    fillTransaction(transaction2, &callback2, layer2);
+    int err = fillTransaction(transaction1, &callback1, layer1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2, layer2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
@@ -3025,12 +3151,21 @@
     expected.reset();
 
     // Test
-    fillTransaction(transaction1, &callback1);
-    fillTransaction(transaction2, &callback2);
+    err = fillTransaction(transaction1, &callback1);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+    err = fillTransaction(transaction2, &callback2);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
 
-    expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2);
+    expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2,
+                        ExpectedResult::Buffer::NOT_ACQUIRED);
     EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
     EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
 }
@@ -3047,13 +3182,16 @@
     for (auto& expected : expectedResults) {
         expected.reset();
         expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
-                            ExpectedResult::Buffer::NOT_ACQUIRED, previousBufferResult);
+                            ExpectedResult::Buffer::ACQUIRED, previousBufferResult);
         previousBufferResult = ExpectedResult::PreviousBuffer::RELEASED;
 
-        fillTransaction(transaction, &callback, layer);
+        int err = fillTransaction(transaction, &callback, layer);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction.apply();
-        std::this_thread::sleep_for(200ms);
     }
     EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
 }
@@ -3062,23 +3200,33 @@
     sp<SurfaceControl> layer;
     ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
 
+    // Normal call to set up test
     Transaction transaction;
     CallbackHelper callback;
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
+
+    transaction.apply();
+
+    ExpectedResult expected;
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+    EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+
+    // Test
     std::vector<ExpectedResult> expectedResults(50);
-    bool first = true;
     for (auto& expected : expectedResults) {
         expected.reset();
 
-        if (first) {
-            fillTransaction(transaction, &callback, layer);
-            expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
-            first = false;
-        } else {
-            fillTransaction(transaction, &callback);
+        err = fillTransaction(transaction, &callback);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
         }
 
         transaction.apply();
-        std::this_thread::sleep_for(200ms);
     }
     EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
 }
@@ -3090,7 +3238,11 @@
     // Normal call to set up test
     Transaction transaction;
     CallbackHelper callback;
-    fillTransaction(transaction, &callback, layer);
+    int err = fillTransaction(transaction, &callback, layer);
+    if (err) {
+        GTEST_SUCCEED() << "test not supported";
+        return;
+    }
 
     transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
 
@@ -3102,13 +3254,16 @@
     std::vector<ExpectedResult> expectedResults(50);
     for (auto& expected : expectedResults) {
         expected.reset();
-        expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer);
+        expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer,
+                            ExpectedResult::Buffer::NOT_ACQUIRED);
 
-        fillTransaction(transaction, &callback);
+        err = fillTransaction(transaction, &callback);
+        if (err) {
+            GTEST_SUCCEED() << "test not supported";
+            return;
+        }
 
         transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
-
-        std::this_thread::sleep_for(200ms);
     }
     EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true));
 }
diff --git a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
index 676617d..01520fc 100644
--- a/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
+++ b/services/vr/bufferhubd/include/private/dvr/buffer_hub.h
@@ -41,12 +41,12 @@
 
   // Captures buffer info for use by BufferHubService::DumpState().
   struct BufferInfo {
-    // Common data field shared by BufferProducer and ProducerQueue.
+    // Common data field shared by ProducerBuffer and ProducerQueue.
     int id = -1;
     int type = -1;
     size_t consumer_count = 0;
 
-    // Data field for buffer producer.
+    // Data field for producer buffer.
     uint32_t width = 0;
     uint32_t height = 0;
     uint32_t layer_count = 0;
diff --git a/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h b/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
index c4003da..0456ad8 100644
--- a/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
+++ b/services/vr/bufferhubd/include/private/dvr/producer_queue_channel.h
@@ -37,11 +37,11 @@
                                  uint32_t format, uint64_t usage,
                                  size_t buffer_count);
 
-  // Inserts a BufferProducer into the queue. Note that the buffer must be in
+  // Inserts a ProducerBuffer into the queue. Note that the buffer must be in
   // Gain'ed state for the operation to succeed.
   pdx::Status<size_t> OnProducerQueueInsertBuffer(pdx::Message& message, int buffer_cid);
 
-  // Removes a BufferProducer indicated by |slot|. Note that the buffer must be
+  // Removes a ProducerBuffer indicated by |slot|. Note that the buffer must be
   // in Gain'ed state for the operation to succeed.
   pdx::Status<void> OnProducerQueueRemoveBuffer(pdx::Message& message,
                                                 size_t slot);
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 5c484b8..2a6e9da 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -455,7 +455,7 @@
   uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire);
   if (!BufferHubDefs::IsClientGained(
       buffer_state, BufferHubDefs::kFirstClientStateMask)) {
-    // Can only detach a BufferProducer when it's in gained state.
+    // Can only detach a ProducerBuffer when it's in gained state.
     ALOGW(
         "ProducerChannel::OnProducerDetach: The buffer (id=%d, state=%"
         PRIx32