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