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 StatsBufferPool::Stats120 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. onBufferAllocatedBufferPool::Stats125 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. onBufferEvictedBufferPool::Stats136 void onBufferEvicted(size_t allocSize) { 137 mSizeCached -= allocSize; 138 mBuffersCached--; 139 } 140 141 /// A buffer is recycled on an allocation request. onBufferRecycledBufferPool::Stats142 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. onBufferUnusedBufferPool::Stats151 void onBufferUnused(size_t allocSize) { 152 mSizeInUse -= allocSize; 153 mBuffersInUse--; 154 } 155 156 /// A buffer transfer is initiated. onBufferSentBufferPool::Stats157 void onBufferSent() { 158 mTotalTransfers++; 159 } 160 161 /// A buffer fetch is invoked by a buffer transfer. onBufferFetchedBufferPool::Stats162 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> ¶ms, 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> ¶ms, 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