| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 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> | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 22 | #include <condition_variable> | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 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.) */ | 
| Sungtak Lee | d312838 | 2018-11-07 17:30:37 -0800 | [diff] [blame] | 37 | class Accessor::Impl | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 38 |     : public std::enable_shared_from_this<Accessor::Impl> { | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 39 | public: | 
 | 40 |     Impl(const std::shared_ptr<BufferPoolAllocator> &allocator); | 
 | 41 |  | 
 | 42 |     ~Impl(); | 
 | 43 |  | 
 | 44 |     ResultStatus connect( | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 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); | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 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 |  | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 64 |     void flush(); | 
 | 65 |  | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 66 |     void cleanUp(bool clearCache); | 
 | 67 |  | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 68 |     bool isValid(); | 
 | 69 |  | 
 | 70 |     void handleInvalidateAck(); | 
 | 71 |  | 
| Sungtak Lee | d312838 | 2018-11-07 17:30:37 -0800 | [diff] [blame] | 72 |     static void createInvalidator(); | 
 | 73 |  | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 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; | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 95 |         BufferId mStartSeq; | 
 | 96 |         bool mValid; | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 97 |         BufferStatusObserver mObserver; | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 98 |         BufferInvalidationChannel mInvalidationChannel; | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 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 |  | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 115 |         struct Invalidation { | 
| Sungtak Lee | d312838 | 2018-11-07 17:30:37 -0800 | [diff] [blame] | 116 |             static std::atomic<std::uint32_t> sInvSeqId; | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 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 |  | 
| Sungtak Lee | d312838 | 2018-11-07 17:30:37 -0800 | [diff] [blame] | 133 |                 bool isInvalidated(uint32_t bufferId) { | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 134 |                     return isBufferInRange(mFrom, mTo, bufferId) && --mLeft == 0; | 
 | 135 |                 } | 
 | 136 |             }; | 
 | 137 |  | 
 | 138 |             std::list<Pending> mPendings; | 
 | 139 |             std::map<ConnectionId, uint32_t> mAcks; | 
| Sungtak Lee | d312838 | 2018-11-07 17:30:37 -0800 | [diff] [blame] | 140 |             std::map<ConnectionId, const sp<IObserver>> mObservers; | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 141 |             uint32_t mInvalidationId; | 
 | 142 |             uint32_t mId; | 
 | 143 |  | 
| Sungtak Lee | d312838 | 2018-11-07 17:30:37 -0800 | [diff] [blame] | 144 |             Invalidation() : mInvalidationId(0), mId(sInvSeqId.fetch_add(1)) {} | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 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 |         } mInvalidation; | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 163 |         /// Buffer pool statistics which tracks allocation and transfer statistics. | 
 | 164 |         struct Stats { | 
 | 165 |             /// Total size of allocations which are used or available to use. | 
 | 166 |             /// (bytes or pixels) | 
 | 167 |             size_t mSizeCached; | 
 | 168 |             /// # of cached buffers which are used or available to use. | 
 | 169 |             size_t mBuffersCached; | 
 | 170 |             /// Total size of allocations which are currently used. (bytes or pixels) | 
 | 171 |             size_t mSizeInUse; | 
 | 172 |             /// # of currently used buffers | 
 | 173 |             size_t mBuffersInUse; | 
 | 174 |  | 
 | 175 |             /// # of allocations called on bufferpool. (# of fetched from BlockPool) | 
 | 176 |             size_t mTotalAllocations; | 
 | 177 |             /// # of allocations that were served from the cache. | 
 | 178 |             /// (# of allocator alloc prevented) | 
 | 179 |             size_t mTotalRecycles; | 
 | 180 |             /// # of buffer transfers initiated. | 
 | 181 |             size_t mTotalTransfers; | 
 | 182 |             /// # of transfers that had to be fetched. | 
 | 183 |             size_t mTotalFetches; | 
 | 184 |  | 
 | 185 |             Stats() | 
 | 186 |                 : mSizeCached(0), mBuffersCached(0), mSizeInUse(0), mBuffersInUse(0), | 
 | 187 |                   mTotalAllocations(0), mTotalRecycles(0), mTotalTransfers(0), mTotalFetches(0) {} | 
 | 188 |  | 
 | 189 |             /// A new buffer is allocated on an allocation request. | 
 | 190 |             void onBufferAllocated(size_t allocSize) { | 
 | 191 |                 mSizeCached += allocSize; | 
 | 192 |                 mBuffersCached++; | 
 | 193 |  | 
 | 194 |                 mSizeInUse += allocSize; | 
 | 195 |                 mBuffersInUse++; | 
 | 196 |  | 
 | 197 |                 mTotalAllocations++; | 
 | 198 |             } | 
 | 199 |  | 
 | 200 |             /// A buffer is evicted and destroyed. | 
 | 201 |             void onBufferEvicted(size_t allocSize) { | 
 | 202 |                 mSizeCached -= allocSize; | 
 | 203 |                 mBuffersCached--; | 
 | 204 |             } | 
 | 205 |  | 
 | 206 |             /// A buffer is recycled on an allocation request. | 
 | 207 |             void onBufferRecycled(size_t allocSize) { | 
 | 208 |                 mSizeInUse += allocSize; | 
 | 209 |                 mBuffersInUse++; | 
 | 210 |  | 
 | 211 |                 mTotalAllocations++; | 
 | 212 |                 mTotalRecycles++; | 
 | 213 |             } | 
 | 214 |  | 
 | 215 |             /// A buffer is available to be recycled. | 
 | 216 |             void onBufferUnused(size_t allocSize) { | 
 | 217 |                 mSizeInUse -= allocSize; | 
 | 218 |                 mBuffersInUse--; | 
 | 219 |             } | 
 | 220 |  | 
 | 221 |             /// A buffer transfer is initiated. | 
 | 222 |             void onBufferSent() { | 
 | 223 |                 mTotalTransfers++; | 
 | 224 |             } | 
 | 225 |  | 
 | 226 |             /// A buffer fetch is invoked by a buffer transfer. | 
 | 227 |             void onBufferFetched() { | 
 | 228 |                 mTotalFetches++; | 
 | 229 |             } | 
 | 230 |         } mStats; | 
 | 231 |  | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 232 |         bool isValid() { | 
 | 233 |             return mValid; | 
 | 234 |         } | 
 | 235 |  | 
 | 236 |         void invalidate(bool needsAck, BufferId from, BufferId to, | 
 | 237 |                         const std::shared_ptr<Accessor::Impl> &impl); | 
 | 238 |  | 
| Sungtak Lee | d312838 | 2018-11-07 17:30:37 -0800 | [diff] [blame] | 239 |         static void createInvalidator(); | 
 | 240 |  | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 241 |     public: | 
 | 242 |         /** Creates a buffer pool. */ | 
 | 243 |         BufferPool(); | 
 | 244 |  | 
 | 245 |         /** Destroys a buffer pool. */ | 
 | 246 |         ~BufferPool(); | 
 | 247 |  | 
 | 248 |         /** | 
 | 249 |          * Processes all pending buffer status messages, and returns the result. | 
 | 250 |          * Each status message is handled by methods with 'handle' prefix. | 
 | 251 |          */ | 
 | 252 |         void processStatusMessages(); | 
 | 253 |  | 
 | 254 |         /** | 
 | 255 |          * Handles a buffer being owned by a connection. | 
 | 256 |          * | 
 | 257 |          * @param connectionId  the id of the buffer owning connection. | 
 | 258 |          * @param bufferId      the id of the buffer. | 
 | 259 |          * | 
 | 260 |          * @return {@code true} when the buffer is owned, | 
 | 261 |          *         {@code false} otherwise. | 
 | 262 |          */ | 
 | 263 |         bool handleOwnBuffer(ConnectionId connectionId, BufferId bufferId); | 
 | 264 |  | 
 | 265 |         /** | 
 | 266 |          * Handles a buffer being released by a connection. | 
 | 267 |          * | 
 | 268 |          * @param connectionId  the id of the buffer owning connection. | 
 | 269 |          * @param bufferId      the id of the buffer. | 
 | 270 |          * | 
 | 271 |          * @return {@code true} when the buffer ownership is released, | 
 | 272 |          *         {@code false} otherwise. | 
 | 273 |          */ | 
 | 274 |         bool handleReleaseBuffer(ConnectionId connectionId, BufferId bufferId); | 
 | 275 |  | 
 | 276 |         /** | 
 | 277 |          * Handles a transfer transaction start message from the sender. | 
 | 278 |          * | 
 | 279 |          * @param message   a buffer status message for the transaction. | 
 | 280 |          * | 
 | 281 |          * @result {@code true} when transfer_to message is acknowledged, | 
 | 282 |          *         {@code false} otherwise. | 
 | 283 |          */ | 
 | 284 |         bool handleTransferTo(const BufferStatusMessage &message); | 
 | 285 |  | 
 | 286 |         /** | 
 | 287 |          * Handles a transfer transaction being acked by the receiver. | 
 | 288 |          * | 
 | 289 |          * @param message   a buffer status message for the transaction. | 
 | 290 |          * | 
 | 291 |          * @result {@code true} when transfer_from message is acknowledged, | 
 | 292 |          *         {@code false} otherwise. | 
 | 293 |          */ | 
 | 294 |         bool handleTransferFrom(const BufferStatusMessage &message); | 
 | 295 |  | 
 | 296 |         /** | 
 | 297 |          * Handles a transfer transaction result message from the receiver. | 
 | 298 |          * | 
 | 299 |          * @param message   a buffer status message for the transaction. | 
 | 300 |          * | 
 | 301 |          * @result {@code true} when the exisitng transaction is finished, | 
 | 302 |          *         {@code false} otherwise. | 
 | 303 |          */ | 
 | 304 |         bool handleTransferResult(const BufferStatusMessage &message); | 
 | 305 |  | 
 | 306 |         /** | 
 | 307 |          * Handles a connection being closed, and returns the result. All the | 
 | 308 |          * buffers and transactions owned by the connection will be cleaned up. | 
 | 309 |          * The related FMQ will be cleaned up too. | 
 | 310 |          * | 
 | 311 |          * @param connectionId  the id of the connection. | 
 | 312 |          * | 
 | 313 |          * @result {@code true} when the connection existed, | 
 | 314 |          *         {@code false} otherwise. | 
 | 315 |          */ | 
 | 316 |         bool handleClose(ConnectionId connectionId); | 
 | 317 |  | 
 | 318 |         /** | 
 | 319 |          * Recycles a existing free buffer if it is possible. | 
 | 320 |          * | 
 | 321 |          * @param allocator the buffer allocator | 
 | 322 |          * @param params    the allocation parameters. | 
 | 323 |          * @param pId       the id of the recycled buffer. | 
 | 324 |          * @param handle    the native handle of the recycled buffer. | 
 | 325 |          * | 
 | 326 |          * @return {@code true} when a buffer is recycled, {@code false} | 
 | 327 |          *         otherwise. | 
 | 328 |          */ | 
 | 329 |         bool getFreeBuffer( | 
 | 330 |                 const std::shared_ptr<BufferPoolAllocator> &allocator, | 
 | 331 |                 const std::vector<uint8_t> ¶ms, | 
 | 332 |                 BufferId *pId, const native_handle_t **handle); | 
 | 333 |  | 
 | 334 |         /** | 
 | 335 |          * Adds a newly allocated buffer to bufferpool. | 
 | 336 |          * | 
 | 337 |          * @param alloc     the newly allocated buffer. | 
 | 338 |          * @param allocSize the size of the newly allocated buffer. | 
 | 339 |          * @param params    the allocation parameters. | 
 | 340 |          * @param pId       the buffer id for the newly allocated buffer. | 
 | 341 |          * @param handle    the native handle for the newly allocated buffer. | 
 | 342 |          * | 
 | 343 |          * @return OK when an allocation is successfully allocated. | 
 | 344 |          *         NO_MEMORY when there is no memory. | 
 | 345 |          *         CRITICAL_ERROR otherwise. | 
 | 346 |          */ | 
 | 347 |         ResultStatus addNewBuffer( | 
 | 348 |                 const std::shared_ptr<BufferPoolAllocation> &alloc, | 
 | 349 |                 const size_t allocSize, | 
 | 350 |                 const std::vector<uint8_t> ¶ms, | 
 | 351 |                 BufferId *pId, | 
 | 352 |                 const native_handle_t **handle); | 
 | 353 |  | 
 | 354 |         /** | 
 | 355 |          * Processes pending buffer status messages and performs periodic cache | 
 | 356 |          * cleaning. | 
 | 357 |          * | 
 | 358 |          * @param clearCache    if clearCache is true, it frees all buffers | 
 | 359 |          *                      waiting to be recycled. | 
 | 360 |          */ | 
 | 361 |         void cleanUp(bool clearCache = false); | 
 | 362 |  | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 363 |         /** | 
 | 364 |          * Processes pending buffer status messages and invalidate all current | 
 | 365 |          * free buffers. Active buffers are invalidated after being inactive. | 
 | 366 |          */ | 
 | 367 |         void flush(const std::shared_ptr<Accessor::Impl> &impl); | 
 | 368 |  | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 369 |         friend class Accessor::Impl; | 
 | 370 |     } mBufferPool; | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 371 |  | 
 | 372 |     struct  AccessorInvalidator { | 
 | 373 |         std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> mAccessors; | 
 | 374 |         std::mutex mMutex; | 
 | 375 |         std::condition_variable mCv; | 
 | 376 |         bool mReady; | 
 | 377 |  | 
 | 378 |         AccessorInvalidator(); | 
 | 379 |         void addAccessor(uint32_t accessorId, const std::weak_ptr<Accessor::Impl> &impl); | 
 | 380 |         void delAccessor(uint32_t accessorId); | 
 | 381 |     }; | 
 | 382 |  | 
| Sungtak Lee | d312838 | 2018-11-07 17:30:37 -0800 | [diff] [blame] | 383 |     static std::unique_ptr<AccessorInvalidator> sInvalidator; | 
| Sungtak Lee | c7f9e2c | 2018-09-14 16:23:40 -0700 | [diff] [blame] | 384 |  | 
 | 385 |     static void invalidatorThread( | 
 | 386 |         std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> &accessors, | 
 | 387 |         std::mutex &mutex, | 
 | 388 |         std::condition_variable &cv, | 
 | 389 |         bool &ready); | 
| Sungtak Lee | bbe37b6 | 2018-08-29 15:15:48 -0700 | [diff] [blame] | 390 | }; | 
 | 391 |  | 
 | 392 | }  // namespace implementation | 
 | 393 | }  // namespace V2_0 | 
 | 394 | }  // namespace ufferpool | 
 | 395 | }  // namespace media | 
 | 396 | }  // namespace hardware | 
 | 397 | }  // namespace android | 
 | 398 |  | 
 | 399 | #endif  // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_ACCESSORIMPL_H |