Loading media/bufferpool/2.0/Accessor.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,10 @@ void Accessor::createInvalidator() { Accessor::Impl::createInvalidator(); } void Accessor::createEvictor() { Accessor::Impl::createEvictor(); } // Methods from ::android::hardware::media::bufferpool::V2_0::IAccessor follow. Return<void> Accessor::connect( const sp<::android::hardware::media::bufferpool::V2_0::IObserver>& observer, Loading media/bufferpool/2.0/Accessor.h +2 −0 Original line number Diff line number Diff line Loading @@ -187,6 +187,8 @@ struct Accessor : public IAccessor { static void createInvalidator(); static void createEvictor(); private: class Impl; std::shared_ptr<Impl> mImpl; Loading media/bufferpool/2.0/AccessorImpl.cpp +90 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,9 @@ namespace { static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15; static constexpr size_t kMinBufferCountForEviction = 25; static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs } // Buffer structure in bufferpool process Loading Loading @@ -146,7 +149,7 @@ uint32_t Accessor::Impl::sSeqId = time(nullptr) & kSeqIdMax; Accessor::Impl::Impl( const std::shared_ptr<BufferPoolAllocator> &allocator) : mAllocator(allocator) {} : mAllocator(allocator), mScheduleEvictTs(0) {} Accessor::Impl::~Impl() { } Loading Loading @@ -184,6 +187,7 @@ ResultStatus Accessor::Impl::connect( } mBufferPool.processStatusMessages(); mBufferPool.cleanUp(); scheduleEvictIfNeeded(); } return status; } Loading @@ -198,6 +202,7 @@ ResultStatus Accessor::Impl::close(ConnectionId connectionId) { // Since close# will be called after all works are finished, it is OK to // evict unused buffers. mBufferPool.cleanUp(true); scheduleEvictIfNeeded(); return ResultStatus::OK; } Loading @@ -224,6 +229,7 @@ ResultStatus Accessor::Impl::allocate( mBufferPool.handleOwnBuffer(connectionId, *bufferId); } mBufferPool.cleanUp(); scheduleEvictIfNeeded(); return status; } Loading @@ -249,6 +255,7 @@ ResultStatus Accessor::Impl::fetch( } } mBufferPool.cleanUp(); scheduleEvictIfNeeded(); return ResultStatus::CRITICAL_ERROR; } Loading Loading @@ -891,6 +898,88 @@ void Accessor::Impl::createInvalidator() { } } void Accessor::Impl::evictorThread( std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors, std::mutex &mutex, std::condition_variable &cv) { std::list<const std::weak_ptr<Accessor::Impl>> evictList; while (true) { int expired = 0; int evicted = 0; { nsecs_t now = systemTime(); std::unique_lock<std::mutex> lock(mutex); if (accessors.size() == 0) { cv.wait(lock); } auto it = accessors.begin(); while (it != accessors.end()) { if (now > (it->second + kEvictDurationNs)) { ++expired; evictList.push_back(it->first); it = accessors.erase(it); } else { ++it; } } } // evict idle accessors; for (auto it = evictList.begin(); it != evictList.end(); ++it) { const std::shared_ptr<Accessor::Impl> accessor = it->lock(); if (accessor) { accessor->cleanUp(true); ++evicted; } } if (expired > 0) { ALOGD("evictor expired: %d, evicted: %d", expired, evicted); } evictList.clear(); ::usleep(kEvictGranularityNs / 1000); } } Accessor::Impl::AccessorEvictor::AccessorEvictor() { std::thread evictor( evictorThread, std::ref(mAccessors), std::ref(mMutex), std::ref(mCv)); evictor.detach(); } void Accessor::Impl::AccessorEvictor::addAccessor( const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts) { std::lock_guard<std::mutex> lock(mMutex); bool notify = mAccessors.empty(); auto it = mAccessors.find(impl); if (it == mAccessors.end()) { mAccessors.emplace(impl, ts); } else { it->second = ts; } if (notify) { mCv.notify_one(); } } std::unique_ptr<Accessor::Impl::AccessorEvictor> Accessor::Impl::sEvictor; void Accessor::Impl::createEvictor() { if (!sEvictor) { sEvictor = std::make_unique<Accessor::Impl::AccessorEvictor>(); } } void Accessor::Impl::scheduleEvictIfNeeded() { nsecs_t now = systemTime(); if (now > (mScheduleEvictTs + kEvictGranularityNs)) { mScheduleEvictTs = now; sEvictor->addAccessor(shared_from_this(), now); } } } // namespace implementation } // namespace V2_0 } // namespace bufferpool Loading media/bufferpool/2.0/AccessorImpl.h +24 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <map> #include <set> #include <condition_variable> #include <utils/Timers.h> #include "Accessor.h" namespace android { Loading Loading @@ -71,6 +72,8 @@ public: static void createInvalidator(); static void createEvictor(); private: // ConnectionId = pid : (timestamp_created + seqId) // in order to guarantee uniqueness for each connection Loading @@ -78,6 +81,8 @@ private: const std::shared_ptr<BufferPoolAllocator> mAllocator; nsecs_t mScheduleEvictTs; /** * Buffer pool implementation. * Loading Loading @@ -389,6 +394,25 @@ private: std::mutex &mutex, std::condition_variable &cv, bool &ready); struct AccessorEvictor { std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> mAccessors; std::mutex mMutex; std::condition_variable mCv; AccessorEvictor(); void addAccessor(const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts); }; static std::unique_ptr<AccessorEvictor> sEvictor; static void evictorThread( std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors, std::mutex &mutex, std::condition_variable &cv); void scheduleEvictIfNeeded(); }; } // namespace implementation Loading media/bufferpool/2.0/ClientManager.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -484,6 +484,7 @@ sp<ClientManager> ClientManager::getInstance() { sInstance = new ClientManager(); } Accessor::createInvalidator(); Accessor::createEvictor(); return sInstance; } Loading Loading
media/bufferpool/2.0/Accessor.cpp +4 −0 Original line number Diff line number Diff line Loading @@ -117,6 +117,10 @@ void Accessor::createInvalidator() { Accessor::Impl::createInvalidator(); } void Accessor::createEvictor() { Accessor::Impl::createEvictor(); } // Methods from ::android::hardware::media::bufferpool::V2_0::IAccessor follow. Return<void> Accessor::connect( const sp<::android::hardware::media::bufferpool::V2_0::IObserver>& observer, Loading
media/bufferpool/2.0/Accessor.h +2 −0 Original line number Diff line number Diff line Loading @@ -187,6 +187,8 @@ struct Accessor : public IAccessor { static void createInvalidator(); static void createEvictor(); private: class Impl; std::shared_ptr<Impl> mImpl; Loading
media/bufferpool/2.0/AccessorImpl.cpp +90 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,9 @@ namespace { static constexpr size_t kMinAllocBytesForEviction = 1024*1024*15; static constexpr size_t kMinBufferCountForEviction = 25; static constexpr nsecs_t kEvictGranularityNs = 1000000000; // 1 sec static constexpr nsecs_t kEvictDurationNs = 5000000000; // 5 secs } // Buffer structure in bufferpool process Loading Loading @@ -146,7 +149,7 @@ uint32_t Accessor::Impl::sSeqId = time(nullptr) & kSeqIdMax; Accessor::Impl::Impl( const std::shared_ptr<BufferPoolAllocator> &allocator) : mAllocator(allocator) {} : mAllocator(allocator), mScheduleEvictTs(0) {} Accessor::Impl::~Impl() { } Loading Loading @@ -184,6 +187,7 @@ ResultStatus Accessor::Impl::connect( } mBufferPool.processStatusMessages(); mBufferPool.cleanUp(); scheduleEvictIfNeeded(); } return status; } Loading @@ -198,6 +202,7 @@ ResultStatus Accessor::Impl::close(ConnectionId connectionId) { // Since close# will be called after all works are finished, it is OK to // evict unused buffers. mBufferPool.cleanUp(true); scheduleEvictIfNeeded(); return ResultStatus::OK; } Loading @@ -224,6 +229,7 @@ ResultStatus Accessor::Impl::allocate( mBufferPool.handleOwnBuffer(connectionId, *bufferId); } mBufferPool.cleanUp(); scheduleEvictIfNeeded(); return status; } Loading @@ -249,6 +255,7 @@ ResultStatus Accessor::Impl::fetch( } } mBufferPool.cleanUp(); scheduleEvictIfNeeded(); return ResultStatus::CRITICAL_ERROR; } Loading Loading @@ -891,6 +898,88 @@ void Accessor::Impl::createInvalidator() { } } void Accessor::Impl::evictorThread( std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors, std::mutex &mutex, std::condition_variable &cv) { std::list<const std::weak_ptr<Accessor::Impl>> evictList; while (true) { int expired = 0; int evicted = 0; { nsecs_t now = systemTime(); std::unique_lock<std::mutex> lock(mutex); if (accessors.size() == 0) { cv.wait(lock); } auto it = accessors.begin(); while (it != accessors.end()) { if (now > (it->second + kEvictDurationNs)) { ++expired; evictList.push_back(it->first); it = accessors.erase(it); } else { ++it; } } } // evict idle accessors; for (auto it = evictList.begin(); it != evictList.end(); ++it) { const std::shared_ptr<Accessor::Impl> accessor = it->lock(); if (accessor) { accessor->cleanUp(true); ++evicted; } } if (expired > 0) { ALOGD("evictor expired: %d, evicted: %d", expired, evicted); } evictList.clear(); ::usleep(kEvictGranularityNs / 1000); } } Accessor::Impl::AccessorEvictor::AccessorEvictor() { std::thread evictor( evictorThread, std::ref(mAccessors), std::ref(mMutex), std::ref(mCv)); evictor.detach(); } void Accessor::Impl::AccessorEvictor::addAccessor( const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts) { std::lock_guard<std::mutex> lock(mMutex); bool notify = mAccessors.empty(); auto it = mAccessors.find(impl); if (it == mAccessors.end()) { mAccessors.emplace(impl, ts); } else { it->second = ts; } if (notify) { mCv.notify_one(); } } std::unique_ptr<Accessor::Impl::AccessorEvictor> Accessor::Impl::sEvictor; void Accessor::Impl::createEvictor() { if (!sEvictor) { sEvictor = std::make_unique<Accessor::Impl::AccessorEvictor>(); } } void Accessor::Impl::scheduleEvictIfNeeded() { nsecs_t now = systemTime(); if (now > (mScheduleEvictTs + kEvictGranularityNs)) { mScheduleEvictTs = now; sEvictor->addAccessor(shared_from_this(), now); } } } // namespace implementation } // namespace V2_0 } // namespace bufferpool Loading
media/bufferpool/2.0/AccessorImpl.h +24 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <map> #include <set> #include <condition_variable> #include <utils/Timers.h> #include "Accessor.h" namespace android { Loading Loading @@ -71,6 +72,8 @@ public: static void createInvalidator(); static void createEvictor(); private: // ConnectionId = pid : (timestamp_created + seqId) // in order to guarantee uniqueness for each connection Loading @@ -78,6 +81,8 @@ private: const std::shared_ptr<BufferPoolAllocator> mAllocator; nsecs_t mScheduleEvictTs; /** * Buffer pool implementation. * Loading Loading @@ -389,6 +394,25 @@ private: std::mutex &mutex, std::condition_variable &cv, bool &ready); struct AccessorEvictor { std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> mAccessors; std::mutex mMutex; std::condition_variable mCv; AccessorEvictor(); void addAccessor(const std::weak_ptr<Accessor::Impl> &impl, nsecs_t ts); }; static std::unique_ptr<AccessorEvictor> sEvictor; static void evictorThread( std::map<const std::weak_ptr<Accessor::Impl>, nsecs_t, std::owner_less<>> &accessors, std::mutex &mutex, std::condition_variable &cv); void scheduleEvictIfNeeded(); }; } // namespace implementation Loading
media/bufferpool/2.0/ClientManager.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -484,6 +484,7 @@ sp<ClientManager> ClientManager::getInstance() { sInstance = new ClientManager(); } Accessor::createInvalidator(); Accessor::createEvictor(); return sInstance; } Loading