• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
17 #pragma once
18 
19 #include <map>
20 #include <set>
21 #include <vector>
22 #include <mutex>
23 #include <condition_variable>
24 #include <utils/Timers.h>
25 
26 #include "BufferStatus.h"
27 
28 namespace aidl::android::hardware::media::bufferpool2::implementation {
29 
30 using BufferStatus = aidl::android::hardware::media::bufferpool2::BufferStatus;
31 using BufferStatusMessage = aidl::android::hardware::media::bufferpool2::BufferStatusMessage;
32 
33 struct Accessor;
34 struct InternalBuffer;
35 struct TransactionStatus;
36 
37 /**
38  * Buffer pool implementation.
39  *
40  * Handles buffer status messages. Handles buffer allocation/recycling.
41  * Handles buffer transfer between buffer pool clients.
42  */
43 struct BufferPool {
44 private:
45     std::mutex mMutex;
46     int64_t mTimestampMs;
47     int64_t mLastCleanUpMs;
48     int64_t mLastLogMs;
49     BufferId mSeq;
50     BufferId mStartSeq;
51     bool mValid;
52     BufferStatusObserver mObserver;
53     BufferInvalidationChannel mInvalidationChannel;
54 
55     std::map<ConnectionId, std::set<BufferId>> mUsingBuffers;
56     std::map<BufferId, std::set<ConnectionId>> mUsingConnections;
57 
58     std::map<ConnectionId, std::set<TransactionId>> mPendingTransactions;
59     // Transactions completed before TRANSFER_TO message arrival.
60     // Fetch does not occur for the transactions.
61     // Only transaction id is kept for the transactions in short duration.
62     std::set<TransactionId> mCompletedTransactions;
63     // Currently active(pending) transations' status & information.
64     std::map<TransactionId, std::unique_ptr<TransactionStatus>>
65             mTransactions;
66 
67     std::map<BufferId, std::unique_ptr<InternalBuffer>> mBuffers;
68     std::set<BufferId> mFreeBuffers;
69     std::set<ConnectionId> mConnectionIds;
70 
71     struct Invalidation {
72         static std::atomic<std::uint32_t> sInvSeqId;
73 
74         struct Pending {
75             bool mNeedsAck;
76             uint32_t mFrom;
77             uint32_t mTo;
78             size_t mLeft;
79             const std::weak_ptr<Accessor> mImpl;
PendingBufferPool::Invalidation::Pending80             Pending(bool needsAck, uint32_t from, uint32_t to, size_t left,
81                     const std::shared_ptr<Accessor> &impl)
82                     : mNeedsAck(needsAck),
83                       mFrom(from),
84                       mTo(to),
85                       mLeft(left),
86                       mImpl(impl)
87             {}
88 
isInvalidatedBufferPool::Invalidation::Pending89             bool isInvalidated(uint32_t bufferId) {
90                 return isBufferInRange(mFrom, mTo, bufferId) && --mLeft == 0;
91             }
92         };
93 
94         std::list<Pending> mPendings;
95         std::map<ConnectionId, uint32_t> mAcks;
96         std::map<ConnectionId, const std::shared_ptr<IObserver>> mObservers;
97         uint32_t mInvalidationId;
98         uint32_t mId;
99 
InvalidationBufferPool::Invalidation100         Invalidation() : mInvalidationId(0), mId(sInvSeqId.fetch_add(1)) {}
101 
102         void onConnect(ConnectionId conId, const std::shared_ptr<IObserver> &observer);
103 
104         void onClose(ConnectionId conId);
105 
106         void onAck(ConnectionId conId, uint32_t msgId);
107 
108         void onBufferInvalidated(
109                 BufferId bufferId,
110                 BufferInvalidationChannel &channel);
111 
112         void onInvalidationRequest(
113                 bool needsAck, uint32_t from, uint32_t to, size_t left,
114                 BufferInvalidationChannel &channel,
115                 const std::shared_ptr<Accessor> &impl);
116 
117         void onHandleAck(
118                 std::map<ConnectionId, const std::shared_ptr<IObserver>> *observers,
119                 uint32_t *invalidationId);
120     } mInvalidation;
121     /// Buffer pool statistics which tracks allocation and transfer statistics.
122     struct Stats {
123         /// Total size of allocations which are used or available to use.
124         /// (bytes or pixels)
125         size_t mSizeCached;
126         /// # of cached buffers which are used or available to use.
127         size_t mBuffersCached;
128         /// Total size of allocations which are currently used. (bytes or pixels)
129         size_t mSizeInUse;
130         /// # of currently used buffers
131         size_t mBuffersInUse;
132 
133         /// # of allocations called on bufferpool. (# of fetched from BlockPool)
134         size_t mTotalAllocations;
135         /// # of allocations that were served from the cache.
136         /// (# of allocator alloc prevented)
137         size_t mTotalRecycles;
138         /// # of buffer transfers initiated.
139         size_t mTotalTransfers;
140         /// # of transfers that had to be fetched.
141         size_t mTotalFetches;
142 
StatsBufferPool::Stats143         Stats()
144             : mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0),
145               mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {}
146 
147         /// # of currently unused buffers
buffersNotInUseBufferPool::Stats148         size_t buffersNotInUse() const {
149             ALOG_ASSERT(mBuffersCached >= mBuffersInUse);
150             return mBuffersCached - mBuffersInUse;
151         }
152 
153         /// A new buffer is allocated on an allocation request.
onBufferAllocatedBufferPool::Stats154         void onBufferAllocated(size_t allocSize) {
155             mSizeCached += allocSize;
156             mBuffersCached++;
157 
158             mSizeInUse += allocSize;
159             mBuffersInUse++;
160 
161             mTotalAllocations++;
162         }
163 
164         /// A buffer is evicted and destroyed.
onBufferEvictedBufferPool::Stats165         void onBufferEvicted(size_t allocSize) {
166             mSizeCached -= allocSize;
167             mBuffersCached--;
168         }
169 
170         /// A buffer is recycled on an allocation request.
onBufferRecycledBufferPool::Stats171         void onBufferRecycled(size_t allocSize) {
172             mSizeInUse += allocSize;
173             mBuffersInUse++;
174 
175             mTotalAllocations++;
176             mTotalRecycles++;
177         }
178 
179         /// A buffer is available to be recycled.
onBufferUnusedBufferPool::Stats180         void onBufferUnused(size_t allocSize) {
181             mSizeInUse -= allocSize;
182             mBuffersInUse--;
183         }
184 
185         /// A buffer transfer is initiated.
onBufferSentBufferPool::Stats186         void onBufferSent() {
187             mTotalTransfers++;
188         }
189 
190         /// A buffer fetch is invoked by a buffer transfer.
onBufferFetchedBufferPool::Stats191         void onBufferFetched() {
192             mTotalFetches++;
193         }
194     } mStats;
195 
isValidBufferPool196     bool isValid() {
197         return mValid;
198     }
199 
200     void invalidate(bool needsAck, BufferId from, BufferId to,
201                     const std::shared_ptr<Accessor> &impl);
202 
203     static void createInvalidator();
204 
205 public:
206     /** Creates a buffer pool. */
207     BufferPool();
208 
209     /** Destroys a buffer pool. */
210     ~BufferPool();
211 
212     /**
213      * Processes all pending buffer status messages, and returns the result.
214      * Each status message is handled by methods with 'handle' prefix.
215      */
216     void processStatusMessages();
217 
218     /**
219      * Handles a buffer being owned by a connection.
220      *
221      * @param connectionId  the id of the buffer owning connection.
222      * @param bufferId      the id of the buffer.
223      *
224      * @return {@code true} when the buffer is owned,
225      *         {@code false} otherwise.
226      */
227     bool handleOwnBuffer(ConnectionId connectionId, BufferId bufferId);
228 
229     /**
230      * Handles a buffer being released by a connection.
231      *
232      * @param connectionId  the id of the buffer owning connection.
233      * @param bufferId      the id of the buffer.
234      *
235      * @return {@code true} when the buffer ownership is released,
236      *         {@code false} otherwise.
237      */
238     bool handleReleaseBuffer(ConnectionId connectionId, BufferId bufferId);
239 
240     /**
241      * Handles a transfer transaction start message from the sender.
242      *
243      * @param message   a buffer status message for the transaction.
244      *
245      * @result {@code true} when transfer_to message is acknowledged,
246      *         {@code false} otherwise.
247      */
248     bool handleTransferTo(const BufferStatusMessage &message);
249 
250     /**
251      * Handles a transfer transaction being acked by the receiver.
252      *
253      * @param message   a buffer status message for the transaction.
254      *
255      * @result {@code true} when transfer_from message is acknowledged,
256      *         {@code false} otherwise.
257      */
258     bool handleTransferFrom(const BufferStatusMessage &message);
259 
260     /**
261      * Handles a transfer transaction result message from the receiver.
262      *
263      * @param message   a buffer status message for the transaction.
264      *
265      * @result {@code true} when the existing transaction is finished,
266      *         {@code false} otherwise.
267      */
268     bool handleTransferResult(const BufferStatusMessage &message);
269 
270     /**
271      * Handles a connection being closed, and returns the result. All the
272      * buffers and transactions owned by the connection will be cleaned up.
273      * The related FMQ will be cleaned up too.
274      *
275      * @param connectionId  the id of the connection.
276      *
277      * @result {@code true} when the connection existed,
278      *         {@code false} otherwise.
279      */
280     bool handleClose(ConnectionId connectionId);
281 
282     /**
283      * Recycles a existing free buffer if it is possible.
284      *
285      * @param allocator the buffer allocator
286      * @param params    the allocation parameters.
287      * @param pId       the id of the recycled buffer.
288      * @param handle    the native handle of the recycled buffer.
289      *
290      * @return {@code true} when a buffer is recycled, {@code false}
291      *         otherwise.
292      */
293     bool getFreeBuffer(
294             const std::shared_ptr<BufferPoolAllocator> &allocator,
295             const std::vector<uint8_t> &params,
296             BufferId *pId, const native_handle_t **handle);
297 
298     /**
299      * Adds a newly allocated buffer to bufferpool.
300      *
301      * @param alloc     the newly allocated buffer.
302      * @param allocSize the size of the newly allocated buffer.
303      * @param params    the allocation parameters.
304      * @param pId       the buffer id for the newly allocated buffer.
305      * @param handle    the native handle for the newly allocated buffer.
306      *
307      * @return OK when an allocation is successfully allocated.
308      *         NO_MEMORY when there is no memory.
309      *         CRITICAL_ERROR otherwise.
310      */
311     BufferPoolStatus addNewBuffer(
312             const std::shared_ptr<BufferPoolAllocation> &alloc,
313             const size_t allocSize,
314             const std::vector<uint8_t> &params,
315             BufferId *pId,
316             const native_handle_t **handle);
317 
318     /**
319      * Processes pending buffer status messages and performs periodic cache
320      * cleaning.
321      *
322      * @param clearCache    if clearCache is true, it frees all buffers
323      *                      waiting to be recycled.
324      */
325     void cleanUp(bool clearCache = false);
326 
327     /**
328      * Processes pending buffer status messages and invalidate all current
329      * free buffers. Active buffers are invalidated after being inactive.
330      */
331     void flush(const std::shared_ptr<Accessor> &impl);
332 
333     friend struct Accessor;
334 };
335 
336 
337 }  // namespace aidl::android::hardware::media::bufferpool2::implementation
338