|  | /* | 
|  | * 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. | 
|  | */ | 
|  |  | 
|  | #ifndef ANDROID_GUI_BUFFERHUBPRODUCER_H_ | 
|  | #define ANDROID_GUI_BUFFERHUBPRODUCER_H_ | 
|  |  | 
|  | #include <gui/BufferSlot.h> | 
|  | #include <gui/IGraphicBufferProducer.h> | 
|  | #include <private/dvr/buffer_hub_queue_client.h> | 
|  | #include <private/dvr/buffer_hub_queue_parcelable.h> | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | class BufferHubProducer : public IGraphicBufferProducer { | 
|  | public: | 
|  | static constexpr int kNoConnectedApi = -1; | 
|  |  | 
|  | // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer | 
|  | // side logic doesn't limit the number of buffer it can acquire | 
|  | // simultaneously. We need a way for consumer logic to configure and enforce | 
|  | // that. | 
|  | static constexpr int kDefaultUndequeuedBuffers = 1; | 
|  |  | 
|  | // Creates a BufferHubProducer instance by importing an existing prodcuer | 
|  | // queue. | 
|  | static sp<BufferHubProducer> Create(const std::shared_ptr<dvr::ProducerQueue>& producer); | 
|  |  | 
|  | // Creates a BufferHubProducer instance by importing an existing prodcuer | 
|  | // parcelable. Note that this call takes the ownership of the parcelable | 
|  | // object and is guaranteed to succeed if parcelable object is valid. | 
|  | static sp<BufferHubProducer> Create(dvr::ProducerQueueParcelable parcelable); | 
|  |  | 
|  | // See |IGraphicBufferProducer::requestBuffer| | 
|  | status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override; | 
|  |  | 
|  | // For the BufferHub based implementation. All buffers in the queue are | 
|  | // allowed to be dequeued from the consumer side. It call always returns | 
|  | // 0 for |NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS| query. Thus setting | 
|  | // |max_dequeued_buffers| here can be considered the same as setting queue | 
|  | // capacity. | 
|  | // | 
|  | // See |IGraphicBufferProducer::setMaxDequeuedBufferCount| for more info | 
|  | status_t setMaxDequeuedBufferCount(int max_dequeued_buffers) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::setAsyncMode| | 
|  | status_t setAsyncMode(bool async) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::dequeueBuffer| | 
|  | status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height, | 
|  | PixelFormat format, uint64_t usage, uint64_t* outBufferAge, | 
|  | FrameEventHistoryDelta* outTimestamps) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::detachBuffer| | 
|  | status_t detachBuffer(int slot) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::detachNextBuffer| | 
|  | status_t detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::attachBuffer| | 
|  | status_t attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::queueBuffer| | 
|  | status_t queueBuffer(int slot, const QueueBufferInput& input, | 
|  | QueueBufferOutput* output) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::cancelBuffer| | 
|  | status_t cancelBuffer(int slot, const sp<Fence>& fence) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::query| | 
|  | status_t query(int what, int* out_value) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::connect| | 
|  | status_t connect(const sp<IProducerListener>& listener, int api, | 
|  | bool producer_controlled_by_app, QueueBufferOutput* output) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::disconnect| | 
|  | status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::setSidebandStream| | 
|  | status_t setSidebandStream(const sp<NativeHandle>& stream) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::allocateBuffers| | 
|  | void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format, | 
|  | uint64_t usage) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::allowAllocation| | 
|  | status_t allowAllocation(bool allow) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::setGenerationNumber| | 
|  | status_t setGenerationNumber(uint32_t generation_number) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::getConsumerName| | 
|  | String8 getConsumerName() const override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::setSharedBufferMode| | 
|  | status_t setSharedBufferMode(bool shared_buffer_mode) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::setAutoRefresh| | 
|  | status_t setAutoRefresh(bool auto_refresh) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::setDequeueTimeout| | 
|  | status_t setDequeueTimeout(nsecs_t timeout) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::getLastQueuedBuffer| | 
|  | status_t getLastQueuedBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence, | 
|  | float out_transform_matrix[16]) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::getFrameTimestamps| | 
|  | void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::getUniqueId| | 
|  | status_t getUniqueId(uint64_t* out_id) const override; | 
|  |  | 
|  | // See |IGraphicBufferProducer::getConsumerUsage| | 
|  | status_t getConsumerUsage(uint64_t* out_usage) const override; | 
|  |  | 
|  | // Takes out the current producer as a binder parcelable object. Note that the | 
|  | // producer must be disconnected to be exportable. After successful export, | 
|  | // the producer queue can no longer be connected again. Returns NO_ERROR when | 
|  | // takeout is successful and out_parcelable will hold the new parcelable | 
|  | // object. Also note that out_parcelable cannot be NULL and must points to an | 
|  | // invalid parcelable. | 
|  | status_t TakeAsParcelable(dvr::ProducerQueueParcelable* out_parcelable); | 
|  |  | 
|  | IBinder* onAsBinder() override; | 
|  |  | 
|  | protected: | 
|  | // See |IGraphicBufferProducer::exportToParcel| | 
|  | status_t exportToParcel(Parcel* parcel) override; | 
|  |  | 
|  | private: | 
|  | using LocalHandle = pdx::LocalHandle; | 
|  |  | 
|  | // Private constructor to force use of |Create|. | 
|  | BufferHubProducer() {} | 
|  |  | 
|  | static uint64_t genUniqueId() { | 
|  | static std::atomic<uint32_t> counter{0}; | 
|  | static uint64_t id = static_cast<uint64_t>(getpid()) << 32; | 
|  | return id | counter++; | 
|  | } | 
|  |  | 
|  | // Allocate new buffer through BufferHub and add it into |queue_| for | 
|  | // bookkeeping. | 
|  | status_t AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count, | 
|  | PixelFormat format, uint64_t usage); | 
|  |  | 
|  | // Remove a buffer via BufferHubRPC. | 
|  | status_t RemoveBuffer(size_t slot); | 
|  |  | 
|  | // Free all buffers which are owned by the prodcuer. Note that if graphic | 
|  | // buffers are acquired by the consumer, we can't . | 
|  | status_t FreeAllBuffers(); | 
|  |  | 
|  | // Helper function that implements the detachBuffer() call, but assuming |mutex_| has been | 
|  | // locked already. | 
|  | status_t DetachBufferLocked(size_t slot); | 
|  |  | 
|  | // Concreate implementation backed by BufferHubBuffer. | 
|  | std::shared_ptr<dvr::ProducerQueue> queue_; | 
|  |  | 
|  | // Mutex for thread safety. | 
|  | std::mutex mutex_; | 
|  |  | 
|  | // Connect client API, should be one of the NATIVE_WINDOW_API_* flags. | 
|  | int connected_api_{kNoConnectedApi}; | 
|  |  | 
|  | // |max_buffer_count_| sets the capacity of the underlying buffer queue. | 
|  | int32_t max_buffer_count_{dvr::BufferHubQueue::kMaxQueueCapacity}; | 
|  |  | 
|  | // |max_dequeued_buffer_count_| set the maximum number of buffers that can | 
|  | // be dequeued at the same momment. | 
|  | int32_t max_dequeued_buffer_count_{1}; | 
|  |  | 
|  | // Sets how long dequeueBuffer or attachBuffer will block if a buffer or | 
|  | // slot is not yet available. The timeout is stored in milliseconds. | 
|  | int dequeue_timeout_ms_{dvr::BufferHubQueue::kNoTimeOut}; | 
|  |  | 
|  | // |generation_number_| stores the current generation number of the attached | 
|  | // producer. Any attempt to attach a buffer with a different generation | 
|  | // number will fail. | 
|  | // TOOD(b/38137191) Currently not used as we don't support | 
|  | // IGraphicBufferProducer::detachBuffer. | 
|  | uint32_t generation_number_{0}; | 
|  |  | 
|  | // |buffers_| stores the buffers that have been dequeued from | 
|  | // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets | 
|  | // filled in with the result of |Dequeue|. | 
|  | // TODO(jwcai) The buffer allocated to a slot will also be replaced if the | 
|  | // requested buffer usage or geometry differs from that of the buffer | 
|  | // allocated to a slot. | 
|  | struct BufferHubSlot : public BufferSlot { | 
|  | 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::ProducerBuffer> mProducerBuffer; | 
|  | bool mIsReallocating; | 
|  | }; | 
|  | BufferHubSlot buffers_[dvr::BufferHubQueue::kMaxQueueCapacity]; | 
|  |  | 
|  | // A uniqueId used by IGraphicBufferProducer interface. | 
|  | const uint64_t unique_id_{genUniqueId()}; | 
|  |  | 
|  | // A pending parcelable object which keeps the bufferhub channel alive. | 
|  | dvr::ProducerQueueParcelable pending_producer_parcelable_; | 
|  | }; | 
|  |  | 
|  | } // namespace android | 
|  |  | 
|  | #endif // ANDROID_GUI_BUFFERHUBPRODUCER_H_ |