Home | History | Annotate | Download | only in 1.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_V1_0_ACCESSORIMPL_H
     18 #define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V1_0_ACCESSORIMPL_H
     19 
     20 #include <map>
     21 #include <set>
     22 #include "Accessor.h"
     23 
     24 namespace android {
     25 namespace hardware {
     26 namespace media {
     27 namespace bufferpool {
     28 namespace V1_0 {
     29 namespace implementation {
     30 
     31 struct InternalBuffer;
     32 struct TransactionStatus;
     33 
     34 /**
     35  * An implementation of a buffer pool accessor(or a buffer pool implementation.) */
     36 class Accessor::Impl {
     37 public:
     38     Impl(const std::shared_ptr<BufferPoolAllocator> &allocator);
     39 
     40     ~Impl();
     41 
     42     ResultStatus connect(
     43             const sp<Accessor> &accessor, sp<Connection> *connection,
     44             ConnectionId *pConnectionId, const QueueDescriptor** fmqDescPtr);
     45 
     46     ResultStatus close(ConnectionId connectionId);
     47 
     48     ResultStatus allocate(ConnectionId connectionId,
     49                           const std::vector<uint8_t>& params,
     50                           BufferId *bufferId,
     51                           const native_handle_t** handle);
     52 
     53     ResultStatus fetch(ConnectionId connectionId,
     54                        TransactionId transactionId,
     55                        BufferId bufferId,
     56                        const native_handle_t** handle);
     57 
     58     void cleanUp(bool clearCache);
     59 
     60 private:
     61     // ConnectionId = pid : (timestamp_created + seqId)
     62     // in order to guarantee uniqueness for each connection
     63     static uint32_t sSeqId;
     64     static int32_t sPid;
     65 
     66     const std::shared_ptr<BufferPoolAllocator> mAllocator;
     67 
     68     /**
     69      * Buffer pool implementation.
     70      *
     71      * Handles buffer status messages. Handles buffer allocation/recycling.
     72      * Handles buffer transfer between buffer pool clients.
     73      */
     74     struct BufferPool {
     75     private:
     76         std::mutex mMutex;
     77         int64_t mTimestampUs;
     78         int64_t mLastCleanUpUs;
     79         int64_t mLastLogUs;
     80         BufferId mSeq;
     81         BufferStatusObserver mObserver;
     82 
     83         std::map<ConnectionId, std::set<BufferId>> mUsingBuffers;
     84         std::map<BufferId, std::set<ConnectionId>> mUsingConnections;
     85 
     86         std::map<ConnectionId, std::set<TransactionId>> mPendingTransactions;
     87         // Transactions completed before TRANSFER_TO message arrival.
     88         // Fetch does not occur for the transactions.
     89         // Only transaction id is kept for the transactions in short duration.
     90         std::set<TransactionId> mCompletedTransactions;
     91         // Currently active(pending) transations' status & information.
     92         std::map<TransactionId, std::unique_ptr<TransactionStatus>>
     93                 mTransactions;
     94 
     95         std::map<BufferId, std::unique_ptr<InternalBuffer>> mBuffers;
     96         std::set<BufferId> mFreeBuffers;
     97 
     98         /// Buffer pool statistics which tracks allocation and transfer statistics.
     99         struct Stats {
    100             /// Total size of allocations which are used or available to use.
    101             /// (bytes or pixels)
    102             size_t mSizeCached;
    103             /// # of cached buffers which are used or available to use.
    104             size_t mBuffersCached;
    105             /// Total size of allocations which are currently used. (bytes or pixels)
    106             size_t mSizeInUse;
    107             /// # of currently used buffers
    108             size_t mBuffersInUse;
    109 
    110             /// # of allocations called on bufferpool. (# of fetched from BlockPool)
    111             size_t mTotalAllocations;
    112             /// # of allocations that were served from the cache.
    113             /// (# of allocator alloc prevented)
    114             size_t mTotalRecycles;
    115             /// # of buffer transfers initiated.
    116             size_t mTotalTransfers;
    117             /// # of transfers that had to be fetched.
    118             size_t mTotalFetches;
    119 
    120             Stats()
    121                 : mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0),
    122                   mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {}
    123 
    124             /// A new buffer is allocated on an allocation request.
    125             void onBufferAllocated(size_t allocSize) {
    126                 mSizeCached += allocSize;
    127                 mBuffersCached++;
    128 
    129                 mSizeInUse += allocSize;
    130                 mBuffersInUse++;
    131 
    132                 mTotalAllocations++;
    133             }
    134 
    135             /// A buffer is evicted and destroyed.
    136             void onBufferEvicted(size_t allocSize) {
    137                 mSizeCached -= allocSize;
    138                 mBuffersCached--;
    139             }
    140 
    141             /// A buffer is recycled on an allocation request.
    142             void onBufferRecycled(size_t allocSize) {
    143                 mSizeInUse += allocSize;
    144                 mBuffersInUse++;
    145 
    146                 mTotalAllocations++;
    147                 mTotalRecycles++;
    148             }
    149 
    150             /// A buffer is available to be recycled.
    151             void onBufferUnused(size_t allocSize) {
    152                 mSizeInUse -= allocSize;
    153                 mBuffersInUse--;
    154             }
    155 
    156             /// A buffer transfer is initiated.
    157             void onBufferSent() {
    158                 mTotalTransfers++;
    159             }
    160 
    161             /// A buffer fetch is invoked by a buffer transfer.
    162             void onBufferFetched() {
    163                 mTotalFetches++;
    164             }
    165         } mStats;
    166 
    167     public:
    168         /** Creates a buffer pool. */
    169         BufferPool();
    170 
    171         /** Destroys a buffer pool. */
    172         ~BufferPool();
    173 
    174         /**
    175          * Processes all pending buffer status messages, and returns the result.
    176          * Each status message is handled by methods with 'handle' prefix.
    177          */
    178         void processStatusMessages();
    179 
    180         /**
    181          * Handles a buffer being owned by a connection.
    182          *
    183          * @param connectionId  the id of the buffer owning connection.
    184          * @param bufferId      the id of the buffer.
    185          *
    186          * @return {@code true} when the buffer is owned,
    187          *         {@code false} otherwise.
    188          */
    189         bool handleOwnBuffer(ConnectionId connectionId, BufferId bufferId);
    190 
    191         /**
    192          * Handles a buffer being released by a connection.
    193          *
    194          * @param connectionId  the id of the buffer owning connection.
    195          * @param bufferId      the id of the buffer.
    196          *
    197          * @return {@code true} when the buffer ownership is released,
    198          *         {@code false} otherwise.
    199          */
    200         bool handleReleaseBuffer(ConnectionId connectionId, BufferId bufferId);
    201 
    202         /**
    203          * Handles a transfer transaction start message from the sender.
    204          *
    205          * @param message   a buffer status message for the transaction.
    206          *
    207          * @result {@code true} when transfer_to message is acknowledged,
    208          *         {@code false} otherwise.
    209          */
    210         bool handleTransferTo(const BufferStatusMessage &message);
    211 
    212         /**
    213          * Handles a transfer transaction being acked by the receiver.
    214          *
    215          * @param message   a buffer status message for the transaction.
    216          *
    217          * @result {@code true} when transfer_from message is acknowledged,
    218          *         {@code false} otherwise.
    219          */
    220         bool handleTransferFrom(const BufferStatusMessage &message);
    221 
    222         /**
    223          * Handles a transfer transaction result message from the receiver.
    224          *
    225          * @param message   a buffer status message for the transaction.
    226          *
    227          * @result {@code true} when the exisitng transaction is finished,
    228          *         {@code false} otherwise.
    229          */
    230         bool handleTransferResult(const BufferStatusMessage &message);
    231 
    232         /**
    233          * Handles a connection being closed, and returns the result. All the
    234          * buffers and transactions owned by the connection will be cleaned up.
    235          * The related FMQ will be cleaned up too.
    236          *
    237          * @param connectionId  the id of the connection.
    238          *
    239          * @result {@code true} when the connection existed,
    240          *         {@code false} otherwise.
    241          */
    242         bool handleClose(ConnectionId connectionId);
    243 
    244         /**
    245          * Recycles a existing free buffer if it is possible.
    246          *
    247          * @param allocator the buffer allocator
    248          * @param params    the allocation parameters.
    249          * @param pId       the id of the recycled buffer.
    250          * @param handle    the native handle of the recycled buffer.
    251          *
    252          * @return {@code true} when a buffer is recycled, {@code false}
    253          *         otherwise.
    254          */
    255         bool getFreeBuffer(
    256                 const std::shared_ptr<BufferPoolAllocator> &allocator,
    257                 const std::vector<uint8_t> &params,
    258                 BufferId *pId, const native_handle_t **handle);
    259 
    260         /**
    261          * Adds a newly allocated buffer to bufferpool.
    262          *
    263          * @param alloc     the newly allocated buffer.
    264          * @param allocSize the size of the newly allocated buffer.
    265          * @param params    the allocation parameters.
    266          * @param pId       the buffer id for the newly allocated buffer.
    267          * @param handle    the native handle for the newly allocated buffer.
    268          *
    269          * @return OK when an allocation is successfully allocated.
    270          *         NO_MEMORY when there is no memory.
    271          *         CRITICAL_ERROR otherwise.
    272          */
    273         ResultStatus addNewBuffer(
    274                 const std::shared_ptr<BufferPoolAllocation> &alloc,
    275                 const size_t allocSize,
    276                 const std::vector<uint8_t> &params,
    277                 BufferId *pId,
    278                 const native_handle_t **handle);
    279 
    280         /**
    281          * Processes pending buffer status messages and performs periodic cache
    282          * cleaning.
    283          *
    284          * @param clearCache    if clearCache is true, it frees all buffers
    285          *                      waiting to be recycled.
    286          */
    287         void cleanUp(bool clearCache = false);
    288 
    289         friend class Accessor::Impl;
    290     } mBufferPool;
    291 };
    292 
    293 }  // namespace implementation
    294 }  // namespace V1_0
    295 }  // namespace ufferpool
    296 }  // namespace media
    297 }  // namespace hardware
    298 }  // namespace android
    299 
    300 #endif  // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V1_0_ACCESSORIMPL_H
    301