• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 
17 #ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSORIMPL_H
18 #define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSORIMPL_H
19 
20 #include <map>
21 #include <set>
22 #include <condition_variable>
23 #include <utils/Timers.h>
24 #include "Accessor.h"
25 
26 namespace android {
27 namespace hardware {
28 namespace media {
29 namespace bufferpool {
30 namespace V2_0 {
31 namespace implementation {
32 
33 struct InternalBuffer;
34 struct TransactionStatus;
35 
36 /**
37  * An implementation of a buffer pool accessor(or a buffer pool implementation.) */
38 class Accessor::Impl
39     : public std::enable_shared_from_this<Accessor::Impl> {
40 public:
41     Impl(const std::shared_ptr<BufferPoolAllocator> &allocator);
42 
43     ~Impl();
44 
45     ResultStatus connect(
46             const sp<Accessor> &accessor, const sp<IObserver> &observer,
47             sp<Connection> *connection,
48             ConnectionId *pConnectionId,
49             uint32_t *pMsgId,
50             const StatusDescriptor** statusDescPtr,
51             const InvalidationDescriptor** invDescPtr);
52 
53     ResultStatus close(ConnectionId connectionId);
54 
55     ResultStatus allocate(ConnectionId connectionId,
56                           const std::vector<uint8_t>& params,
57                           BufferId *bufferId,
58                           const native_handle_t** handle);
59 
60     ResultStatus fetch(ConnectionId connectionId,
61                        TransactionId transactionId,
62                        BufferId bufferId,
63                        const native_handle_t** handle);
64 
65     void flush();
66 
67     void cleanUp(bool clearCache);
68 
69     bool isValid();
70 
71     void handleInvalidateAck();
72 
73     static void createInvalidator();
74 
75     static void createEvictor();
76 
77 private:
78     // ConnectionId = pid : (timestamp_created + seqId)
79     // in order to guarantee uniqueness for each connection
80     static uint32_t sSeqId;
81 
82     const std::shared_ptr<BufferPoolAllocator> mAllocator;
83 
84     nsecs_t mScheduleEvictTs;
85 
86     /**
87      * Buffer pool implementation.
88      *
89      * Handles buffer status messages. Handles buffer allocation/recycling.
90      * Handles buffer transfer between buffer pool clients.
91      */
92     struct BufferPool {
93     private:
94         std::mutex mMutex;
95         int64_t mTimestampUs;
96         int64_t mLastCleanUpUs;
97         int64_t mLastLogUs;
98         BufferId mSeq;
99         BufferId mStartSeq;
100         bool mValid;
101         BufferStatusObserver mObserver;
102         BufferInvalidationChannel mInvalidationChannel;
103 
104         std::map<ConnectionId, std::set<BufferId>> mUsingBuffers;
105         std::map<BufferId, std::set<ConnectionId>> mUsingConnections;
106 
107         std::map<ConnectionId, std::set<TransactionId>> mPendingTransactions;
108         // Transactions completed before TRANSFER_TO message arrival.
109         // Fetch does not occur for the transactions.
110         // Only transaction id is kept for the transactions in short duration.
111         std::set<TransactionId> mCompletedTransactions;
112         // Currently active(pending) transations' status & information.
113         std::map<TransactionId, std::unique_ptr<TransactionStatus>>
114                 mTransactions;
115 
116         std::map<BufferId, std::unique_ptr<InternalBuffer>> mBuffers;
117         std::set<BufferId> mFreeBuffers;
118         std::set<ConnectionId> mConnectionIds;
119 
120         struct Invalidation {
121             static std::atomic<std::uint32_t> sInvSeqId;
122 
123             struct Pending {
124                 bool mNeedsAck;
125                 uint32_t mFrom;
126                 uint32_t mTo;
127                 size_t mLeft;
128                 const std::weak_ptr<Accessor::Impl> mImpl;
PendingBufferPool::Invalidation::Pending129                 Pending(bool needsAck, uint32_t from, uint32_t to, size_t left,
130                         const std::shared_ptr<Accessor::Impl> &impl)
131                         : mNeedsAck(needsAck),
132                           mFrom(from),
133                           mTo(to),
134                           mLeft(left),
135                           mImpl(impl)
136                 {}
137 
isInvalidatedBufferPool::Invalidation::Pending138                 bool isInvalidated(uint32_t bufferId) {
139                     return isBufferInRange(mFrom, mTo, bufferId) && --mLeft == 0;
140                 }
141             };
142 
143             std::list<Pending> mPendings;
144             std::map<ConnectionId, uint32_t> mAcks;
145             std::map<ConnectionId, const sp<IObserver>> mObservers;
146             uint32_t mInvalidationId;
147             uint32_t mId;
148 
InvalidationBufferPool::Invalidation149             Invalidation() : mInvalidationId(0), mId(sInvSeqId.fetch_add(1)) {}
150 
151             void onConnect(ConnectionId conId, const sp<IObserver> &observer);
152 
153             void onClose(ConnectionId conId);
154 
155             void onAck(ConnectionId conId, uint32_t msgId);
156 
157             void onBufferInvalidated(
158                     BufferId bufferId,
159                     BufferInvalidationChannel &channel);
160 
161             void onInvalidationRequest(
162                     bool needsAck, uint32_t from, uint32_t to, size_t left,
163                     BufferInvalidationChannel &channel,
164                     const std::shared_ptr<Accessor::Impl> &impl);
165 
166             void onHandleAck(
167                     std::map<ConnectionId, const sp<IObserver>> *observers,
168                     uint32_t *invalidationId);
169         } mInvalidation;
170         /// Buffer pool statistics which tracks allocation and transfer statistics.
171         struct Stats {
172             /// Total size of allocations which are used or available to use.
173             /// (bytes or pixels)
174             size_t mSizeCached;
175             /// # of cached buffers which are used or available to use.
176             size_t mBuffersCached;
177             /// Total size of allocations which are currently used. (bytes or pixels)
178             size_t mSizeInUse;
179             /// # of currently used buffers
180             size_t mBuffersInUse;
181 
182             /// # of allocations called on bufferpool. (# of fetched from BlockPool)
183             size_t mTotalAllocations;
184             /// # of allocations that were served from the cache.
185             /// (# of allocator alloc prevented)
186             size_t mTotalRecycles;
187             /// # of buffer transfers initiated.
188             size_t mTotalTransfers;
189             /// # of transfers that had to be fetched.
190             size_t mTotalFetches;
191 
StatsBufferPool::Stats192             Stats()
193                 : mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0),
194                   mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {}
195 
196             /// # of currently unused buffers
buffersNotInUseBufferPool::Stats197             size_t buffersNotInUse() const {
198                 ALOG_ASSERT(mBuffersCached >= mBuffersInUse);
199                 return mBuffersCached - mBuffersInUse;
200             }
201 
202             /// A new buffer is allocated on an allocation request.
onBufferAllocatedBufferPool::Stats203             void onBufferAllocated(size_t allocSize) {
204                 mSizeCached += allocSize;
205                 mBuffersCached++;
206 
207                 mSizeInUse += allocSize;
208                 mBuffersInUse++;
209 
210                 mTotalAllocations++;
211             }
212 
213             /// A buffer is evicted and destroyed.
onBufferEvictedBufferPool::Stats214             void onBufferEvicted(size_t allocSize) {
215                 mSizeCached -= allocSize;
216                 mBuffersCached--;
217             }
218 
219             /// A buffer is recycled on an allocation request.
onBufferRecycledBufferPool::Stats220             void onBufferRecycled(size_t allocSize) {
221                 mSizeInUse += allocSize;
222                 mBuffersInUse++;
223 
224                 mTotalAllocations++;
225                 mTotalRecycles++;
226             }
227 
228             /// A buffer is available to be recycled.
onBufferUnusedBufferPool::Stats229             void onBufferUnused(size_t allocSize) {
230                 mSizeInUse -= allocSize;
231                 mBuffersInUse--;
232             }
233 
234             /// A buffer transfer is initiated.
onBufferSentBufferPool::Stats235             void onBufferSent() {
236                 mTotalTransfers++;
237             }
238 
239             /// A buffer fetch is invoked by a buffer transfer.
onBufferFetchedBufferPool::Stats240             void onBufferFetched() {
241                 mTotalFetches++;
242             }
243         } mStats;
244 
isValidBufferPool245         bool isValid() {
246             return mValid;
247         }
248 
249         void invalidate(bool needsAck, BufferId from, BufferId to,
250                         const std::shared_ptr<Accessor::Impl> &impl);
251 
252         static void createInvalidator();
253 
254     public:
255         /** Creates a buffer pool. */
256         BufferPool();
257 
258         /** Destroys a buffer pool. */
259         ~BufferPool();
260 
261         /**
262          * Processes all pending buffer status messages, and returns the result.
263          * Each status message is handled by methods with 'handle' prefix.
264          */
265         void processStatusMessages();
266 
267         /**
268          * Handles a buffer being owned by a connection.
269          *
270          * @param connectionId  the id of the buffer owning connection.
271          * @param bufferId      the id of the buffer.
272          *
273          * @return {@code true} when the buffer is owned,
274          *         {@code false} otherwise.
275          */
276         bool handleOwnBuffer(ConnectionId connectionId, BufferId bufferId);
277 
278         /**
279          * Handles a buffer being released by a connection.
280          *
281          * @param connectionId  the id of the buffer owning connection.
282          * @param bufferId      the id of the buffer.
283          *
284          * @return {@code true} when the buffer ownership is released,
285          *         {@code false} otherwise.
286          */
287         bool handleReleaseBuffer(ConnectionId connectionId, BufferId bufferId);
288 
289         /**
290          * Handles a transfer transaction start message from the sender.
291          *
292          * @param message   a buffer status message for the transaction.
293          *
294          * @result {@code true} when transfer_to message is acknowledged,
295          *         {@code false} otherwise.
296          */
297         bool handleTransferTo(const BufferStatusMessage &message);
298 
299         /**
300          * Handles a transfer transaction being acked by the receiver.
301          *
302          * @param message   a buffer status message for the transaction.
303          *
304          * @result {@code true} when transfer_from message is acknowledged,
305          *         {@code false} otherwise.
306          */
307         bool handleTransferFrom(const BufferStatusMessage &message);
308 
309         /**
310          * Handles a transfer transaction result message from the receiver.
311          *
312          * @param message   a buffer status message for the transaction.
313          *
314          * @result {@code true} when the exisitng transaction is finished,
315          *         {@code false} otherwise.
316          */
317         bool handleTransferResult(const BufferStatusMessage &message);
318 
319         /**
320          * Handles a connection being closed, and returns the result. All the
321          * buffers and transactions owned by the connection will be cleaned up.
322          * The related FMQ will be cleaned up too.
323          *
324          * @param connectionId  the id of the connection.
325          *
326          * @result {@code true} when the connection existed,
327          *         {@code false} otherwise.
328          */
329         bool handleClose(ConnectionId connectionId);
330 
331         /**
332          * Recycles a existing free buffer if it is possible.
333          *
334          * @param allocator the buffer allocator
335          * @param params    the allocation parameters.
336          * @param pId       the id of the recycled buffer.
337          * @param handle    the native handle of the recycled buffer.
338          *
339          * @return {@code true} when a buffer is recycled, {@code false}
340          *         otherwise.
341          */
342         bool getFreeBuffer(
343                 const std::shared_ptr<BufferPoolAllocator> &allocator,
344                 const std::vector<uint8_t> &params,
345                 BufferId *pId, const native_handle_t **handle);
346 
347         /**
348          * Adds a newly allocated buffer to bufferpool.
349          *
350          * @param alloc     the newly allocated buffer.
351          * @param allocSize the size of the newly allocated buffer.
352          * @param params    the allocation parameters.
353          * @param pId       the buffer id for the newly allocated buffer.
354          * @param handle    the native handle for the newly allocated buffer.
355          *
356          * @return OK when an allocation is successfully allocated.
357          *         NO_MEMORY when there is no memory.
358          *         CRITICAL_ERROR otherwise.
359          */
360         ResultStatus addNewBuffer(
361                 const std::shared_ptr<BufferPoolAllocation> &alloc,
362                 const size_t allocSize,
363                 const std::vector<uint8_t> &params,
364                 BufferId *pId,
365                 const native_handle_t **handle);
366 
367         /**
368          * Processes pending buffer status messages and performs periodic cache
369          * cleaning.
370          *
371          * @param clearCache    if clearCache is true, it frees all buffers
372          *                      waiting to be recycled.
373          */
374         void cleanUp(bool clearCache = false);
375 
376         /**
377          * Processes pending buffer status messages and invalidate all current
378          * free buffers. Active buffers are invalidated after being inactive.
379          */
380         void flush(const std::shared_ptr<Accessor::Impl> &impl);
381 
382         friend class Accessor::Impl;
383     } mBufferPool;
384 
385     struct  AccessorInvalidator {
386         std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> mAccessors;
387         std::mutex mMutex;
388         std::condition_variable mCv;
389         bool mReady;
390 
391         AccessorInvalidator();
392         void addAccessor(uint32_t accessorId, const std::weak_ptr<Accessor::Impl> &impl);
393         void delAccessor(uint32_t accessorId);
394     };
395 
396     static std::unique_ptr<AccessorInvalidator> sInvalidator;
397 
398     static void invalidatorThread(
399         std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> &accessors,
400         std::mutex &mutex,
401         std::condition_variable &cv,
402         bool &ready);
403 
404     struct AccessorEvictor {
405         std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> mAccessors;
406         std::mutex mMutex;
407         std::condition_variable mCv;
408 
409         AccessorEvictor();
410         void addAccessor(const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts);
411     };
412 
413     static std::unique_ptr<AccessorEvictor> sEvictor;
414 
415     static void evictorThread(
416         std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors,
417         std::mutex &mutex,
418         std::condition_variable &cv);
419 
420     void scheduleEvictIfNeeded();
421 
422 };
423 
424 }  // namespace implementation
425 }  // namespace V2_0
426 }  // namespace ufferpool
427 }  // namespace media
428 }  // namespace hardware
429 }  // namespace android
430 
431 #endif  // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSORIMPL_H
432