| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| Jiwen 'Steve' Cai | 0f95084 | 2018-01-16 17:05:54 -0800 | [diff] [blame] | 17 | #ifndef ANDROID_GUI_BUFFERHUBPRODUCER_H_ |
| 18 | #define ANDROID_GUI_BUFFERHUBPRODUCER_H_ |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 19 | |
| Jiwen 'Steve' Cai | 0f95084 | 2018-01-16 17:05:54 -0800 | [diff] [blame] | 20 | #include <gui/BufferSlot.h> |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 21 | #include <gui/IGraphicBufferProducer.h> |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 22 | #include <private/dvr/buffer_hub_queue_client.h> |
| Jiwen 'Steve' Cai | 5afb740 | 2017-11-09 18:50:32 -0800 | [diff] [blame] | 23 | #include <private/dvr/buffer_hub_queue_parcelable.h> |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 24 | |
| 25 | namespace android { |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 26 | |
| Jiwen 'Steve' Cai | c90a77f | 2018-01-14 15:42:29 -0800 | [diff] [blame] | 27 | class BufferHubProducer : public IGraphicBufferProducer { |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 28 | public: |
| 29 | static constexpr int kNoConnectedApi = -1; |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 30 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 31 | // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer |
| 32 | // side logic doesn't limit the number of buffer it can acquire |
| 33 | // simultaneously. We need a way for consumer logic to configure and enforce |
| 34 | // that. |
| 35 | static constexpr int kDefaultUndequeuedBuffers = 1; |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 36 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 37 | // Creates a BufferHubProducer instance by importing an existing prodcuer |
| 38 | // queue. |
| 39 | static sp<BufferHubProducer> Create(const std::shared_ptr<dvr::ProducerQueue>& producer); |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 40 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 41 | // Creates a BufferHubProducer instance by importing an existing prodcuer |
| 42 | // parcelable. Note that this call takes the ownership of the parcelable |
| 43 | // object and is guaranteed to succeed if parcelable object is valid. |
| 44 | static sp<BufferHubProducer> Create(dvr::ProducerQueueParcelable parcelable); |
| Jiwen 'Steve' Cai | 5afb740 | 2017-11-09 18:50:32 -0800 | [diff] [blame] | 45 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 46 | // See |IGraphicBufferProducer::requestBuffer| |
| 47 | status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 48 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 49 | // For the BufferHub based implementation. All buffers in the queue are |
| 50 | // allowed to be dequeued from the consumer side. It call always returns |
| 51 | // 0 for |NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS| query. Thus setting |
| 52 | // |max_dequeued_buffers| here can be considered the same as setting queue |
| 53 | // capacity. |
| 54 | // |
| 55 | // See |IGraphicBufferProducer::setMaxDequeuedBufferCount| for more info |
| 56 | status_t setMaxDequeuedBufferCount(int max_dequeued_buffers) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 57 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 58 | // See |IGraphicBufferProducer::setAsyncMode| |
| 59 | status_t setAsyncMode(bool async) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 60 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 61 | // See |IGraphicBufferProducer::dequeueBuffer| |
| 62 | status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height, |
| 63 | PixelFormat format, uint64_t usage, uint64_t* outBufferAge, |
| 64 | FrameEventHistoryDelta* outTimestamps) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 65 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 66 | // See |IGraphicBufferProducer::detachBuffer| |
| 67 | status_t detachBuffer(int slot) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 68 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 69 | // See |IGraphicBufferProducer::detachNextBuffer| |
| 70 | status_t detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 71 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 72 | // See |IGraphicBufferProducer::attachBuffer| |
| 73 | status_t attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 74 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 75 | // See |IGraphicBufferProducer::queueBuffer| |
| 76 | status_t queueBuffer(int slot, const QueueBufferInput& input, |
| 77 | QueueBufferOutput* output) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 78 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 79 | // See |IGraphicBufferProducer::cancelBuffer| |
| 80 | status_t cancelBuffer(int slot, const sp<Fence>& fence) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 81 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 82 | // See |IGraphicBufferProducer::query| |
| 83 | status_t query(int what, int* out_value) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 84 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 85 | // See |IGraphicBufferProducer::connect| |
| 86 | status_t connect(const sp<IProducerListener>& listener, int api, |
| 87 | bool producer_controlled_by_app, QueueBufferOutput* output) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 88 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 89 | // See |IGraphicBufferProducer::disconnect| |
| 90 | status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 91 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 92 | // See |IGraphicBufferProducer::setSidebandStream| |
| 93 | status_t setSidebandStream(const sp<NativeHandle>& stream) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 94 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 95 | // See |IGraphicBufferProducer::allocateBuffers| |
| 96 | void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format, |
| 97 | uint64_t usage) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 98 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 99 | // See |IGraphicBufferProducer::allowAllocation| |
| 100 | status_t allowAllocation(bool allow) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 101 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 102 | // See |IGraphicBufferProducer::setGenerationNumber| |
| 103 | status_t setGenerationNumber(uint32_t generation_number) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 104 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 105 | // See |IGraphicBufferProducer::getConsumerName| |
| 106 | String8 getConsumerName() const override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 107 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 108 | // See |IGraphicBufferProducer::setSharedBufferMode| |
| 109 | status_t setSharedBufferMode(bool shared_buffer_mode) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 110 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 111 | // See |IGraphicBufferProducer::setAutoRefresh| |
| 112 | status_t setAutoRefresh(bool auto_refresh) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 113 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 114 | // See |IGraphicBufferProducer::setDequeueTimeout| |
| 115 | status_t setDequeueTimeout(nsecs_t timeout) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 116 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 117 | // See |IGraphicBufferProducer::getLastQueuedBuffer| |
| 118 | status_t getLastQueuedBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence, |
| 119 | float out_transform_matrix[16]) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 120 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 121 | // See |IGraphicBufferProducer::getFrameTimestamps| |
| 122 | void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 123 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 124 | // See |IGraphicBufferProducer::getUniqueId| |
| 125 | status_t getUniqueId(uint64_t* out_id) const override; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 126 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 127 | // See |IGraphicBufferProducer::getConsumerUsage| |
| 128 | status_t getConsumerUsage(uint64_t* out_usage) const override; |
| Chia-I Wu | e2786ea | 2017-08-07 10:36:08 -0700 | [diff] [blame] | 129 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 130 | // Takes out the current producer as a binder parcelable object. Note that the |
| 131 | // producer must be disconnected to be exportable. After successful export, |
| 132 | // the producer queue can no longer be connected again. Returns NO_ERROR when |
| 133 | // takeout is successful and out_parcelable will hold the new parcelable |
| 134 | // object. Also note that out_parcelable cannot be NULL and must points to an |
| 135 | // invalid parcelable. |
| 136 | status_t TakeAsParcelable(dvr::ProducerQueueParcelable* out_parcelable); |
| Jiwen 'Steve' Cai | 5afb740 | 2017-11-09 18:50:32 -0800 | [diff] [blame] | 137 | |
| Jiwen 'Steve' Cai | c90a77f | 2018-01-14 15:42:29 -0800 | [diff] [blame] | 138 | IBinder* onAsBinder() override; |
| 139 | |
| 140 | protected: |
| 141 | // See |IGraphicBufferProducer::exportToParcel| |
| 142 | status_t exportToParcel(Parcel* parcel) override; |
| 143 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 144 | private: |
| 145 | using LocalHandle = pdx::LocalHandle; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 146 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 147 | // Private constructor to force use of |Create|. |
| 148 | BufferHubProducer() {} |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 149 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 150 | static uint64_t genUniqueId() { |
| 151 | static std::atomic<uint32_t> counter{0}; |
| 152 | static uint64_t id = static_cast<uint64_t>(getpid()) << 32; |
| 153 | return id | counter++; |
| 154 | } |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 155 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 156 | // Allocate new buffer through BufferHub and add it into |queue_| for |
| 157 | // bookkeeping. |
| 158 | status_t AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count, |
| 159 | PixelFormat format, uint64_t usage); |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 160 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 161 | // Remove a buffer via BufferHubRPC. |
| 162 | status_t RemoveBuffer(size_t slot); |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 163 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 164 | // Free all buffers which are owned by the prodcuer. Note that if graphic |
| 165 | // buffers are acquired by the consumer, we can't . |
| 166 | status_t FreeAllBuffers(); |
| Jiwen 'Steve' Cai | 005f45d | 2017-08-04 17:34:37 -0700 | [diff] [blame] | 167 | |
| Jiwen 'Steve' Cai | 4287535 | 2018-04-30 17:55:11 -0700 | [diff] [blame] | 168 | // Helper function that implements the detachBuffer() call, but assuming |mutex_| has been |
| 169 | // locked already. |
| 170 | status_t DetachBufferLocked(size_t slot); |
| 171 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 172 | // Concreate implementation backed by BufferHubBuffer. |
| 173 | std::shared_ptr<dvr::ProducerQueue> queue_; |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 174 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 175 | // Mutex for thread safety. |
| 176 | std::mutex mutex_; |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 177 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 178 | // Connect client API, should be one of the NATIVE_WINDOW_API_* flags. |
| 179 | int connected_api_{kNoConnectedApi}; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 180 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 181 | // |max_buffer_count_| sets the capacity of the underlying buffer queue. |
| 182 | int32_t max_buffer_count_{dvr::BufferHubQueue::kMaxQueueCapacity}; |
| Jiwen 'Steve' Cai | 1601bcf | 2017-03-24 14:03:06 -0700 | [diff] [blame] | 183 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 184 | // |max_dequeued_buffer_count_| set the maximum number of buffers that can |
| 185 | // be dequeued at the same momment. |
| 186 | int32_t max_dequeued_buffer_count_{1}; |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 187 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 188 | // Sets how long dequeueBuffer or attachBuffer will block if a buffer or |
| 189 | // slot is not yet available. The timeout is stored in milliseconds. |
| 190 | int dequeue_timeout_ms_{dvr::BufferHubQueue::kNoTimeOut}; |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 191 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 192 | // |generation_number_| stores the current generation number of the attached |
| 193 | // producer. Any attempt to attach a buffer with a different generation |
| 194 | // number will fail. |
| 195 | // TOOD(b/38137191) Currently not used as we don't support |
| 196 | // IGraphicBufferProducer::detachBuffer. |
| 197 | uint32_t generation_number_{0}; |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 198 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 199 | // |buffers_| stores the buffers that have been dequeued from |
| 200 | // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets |
| 201 | // filled in with the result of |Dequeue|. |
| 202 | // TODO(jwcai) The buffer allocated to a slot will also be replaced if the |
| 203 | // requested buffer usage or geometry differs from that of the buffer |
| 204 | // allocated to a slot. |
| 205 | struct BufferHubSlot : public BufferSlot { |
| Jiwen 'Steve' Cai | 1c73024 | 2018-12-31 18:40:02 -0800 | [diff] [blame] | 206 | BufferHubSlot() : mProducerBuffer(nullptr), mIsReallocating(false) {} |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 207 | // BufferSlot comes from android framework, using m prefix to comply with |
| 208 | // the name convention with the reset of data fields from BufferSlot. |
| Jiwen 'Steve' Cai | 1c73024 | 2018-12-31 18:40:02 -0800 | [diff] [blame] | 209 | std::shared_ptr<dvr::ProducerBuffer> mProducerBuffer; |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 210 | bool mIsReallocating; |
| 211 | }; |
| 212 | BufferHubSlot buffers_[dvr::BufferHubQueue::kMaxQueueCapacity]; |
| Jiwen 'Steve' Cai | d6cb17f | 2017-05-08 16:15:35 -0700 | [diff] [blame] | 213 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 214 | // A uniqueId used by IGraphicBufferProducer interface. |
| 215 | const uint64_t unique_id_{genUniqueId()}; |
| Jiwen 'Steve' Cai | c90a77f | 2018-01-14 15:42:29 -0800 | [diff] [blame] | 216 | |
| 217 | // A pending parcelable object which keeps the bufferhub channel alive. |
| 218 | dvr::ProducerQueueParcelable pending_producer_parcelable_; |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 219 | }; |
| 220 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 221 | } // namespace android |
| Alex Vakulenko | e4eec20 | 2017-01-27 14:41:04 -0800 | [diff] [blame] | 222 | |
| Jiwen 'Steve' Cai | 9a6ddf7 | 2018-01-18 14:37:24 -0800 | [diff] [blame] | 223 | #endif // ANDROID_GUI_BUFFERHUBPRODUCER_H_ |