OSDN Git Service

Make IGraphicBufferProducer a hybrid interface.
[android-x86/frameworks-native.git] / libs / gui / IGraphicBufferProducer.cpp
index c3c6235..74117c8 100644 (file)
@@ -20,6 +20,7 @@
 #include <utils/Errors.h>
 #include <utils/NativeHandle.h>
 #include <utils/RefBase.h>
+#include <utils/String8.h>
 #include <utils/Timers.h>
 #include <utils/Vector.h>
 
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/IProducerListener.h>
 
+#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
+
 namespace android {
 // ----------------------------------------------------------------------------
 
+using ::android::hardware::graphics::bufferqueue::V1_0::utils::
+        H2BGraphicBufferProducer;
+
 enum {
     REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
-    SET_BUFFER_COUNT,
     DEQUEUE_BUFFER,
     DETACH_BUFFER,
     DETACH_NEXT_BUFFER,
@@ -49,12 +54,20 @@ enum {
     ALLOW_ALLOCATION,
     SET_GENERATION_NUMBER,
     GET_CONSUMER_NAME,
+    SET_MAX_DEQUEUED_BUFFER_COUNT,
+    SET_ASYNC_MODE,
+    SET_SHARED_BUFFER_MODE,
+    SET_AUTO_REFRESH,
+    SET_DEQUEUE_TIMEOUT,
+    GET_LAST_QUEUED_BUFFER,
+    GET_FRAME_TIMESTAMPS,
+    GET_UNIQUE_ID
 };
 
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
 {
 public:
-    BpGraphicBufferProducer(const sp<IBinder>& impl)
+    explicit BpGraphicBufferProducer(const sp<IBinder>& impl)
         : BpInterface<IGraphicBufferProducer>(impl)
     {
     }
@@ -82,12 +95,13 @@ public:
         return result;
     }
 
-    virtual status_t setBufferCount(int bufferCount)
-    {
+    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
         Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(bufferCount);
-        status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(maxDequeuedBuffers);
+        status_t result = remote()->transact(SET_MAX_DEQUEUED_BUFFER_COUNT,
+                data, &reply);
         if (result != NO_ERROR) {
             return result;
         }
@@ -95,25 +109,52 @@ public:
         return result;
     }
 
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
-            uint32_t width, uint32_t height, PixelFormat format,
-            uint32_t usage) {
+    virtual status_t setAsyncMode(bool async) {
         Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(async);
+        status_t result = remote()->transact(SET_ASYNC_MODE,
+                data, &reply);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        result = reply.readInt32();
+        return result;
+    }
+
+    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
+            uint32_t height, PixelFormat format, uint32_t usage,
+            FrameEventHistoryDelta* outTimestamps) {
+        Parcel data, reply;
+        bool getFrameTimestamps = (outTimestamps != nullptr);
+
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(async));
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
         data.writeUint32(usage);
+        data.writeBool(getFrameTimestamps);
+
         status_t result = remote()->transact(DEQUEUE_BUFFER, data, &reply);
         if (result != NO_ERROR) {
             return result;
         }
+
         *buf = reply.readInt32();
-        bool nonNull = reply.readInt32();
-        if (nonNull) {
-            *fence = new Fence();
-            reply.read(**fence);
+        *fence = new Fence();
+        result = reply.read(**fence);
+        if (result != NO_ERROR) {
+            fence->clear();
+            return result;
+        }
+        if (getFrameTimestamps) {
+            result = reply.read(*outTimestamps);
+            if (result != NO_ERROR) {
+                ALOGE("IGBP::dequeueBuffer failed to read timestamps: %d",
+                        result);
+                return result;
+            }
         }
         result = reply.readInt32();
         return result;
@@ -151,12 +192,21 @@ public:
             bool nonNull = reply.readInt32();
             if (nonNull) {
                 *outBuffer = new GraphicBuffer;
-                reply.read(**outBuffer);
+                result = reply.read(**outBuffer);
+                if (result != NO_ERROR) {
+                    outBuffer->clear();
+                    return result;
+                }
             }
             nonNull = reply.readInt32();
             if (nonNull) {
                 *outFence = new Fence;
-                reply.read(**outFence);
+                result = reply.read(**outFence);
+                if (result != NO_ERROR) {
+                    outBuffer->clear();
+                    outFence->clear();
+                    return result;
+                }
             }
         }
         return result;
@@ -178,24 +228,36 @@ public:
     virtual status_t queueBuffer(int buf,
             const QueueBufferInput& input, QueueBufferOutput* output) {
         Parcel data, reply;
+
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeInt32(buf);
         data.write(input);
+
         status_t result = remote()->transact(QUEUE_BUFFER, data, &reply);
         if (result != NO_ERROR) {
             return result;
         }
-        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
+
+        result = reply.read(*output);
+        if (result != NO_ERROR) {
+            return result;
+        }
+
         result = reply.readInt32();
         return result;
     }
 
-    virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
+    virtual status_t cancelBuffer(int buf, const sp<Fence>& fence) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeInt32(buf);
         data.write(*fence.get());
-        remote()->transact(CANCEL_BUFFER, data, &reply);
+        status_t result = remote()->transact(CANCEL_BUFFER, data, &reply);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        result = reply.readInt32();
+        return result;
     }
 
     virtual int query(int what, int* value) {
@@ -227,15 +289,16 @@ public:
         if (result != NO_ERROR) {
             return result;
         }
-        memcpy(output, reply.readInplace(sizeof(*output)), sizeof(*output));
+        reply.read(*output);
         result = reply.readInt32();
         return result;
     }
 
-    virtual status_t disconnect(int api) {
+    virtual status_t disconnect(int api, DisconnectMode mode) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeInt32(api);
+        data.writeInt32(static_cast<int32_t>(mode));
         status_t result =remote()->transact(DISCONNECT, data, &reply);
         if (result != NO_ERROR) {
             return result;
@@ -260,11 +323,10 @@ public:
         return result;
     }
 
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(async));
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
@@ -308,13 +370,243 @@ public:
         }
         return reply.readString8();
     }
+
+    virtual status_t setSharedBufferMode(bool sharedBufferMode) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(sharedBufferMode);
+        status_t result = remote()->transact(SET_SHARED_BUFFER_MODE, data,
+                &reply);
+        if (result == NO_ERROR) {
+            result = reply.readInt32();
+        }
+        return result;
+    }
+
+    virtual status_t setAutoRefresh(bool autoRefresh) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(autoRefresh);
+        status_t result = remote()->transact(SET_AUTO_REFRESH, data, &reply);
+        if (result == NO_ERROR) {
+            result = reply.readInt32();
+        }
+        return result;
+    }
+
+    virtual status_t setDequeueTimeout(nsecs_t timeout) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt64(timeout);
+        status_t result = remote()->transact(SET_DEQUEUE_TIMEOUT, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("setDequeueTimeout failed to transact: %d", result);
+            return result;
+        }
+        return reply.readInt32();
+    }
+
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence, float outTransformMatrix[16]) override {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER, data,
+                &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to transact: %d", result);
+            return result;
+        }
+        result = reply.readInt32();
+        if (result != NO_ERROR) {
+            return result;
+        }
+        bool hasBuffer = reply.readBool();
+        sp<GraphicBuffer> buffer;
+        if (hasBuffer) {
+            buffer = new GraphicBuffer();
+            result = reply.read(*buffer);
+            if (result == NO_ERROR) {
+                result = reply.read(outTransformMatrix, sizeof(float) * 16);
+            }
+        }
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
+            return result;
+        }
+        sp<Fence> fence(new Fence);
+        result = reply.read(*fence);
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to read fence: %d", result);
+            return result;
+        }
+        *outBuffer = buffer;
+        *outFence = fence;
+        return result;
+    }
+
+    virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) {
+        Parcel data, reply;
+        status_t result = data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        if (result != NO_ERROR) {
+            ALOGE("IGBP::getFrameTimestamps failed to write token: %d", result);
+            return;
+        }
+        result = remote()->transact(GET_FRAME_TIMESTAMPS, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("IGBP::getFrameTimestamps failed to transact: %d", result);
+            return;
+        }
+        result = reply.read(*outDelta);
+        if (result != NO_ERROR) {
+            ALOGE("IGBP::getFrameTimestamps failed to read timestamps: %d",
+                    result);
+        }
+    }
+
+    virtual status_t getUniqueId(uint64_t* outId) const {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        status_t result = remote()->transact(GET_UNIQUE_ID, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getUniqueId failed to transact: %d", result);
+        }
+        status_t actualResult = NO_ERROR;
+        result = reply.readInt32(&actualResult);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        result = reply.readUint64(outId);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        return actualResult;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
 // translation unit (see clang warning -Wweak-vtables)
 BpGraphicBufferProducer::~BpGraphicBufferProducer() {}
 
-IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer");
+class HpGraphicBufferProducer : public HpInterface<
+        BpGraphicBufferProducer, H2BGraphicBufferProducer> {
+public:
+    HpGraphicBufferProducer(const sp<IBinder>& base) : PBase(base) {}
+
+    status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override {
+        return mBase->requestBuffer(slot, buf);
+    }
+
+    status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) override {
+        return mBase->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+    }
+
+    status_t setAsyncMode(bool async) override {
+        return mBase->setAsyncMode(async);
+    }
+
+    status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
+            PixelFormat format, uint32_t usage,
+            FrameEventHistoryDelta* outTimestamps) override {
+        return mBase->dequeueBuffer(
+                slot, fence, w, h, format, usage, outTimestamps);
+    }
+
+    status_t detachBuffer(int slot) override {
+        return mBase->detachBuffer(slot);
+    }
+
+    status_t detachNextBuffer(
+            sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) override {
+        return mBase->detachNextBuffer(outBuffer, outFence);
+    }
+
+    status_t attachBuffer(
+            int* outSlot, const sp<GraphicBuffer>& buffer) override {
+        return mBase->attachBuffer(outSlot, buffer);
+    }
+
+    status_t queueBuffer(
+            int slot,
+            const QueueBufferInput& input,
+            QueueBufferOutput* output) override {
+        return mBase->queueBuffer(slot, input, output);
+    }
+
+    status_t cancelBuffer(int slot, const sp<Fence>& fence) override {
+        return mBase->cancelBuffer(slot, fence);
+    }
+
+    int query(int what, int* value) override {
+        return mBase->query(what, value);
+    }
+
+    status_t connect(
+            const sp<IProducerListener>& listener,
+            int api, bool producerControlledByApp,
+            QueueBufferOutput* output) override {
+        return mBase->connect(listener, api, producerControlledByApp, output);
+    }
+
+    status_t disconnect(
+            int api, DisconnectMode mode = DisconnectMode::Api) override {
+        return mBase->disconnect(api, mode);
+    }
+
+    status_t setSidebandStream(const sp<NativeHandle>& stream) override {
+        return mBase->setSidebandStream(stream);
+    }
+
+    void allocateBuffers(uint32_t width, uint32_t height,
+            PixelFormat format, uint32_t usage) override {
+        return mBase->allocateBuffers(width, height, format, usage);
+    }
+
+    status_t allowAllocation(bool allow) override {
+        return mBase->allowAllocation(allow);
+    }
+
+    status_t setGenerationNumber(uint32_t generationNumber) override {
+        return mBase->setGenerationNumber(generationNumber);
+    }
+
+    String8 getConsumerName() const override {
+        return mBase->getConsumerName();
+    }
+
+    status_t setSharedBufferMode(bool sharedBufferMode) override {
+        return mBase->setSharedBufferMode(sharedBufferMode);
+    }
+
+    status_t setAutoRefresh(bool autoRefresh) override {
+        return mBase->setAutoRefresh(autoRefresh);
+    }
+
+    status_t setDequeueTimeout(nsecs_t timeout) override {
+        return mBase->setDequeueTimeout(timeout);
+    }
+
+    status_t getLastQueuedBuffer(
+            sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence,
+            float outTransformMatrix[16]) override {
+        return mBase->getLastQueuedBuffer(
+                outBuffer, outFence, outTransformMatrix);
+    }
+
+    void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override {
+        return mBase->getFrameTimestamps(outDelta);
+    }
+
+    status_t getUniqueId(uint64_t* outId) const override {
+        return mBase->getUniqueId(outId);
+    }
+};
+
+IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer, HGraphicBufferProducer,
+        "android.gui.IGraphicBufferProducer");
 
 // ----------------------------------------------------------------------
 
@@ -334,28 +626,38 @@ status_t BnGraphicBufferProducer::onTransact(
             reply->writeInt32(result);
             return NO_ERROR;
         }
-        case SET_BUFFER_COUNT: {
+        case SET_MAX_DEQUEUED_BUFFER_COUNT: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            int bufferCount = data.readInt32();
-            int result = setBufferCount(bufferCount);
+            int maxDequeuedBuffers = data.readInt32();
+            int result = setMaxDequeuedBufferCount(maxDequeuedBuffers);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case SET_ASYNC_MODE: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            bool async = data.readInt32();
+            int result = setAsyncMode(async);
             reply->writeInt32(result);
             return NO_ERROR;
         }
         case DEQUEUE_BUFFER: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            bool async = static_cast<bool>(data.readInt32());
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
+            bool getTimestamps = data.readBool();
+
             int buf = 0;
-            sp<Fence> fence;
-            int result = dequeueBuffer(&buf, &fence, async, width, height,
-                    format, usage);
+            sp<Fence> fence = Fence::NO_FENCE;
+            FrameEventHistoryDelta frameTimestamps;
+            int result = dequeueBuffer(&buf, &fence, width, height, format,
+                    usage, getTimestamps ? &frameTimestamps : nullptr);
+
             reply->writeInt32(buf);
-            reply->writeInt32(fence != NULL);
-            if (fence != NULL) {
-                reply->write(*fence);
+            reply->write(*fence);
+            if (getTimestamps) {
+                reply->write(frameTimestamps);
             }
             reply->writeInt32(result);
             return NO_ERROR;
@@ -388,31 +690,36 @@ status_t BnGraphicBufferProducer::onTransact(
         case ATTACH_BUFFER: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
             sp<GraphicBuffer> buffer = new GraphicBuffer();
-            data.read(*buffer.get());
+            status_t result = data.read(*buffer.get());
             int slot = 0;
-            int result = attachBuffer(&slot, buffer);
+            if (result == NO_ERROR) {
+                result = attachBuffer(&slot, buffer);
+            }
             reply->writeInt32(slot);
             reply->writeInt32(result);
             return NO_ERROR;
         }
         case QUEUE_BUFFER: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+
             int buf = data.readInt32();
             QueueBufferInput input(data);
-            QueueBufferOutput* const output =
-                    reinterpret_cast<QueueBufferOutput *>(
-                            reply->writeInplace(sizeof(QueueBufferOutput)));
-            memset(output, 0, sizeof(QueueBufferOutput));
-            status_t result = queueBuffer(buf, input, output);
+            QueueBufferOutput output;
+            status_t result = queueBuffer(buf, input, &output);
+            reply->write(output);
             reply->writeInt32(result);
+
             return NO_ERROR;
         }
         case CANCEL_BUFFER: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
             int buf = data.readInt32();
             sp<Fence> fence = new Fence();
-            data.read(*fence.get());
-            cancelBuffer(buf, fence);
+            status_t result = data.read(*fence.get());
+            if (result == NO_ERROR) {
+                result = cancelBuffer(buf, fence);
+            }
+            reply->writeInt32(result);
             return NO_ERROR;
         }
         case QUERY: {
@@ -432,18 +739,17 @@ status_t BnGraphicBufferProducer::onTransact(
             }
             int api = data.readInt32();
             bool producerControlledByApp = data.readInt32();
-            QueueBufferOutput* const output =
-                    reinterpret_cast<QueueBufferOutput *>(
-                            reply->writeInplace(sizeof(QueueBufferOutput)));
-            memset(output, 0, sizeof(QueueBufferOutput));
-            status_t res = connect(listener, api, producerControlledByApp, output);
+            QueueBufferOutput output;
+            status_t res = connect(listener, api, producerControlledByApp, &output);
+            reply->write(output);
             reply->writeInt32(res);
             return NO_ERROR;
         }
         case DISCONNECT: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
             int api = data.readInt32();
-            status_t res = disconnect(api);
+            DisconnectMode mode = static_cast<DisconnectMode>(data.readInt32());
+            status_t res = disconnect(api, mode);
             reply->writeInt32(res);
             return NO_ERROR;
         }
@@ -459,12 +765,11 @@ status_t BnGraphicBufferProducer::onTransact(
         }
         case ALLOCATE_BUFFERS: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            bool async = static_cast<bool>(data.readInt32());
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
-            allocateBuffers(async, width, height, format, usage);
+            allocateBuffers(width, height, format, usage);
             return NO_ERROR;
         }
         case ALLOW_ALLOCATION: {
@@ -486,6 +791,83 @@ status_t BnGraphicBufferProducer::onTransact(
             reply->writeString8(getConsumerName());
             return NO_ERROR;
         }
+        case SET_SHARED_BUFFER_MODE: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            bool sharedBufferMode = data.readInt32();
+            status_t result = setSharedBufferMode(sharedBufferMode);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case SET_AUTO_REFRESH: {
+            CHECK_INTERFACE(IGraphicBuffer, data, reply);
+            bool autoRefresh = data.readInt32();
+            status_t result = setAutoRefresh(autoRefresh);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case SET_DEQUEUE_TIMEOUT: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            nsecs_t timeout = data.readInt64();
+            status_t result = setDequeueTimeout(timeout);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case GET_LAST_QUEUED_BUFFER: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            sp<GraphicBuffer> buffer(nullptr);
+            sp<Fence> fence(Fence::NO_FENCE);
+            float transform[16] = {};
+            status_t result = getLastQueuedBuffer(&buffer, &fence, transform);
+            reply->writeInt32(result);
+            if (result != NO_ERROR) {
+                return result;
+            }
+            if (!buffer.get()) {
+                reply->writeBool(false);
+            } else {
+                reply->writeBool(true);
+                result = reply->write(*buffer);
+                if (result == NO_ERROR) {
+                    reply->write(transform, sizeof(float) * 16);
+                }
+            }
+            if (result != NO_ERROR) {
+                ALOGE("getLastQueuedBuffer failed to write buffer: %d", result);
+                return result;
+            }
+            result = reply->write(*fence);
+            if (result != NO_ERROR) {
+                ALOGE("getLastQueuedBuffer failed to write fence: %d", result);
+                return result;
+            }
+            return NO_ERROR;
+        }
+        case GET_FRAME_TIMESTAMPS: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            FrameEventHistoryDelta frameTimestamps;
+            getFrameTimestamps(&frameTimestamps);
+            status_t result = reply->write(frameTimestamps);
+            if (result != NO_ERROR) {
+                ALOGE("BnGBP::GET_FRAME_TIMESTAMPS failed to write buffer: %d",
+                        result);
+                return result;
+            }
+            return NO_ERROR;
+        }
+        case GET_UNIQUE_ID: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            uint64_t outId = 0;
+            status_t actualResult = getUniqueId(&outId);
+            status_t result = reply->writeInt32(actualResult);
+            if (result != NO_ERROR) {
+                return result;
+            }
+            result = reply->writeUint64(outId);
+            if (result != NO_ERROR) {
+                return result;
+            }
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
@@ -496,17 +878,21 @@ IGraphicBufferProducer::QueueBufferInput::QueueBufferInput(const Parcel& parcel)
     parcel.read(*this);
 }
 
+constexpr size_t IGraphicBufferProducer::QueueBufferInput::minFlattenedSize() {
+    return sizeof(timestamp) +
+            sizeof(isAutoTimestamp) +
+            sizeof(dataSpace) +
+            sizeof(crop) +
+            sizeof(scalingMode) +
+            sizeof(transform) +
+            sizeof(stickyTransform) +
+            sizeof(getFrameTimestamps);
+}
+
 size_t IGraphicBufferProducer::QueueBufferInput::getFlattenedSize() const {
-    return sizeof(timestamp)
-         + sizeof(isAutoTimestamp)
-         + sizeof(dataSpace)
-         + sizeof(crop)
-         + sizeof(scalingMode)
-         + sizeof(transform)
-         + sizeof(stickyTransform)
-         + sizeof(async)
-         + fence->getFlattenedSize()
-         + surfaceDamage.getFlattenedSize();
+    return minFlattenedSize() +
+            fence->getFlattenedSize() +
+            surfaceDamage.getFlattenedSize();
 }
 
 size_t IGraphicBufferProducer::QueueBufferInput::getFdCount() const {
@@ -519,6 +905,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(
     if (size < getFlattenedSize()) {
         return NO_MEMORY;
     }
+
     FlattenableUtils::write(buffer, size, timestamp);
     FlattenableUtils::write(buffer, size, isAutoTimestamp);
     FlattenableUtils::write(buffer, size, dataSpace);
@@ -526,7 +913,8 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(
     FlattenableUtils::write(buffer, size, scalingMode);
     FlattenableUtils::write(buffer, size, transform);
     FlattenableUtils::write(buffer, size, stickyTransform);
-    FlattenableUtils::write(buffer, size, async);
+    FlattenableUtils::write(buffer, size, getFrameTimestamps);
+
     status_t result = fence->flatten(buffer, size, fds, count);
     if (result != NO_ERROR) {
         return result;
@@ -537,17 +925,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::flatten(
 status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
         void const*& buffer, size_t& size, int const*& fds, size_t& count)
 {
-    size_t minNeeded =
-              sizeof(timestamp)
-            + sizeof(isAutoTimestamp)
-            + sizeof(dataSpace)
-            + sizeof(crop)
-            + sizeof(scalingMode)
-            + sizeof(transform)
-            + sizeof(stickyTransform)
-            + sizeof(async);
-
-    if (size < minNeeded) {
+    if (size < minFlattenedSize()) {
         return NO_MEMORY;
     }
 
@@ -558,7 +936,7 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
     FlattenableUtils::read(buffer, size, scalingMode);
     FlattenableUtils::read(buffer, size, transform);
     FlattenableUtils::read(buffer, size, stickyTransform);
-    FlattenableUtils::read(buffer, size, async);
+    FlattenableUtils::read(buffer, size, getFrameTimestamps);
 
     fence = new Fence();
     status_t result = fence->unflatten(buffer, size, fds, count);
@@ -568,4 +946,56 @@ status_t IGraphicBufferProducer::QueueBufferInput::unflatten(
     return surfaceDamage.unflatten(buffer, size);
 }
 
+// ----------------------------------------------------------------------------
+constexpr size_t IGraphicBufferProducer::QueueBufferOutput::minFlattenedSize() {
+    return sizeof(width) +
+            sizeof(height) +
+            sizeof(transformHint) +
+            sizeof(numPendingBuffers) +
+            sizeof(nextFrameNumber) +
+            sizeof(bufferReplaced);
+}
+
+size_t IGraphicBufferProducer::QueueBufferOutput::getFlattenedSize() const {
+    return minFlattenedSize() + frameTimestamps.getFlattenedSize();
+}
+
+size_t IGraphicBufferProducer::QueueBufferOutput::getFdCount() const {
+    return frameTimestamps.getFdCount();
+}
+
+status_t IGraphicBufferProducer::QueueBufferOutput::flatten(
+        void*& buffer, size_t& size, int*& fds, size_t& count) const
+{
+    if (size < getFlattenedSize()) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::write(buffer, size, width);
+    FlattenableUtils::write(buffer, size, height);
+    FlattenableUtils::write(buffer, size, transformHint);
+    FlattenableUtils::write(buffer, size, numPendingBuffers);
+    FlattenableUtils::write(buffer, size, nextFrameNumber);
+    FlattenableUtils::write(buffer, size, bufferReplaced);
+
+    return frameTimestamps.flatten(buffer, size, fds, count);
+}
+
+status_t IGraphicBufferProducer::QueueBufferOutput::unflatten(
+        void const*& buffer, size_t& size, int const*& fds, size_t& count)
+{
+    if (size < minFlattenedSize()) {
+        return NO_MEMORY;
+    }
+
+    FlattenableUtils::read(buffer, size, width);
+    FlattenableUtils::read(buffer, size, height);
+    FlattenableUtils::read(buffer, size, transformHint);
+    FlattenableUtils::read(buffer, size, numPendingBuffers);
+    FlattenableUtils::read(buffer, size, nextFrameNumber);
+    FlattenableUtils::read(buffer, size, bufferReplaced);
+
+    return frameTimestamps.unflatten(buffer, size, fds, count);
+}
+
 }; // namespace android